การเข้าถึงโฟลเดอร์ที่ใช้ร่วมกันบนเซิร์ฟเวอร์อื่นจากแอปพลิเคชัน ASP.NET Core (เวอร์ชันโปรแกรมที่เชื่อมต่อเครือข่าย)

ปรับปรุงหน้า :
วันที่สร้างเพจ :

สภาพแวดล้อมการตรวจสอบการทํางาน

วิชวลสตูดิโอ
  • วิชวลสตูดิโอ 2022
แกน ASP.NET
  • 8 (หน้ามีดโกน, 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 Core มีวัตถุประสงค์เพื่อทํางานบน IIS
  • เนื่องจากใช้ Windows API สําหรับการรับรองความถูกต้อง จึงไม่ทํางานบนที่ไม่ใช่ Windows

สิ่งแวดล้อม

มีการตรวจสอบในสภาพแวดล้อมต่อไปนี้

วัตถุประสงค์ในการใช้พีซีและเซิร์ฟเวอร์
Windows 11 (ในเครื่อง) สภาพแวดล้อมสําหรับการพัฒนาโปรแกรม
SV2022 ทดสอบ สภาพแวดล้อมที่เรียกใช้ IIS และ ASP.NET Core เข้าถึงโฟลเดอร์ที่ใช้ร่วมกัน SV2019Test จากที่นี่
SV2019 ทดสอบ เซิร์ฟเวอร์ที่มีโฟลเดอร์ที่ใช้ร่วมกัน

นอกจากนี้การตั้งค่าต่างๆมีดังนี้

ค่าชื่อพารามิเตอร์
เข้าถึงชื่อผู้ใช้ แชร์โฮสติ้ง User
ชื่อโฟลเดอร์ที่ใช้ร่วมกัน แชร์โฮสติ้ง Folder

การสร้างเซิร์ฟเวอร์โฟลเดอร์ที่ใช้ร่วมกัน

สร้างผู้ใช้

สร้างผู้ใช้เพื่อเข้าถึงโฟลเดอร์ทั่วไป ในกรณีนี้เราจะสร้างบัญชีท้องถิ่น แต่ถ้าคุณจัดการกับเซิร์ฟเวอร์และบัญชีในโดเมนเช่น Active Directory คุณสามารถใช้ได้เช่นกัน

กระบวนการสร้างผู้ใช้อยู่นอกเหนือขอบเขตของเคล็ดลับเหล่านี้ดังนั้นเราจะไม่ลงรายละเอียดมากเกินไป

SharedUserในกรณีนี้เราจะสร้างด้วยชื่อ . เนื่องจากผู้ใช้รายนี้ไม่ได้ใช้งานหน้าจอหรือเปลี่ยนการตั้งค่า จึงไม่สามารถเปลี่ยนรหัสผ่านได้

หากคุณปล่อยให้เป็นค่าเริ่มต้นคุณสามารถเข้าสู่ระบบด้วยผู้ใช้รายนี้ด้วย Remote Desktop ฯลฯ ดังนั้นโปรดลบออกจากกลุ่มUsers

การสร้างโฟลเดอร์ที่ใช้ร่วมกัน

ไม่สําคัญว่าคุณจะสร้างมันขึ้นมาที่ไหน นี่เป็นเพราะเซิร์ฟเวอร์อื่นไม่สนใจตําแหน่งของโฟลเดอร์จริง ในกรณีนี้เราจะสร้างโฟลเดอร์ที่มีชื่อโดยตรงภายใต้ SharedFolder ไดรฟ์ C และแบ่งปัน

เปิดคุณสมบัติและกําหนดการตั้งค่าการแชร์

ชื่อของโฟลเดอร์ที่แชร์ควรเป็น SharedFolder ชื่อนี้จะปรากฏแก่เซิร์ฟเวอร์อื่น เพิ่ม SharedUser สิทธิ์

Everyoneลบที่มีอยู่

ยืนยันด้วยสิทธิ์ "เปลี่ยน"

เนื่องจากเราได้เพิ่มการอนุญาตที่สามารถเข้าถึงได้จากภายนอกเท่านั้นเราจะตั้งค่าภายใน SharedUser เพื่อให้สามารถทํางานในโฟลเดอร์นี้ได้

ยืนยันด้วยสิทธิ์ "เปลี่ยน"

สร้างไฟล์เพื่อตรวจสอบการทํางาน การเข้ารหัสจะถูกประมวลผลใน UFT-8 ดังนั้นโปรดบันทึกไว้ใน UTF-8

ไม่เป็นไรหากคุณสามารถเข้าถึงได้ใน Explorer จาก \\<サーバー名>\ พีซีเครื่องอื่น เข้าสู่ระบบSharedUser ด้วย และดูไฟล์

สร้างโปรแกรมเพื่ออ่านและเขียนไฟล์จากโฟลเดอร์ที่ใช้ร่วมกันจากแอปพลิเคชัน ASP.NET Core

การดําเนินการของ Mr./Ms. คือการคลิกปุ่ม

  • โหลดไฟล์ในโฟลเดอร์ที่ใช้ร่วมกันและแสดงบนหน้าจอ
  • เขียนไฟล์ใหม่ไปยังโฟลเดอร์ที่แชร์

แปรรูป

Razor Pages และรหัส MVC เป็นตัวอย่างของสิ่งนี้ แต่โปรแกรมที่เข้าถึงโฟลเดอร์ที่ใช้ร่วมกันจะเหมือนกันสําหรับทั้งคู่ เช่นเดียวกับ Web 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,
  }
}

เนื่องจากใช้ Win32 API และ 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 Pages เราวางปุ่มใน Index.cshtml คลิก เรียกใช้โค้ดทดสอบ และแสดงผลลัพธ์บนหน้าจอ ในบางกรณี โฟลเดอร์ที่ใช้ร่วมกันอาจไม่สามารถเข้าถึงได้ ดังนั้นจึงอยู่ในการลองจับ

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

ดัชนี.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();
    }

    // 省略
  }
}

ดัชนี.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 Hosting Bundle

เนื่องจากเราใช้ ASP.NET Core 8 เราจึงจําเป็นต้องติดตั้งรันไทม์ตามนั้น ดาวน์โหลดได้จาก URL ต่อไปนี้:

ในการเรียกใช้ ASP.NET Core ใน IIS คุณต้องมีสิ่งที่เรียกว่า "Hosting Bundle" ดาวน์โหลด "Hosting Bundle" จาก ASP.NET Core Runtime

เมื่อดาวน์โหลดแล้วให้เรียกใช้บนเซิร์ฟเวอร์

ทําตามวิซาร์ดเพื่อติดตั้ง

เผยแพร่โปรแกรมของคุณ

ส่งออกโปรแกรมที่คุณต้องการปรับใช้กับ IIS เป็นแฟ้มจาก Visual Studio

แก้ไขสําหรับ Windows

เผยแพร่เมื่อคุณทําเสร็จแล้ว

หากคุณคลิกที่ตําแหน่งเป้าหมายคุณสามารถเปิดโฟลเดอร์ที่มีไฟล์ที่เผยแพร่อยู่

คุณไม่จําเป็นต้องนํามาทั้งหมด แต่ถ้าคุณไม่แน่ใจ คุณสามารถนําพวกเขาทั้งหมดไปได้ในตอนนี้ ณ จุดนี้สิ่งที่คุณต้องทําคือตรวจสอบให้แน่ใจว่ามีไฟล์อยู่

การสร้างและการปรับใช้เว็บแอปพลิเคชัน

จาก Windows Administrative Tools ให้เปิด Internet Information Services (IIS) Manager

เราจะสร้างเว็บไซต์ แต่คราวนี้เราจะใช้ "เว็บไซต์เริ่มต้น" ที่มีอยู่ตั้งแต่ต้น

เมื่อเลือก เว็บไซต์เริ่มต้น ให้คลิก Explorer เพื่อเปิดโฟลเดอร์ คัดลอกโปรแกรมที่เผยแพร่ที่นี่ คุณสามารถลบไฟล์ต้นฉบับได้

เปิดหน้าจากการเชื่อมโยง IIS และดูว่าหน้าจอปรากฏขึ้นหรือไม่ คุณสามารถเปิดเว็บเบราว์เซอร์ก่อนและป้อน URL โดยตรง

การยืนยันการดําเนินการ

คลิกปุ่มเพื่อตรวจสอบว่าใช้งานได้โดยไม่มีปัญหาใดๆ ในข้างต้นสามารถเข้าถึงได้จากภายในเว็บเซิร์ฟเวอร์ แต่เนื่องจากเป็นเว็บเซิร์ฟเวอร์จึงควรสามารถใช้งานได้จากพีซีเครื่องอื่น