Acessando pastas compartilhadas em outros servidores a partir de um aplicativo ASP.NET Core (versão do Programa Conectado à Rede)

Página atualizada :
Data de criação de página :

Ambiente de verificação de operação

Estúdio Visual
  • Visual Studio 2022
ASP.NET Núcleo
  • 8 (Páginas da navalha, MVC)
Servidor Windows
  • 2022 (ASP.NET Core Requisitos do sistema)
  • 2019 (Servidor de Implantação de Pasta Compartilhada)
IIS
  • 10.0

Ambiente operacional

Não o testamos em todos os casos, mas deve funcionar geralmente nas seguintes condições:

Estúdio Visual
  • Qualquer coisa que possa desenvolver um projeto ASP.NET Core
ASP.NET Núcleo
  • Qualquer versão (MVC, Razor Pages, API)
Servidor Windows
  • Windows Server 2008 ou posterior
IIS
  • 7.0 ou posterior

pré-condição

  • ASP.NET aplicativos principais devem ser executados no IIS.
  • Como ele usa APIs do Windows para autenticação, ele não funciona em não-Windows.

ambiente

Ele é verificado no seguinte ambiente.

Finalidade de uso de PCs e servidores
Windows 11 (Local) Um ambiente para o desenvolvimento de programas.
SV2022Teste Um ambiente que executa o IIS e o ASP.NET Core. Acesse a pasta compartilhada SV2019Test aqui
SV2019Teste Servidores com pastas compartilhadas

Além disso, as várias configurações são as seguintes.

Valor do nome do parâmetro
Nome de usuário do Access SharedUser
Nome da pasta compartilhada SharedFolder

Criando um servidor de pasta compartilhada

Criar um usuário

Crie um usuário para acessar a pasta comum. Nesse caso, criaremos uma conta local, mas se você estiver lidando com servidores e contas em um domínio como o Active Directory, também poderá usá-la.

O processo de criação de um usuário está além do escopo dessas dicas, então não entraremos em muitos detalhes.

SharedUser Neste caso, vamos criá-lo com o nome . Como esse usuário não opera a tela nem altera as configurações, a senha não pode ser alterada.

Se você deixar o padrão, você pode fazer login com este usuário com Área de Trabalho Remota, etc., então remova do grupo Users .

Criando uma pasta compartilhada

Não importa onde você o crie. Isso ocorre porque outros servidores não se importam com o local da pasta física. Neste caso, vamos criar uma pasta nomeada diretamente sob SharedFolder a unidade C e compartilhá-la.

Abra as propriedades e defina as configurações de compartilhamento.

O nome da pasta compartilhada deve SharedFolder ser . Esse nome ficará visível para outros servidores. Adicione SharedUser as permissões.

Everyone Exclua o arquivo .

Confirme com a permissão "Alterar".

Como só adicionamos permissões que podem ser acessadas de fora, vamos defini-lo internamente SharedUser para que possa operar nesta pasta.

Confirme com a permissão "Alterar".

Crie um arquivo para verificar a operação. Neste programa, a codificação é processada em UFT-8, então salve-a em UTF-8.

Tudo bem se você puder acessar no Explorer de \\<サーバー名>\ outro PC, fazer loginSharedUser com o e exibir o arquivo.

Criar um programa para ler e gravar arquivos de uma pasta compartilhada de um aplicativo ASP.NET Core

A operação Mr./Ms. é clicar no botão.

  • Carregar arquivos em uma pasta compartilhada e exibi-los na tela
  • Gravar um novo arquivo em uma pasta compartilhada

processo.

Razor Pages e código MVC são exemplos disso, mas o programa que acessa a pasta compartilhada é o mesmo para ambos. O mesmo é verdadeiro para APIs da Web. Se alguma coisa, ele deve funcionar no programa cliente também.

Um processo que se conecta a uma rede durante um processo específico

Crie o código a seguir em qualquer lugar do seu projeto. O nome da classe é SharedFolderAccessor , mas o nome é arbitrário. SharedFolderAccessor Você pode acessar a pasta compartilhada até criar uma Dispose instância do . using permite especificar o período de tempo durante o qual o acesso pode ser acessado em um escopo explícito.

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

Como ele usa as APIs do Win32 e WNetAddConnection2 WNetCancelConnection2 , ele funciona apenas no ambiente Windows. Eu tenho um comentário por enquanto, mas se você quiser saber mais, por favor, procure-o na Internet. Além das pastas compartilhadas, você também pode executar operações para acessar recursos de rede.

É fácil de usar e, se você escrever o seguinte, using poderá acessar a pasta compartilhada durante o escopo.

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

No entanto, na realidade WNetCancelConnection2 , a conexão não é imediatamente desconectada no momento da chamada, para que using você possa acessar a pasta compartilhada mesmo após o escopo.

Código de teste usando SharedFolderAccessor

Como o processo de acesso à pasta compartilhada não depende da estrutura, criamos um método comum para testar que lê e grava arquivos. Pazor Pages e MVC devem ser chamados da mesma forma.

O conteúdo é um processo que grava o texto passado para o argumento para a pasta compartilhada, lê o arquivo de texto já na pasta compartilhada e retorna o texto.

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

Páginas da navalha

No Razor Pages, colocamos um botão em Index.cshtml, clicamos nele, executamos o código de teste e exibimos os resultados na tela. Em alguns casos, a pasta compartilhada pode não estar acessível, portanto, ela é incluída em uma tentativa de captura.

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

Da mesma forma, no caso do MVC, Index.cshtml um botão é colocado no , e quando clicado, ele chama o código de teste da pasta compartilhada.

Controladores/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>
@* ここまで追加 *@

Confirmação de operação

Depure e verifique se você pode acessar com êxito a pasta compartilhada.

Criando um servidor de aplicativos

Como confirmamos que a pasta compartilhada pode ser acessada executando o programa, a próxima etapa é desnecessária. Se você quiser verificar a operação no servidor IIS, você pode fazê-lo seguindo as etapas abaixo.

A partir daqui, é um suplemento, então não vou explicar com muitos detalhes, mas principalmente explicar a imagem.

Instalando o IIS

Instale-o por padrão a partir do Gerenciador do Servidor. Não vou entrar em detalhes do procedimento.

Não são necessários recursos adicionais.

Nenhum serviço IIS adicional é necessário no momento.

Instalação do pacote de hospedagem do ASP.NET Core Runtime

Como estamos usando o ASP.NET Core 8, precisamos instalar o tempo de execução de acordo. Baixe-o a partir do seguinte URL:

Para executar ASP.NET Core no IIS, você precisa de algo chamado "Hosting Bundle". Baixe o "Hosting Bundle" do ASP.NET Core Runtime.

Uma vez baixado, execute-o no servidor.

Siga o assistente para instalá-lo.

Publique seu programa

Saída do programa que você deseja implantar no IIS como um arquivo do Visual Studio.

Modifique-o para Windows.

Publique quando terminar.

Se você clicar no local de destino, poderá abrir a pasta onde o arquivo publicado está localizado.

Você não precisa trazer todas, mas se não tiver certeza, pode levar todas por enquanto. Neste ponto, tudo o que você precisa fazer é certificar-se de que o arquivo existe.

Criando e implantando aplicativos Web

Nas Ferramentas Administrativas do Windows, abra o Gerenciador dos Serviços de Informações da Internet (IIS).

Vamos criar um site, mas desta vez vamos usar o "Site Padrão" que está lá desde o início.

Com a opção Site padrão selecionada, clique em Explorer para abrir a pasta. Copie o programa publicado aqui. Você pode excluir o arquivo original.

Abra a página a partir do link do IIS e veja se a tela aparece. Você pode abrir um navegador da Web primeiro e inserir a URL diretamente.

Confirmação de operação

Clique no botão para verificar se ele funciona sem problemas. No acima, ele é acessado de dentro do servidor web, mas como é um servidor web, deve ser possível operá-lo a partir de outros PCs.