Truy cập các thư mục được chia sẻ trên các máy chủ khác từ ứng dụng ASP.NET Core (phiên bản Chương trình kết nối mạng)

Trang Cập Nhật :
Ngày tạo trang :

Môi trường xác minh hoạt động

Visual Studio
  • Visual Studio 2022
Lõi ASP.NET
  • 8 (Trang dao cạo, MVC)
Máy chủ Windows
  • 2022 (Yêu cầu hệ thống ASP.NET Core)
  • 2019 (Máy chủ triển khai thư mục dùng chung)
IIS
  • 10.0

Môi trường hoạt động

Chúng tôi chưa thử nghiệm nó trong mọi trường hợp, nhưng nó sẽ hoạt động chung trong các điều kiện sau:

Visual Studio
  • Bất cứ điều gì có thể phát triển một dự án ASP.NET Core
Lõi ASP.NET
  • Bất kỳ phiên bản nào (MVC, Razor Pages, API)
Máy chủ Windows
  • Windows Server 2008 trở lên
IIS
  • 7.0 trở lên

Điều kiện tiên quyết

  • ASP.NET ứng dụng Core được thiết kế để chạy trên IIS.
  • Vì nó sử dụng API Windows để xác thực, nó không hoạt động trên không phải Windows.

môi trường

Nó được xác minh trong môi trường sau.

Mục đích sử dụng PC và máy chủ
Windows 11 (Cục bộ) Một môi trường để phát triển các chương trình.
SV2022Thử nghiệm Môi trường chạy IIS và ASP.NET Core. Truy cập thư mục chia sẻ SV2019Test từ đây
SV2019Thử nghiệm Máy chủ có thư mục dùng chung

Ngoài ra, các cài đặt khác nhau như sau.

Giá trị tên tham số
Truy cập tên người dùng Người dùng đã chia sẻ
Tên thư mục được chia sẻ SharedFolder

Xây dựng máy chủ thư mục dùng chung

Tạo người dùng

Tạo người dùng để truy cập thư mục chung. Trong trường hợp này, chúng tôi sẽ tạo một tài khoản cục bộ, nhưng nếu bạn đang xử lý các máy chủ và tài khoản trong một miền như Active Directory, bạn cũng có thể sử dụng tài khoản đó.

Quá trình tạo người dùng nằm ngoài phạm vi của các mẹo này, vì vậy chúng tôi sẽ không đi vào quá nhiều chi tiết.

SharedUser Trong trường hợp này, chúng ta sẽ tạo nó với tên . Vì người dùng này không vận hành màn hình hoặc thay đổi cài đặt, mật khẩu không thể thay đổi.

Nếu bạn để mặc định, bạn có thể đăng nhập bằng người dùng này bằng Máy tính Từ xa, v.v., vì vậy vui lòng xóa khỏi nhóm Users .

Tạo thư mục được chia sẻ

Không quan trọng bạn tạo nó ở đâu. Điều này là do các máy chủ khác không quan tâm đến vị trí của thư mục vật lý. Trong trường hợp này, chúng tôi sẽ tạo một thư mục có tên trực tiếp dưới SharedFolder ổ C và chia sẻ nó.

Mở các thuộc tính và định cấu hình cài đặt chia sẻ.

Tên của thư mục SharedFolder được chia sẻ phải là . Tên này sẽ hiển thị cho các máy chủ khác. Thêm SharedUser quyền.

Everyone Xóa tệp . hiện có

Xác nhận bằng quyền "Thay đổi".

Vì chúng tôi chỉ thêm các quyền có thể được truy cập từ bên ngoài, chúng tôi sẽ đặt nó bên trong SharedUser để có thể hoạt động trong thư mục này.

Xác nhận bằng quyền "Thay đổi".

Tạo một tập tin để kiểm tra hoạt động. Trong chương trình này, mã hóa được xử lý trong UFT-8, vì vậy vui lòng lưu nó trong UTF-8.

Không sao nếu bạn có thể truy cập trong Explorer từ \\<サーバー名>\ một PC khác, đăng nhậpSharedUser bằng , và xem tệp.

Tạo một chương trình để đọc và ghi tệp từ thư mục được chia sẻ từ ứng dụng ASP.NET Core

Thao tác Mr./Ms. là nhấp vào nút.

  • Tải tệp trong thư mục được chia sẻ và hiển thị chúng trên màn hình
  • Ghi tệp mới vào thư mục được chia sẻ

quá trình.

Razor Pages và mã MVC là những ví dụ về điều này, nhưng chương trình truy cập thư mục được chia sẻ là giống nhau cho cả hai. Điều này cũng đúng với API Web. Nếu bất cứ điều gì, nó cũng sẽ hoạt động trong chương trình khách hàng.

Một quá trình kết nối với mạng trong suốt thời gian của một quy trình cụ thể

Tạo mã sau ở bất kỳ đâu trong dự án của bạn. Tên lớp là SharedFolderAccessor , nhưng tên là tùy ý. SharedFolderAccessor Bạn có thể truy cập thư mục được chia sẻ cho đến khi bạn tạo một Dispose phiên bản . using cho phép bạn chỉ định khoảng thời gian mà quyền truy cập có thể được truy cập trong một phạm vi rõ ràng.

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

Vì nó sử dụng API Win32 và WNetAddConnection2 WNetCancelConnection2 , nó chỉ hoạt động trong môi trường Windows. Tôi có một bình luận cho thời điểm hiện tại, nhưng nếu bạn muốn biết thêm, xin vui lòng tra cứu nó trên Internet. Ngoài các thư mục được chia sẻ, bạn cũng có thể thực hiện các thao tác để truy cập tài nguyên mạng.

Nó rất dễ sử dụng và nếu bạn viết như sau, bạn using có thể truy cập thư mục được chia sẻ trong phạm vi.

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

Tuy nhiên, trong thực tế WNetCancelConnection2 , kết nối không bị ngắt kết nối ngay lập tức tại thời điểm gọi , vì vậy using bạn có thể truy cập vào thư mục được chia sẻ ngay cả sau phạm vi.

Kiểm tra mã bằng SharedFolderAccessor

Vì quá trình truy cập thư mục được chia sẻ không phụ thuộc vào khung, chúng tôi tạo một phương pháp chung để kiểm tra đọc và ghi tệp. Trang Pazor và MVC nên được gọi giống nhau.

Nội dung là một quá trình ghi văn bản được truyền vào đối số vào thư mục được chia sẻ, đọc tệp văn bản đã có trong thư mục được chia sẻ và trả về văn bản.

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

Trang dao cạo

Trong Razor Pages, chúng tôi đặt một nút trong Index.cshtml, nhấp vào nó, chạy mã kiểm tra và hiển thị kết quả trên màn hình. Trong một số trường hợp, thư mục được chia sẻ có thể không truy cập được, vì vậy nó được đặt trong một lần bắt thử.

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

Chỉ mục.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

Tương tự, trong trường hợp MVC, Index.cshtml một nút được đặt trong và khi được nhấp, nó sẽ gọi mã kiểm tra của thư mục được chia sẻ.

Bộ điều khiển/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();
    }

    // 省略
  }
}

Chỉ mục.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>
@* ここまで追加 *@

Xác nhận hoạt động

Gỡ lỗi và xác minh rằng bạn có thể truy cập thành công vào thư mục được chia sẻ.

Xây dựng máy chủ ứng dụng

Vì chúng tôi đã xác nhận rằng thư mục được chia sẻ có thể được truy cập bằng cách chạy chương trình, bước tiếp theo là không cần thiết. Nếu bạn muốn kiểm tra hoạt động trên máy chủ IIS, bạn có thể thực hiện bằng cách làm theo các bước dưới đây.

Từ đây, nó là một bổ sung, vì vậy tôi sẽ không giải thích nó quá chi tiết, mà sẽ chủ yếu giải thích hình ảnh.

Cài đặt IIS

Cài đặt nó theo mặc định từ Trình quản lý máy chủ. Tôi sẽ không đi vào chi tiết của thủ tục.

Không có tính năng bổ sung được yêu cầu.

Không có dịch vụ IIS bổ sung được yêu cầu tại thời điểm này.

Cài đặt gói lưu trữ thời gian chạy lõi ASP.NET

Vì chúng tôi đang sử dụng ASP.NET Core 8, chúng tôi cần cài đặt thời gian chạy cho phù hợp. Tải xuống từ URL sau:

Để chạy ASP.NET Core trong IIS, bạn cần một thứ gọi là "Hosting Bundle". Tải xuống "Gói lưu trữ" từ ASP.NET Core Runtime.

Sau khi tải xuống, hãy chạy nó trên máy chủ.

Làm theo trình hướng dẫn để cài đặt nó.

Xuất bản chương trình của bạn

Xuất chương trình mà bạn muốn triển khai IIS dưới dạng tệp từ Visual Studio.

Sửa đổi nó cho Windows.

Xuất bản khi bạn hoàn tất.

Nếu bạn nhấp vào vị trí đích, bạn có thể mở thư mục chứa tệp đã xuất bản.

Bạn không cần phải mang theo tất cả, nhưng nếu bạn không chắc chắn, bạn có thể mang tất cả chúng ngay bây giờ. Tại thời điểm này, tất cả những gì bạn cần làm là đảm bảo rằng tệp tồn tại.

Tạo và triển khai các ứng dụng web

Từ Công cụ Quản trị Windows, mở Trình quản lý Dịch vụ Thông tin Internet (IIS).

Chúng tôi sẽ tạo một trang web, nhưng lần này chúng tôi sẽ sử dụng "Trang web mặc định" ở đó ngay từ đầu.

Với trang Web mặc định được chọn, bấm Explorer để mở thư mục. Sao chép chương trình đã xuất bản tại đây. Bạn có thể xóa tệp gốc.

Mở trang từ liên kết IIS và xem màn hình có xuất hiện không. Trước tiên, bạn có thể mở trình duyệt web và nhập URL trực tiếp.

Xác nhận hoạt động

Nhấp vào nút để xác minh rằng nó hoạt động mà không gặp bất kỳ sự cố nào. Ở trên, nó được truy cập từ bên trong máy chủ web, nhưng vì nó là một máy chủ web, nên có thể vận hành nó từ các PC khác.