Bir ASP.NET Core uygulamasından diğer sunuculardaki paylaşımlı klasörlere erişme (Ağ Bağlantılı Program sürümü)

Sayfa güncel :
Sayfa oluşturma tarihi :

Operasyon doğrulama ortamı

Visual Studio
  • Visual Studio 2022
ASP.NET Çekirdeği
  • 8 (Razor Sayfaları, MVC)
Windows Sunucusu
  • 2022 (ASP.NET Çekirdek Sistem Gereksinimleri)
  • 2019 (Paylaşımlı Klasör Dağıtım Sunucusu)
IIS (IIS)
  • 10.0

Çalışma ortamı

Her durumda test etmedik, ancak genellikle aşağıdaki koşullar altında çalışması gerekir:

Visual Studio
  • ASP.NET Core projesi geliştirebilecek her şey
ASP.NET Çekirdeği
  • Herhangi bir sürüm (MVC, Razor Pages, API)
Windows Sunucusu
  • Windows Server 2008 veya üzeri
IIS (IIS)
  • 7.0 veya üstü

önkoşul

  • ASP.NET Core uygulamaları IIS üzerinde çalışacak şekilde tasarlanmıştır.
  • Kimlik doğrulaması için Windows API'lerini kullandığından, Windows olmayanlarda çalışmaz.

çevre

Aşağıdaki ortamda doğrulanır.

PC'lerin ve sunucuların kullanım amacı
Windows 11 (Yerel) Program geliştirmek için bir ortam.
SV2022 Testi IIS ve ASP.NET Core çalıştıran bir ortam. SV2019Test paylaşımlı klasörüne buradan erişin
SV2019 Testi Paylaşılan klasörlere sahip sunucular

Ek olarak, çeşitli ayarlar aşağıdaki gibidir.

Parametre Adı Değeri
Erişim Kullanıcı Adı Paylaşılan Kullanıcı
Paylaşılan Klasör Adı Paylaşılan Klasör

Paylaşımlı Klasör Sunucusu Oluşturma

Kullanıcı oluşturma

Ortak klasöre erişmek için bir kullanıcı oluşturun. Bu durumda, yerel bir hesap oluşturacağız, ancak Active Directory gibi bir etki alanındaki sunucular ve hesaplarla uğraşıyorsanız, onu da kullanabilirsiniz.

Kullanıcı oluşturma süreci bu ipuçlarının kapsamı dışındadır, bu nedenle çok fazla ayrıntıya girmeyeceğiz.

SharedUser Bu durumda, onu adıyla oluşturacağız. Bu kullanıcı ekranı çalıştırmadığı veya ayarları değiştirmediği için şifre değiştirilemez.

Varsayılanı bırakırsanız, bu kullanıcıyla Uzak Masaüstü vb. ile oturum açabilirsiniz, bu nedenle lütfen gruptan Users kaldırın .

Paylaşılan Klasör Oluşturma

Nerede oluşturduğunuz önemli değil. Bunun nedeni, diğer sunucuların fiziksel klasörün konumunu önemsememesidir. Bu durumda, doğrudan C sürücüsünün altında SharedFolder adında bir klasör oluşturacağız ve paylaşacağız.

Özellikleri açın ve paylaşım ayarlarını yapılandırın.

Paylaşılan klasörün SharedFolder adı olmalıdır. Bu ad diğer sunucular tarafından görülebilir. İzinleri ekleyin SharedUser .

Everyone Var olan .

"Değiştir" izniyle onaylayın.

Yalnızca dışarıdan erişilebilen izinler eklediğimizden, bu klasörde çalışabilmesi için dahili olarak SharedUser ayarlayacağız.

"Değiştir" izniyle onaylayın.

İşlemi kontrol etmek için bir dosya oluşturun. Bu programda, kodlama UFT-8'de işlenir, bu nedenle lütfen UTF-8'e kaydedin.

Explorer'a \\<サーバー名>\ başka bir bilgisayardan erişebiliyorsanız, ile oturum açabiliyorsanızSharedUser ve dosyayı görüntüleyebiliyorsanız, sorun değil.

ASP.NET Core uygulamasından paylaşılan bir klasördeki dosyaları okumak ve yazmak için bir program oluşturma

Mr./Ms. işlemi düğmesine tıklamaktır.

  • Dosyaları paylaşılan bir klasöre yükleyin ve ekranda görüntüleyin
  • Paylaşılan klasöre yeni bir dosya yazma

işlem.

Razor Pages ve MVC kodu buna örnektir, ancak paylaşılan klasöre erişen program her ikisi için de aynıdır. Aynısı Web API'leri için de geçerlidir. Bir şey varsa, istemci programında da çalışmalıdır.

Belirli bir işlem süresince bir ağa bağlanan bir işlem

Projenizin herhangi bir yerinde aşağıdaki kodu oluşturun. Sınıf adı 'dir SharedFolderAccessor , ancak ad isteğe bağlıdır. SharedFolderAccessor 'nin bir Dispose örneğini oluşturana kadar paylaşılan klasöre erişebilirsiniz. using Açık bir kapsamda erişime erişilebilecek süreyi belirtmenize olanak tanır.

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'lerini kullandığından ve WNetAddConnection2 WNetCancelConnection2 , yalnızca Windows ortamında çalışır. Şu an için bir yorumum var, ancak daha fazlasını öğrenmek istiyorsanız, lütfen İnternet'e bakın. Paylaşılan klasörlere ek olarak, ağ kaynaklarına erişmek için de işlemler gerçekleştirebilirsiniz.

Kullanımı kolaydır ve aşağıdakileri yazarsanız, using kapsam sırasında paylaşılan klasöre erişebilirsiniz.

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

Ancak, gerçekte WNetCancelConnection2 , bağlantı arama zamanlamasında hemen kesilmez , böylece using kapsamdan sonra bile paylaşılan klasöre erişebilirsiniz.

SharedFolderAccessor kullanarak kodu test etme

Paylaşılan klasöre erişim işlemi çerçeveye bağlı olmadığından, dosyaları okuyan ve yazan test için ortak bir yöntem oluşturuyoruz. Pazor Sayfaları ve MVC aynı şekilde adlandırılmalıdır.

İçerik, bağımsız değişkene iletilen metni paylaşılan klasöre yazan, paylaşılan klasörde bulunan metin dosyasını okuyan ve metni döndüren bir işlemdir.

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 Sayfaları

Razor Pages'da Index.cshtml'ye bir düğme yerleştiriyoruz, tıklıyoruz, test kodunu çalıştırıyoruz ve sonuçları ekranda görüntülüyoruz. Bazı durumlarda, paylaşılan klasöre erişilemeyebilir, bu nedenle bir deneme yakalama içine alınır.

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

Dizin.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 (MVC)

Benzer şekilde, MVC durumunda, Index.cshtml içine bir düğme yerleştirilir ve tıklandığında, paylaşılan klasörün test kodunu çağırır.

Kontrolörler/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();
    }

    // 省略
  }
}

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

Operasyonun onaylanması

Hata ayıklayın ve paylaşılan klasöre başarıyla erişebildiğinizi doğrulayın.

Uygulama Sunucusu Oluşturma

Paylaşılan klasöre programı çalıştırarak erişilebileceğini onayladığımız için bir sonraki adım gereksizdir. IIS sunucusunda işlemi kontrol etmek istiyorsanız, aşağıdaki adımları izleyerek yapabilirsiniz.

Buradan bir ektir, bu yüzden çok ayrıntılı olarak açıklamayacağım, esas olarak görüntüyü açıklayacağım.

IIS'yi yükleme

Varsayılan olarak Sunucu Yöneticisi'nden yükleyin. Prosedürün ayrıntılarına girmeyeceğim.

Ek özellik gerekmez.

Şu anda ek IIS hizmetleri gerekli değildir.

ASP.NET Core Çalışma Zamanı Barındırma Paketi Kurulumu

ASP.NET Core 8 kullandığımız için çalışma zamanını buna göre kurmamız gerekiyor. Aşağıdaki URL'den indirin:

ASP.NET Core'u IIS'de çalıştırmak için "Hosting Bundle" adlı bir şeye ihtiyacınız var. ASP.NET Core Runtime'dan "Hosting Bundle"ı indirin.

İndirdikten sonra sunucuda çalıştırın.

Yüklemek için sihirbazı izleyin.

Programınızı yayımlama

IIS'ye dağıtmak istediğiniz programın çıktısını Visual Studio'dan bir dosya olarak alın.

Windows için değiştirin.

İşiniz bittiğinde yayınlayın.

Hedef konuma tıklarsanız, yayınlanan dosyanın bulunduğu klasörü açabilirsiniz.

Hepsini getirmek zorunda değilsiniz, ancak emin değilseniz, şimdilik hepsini alabilirsiniz. Bu noktada tek yapmanız gereken dosyanın var olduğundan emin olmaktır.

Web Uygulamaları Oluşturma ve Dağıtma

Windows Yönetimsel Araçlar'dan Internet Information Services (IIS) Yöneticisi'ni açın.

Bir site oluşturacağız, ancak bu sefer baştan orada olan "Varsayılan Web Sitesi"ni kullanacağız.

Varsayılan Web Sitesi seçiliyken, klasörü açmak için Explorer'ı tıklatın. Yayınlanan programı buraya kopyalayın. Orijinal dosyayı silebilirsiniz.

Sayfayı IIS bağlantısından açın ve ekranın görünüp görünmediğine bakın. Önce bir web tarayıcısı açabilir ve URL'yi doğrudan girebilirsiniz.

Operasyonun onaylanması

Herhangi bir sorun olmadan çalıştığını doğrulamak için düğmeye tıklayın. Yukarıda, web sunucusu içinden erişilir, ancak bir web sunucusu olduğu için diğer bilgisayarlardan çalıştırılması mümkün olmalıdır.