Adgang til delte mapper på andre servere fra et ASP.NET Core-program (version af Network Connected Program)

Side opdateret :
Dato for oprettelse af side :

Miljø til driftsbekræftelse

Visual Studio
  • Visual Studio 2022
ASP.NET kerne
  • 8 (Barberbladssider, MVC)
Windows Server
  • 2022 (ASP.NET Core Systemkrav)
  • 2019 (Implementeringsserver til delt mappe)
IIS
  • 10.0

Driftsmiljø

Vi har ikke testet det i alle tilfælde, men det skal fungere generelt under følgende forhold:

Visual Studio
  • Alt, hvad der kan udvikle et ASP.NET Core-projekt
ASP.NET kerne
  • Enhver version (MVC, Razor Pages, API)
Windows Server
  • Windows Server 2008 eller nyere
IIS
  • 7.0 eller nyere

forudsætning

  • ASP.NET Core-programmer er beregnet til at køre på IIS.
  • Da det bruger Windows API'er til godkendelse, fungerer det ikke på ikke-Windows.

miljø

Det er verificeret i følgende miljø.

Formål med brug af pc'er og servere
Windows 11 (lokalt) Et miljø til udvikling af programmer.
SV2022Test Et miljø, der kører IIS og ASP.NET Core. Få adgang til den delte mappe SV2019Test herfra
SV2019Test Servere med delte mapper

Derudover er de forskellige indstillinger som følger.

Værdi for parameternavn
Få adgang til brugernavn Deltbruger
Navn på delt mappe Deltmappe

Opbygning af en delt mappeserver

Opret en bruger

Opret en bruger for at få adgang til den fælles mappe. I dette tilfælde opretter vi en lokal konto, men hvis du har at gøre med servere og konti i et domæne som Active Directory, kan du også bruge det.

Processen med at oprette en bruger ligger uden for rammerne af disse tip, så vi vil ikke gå for meget i detaljer.

SharedUser I dette tilfælde opretter vi det med navnet . Da denne bruger ikke betjener skærmen eller ændrer indstillingerne, kan adgangskoden ikke ændres.

Hvis du forlader standard, kan du logge ind med denne bruger med Remote Desktop osv., Så fjern venligst fra gruppen Users .

Oprettelse af en delt mappe

Det betyder ikke noget, hvor du opretter det. Dette skyldes, at andre servere er ligeglade med placeringen af den fysiske mappe. I dette tilfælde opretter vi en mappe navngivet direkte under SharedFolder C-drevet og deler den.

Åbn egenskaberne, og konfigurer delingsindstillingerne.

Navnet på den delte mappe skal SharedFolder være . Dette navn vil være synligt for andre servere. Tilføj SharedUser tilladelserne.

Everyone Slet den eksisterende .

Bekræft med tilladelsen "Skift".

Da vi kun har tilføjet tilladelser, der kan tilgås udefra, indstiller vi det internt SharedUser , så det kan fungere i denne mappe.

Bekræft med tilladelsen "Skift".

Opret en fil for at kontrollere handlingen. I dette program behandles kodningen i UFT-8, så gem den i UTF-8.

Det er OK, hvis du kan få adgang til Explorer fra \\<サーバー名>\ en anden pc, loggeSharedUser ind med og se filen.

Opret et program til at læse og skrive filer fra en delt mappe fra et ASP.NET Core-program

Hr. / Ms. handling er at klikke på knappen.

  • Indlæs filer i en delt mappe, og vis dem på skærmen
  • Skriv en ny fil til en delt mappe

proces.

Razor Pages og MVC-kode er eksempler på dette, men programmet, der får adgang til den delte mappe, er det samme for begge. Det samme gælder for web-API'er. Hvis noget, skal det også fungere i klientprogrammet.

En proces, der opretter forbindelse til et netværk i løbet af en bestemt proces

Opret følgende kode hvor som helst i projektet. Klassenavnet er SharedFolderAccessor , men navnet er vilkårligt. SharedFolderAccessor Du kan få adgang til den delte mappe, indtil du opretter en Dispose forekomst af . using Giver dig mulighed for at angive den periode, hvor der kan opnås adgang til adgang i et eksplicit omfang.

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

Da det bruger Win32 API'er og WNetAddConnection2 WNetCancelConnection2 , fungerer det kun i Windows-miljøet. Jeg har en kommentar for øjeblikket, men hvis du vil vide mere, kan du slå den op på internettet. Ud over delte mapper kan du også udføre handlinger for at få adgang til netværksressourcer.

Det er nemt at bruge, og hvis du skriver følgende, kan du using få adgang til den delte mappe under omfanget.

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

Dog i virkeligheden WNetCancelConnection2 , forbindelsen afbrydes ikke straks på tidspunktet for opkald , så using du kan få adgang til den delte mappe, selv efter omfanget.

Test kode ved hjælp af SharedFolderAccessor

Da processen med at få adgang til den delte mappe ikke afhænger af rammen, opretter vi en fælles metode til test, der læser og skriver filer. Pazor Pages og MVC skal kaldes det samme.

Indholdet er en proces, der skriver den tekst, der overføres til argumentet, til den delte mappe, læser den tekstfil, der allerede findes i den delte mappe, og returnerer teksten.

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

Barbermaskine sider

I Razor Pages placerer vi en knap i Index.cshtml, klikker på den, kører testkoden og viser resultaterne på skærmen. I nogle tilfælde er den delte mappe muligvis ikke tilgængelig, så den er omsluttet af en prøvefangst.

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

Indeks.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

Tilsvarende, i tilfælde af MVC, Index.cshtml en knap er placeret i , og når der klikkes på den, kalder den testkoden for den delte mappe.

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

    // 省略
  }
}

Indeks.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>
@* ここまで追加 *@

Bekræftelse af operationen

Foretag fejlfinding og kontroller, at du kan få adgang til den delte mappe.

Opbygning af en applikationsserver

Da vi har bekræftet, at den delte mappe kan tilgås ved at køre programmet, er det næste trin unødvendigt. Hvis du vil kontrollere handlingen på IIS-serveren, kan du gøre det ved at følge nedenstående trin.

Herfra er det et supplement, så jeg vil ikke forklare det for meget detaljeret, men vil hovedsageligt forklare billedet.

Installation af IIS

Installer det som standard fra Server Manager. Jeg vil ikke gå i detaljer med proceduren.

Der kræves ingen yderligere funktioner.

Der kræves ingen yderligere IIS-tjenester på nuværende tidspunkt.

ASP.NET Core Runtime Hosting Bundle Installation

Da vi bruger ASP.NET Core 8, er vi nødt til at installere runtime i overensstemmelse hermed. Download det fra følgende URL:

For at køre ASP.NET Core i IIS har du brug for noget, der hedder "Hosting Bundle". Download "Hosting Bundle" fra ASP.NET Core Runtime.

Når den er downloadet, skal du køre den på serveren.

Følg guiden for at installere den.

Udgiv dit program

Send det program, du vil installere til IIS, som en fil fra Visual Studio.

Rediger det til Windows.

Udgiv, når du er færdig.

Hvis du klikker på målplaceringen, kan du åbne den mappe, hvor den offentliggjorte fil er placeret.

Du behøver ikke at medbringe dem alle, men hvis du ikke er sikker, kan du tage dem alle for nu. På dette tidspunkt er alt, hvad du skal gøre, at sikre dig, at filen findes.

Oprettelse og implementering af webapplikationer

Åbn Internet Information Services (IIS) Manager fra Windows Administration.

Vi opretter et websted, men denne gang bruger vi "Standardwebstedet", der er der fra starten.

Når Standardwebsted er valgt, skal du klikke på Stifinder for at åbne mappen. Kopier det offentliggjorte program her. Du kan slette den oprindelige fil.

Åbn siden fra IIS-linket, og se, om skærmen vises. Du kan åbne en webbrowser først og indtaste URL'en direkte.

Bekræftelse af operationen

Klik på knappen for at kontrollere, at den fungerer uden problemer. I ovenstående tilgås den fra webserveren, men da det er en webserver, skal det være muligt at betjene den fra andre pc'er.