Accès aux dossiers partagés sur d’autres serveurs à partir d’une application ASP.NET Core (version Network Connected Program)

Page mise à jour :
Date de création de la page :

Environnement de vérification des opérations

Studio visuel
  • Visual Studio 2022
ASP.NET Noyau
  • 8 (Razor Pages, MVC)
Serveur Windows
  • 2022 (ASP.NET Configuration système de base)
  • 2019 (serveur de déploiement de dossiers partagés)
L’IIS
  • 10.0

Environnement d’exploitation

Nous ne l’avons pas testé dans tous les cas, mais il devrait fonctionner généralement dans les conditions suivantes :

Studio visuel
  • Tout ce qui peut développer un projet ASP.NET Core
ASP.NET Noyau
  • Toute version (MVC, Razor Pages, API)
Serveur Windows
  • Windows Server 2008 ou version ultérieure
L’IIS
  • 7.0 ou version ultérieure

condition préalable

  • ASP.NET applications principales sont destinées à s’exécuter sur IIS.
  • Comme il utilise les API Windows pour l’authentification, il ne fonctionne pas sur les non-Windows.

environnement

Elle est vérifiée dans l’environnement suivant.

Objectif d’utilisation des PC et des serveurs
Windows 11 (local) Un environnement propice à l’élaboration de programmes.
SV2022Test Un environnement qui exécute IIS et ASP.NET Core. Accédez au dossier partagé SV2019Test à partir d’ici
SV2019Test Serveurs avec dossiers partagés

De plus, les différents réglages sont les suivants.

Valeur du nom du paramètre
Accéder au nom d’utilisateur Utilisateur partagé
Nom du dossier partagé DossierPartagé

Création d’un serveur de dossiers partagés

Créer un utilisateur

Créez un utilisateur pour accéder au dossier commun. Dans ce cas, nous allons créer un compte local, mais si vous avez affaire à des serveurs et à des comptes dans un domaine tel qu’Active Directory, vous pouvez également l’utiliser.

Le processus de création d’un utilisateur dépasse le cadre de ces conseils, nous n’entrerons donc pas trop dans les détails.

SharedUser Dans ce cas, nous allons le créer avec le nom . Comme cet utilisateur n’utilise pas l’écran ou ne modifie pas les paramètres, le mot de passe ne peut pas être modifié.

Si vous laissez la valeur par défaut, vous pouvez vous connecter avec cet utilisateur avec Remote Desktop, etc., veuillez donc supprimer du groupe Users .

Création d’un dossier partagé

Peu importe où vous le créez. En effet, les autres serveurs ne se soucient pas de l’emplacement du dossier physique. Dans ce cas, nous allons créer un dossier nommé directement sous SharedFolder le lecteur C et le partager.

Ouvrez les propriétés et configurez les paramètres de partage.

Le nom du dossier partagé doit SharedFolder être . Ce nom sera visible par les autres serveurs. Ajoutez SharedUser les autorisations.

Everyone Supprimez le fichier .

Confirmez avec l’autorisation « Modifier ».

Comme nous n’avons ajouté que des autorisations accessibles de l’extérieur, nous allons le définir en interne SharedUser afin qu’il puisse fonctionner dans ce dossier.

Confirmez avec l’autorisation « Modifier ».

Créez un fichier pour vérifier l’opération. Dans ce programme, l’encodage est traité en UFT-8, veuillez donc l’enregistrer en UTF-8.

Vous pouvez accéder à l’Explorateur à partir d’un \\<サーバー名>\ autre PC, vous connecterSharedUser avec et afficher le fichier.

Créer un programme pour lire et écrire des fichiers à partir d’un dossier partagé à partir d’une application ASP.NET Core

L’opération Mr./Ms. consiste à cliquer sur le bouton.

  • Charger des fichiers dans un dossier partagé et les afficher à l’écran
  • Écrire un nouveau fichier dans un dossier partagé

processus.

Razor Pages et le code MVC en sont des exemples, mais le programme qui accède au dossier partagé est le même pour les deux. Il en va de même pour les API Web. Au contraire, cela devrait également fonctionner dans le programme client.

Processus qui se connecte à un réseau pendant la durée d’un processus spécifique

Créez le code suivant n’importe où dans votre projet. Le nom de la classe est SharedFolderAccessor , mais le nom est arbitraire. SharedFolderAccessor Vous pouvez accéder au dossier partagé jusqu’à ce que vous créiez une Dispose instance de . using vous permet de spécifier la période pendant laquelle l’accès est accessible dans une étendue explicite.

using System.ComponentModel;
using System.Net;
using System.Runtime.InteropServices;

/// <summary>
/// 共有フォルダにユーザー名とパスワードでアクセスするためのクラスです。
/// using を使用すればそのスコープの間、共有フォルダにアクセスできます。
/// </summary>
public class SharedFolderAccessor : IDisposable
{
  private readonly string _networkName;

  /// <summary>
  /// コンストラクタです。
  /// </summary>
  /// <param name="networkName">共有フォルダのあるサーバーを「\\&lt;サーバー名&gt;」形式で指定します。</param>
  /// <param name="credentials">共有フォルダにアクセスするための資格情報です。</param>
  /// <exception cref="Win32Exception"></exception>
  public SharedFolderAccessor(string networkName, NetworkCredential credentials)
  {
    _networkName = networkName;

    // 接続するネットワークの情報を設定
    var netResource = new NetResource
    {
      Scope = ResourceScope.GlobalNetwork,
      ResourceType = ResourceType.Disk,
      DisplayType = ResourceDisplaytype.Share,
      RemoteName = networkName,
    };

    // ドメインがある場合はドメイン名も指定、ない場合はユーザー名のみ
    var userName = string.IsNullOrEmpty(credentials.Domain)
        ? credentials.UserName
        : $@"{credentials.Domain}\{credentials.UserName}";

    // 共有フォルダにユーザー名とパスワードで接続
    var result = WNetAddConnection2(netResource, credentials.Password, userName, 0);

    if (result != 0)
    {
      throw new Win32Exception(result, $"共有フォルダに接続できませんでした。(エラーコード:{result})");
    }

    // 正常に接続できれば WNetCancelConnection2 を呼び出すまではプログラムで共有フォルダにアクセス可能
  }

  ~SharedFolderAccessor()
  {
    // Dispose を呼び忘れたときの保険
    WNetCancelConnection2(_networkName, 0, true);
  }

  public void Dispose()
  {
    WNetCancelConnection2(_networkName, 0, true);
    GC.SuppressFinalize(this);  // Dispose を明示的に呼んだ場合はデストラクタの処理は不要
  }

  /// <summary>
  /// ネットワーク リソースへの接続を確立し、ローカル デバイスをネットワーク リソースにリダイレクトできます。
  /// </summary>
  /// <param name="netResource">ネットワーク リソース、ローカル デバイス、ネットワーク リソース プロバイダーに関する情報など。</param>
  /// <param name="password">ネットワーク接続の作成に使用するパスワード。</param>
  /// <param name="username">接続を確立するためのユーザー名。</param>
  /// <param name="flags">接続オプションのセット。</param>
  /// <returns></returns>
  [DllImport("mpr.dll")]
  private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);

  /// <summary>
  /// 既存のネットワーク接続を取り消します。
  /// </summary>
  /// <param name="name">リダイレクトされたローカル デバイスまたは切断するリモート ネットワーク リソースの名前。</param>
  /// <param name="flags">接続の種類。</param>
  /// <param name="force">接続に開いているファイルまたはジョブがある場合に切断を行う必要があるかどうか。</param>
  /// <returns></returns>
  [DllImport("mpr.dll")]
  private static extern int WNetCancelConnection2(string name, int flags, bool force);

  /// <summary>
  /// NETRESOURCE 構造体を定義しています。
  /// </summary>
  [StructLayout(LayoutKind.Sequential)]
  private class NetResource
  {
    public ResourceScope Scope;
    public ResourceType ResourceType;
    public ResourceDisplaytype DisplayType;
    public int Usage;
    public string LocalName = "";
    public string RemoteName = "";
    public string Comment = "";
    public string Provider = "";
  }

  /// <summary>
  /// ネットワークリソースのスコープ。
  /// </summary>
  private enum ResourceScope : int
  {
    /// <summary>ネットワークリソースへの現在の接続。</summary>
    Connected = 1,
    /// <summary>すべてのネットワークリソース。</summary>
    GlobalNetwork = 2,
    Remembered = 3,
    Recent = 4,
    /// <summary>ユーザーの現在および既定のネットワークコンテキストに関連付けられているネットワークリソース。</summary>
    Context = 5,
  };

  /// <summary>
  /// リソースの種類。
  /// </summary>
  private enum ResourceType : int
  {
    /// <summary>印刷リソースとディスクリソースの両方のコンテナー、または印刷またはディスク以外のリソースなど。</summary>
    Any = 0,
    /// <summary>共有ディスクボリューム。</summary>
    Disk = 1,
    /// <summary>共有プリンター。</summary>
    Print = 2,
    Reserved = 8,
  }

  /// <summary>
  /// ユーザーインターフェイスで使用する必要がある表示の種類。
  /// </summary>
  private enum ResourceDisplaytype : int
  {
    /// <summary>リソースの種類を指定しないネットワークプロバイダーによって使用されます。</summary>
    Generic = 0x0,
    /// <summary>サーバーのコレクション。</summary>
    Domain = 0x01,
    /// <summary>サーバー。</summary>
    Server = 0x02,
    /// <summary>共有ポイント。</summary>
    Share = 0x03,
    File = 0x04,
    Group = 0x05,
    /// <summary>ネットワークプロバイダー。</summary>
    Network = 0x06,
    Root = 0x07,
    Shareadmin = 0x08,
    /// <summary>ディレクトリ。</summary>
    Directory = 0x09,
    Tree = 0x0a,
    Ndscontainer = 0x0b,
  }
}

Comme il utilise les API Win32 et WNetAddConnection2 WNetCancelConnection2 , il ne fonctionne que dans l’environnement Windows. J’ai un commentaire pour le moment, mais si vous voulez en savoir plus, n’hésitez pas à le rechercher sur Internet. Outre les dossiers partagés, vous pouvez également effectuer des opérations pour accéder aux ressources réseau.

Il est facile à utiliser, et si vous écrivez ce qui suit, vous using pouvez accéder au dossier partagé pendant la portée.

using (new SharedFolderAccessor($@"\\{serverName}", credentials))
{
  // この間は共有フォルダにアクセスできる
}

Cependant, en réalité WNetCancelConnection2 , la connexion n’est pas immédiatement déconnectée au moment de l’appel, vous pouvez donc using accéder au dossier partagé même après la portée.

Tester le code à l’aide de SharedFolderAccessor

Étant donné que le processus d’accès au dossier partagé ne dépend pas de l’infrastructure, nous créons une méthode commune de test qui lit et écrit des fichiers. Pazor Pages et MVC devraient s’appeler de la même manière.

Le contenu est un processus qui écrit le texte transmis à l’argument dans le dossier partagé, lit le fichier texte déjà présent dans le dossier partagé et renvoie le texte.

using System.Net;

public static class Util
{
  public static string ReadAndWrite(string text)
  {
    var serverName = "ServerName";
    var folderName = "SharedFolder";
    var inputFileName = "Input.txt";
    var outputFileName = "Output.txt";
    var username = "SharedUser";
    var password = "password";

    var credentials = new NetworkCredential(username, password);
    using (new SharedFolderAccessor($@"\\{serverName}", credentials))
    {
      // ファイルの書き出し
      System.IO.File.WriteAllText(Path.Combine($@"\\{serverName}\{folderName}", outputFileName), text);

      // ファイルの読み込み
      return System.IO.File.ReadAllText(Path.Combine($@"\\{serverName}\{folderName}", inputFileName));
    }
  }
}

Pages de rasoir

Dans Razor Pages, nous plaçons un bouton dans Index.cshtml, cliquons dessus, exécutons le code de test et affichons les résultats à l’écran. Dans certains cas, le dossier partagé peut ne pas être accessible, il est donc enfermé dans un try-catch.

Index.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace SharedFolderAccessRazorPages.Pages
{
  public class IndexModel : PageModel
  {
    private readonly ILogger<IndexModel> _logger;
    public string Message { get; set; } = "";

    public IndexModel(ILogger<IndexModel> logger)
    {
      _logger = logger;
    }

    public void OnPost()
    {
      try
      {
        Message = Util.ReadAndWrite($"プログラムからの書き込み ({DateTime.Now})");
      }
      catch (Exception ex)
      {
        Message = ex.ToString();
      }
    }
  }
}

Index.cshtml

@page
@model IndexModel
@{
  ViewData["Title"] = "Home page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

@* ここから追加 *@
<form method="post">
  <button type="submit">サブミット</button>
</form>

<div>
  @Model.Message
</div>
@* ここまで追加 *@

MVC

De même, dans le cas de MVC, Index.cshtml un bouton est placé dans , et lorsqu’il est cliqué, il appelle le code de test du dossier partagé.

Contrôleurs/HomeController.cs

// 省略

namespace SharedFolderAccessMvc.Controllers
{
  public class HomeController : Controller
  {
    // 省略

    public IActionResult Index()
    {
      return View();
    }

    // ここから追加
    [HttpPost]
    public IActionResult Index(string dummy)
    {
      try
      {
        ViewData["Message"] = Util.ReadAndWrite($"プログラムからの書き込み ({DateTime.Now})");
      }
      catch (Exception ex)
      {
        ViewData["Message"] = ex.ToString();
      }
      return View();
    }
    // ここまで追加

    public IActionResult Privacy()
    {
      return View();
    }

    // 省略
  }
}

Index.cshtml

@{
  ViewData["Title"] = "Home Page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

@* ここから追加 *@
<form method="post">
  <button type="submit">サブミット</button>
</form>

<div>
  @ViewData["Message"]
</div>
@* ここまで追加 *@

Confirmation de l’opération

Déboguez et vérifiez que vous pouvez accéder au dossier partagé.

Création d’un serveur d’applications

Puisque nous avons confirmé que le dossier partagé est accessible en exécutant le programme, l’étape suivante n’est pas nécessaire. Si vous souhaitez vérifier l’opération sur le serveur IIS, vous pouvez le faire en suivant les étapes ci-dessous.

À partir de là, il s’agit d’un complément, je ne vais donc pas l’expliquer trop en détail, mais j’expliquerai principalement l’image.

Installation d’IIS

Installez-le par défaut à partir du Gestionnaire de serveur. Je n’entrerai pas dans les détails de la procédure.

Aucune fonctionnalité supplémentaire n’est requise.

Aucun service IIS supplémentaire n’est requis pour le moment.

Installation de l’offre groupée d’hébergement d’exécution ASP.NET Core

Puisque nous utilisons ASP.NET Core 8, nous devons installer le runtime en conséquence. Téléchargez-le à partir de l’URL suivante :

Pour exécuter ASP.NET Core dans IIS, vous avez besoin de quelque chose appelé « Bundle d’hébergement ». Téléchargez le « Bundle d’hébergement » à partir du runtime ASP.NET Core.

Une fois téléchargé, exécutez-le sur le serveur.

Suivez l’assistant pour l’installer.

Publiez votre programme

Générez le programme que vous souhaitez déployer sur IIS sous forme de fichier à partir de Visual Studio.

Modifiez-le pour Windows.

Publiez lorsque vous avez terminé.

Si vous cliquez sur l’emplacement cible, vous pouvez ouvrir le dossier où se trouve le fichier publié.

Vous n’êtes pas obligé de tous les apporter, mais si vous n’êtes pas sûr, vous pouvez tous les prendre pour le moment. À ce stade, tout ce que vous avez à faire est de vous assurer que le fichier existe.

Création et déploiement d’applications Web

Dans Outils d’administration Windows, ouvrez le Gestionnaire des services Internet (IIS).

Nous allons créer un site, mais cette fois-ci nous utiliserons le « Site Web par défaut » qui est là depuis le début.

Lorsque Site Web par défaut est sélectionné, cliquez sur Explorateur pour ouvrir le dossier. Copiez le programme publié ici. Vous pouvez supprimer le fichier d’origine.

Ouvrez la page à partir du lien IIS et voyez si l’écran apparaît. Vous pouvez d’abord ouvrir un navigateur Web et saisir directement l’URL.

Confirmation de l’opération

Cliquez sur le bouton pour vérifier qu’il fonctionne sans problème. Dans ce qui précède, il est accessible depuis le serveur Web, mais comme il s’agit d’un serveur Web, il devrait être possible de l’utiliser à partir d’autres PC.