ネットワーク共有に接続するときにユーザー名とパスワードを提供する方法


191

現在のユーザー(私の場合、ネットワークが有効なサービスユーザー)が権限を持たないネットワーク共有に接続する場合、名前とパスワードを入力する必要があります。

Win32関数(のWNet*ファミリーmpr.dll)でこれを行う方法を知っていますが、.Net(2.0)機能でそれを実行したいと考えています。

どのようなオプションがありますか?

多分いくつかの情報が役立つでしょう:

  • 使用例はWindowsサービスであり、Asp.Netアプリケーションではありません。
  • サービスは、共有に対する権限のないアカウントで実行されています。
  • 共有に必要なユーザーアカウントがクライアント側で認識されていません。
  • クライアントとサーバーは同じドメインのメンバーではありません。

7
私はあなたに有用な答えを提供していませんが、私は反答えを提供することができます。サーバーとクライアントが同じドメイン内にない場合、信頼関係がない限り、Marc positedとしてのなりすましとプロセスの生成は機能しません。 2つのドメイン。信頼があればうまくいくと思います。Marc'sへのコメントとして返信しただけですが、コメントするのに十分な担当者がいません。:-/
ムース

回答:


152

スレッドIDを変更するか、WNetAddConnection2をP / Invokeすることができます。場合によっては、別の場所で複数の資格情報を維持する必要があるため、後者を好みます。これをIDisposableにラップし、WNetCancelConnection2を呼び出して、後で資格情報を削除します(複数のユーザー名のエラーを回避します)。

using (new NetworkConnection(@"\\server\read", readCredentials))
using (new NetworkConnection(@"\\server2\write", writeCredentials)) {
   File.Copy(@"\\server\read\file", @"\\server2\write\file");
}

4
サービスはターゲットドメインのメンバーではありません-セキュリティトークンをローカルで作成して偽装することができないため、偽装は機能しません。PInvokeが唯一の方法です。
stephbu 2008年

@MarkBrackett私はこれが古い答えであることを知っていますが、おそらくあなたはまだ知っているかもしれません...アクセスはプログラムのみに、またはエクスプローラを介してログインしているユーザーにも許可されますか?
Breeze

@Breeze-まだテストしていませんが、ログオンセッションでは認証されると思います。したがって、プログラムがログオンしているユーザーとして実行されている場合は、それらにも(少なくとも操作の間は)アクセスできます。
Mark Brackett 2016年

8
readCredentialsおよびwriteCredentialsの定義を回答に含めることができます。
アンデルスリンデン

2
エラー53が発生する場合は、パスが「\」で終わっていないことを確認してください
Mustafa S.

326

Mark Brackettの答えが気に入ったので、自分ですばやく実装しました。これは、他の誰かが急いでそれを必要とする場合です:

public class NetworkConnection : IDisposable
{
    string _networkName;

    public NetworkConnection(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
            : string.Format(@"{0}\{1}", credentials.Domain, credentials.UserName);

        var result = WNetAddConnection2(
            netResource, 
            credentials.Password,
            userName,
            0);

        if (result != 0)
        {
            throw new Win32Exception(result);
        }   
    }

    ~NetworkConnection()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        WNetCancelConnection2(_networkName, 0, true);
    }

    [DllImport("mpr.dll")]
    private static extern int WNetAddConnection2(NetResource netResource, 
        string password, string username, int flags);

    [DllImport("mpr.dll")]
    private static extern int WNetCancelConnection2(string name, int flags,
        bool force);
}

[StructLayout(LayoutKind.Sequential)]
public 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;
}

public enum ResourceScope : int
{
    Connected = 1,
    GlobalNetwork,
    Remembered,
    Recent,
    Context
};

public enum ResourceType : int
{
    Any = 0,
    Disk = 1,
    Print = 2,
    Reserved = 8,
}

public enum ResourceDisplaytype : int
{
    Generic = 0x0,
    Domain = 0x01,
    Server = 0x02,
    Share = 0x03,
    File = 0x04,
    Group = 0x05,
    Network = 0x06,
    Root = 0x07,
    Shareadmin = 0x08,
    Directory = 0x09,
    Tree = 0x0a,
    Ndscontainer = 0x0b
}

10
throw new Win32Exception(result);WNetAddConnection2はwin32エラーコード(ERROR_XXX)を返すため、これは本当に必要です
torvin

2
これは見事な小さなコードです。MVC5 Webアプリケーションに印刷するためのディレクトリリストを取得するには、UNIXシステムにログオンする必要があり、これでうまくいきました。+1 !!!
Tay

3
上記のコードをコンパイルするには、次のusingステートメントが必要です。using System.Net; System.Runtime.InteropServicesを使用します。System.ComponentModelを使用します。
Matt Nelson、

4
その古いスレッドを更新して申し訳ありませんが、ブロックが完了した後に接続を閉じないようです。私はいくつかの写真をアップロードするプログラムを持っています。最初の写真はうまくいき、2番目の写真は失敗します。プログラムを閉じると接続が解除されます。何かアドバイスは?
arti 2015

3
@artiさんと同じ問題が発生しました。NetworkCredentialオブジェクトのユーザー名とパスワードを設定するだけで、アプリケーションはネットワークドライブに1回接続できました。その後、アプリケーションが再起動されるまで、試行ごとにERROR_LOGON_FAILUREが発生しました。次に、NetworkCredentialオブジェクトにもドメインを指定しようとしましたが、突然機能しました。これがなぜ問題を解決したのか、特にドメインなしで1回接続するだけで機能するという事実はわかりません。
lsmeby

50

7年後の今日、私は同じ問題に直面しており、自分のバージョンのソリューションを共有したいと思います。

コピー&ペーストの準備ができています:-)ここにあります:

ステップ1

コード内(アクセス許可で何かを行う必要がある場合)

ImpersonationHelper.Impersonate(domain, userName, userPassword, delegate
                            {
                                //Your code here 
                                //Let's say file copy:
                                if (!File.Exists(to))
                                {
                                    File.Copy(from, to);
                                }
                            });

ステップ2

魔法をかけるヘルパーファイル

using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;    
using Microsoft.Win32.SafeHandles;


namespace BlaBla
{
    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle()
            : base(true)
        {
        }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }

    public class ImpersonationHelper
    {
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private extern static bool CloseHandle(IntPtr handle);

        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        public static void Impersonate(string domainName, string userName, string userPassword, Action actionToExecute)
        {
            SafeTokenHandle safeTokenHandle;
            try
            {

                const int LOGON32_PROVIDER_DEFAULT = 0;
                //This parameter causes LogonUser to create a primary token.
                const int LOGON32_LOGON_INTERACTIVE = 2;

                // Call LogonUser to obtain a handle to an access token.
                bool returnValue = LogonUser(userName, domainName, userPassword,
                    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    out safeTokenHandle);
                //Facade.Instance.Trace("LogonUser called.");

                if (returnValue == false)
                {
                    int ret = Marshal.GetLastWin32Error();
                    //Facade.Instance.Trace($"LogonUser failed with error code : {ret}");

                    throw new System.ComponentModel.Win32Exception(ret);
                }

                using (safeTokenHandle)
                {
                    //Facade.Instance.Trace($"Value of Windows NT token: {safeTokenHandle}");
                    //Facade.Instance.Trace($"Before impersonation: {WindowsIdentity.GetCurrent().Name}");

                    // Use the token handle returned by LogonUser.
                    using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
                    {
                        using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
                        {
                            //Facade.Instance.Trace($"After impersonation: {WindowsIdentity.GetCurrent().Name}");
                            //Facade.Instance.Trace("Start executing an action");

                            actionToExecute();

                            //Facade.Instance.Trace("Finished executing an action");
                        }
                    }
                    //Facade.Instance.Trace($"After closing the context: {WindowsIdentity.GetCurrent().Name}");
                }

            }
            catch (Exception ex)
            {
                //Facade.Instance.Trace("Oh no! Impersonate method failed.");
                //ex.HandleException();
                //On purpose: we want to notify a caller about the issue /Pavel Kovalev 9/16/2016 2:15:23 PM)/
                throw;
            }
        }
    }
}

2
@MohammadRashid LogonUserのドキュメントによると、これはローカルコンピューターのユーザーに対してのみ機能します。「LogonUser関数は、ユーザーをローカルコンピューターにログオンさせようとします。ローカルコンピューターは、LogonUserの呼び出し元のコンピューターです。LogonUserは使用できません。リモートコンピューターにログオンします。「エラーが表示されます「Win32Exception:ユーザー名またはパスワードが正しくありません。」したがって、マシンは少なくとも同じドメイン上にある必要があると思います。
Charles Chen

1
@CharlesChenは、これがドメイン全体で正常に機能することを証明しました。これを実行しているサーバーはDMZにあり、ファイアウォールを介して別のドメインのファイルサーバーに確実に接続しています。キラースニペットのパベル、あなたは男です、そしてこれはおそらく今日受け入れられた答えになるはずです。
ブライアンマッケイ2017年

これは素晴らしいソリューションです!ありがとう、Pavel Kovalev。
STLDev

これはLDAPで機能しますか?利用可能なログオンサーバーがないと表示されます。imはldap authを使用
Julius Limson '11 / 11/19

28

たくさんのメソッドを検索し、自分のやり方でやった。コマンドプロンプトNET USEコマンドを使用して2台のマシン間の接続を開き、作業が終了したら、コマンドプロンプトNET USE "myconnection" / deleteで接続をクリアする必要があります。

次のようなコードビハインドからコマンドプロンプトプロセスを使用する必要があります。

var savePath = @"\\servername\foldername\myfilename.jpg";
var filePath = @"C:\\temp\myfileTosave.jpg";

使い方は簡単です:

SaveACopyfileToServer(filePath, savePath);

ここに関数があります:

using System.IO
using System.Diagnostics;


public static void SaveACopyfileToServer(string filePath, string savePath)
    {
        var directory = Path.GetDirectoryName(savePath).Trim();
        var username = "loginusername";
        var password = "loginpassword";
        var filenameToSave = Path.GetFileName(savePath);

        if (!directory.EndsWith("\\"))
            filenameToSave = "\\" + filenameToSave;

        var command = "NET USE " + directory + " /delete";
        ExecuteCommand(command, 5000);

        command = "NET USE " + directory + " /user:" + username + " " + password;
        ExecuteCommand(command, 5000);

        command = " copy \"" + filePath + "\"  \"" + directory + filenameToSave + "\"";

        ExecuteCommand(command, 5000);


        command = "NET USE " + directory + " /delete";
        ExecuteCommand(command, 5000);
    }

また、ExecuteCommand関数は次のとおりです。

public static int ExecuteCommand(string command, int timeout)
    {
        var processInfo = new ProcessStartInfo("cmd.exe", "/C " + command)
                              {
                                  CreateNoWindow = true, 
                                  UseShellExecute = false, 
                                  WorkingDirectory = "C:\\",
                              };

        var process = Process.Start(processInfo);
        process.WaitForExit(timeout);
        var exitCode = process.ExitCode;
        process.Close();
        return exitCode;
    } 

この機能は私にとって非常に速く安定しています。


1
共有マッピングが失敗した場合、戻りコードはどうなりますか?
シュレガ2018年

14

Luke Quinaneソリューションは適切に見えますが、ASP.NET MVCアプリケーションでは部分的にしか機能しませんでした。同じサーバー上に2つの共有があり、資格情報が異なる場合、最初の偽装のみを使用できます。

WNetAddConnection2の問題は、Windowsのバージョンによって動作が異なることでもあります。そのため、代替手段を探し、LogonUser関数を見つけました。ASP.NETでも機能する私のコードは次のとおりです。

public sealed class WrappedImpersonationContext
{
    public enum LogonType : int
    {
        Interactive = 2,
        Network = 3,
        Batch = 4,
        Service = 5,
        Unlock = 7,
        NetworkClearText = 8,
        NewCredentials = 9
    }

    public enum LogonProvider : int
    {
        Default = 0,  // LOGON32_PROVIDER_DEFAULT
        WinNT35 = 1,
        WinNT40 = 2,  // Use the NTLM logon provider.
        WinNT50 = 3   // Use the negotiate logon provider.
    }

    [DllImport("advapi32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool LogonUser(String lpszUsername, String lpszDomain,
        String lpszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider, ref IntPtr phToken);

    [DllImport("kernel32.dll")]
    public extern static bool CloseHandle(IntPtr handle);

    private string _domain, _password, _username;
    private IntPtr _token;
    private WindowsImpersonationContext _context;

    private bool IsInContext
    {
        get { return _context != null; }
    }

    public WrappedImpersonationContext(string domain, string username, string password)
    {
        _domain = String.IsNullOrEmpty(domain) ? "." : domain;
        _username = username;
        _password = password;
    }

    // Changes the Windows identity of this thread. Make sure to always call Leave() at the end.
    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Enter()
    {
        if (IsInContext)
            return;

        _token = IntPtr.Zero;
        bool logonSuccessfull = LogonUser(_username, _domain, _password, LogonType.NewCredentials, LogonProvider.WinNT50, ref _token);
        if (!logonSuccessfull)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
        WindowsIdentity identity = new WindowsIdentity(_token);
        _context = identity.Impersonate();

        Debug.WriteLine(WindowsIdentity.GetCurrent().Name);
    }

    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Leave()
    {
        if (!IsInContext)
            return;

        _context.Undo();

        if (_token != IntPtr.Zero)
        {
            CloseHandle(_token);
        }
        _context = null;
    }
}

使用法:

var impersonationContext = new WrappedImpersonationContext(Domain, Username, Password);
impersonationContext.Enter();

//do your stuff here

impersonationContext.Leave();

2
このアプローチは私にとってはうまくいきましたが、私のテストで、ドメインユーザーアカウントで不正なパスワードを使用すると、そのユーザーはすぐにロック状態になることに気付きました。私たちのドメインポリシーは、それが発生する前に3回のログイン試行の失敗を要求していますが、このアプローチでは、1回の不正な試行でロックされます。したがって、注意して使用してください
。– kellyb

5

VB.loversにとっては、VB.NETでLuke Quinaneのコードに相当するもの(Lukeに感謝!)

Imports System
Imports System.Net
Imports System.Runtime.InteropServices
Imports System.ComponentModel

Public Class NetworkConnection
    Implements IDisposable

    Private _networkName As String

    Public Sub New(networkName As String, credentials As NetworkCredential)
        _networkName = networkName

        Dim netResource = New NetResource() With {
             .Scope = ResourceScope.GlobalNetwork,
             .ResourceType = ResourceType.Disk,
             .DisplayType = ResourceDisplaytype.Share,
             .RemoteName = networkName
        }

        Dim userName = If(String.IsNullOrEmpty(credentials.Domain), credentials.UserName, String.Format("{0}\{1}", credentials.Domain, credentials.UserName))

        Dim result = WNetAddConnection2(NetResource, credentials.Password, userName, 0)

        If result <> 0 Then
            Throw New Win32Exception(result, "Error connecting to remote share")
        End If
    End Sub

    Protected Overrides Sub Finalize()
        Try
            Dispose (False)
        Finally
            MyBase.Finalize()
        End Try
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose (True)
        GC.SuppressFinalize (Me)
    End Sub

    Protected Overridable Sub Dispose(disposing As Boolean)
        WNetCancelConnection2(_networkName, 0, True)
    End Sub

    <DllImport("mpr.dll")> _
    Private Shared Function WNetAddConnection2(netResource As NetResource, password As String, username As String, flags As Integer) As Integer
    End Function

    <DllImport("mpr.dll")> _
    Private Shared Function WNetCancelConnection2(name As String, flags As Integer, force As Boolean) As Integer
    End Function

End Class

<StructLayout(LayoutKind.Sequential)> _
Public Class NetResource
    Public Scope As ResourceScope
    Public ResourceType As ResourceType
    Public DisplayType As ResourceDisplaytype
    Public Usage As Integer
    Public LocalName As String
    Public RemoteName As String
    Public Comment As String
    Public Provider As String
End Class

Public Enum ResourceScope As Integer
    Connected = 1
    GlobalNetwork
    Remembered
    Recent
    Context
End Enum

Public Enum ResourceType As Integer
    Any = 0
    Disk = 1
    Print = 2
    Reserved = 8
End Enum

Public Enum ResourceDisplaytype As Integer
    Generic = &H0
    Domain = &H1
    Server = &H2
    Share = &H3
    File = &H4
    Group = &H5
    Network = &H6
    Root = &H7
    Shareadmin = &H8
    Directory = &H9
    Tree = &HA
    Ndscontainer = &HB
End Enum

3

機能する可能性のある1つのオプションは、次のように使用してWindowsIdentity.Impersonate(およびスレッドプリンシパルを変更して)目的のユーザーになることです。です。p / invokeに戻りますが、残念です...

別の生意気な(と同じように理想からかけ離れ)オプションが作業を行うためのプロセスを生成するかもしれない... ProcessStartInfo受け入れ.UserName.Password.Domain

最後に-おそらくアクセス権のある専用アカウントでサービスを実行しますか?(これはオプションではないことを明確にしたため削除されました)。


プロセスのことはそれほど悪い考えではないと思います。グーグルはクロムのマルチプロセッシングの利点についてのいくつかのホワイトペーパーを出しました。
ダスティンゲッツ

スレッドプリンシパルをローカルマシンにアカウントのないユーザーに変更することはできますか?
gyrolf 2008年

正直なところ、私にはわかりません。別のドメインでLogonUserを試してみる必要があります。
Marc Gravell

3

わかりました...

免責事項:私は18時間以上の日を過ごしました(再び)。私は年をとって、忘れてしまいました..綴ることができません..私は注意のスパンが短いので、より速く応答します.. :-)

質問:

スレッドプリンシパルをローカルマシンにアカウントのないユーザーに変更することはできますか?

回答:

はい、使用している資格情報がローカルで定義されていない場合や「フォレスト」外にある場合でも、スレッドプリンシパルを変更できます。

サービスからNTLM認証を使用してSQLサーバーに接続しようとしたときに、この問題が発生しました。この呼び出しでは、プロセスに関連付けられた資格情報を使用します。つまり、偽装するには、ローカルアカウントまたはドメインアカウントを認証する必要があります。なんてこった…

だが...

???? _ NEW_CREDENTIALSの属性でLogonUser(..)を呼び出すと、資格情報の認証を試行せずにセキュリティトークンが返されます。Kewl ..「フォレスト」内でアカウントを定義する必要はありません。トークンを取得したら、偽装を有効にして新しいトークンを生成するオプションを指定してDuplicateToken()を呼び出す必要がある場合があります。次にSetThreadToken(NULL、token);を呼び出します。(&token?の可能性があります。)ImpersonateLoggedonUser(token);への呼び出し。必要かもしれませんが、私はそうは思いません。調べる..

必要なことをしてください。

ImpersonateLoggedonUser()を呼び出してからSetThreadToken(NULL、NULL);を呼び出した場合は、RevertToSelf()を呼び出します。(私は思う...それを調べてください)、そして作成されたハンドルのCloseHandle()

約束はありませんが、これは私にとってはうまくいきました...これは私の頭の上(髪の毛のように)からずれているので、スペルを書くことはできません!!!


1

ローカルで有効なセキュリティトークンを作成できない場合は、すべてのオプションバーのWin32 APIとWNetAddConnection *を除外しているようです。

WNetに関するMSDNのたくさんの情報-PInvokeの情報とUNCパスに接続するサンプルコードはこちら:

http://www.pinvoke.net/default.aspx/mpr/WNetAddConnection2.html#

MSDNリファレンスはこちら:

http://msdn.microsoft.com/en-us/library/aa385391(VS.85).aspx


1

FAKEで使用するためにF#にも移植されています

module NetworkShare

open System
open System.ComponentModel
open System.IO
open System.Net
open System.Runtime.InteropServices

type ResourceScope =
| Connected = 1
| GlobalNetwork = 2
| Remembered = 3
| Recent = 4
type ResourceType =
| Any = 0
| Disk = 1
| Print = 2
| Reserved = 8
type ResourceDisplayType =
| Generic = 0x0
| Domain = 0x01
| Server = 0x02
| Share = 0x03
| File = 0x04
| Group = 0x05
| Network = 0x06
| Root = 0x07
| Shareadmin = 0x08
| Directory = 0x09
| Tree = 0x0a
| Ndscontainer = 0x0b

//Uses of this construct may result in the generation of unverifiable .NET IL code.
#nowarn "9"
[<StructLayout(LayoutKind.Sequential)>]
type NetResource =
  struct
    val mutable Scope : ResourceScope
    val mutable ResourceType : ResourceType
    val mutable DisplayType : ResourceDisplayType
    val mutable Usage : int
    val mutable LocalName : string
    val mutable RemoteName : string
    val mutable Comment : string
    val mutable Provider : string
    new(name) = {
      // lets preset needed fields
      NetResource.Scope = ResourceScope.GlobalNetwork
      ResourceType = ResourceType.Disk
      DisplayType = ResourceDisplayType.Share
      Usage = 0
      LocalName = null
      RemoteName = name
      Comment = null
      Provider = null
    }
  end

type WNetConnection(networkName : string, credential : NetworkCredential) =
  [<Literal>]
  static let Mpr = "mpr.dll"
  [<DllImport(Mpr, EntryPoint = "WNetAddConnection2")>]
  static extern int connect(NetResource netResource, string password, string username, int flags)
  [<DllImport(Mpr, EntryPoint = "WNetCancelConnection2")>]
  static extern int disconnect(string name, int flags, bool force)

  let mutable disposed = false;

  do
    let userName = if String.IsNullOrWhiteSpace credential.Domain
                   then credential.UserName
                   else credential.Domain + "\\" + credential.UserName
    let resource = new NetResource(networkName)

    let result = connect(resource, credential.Password, userName, 0)

    if result <> 0 then
      let msg = "Error connecting to remote share " + networkName
      new Win32Exception(result, msg)
      |> raise

  let cleanup(disposing:bool) =
    if not disposed then
      disposed <- true
      if disposing then () // TODO dispose managed resources here
      disconnect(networkName, 0, true) |> ignore

  interface IDisposable with
    member __.Dispose() =
      disconnect(networkName, 0, true) |> ignore
      GC.SuppressFinalize(__)

  override __.Finalize() = cleanup(false)

type CopyPath =
  | RemotePath of string * NetworkCredential
  | LocalPath of string

let createDisposable() =
  {
    new IDisposable with
      member __.Dispose() = ()
  }

let copyFile overwrite destPath srcPath : unit =
  use _srcConn =
    match srcPath with
    | RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
    | LocalPath(_) -> createDisposable()
  use _destConn =
    match destPath with
    | RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
    | LocalPath(_) -> createDisposable()
  match srcPath, destPath with
  | RemotePath(src, _), RemotePath(dest, _)
  | LocalPath(src), RemotePath(dest, _)
  | RemotePath(src, _), LocalPath(dest)
  | LocalPath(src), LocalPath(dest) ->
    if FileInfo(src).Exists |> not then
      failwith ("Source file not found: " + src)
    let destFilePath =
      if DirectoryInfo(dest).Exists then Path.Combine(dest, Path.GetFileName src)
      else dest
    File.Copy(src, destFilePath, overwrite)

let rec copyDir copySubDirs filePattern destPath srcPath =
  use _srcConn =
    match srcPath with
    | RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
    | LocalPath(_) -> createDisposable()
  use _destConn =
    match destPath with
    | RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
    | LocalPath(_) -> createDisposable()
  match srcPath, destPath with
  | RemotePath(src, _), RemotePath(dest, _)
  | LocalPath(src), RemotePath(dest, _)
  | RemotePath(src, _), LocalPath(dest)
  | LocalPath(src), LocalPath(dest) ->
    let dir = DirectoryInfo(src)
    if dir.Exists |> not then
      failwith ("Source directory not found: " + src)

    let dirs = dir.GetDirectories()
    if Directory.Exists(dest) |> not then
      Directory.CreateDirectory(dest) |> ignore

    let files = dir.GetFiles(filePattern)
    for file in files do
      let tempPath = Path.Combine(dest, file.Name)
      file.CopyTo(tempPath, false) |> ignore

    if copySubDirs then
      for subdir in dirs do
        let subdirSrc =
          match srcPath with
          | RemotePath(_, credential) -> RemotePath(Path.Combine(dest, subdir.Name), credential)
          | LocalPath(_) -> LocalPath(Path.Combine(dest, subdir.Name))
        let subdirDest =
          match destPath with
          | RemotePath(_, credential) -> RemotePath(subdir.FullName, credential)
          | LocalPath(_) -> LocalPath(subdir.FullName)
        copyDir copySubDirs filePattern subdirDest subdirSrc

0

あなたはこのようなものを追加することを見ているは​​ずです:

<identity impersonate="true" userName="domain\user" password="****" />

あなたのweb.configに。

詳しくは。


一部の企業セキュリティは、偽装を使用するアプリケーションを追跡できず、同じドメインまたは信頼されたドメインに存在する必要があるため、偽装の使用を防止します。なりすましのサポートが見つかると思います。pinvokeを使用したドメインサービスアカウントが適切な方法です。
ジム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.