Доступ к общим папкам на других серверах из приложения ASP.NET Core (версия Network Connected Program)

Страница обновлена :
Дата создания страницы :

Среда проверки работы

Визуальная студия
  • Visual Studio 2022
ASP.NET Ядро
  • 8 (Razor Pages, MVC)
Сервер Windows
  • 2022 г. (ASP.NET Основные системные требования)
  • 2019 (сервер развертывания общих папок)
ИИС
  • 10.0

Условия эксплуатации

Мы не тестировали его во всех случаях, но в целом он должен работать при следующих условиях:

Визуальная студия
  • Все, что может разработать проект ASP.NET Core
ASP.NET Ядро
  • Любая версия (MVC, Razor Pages, API)
Сервер Windows
  • Windows Server 2008 или более поздней версии
ИИС
  • 7.0 или более поздняя версия

предварительное условие

  • ASP.NET Основные приложения предназначены для работы в IIS.
  • Поскольку он использует API Windows для проверки подлинности, он не работает в других версиях.

окружающая среда

Он проверяется в следующей среде.

Цель использования ПК и серверов
Windows 11 (локальная) Среда для разработки программ.
SV2022Тест Среда, в которой работают IIS и ASP.NET Core. Доступ к общей папке SV2019Test можно получить отсюда
SV2019Тест Серверы с общими папками

Кроме того, различные настройки следующие.

Значение имени параметра
Доступ к имени пользователя SharedUser (Общий пользователь)
Имя общей папки SharedFolder (Общая папка)

Создание сервера общих папок

Создание пользователя

Создайте пользователя для доступа к общей папке. В этом случае мы создадим локальную учетную запись, но если вы имеете дело с серверами и учетными записями в таком домене, как Active Directory, вы также можете использовать ее.

Процесс создания пользователя выходит за рамки этих советов, поэтому мы не будем вдаваться в подробности.

SharedUser В данном случае мы создадим его с именем . Поскольку этот пользователь не управляет экраном и не изменяет настройки, пароль не может быть изменен.

Если вы оставите значение по умолчанию, вы можете войти с этим пользователем с помощью удаленного рабочего стола и т. д., поэтому, пожалуйста, удалите из группы Users .

Создание общей папки

Не имеет значения, где вы его создадите. Это связано с тем, что другие серверы не заботятся о расположении физической папки. В этом случае мы создадим папку с именем прямо под SharedFolder диском C и предоставим к ней общий доступ.

Откройте свойства и настройте параметры общего доступа.

Имя общей папки должно SharedFolder быть . Это имя будет видно другим серверам. Добавьте SharedUser разрешения.

Everyone Удалите существующий файл .

Подтвердите с помощью разрешения «Изменить».

Поскольку мы добавили только разрешения, к которым можно получить доступ извне, мы установим их внутренне, SharedUser чтобы можно было работать в этой папке.

Подтвердите с помощью разрешения «Изменить».

Создайте файл для проверки операции. В этой программе кодировка обрабатывается в UFT-8, поэтому, пожалуйста, сохраните ее в UTF-8.

Ничего страшного, если вы можете получить доступ в проводнике с \\<サーバー名>\ другого ПК, войти в системуSharedUser с помощью , и просмотреть файл.

Создание программы для чтения и записи файлов из общей папки приложения ASP.NET Core

Операция «Мистер/Мисс» заключается в нажатии кнопки.

  • Загрузка файлов в общую папку и отображение их на экране
  • Запись нового файла в общую папку

процесс.

Примерами этого являются Razor Pages и код MVC, но программа, которая обращается к общей папке, одинакова для обоих. То же самое относится и к веб-API. Во всяком случае, он должен работать и в клиентской программе.

Процесс, который подключается к сети на время выполнения определенного процесса.

Создайте следующий код в любом месте проекта. Имя класса — SharedFolderAccessor , но имя произвольное. SharedFolderAccessor Доступ к общей папке возможен до тех пор, пока не будет создан Dispose экземпляр . using Позволяет указать период времени, в течение которого доступ может быть получен в явной области.

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,
  }
}

Поскольку он использует API Win32 и WNetAddConnection2 WNetCancelConnection2 , он работает только в среде Windows. У меня пока есть комментарий, но если вы хотите узнать больше, пожалуйста, поищите его в Интернете. Помимо общих папок, можно также выполнять операции для доступа к сетевым ресурсам.

Он прост в использовании, и если вы напишете следующее, вы using сможете получить доступ к общей папке во время определения области.

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

Однако в реальности WNetCancelConnection2 соединение не отключается сразу во время вызова, поэтому using вы можете получить доступ к общей папке даже после области.

Тестирование кода с помощью SharedFolderAccessor

Так как процесс доступа к общей папке не зависит от фреймворка, мы создадим общий метод тестирования, который читает и записывает файлы. Pazor Pages и MVC должны называться одинаково.

Содержимое — это процесс, который записывает текст, переданный аргументу, в общую папку, считывает текстовый файл, уже находящийся в общей папке, и возвращает текст.

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));
    }
  }
}

Страницы Razor

В Razor Pages мы помещаем кнопку в Index.cshtml, нажимаем ее, запускаем тестовый код и выводим результаты на экран. В некоторых случаях общая папка может быть недоступна, поэтому она заключена в 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 Index.cshtml кнопка помещается в , и при нажатии на нее вызывается тестовый код общей папки.

Контроллеры/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>
@* ここまで追加 *@

Подтверждение операции

Выполните отладку и убедитесь, что вы можете успешно получить доступ к общей папке.

Создание сервера приложений

Поскольку мы убедились, что доступ к общей папке можно получить, запустив программу, следующий шаг не нужен. Если вы хотите проверить операцию на сервере IIS, вы можете сделать это, выполнив следующие действия.

Отсюда это дополнение, поэтому я не буду объяснять его слишком подробно, а в основном объясню изображение.

Установка IIS

Установите его по умолчанию из диспетчера серверов. Не буду вдаваться в подробности процедуры.

Никаких дополнительных функций не требуется.

В настоящее время дополнительные службы IIS не требуются.

Установка пакета хостинга ASP.NET Core Runtime

Поскольку мы используем ASP.NET Core 8, нам нужно установить среду выполнения соответствующим образом. Загрузите его по следующему URL-адресу:

Для того, чтобы запустить ASP.NET Core в IIS, вам понадобится что-то под названием «Hosting Bundle». Загрузите "Hosting Bundle" из ASP.NET Core Runtime.

После загрузки запустите его на сервере.

Следуйте указаниям мастера, чтобы установить его.

Опубликуйте свою программу

Выведите программу, которую требуется развернуть в IIS, в виде файла из Visual Studio.

Модифицируйте его для Windows.

Опубликуйте, когда закончите.

Если вы нажмете на целевое место, вы сможете открыть папку, в которой находится опубликованный файл.

Вам не обязательно брать их все, но если вы не уверены, вы можете взять их все на данный момент. На этом этапе все, что вам нужно сделать, это убедиться, что файл существует.

Создание и развертывание веб-приложений

В средствах администрирования Windows откройте диспетчер IIS.

Мы создадим сайт, но на этот раз мы будем использовать «Веб-сайт по умолчанию», который существует с самого начала.

Установив флажок Веб-сайт по умолчанию, нажмите кнопку Проводник, чтобы открыть папку. Скопируйте опубликованную программу здесь. Исходный файл можно удалить.

Откройте страницу по ссылке IIS и посмотрите, появится ли экран. Вы можете сначала открыть веб-браузер и ввести URL-адрес напрямую.

Подтверждение операции

Нажмите кнопку, чтобы убедиться, что он работает без каких-либо проблем. В приведенном выше примере доступ к нему осуществляется с веб-сервера, но, поскольку это веб-сервер, должна быть возможность управлять им с других ПК.