通过网络将文件复制到域外的目标 [英] Copy a file over network to a destination outside domain

查看:84
本文介绍了通过网络将文件复制到域外的目标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用c#通过网络将文件从计算机A(帐户为myAccount @ mydomain)复制到计算机B(用户B @ computerB)。
我尝试了标准

I want to copy a file from computer A(with account myAccount@mydomain) to computer B(userB@computerB) over the network using c#. I tried the standard

File.Copy(source,destination)

并尝试启动cmd进程(从计算机A)并调用复制方法

and tried starting a cmd process (from computer A) and call the copy method

System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.UseShellExecute = false;
startInfo.Domain = "computerB"; //ofcourse it wont work since its outside the local domain of A
startInfo.FileName = "cmd.exe";
startInfo.Arguments = @"/C COPY \\computerA\Path\File1.txt \\computerB\Path$ ";
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
//It will exit the user name or password is incorrect

我也尝试使用PSexec来模拟计算机B :

I tried also to use PSexec to impersonate computerB :

 System.Diagnostics.Process process = new System.Diagnostics.Process();
 System.Diagnostics.ProcessStartInfo startInfo = new 
 System.Diagnostics.ProcessStartInfo();
 startInfo.UseShellExecute = false;
 startInfo.FileName = "cmd.exe";
 startInfo.Arguments = @"psexec \\computerB -u computerB\userB -p userBPassword cmd /c COPY \\computerA\Path\File1.txt \\computerB\Path$";
 process.StartInfo = startInfo;
 process.Start();
 process.WaitForExit();
//it will exit that the source file is unknown

总而言之,计算机A能够请参阅源(自身),而不要查看目的地(因为计算机B仅具有授权的本地用户)。
计算机B能够看到目的地(本身)但看不到源(因为计算机A在其域之外并且未通过网络共享)。

To sum it up,computer A is able to see the source(itself) but not the destination(since computer B has only authorized local user). computer B is able to see the destination(itself) but not the source(since computer A is outside its domain and its not shared over the network).

是否有一个此问题的解决方法?

Is there a workaround for this issue?

推荐答案

听起来像这是一个相当简单的身份验证问题,每当当前用户时,该问题就会弹出在域中和域外都没有共享权。在系统用户下运行并尝试访问其他设备上的共享时,也会出现此问题。

It sounds like this is a fairly simple authentication problem of the type that pops up whenever the current user doesn't have rights on a share, both in a domain and out. The problem also arises when running under the system user and trying to access shares on other devices.

解决方案是使用 WNetUseConnection API,执行文件操作,然后关闭调用 WNetCancelConnection2

The solution is to open an authenticated connection to the target device using the WNetUseConnection API, perform your file operations then close the connection with a call to WNetCancelConnection2.

这是我过去使用的一些代码:

Here's some code I have used in the past for this:

class ConnectSMB : IDisposable
{
    public string URI { get; private set; }
    public bool Connected { get; private set; } = false;

    public ConnectSMB(string uri, string username, string encPassword)
    {
        string pass = StringEncryption.Decode(encPassword);
        string connResult = Native.ConnectToRemote(uri, username, pass);
        if (connResult != null)
            throw new Exception(connResult);
            
        URI = uri;
        Connected = true;
    }

    public void Dispose()
    {
        Close();
    }

    public void Close()
    {
        if (Connected)
        {
            Native.DisconnectRemote(URI);
            URI = null;
            Connected = false;
        }
    }
}

public class Native
{
    #region Consts
    const int RESOURCETYPE_DISK = 1;
    const int CONNECT_UPDATE_PROFILE = 0x00000001;
    #endregion

    #region Errors
    public enum ENetUseError
    {
        NoError = 0,
        AccessDenied = 5,
        AlreadyAssigned = 85,
        BadDevice = 1200,
        BadNetName = 67,
        BadProvider = 1204,
        Cancelled = 1223,
        ExtendedError = 1208,
        InvalidAddress = 487,
        InvalidParameter = 87,
        InvalidPassword = 1216,
        MoreData = 234,
        NoMoreItems = 259,
        NoNetOrBadPath = 1203,
        NoNetwork = 1222,
        BadProfile = 1206,
        CannotOpenProfile = 1205,
        DeviceInUse = 2404,
        NotConnected = 2250,
        OpenFiles = 2401
    }
    #endregion

    #region API methods
    [DllImport("Mpr.dll")]
    private static extern ENetUseError WNetUseConnection(
        IntPtr hwndOwner,
        NETRESOURCE lpNetResource,
        string lpPassword,
        string lpUserID,
        int dwFlags,
        string lpAccessName,
        string lpBufferSize,
        string lpResult
    );

    [DllImport("Mpr.dll")]
    private static extern ENetUseError WNetCancelConnection2(
        string lpName,
        int dwFlags,
        bool fForce
    );

    [StructLayout(LayoutKind.Sequential)]
    private class NETRESOURCE
    {
        // Not used
        public int dwScope = 0;
        // Resource Type - disk or printer
        public int dwType = RESOURCETYPE_DISK;
        // Not used
        public int dwDisplayType = 0;
        // Not used
        public int dwUsage = 0;
        // Local Name - name of local device (optional, not used here)
        public string lpLocalName = "";
        // Remote Name - full path to remote share
        public string lpRemoteName = "";
        // Not used
        public string lpComment = "";
        // Not used
        public string lpProvider = "";
    }
    #endregion

    public static string ConnectToRemote(string remoteUNC, string username, string password)
    {
        NETRESOURCE nr = new NETRESOURCE
        {
            lpRemoteName = remoteUNC
        };

        ENetUseError ret = WNetUseConnection(IntPtr.Zero, nr, password, username, 0, null, null, null);
        if (ret == ENetUseError.NoError) return null;
        return ret.ToString();
    }

    public static string DisconnectRemote(string remoteUNC)
    {
        ENetUseError ret = WNetCancelConnection2(remoteUNC, CONNECT_UPDATE_PROFILE, false);
        if (ret == ENetUseError.NoError) return null;
        return ret.ToString();
    }
}

创建 ConnectSMB 类,然后再执行远程文件操作,然后在完成连接后处置(或关闭)该类。

Create an instance of the ConnectSMB class before you do your remote file operations, then dispose (or close) it when you're done with the connection.

using (var smb = new ConnectSMB(@"\\computerB\Path", "userB", "userBPassword"))
{
    File.Copy(source, destination);
}

这篇关于通过网络将文件复制到域外的目标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆