如何使用C#中的IP地址将文件传输到共享文件夹

时间:2017-07-16 15:47:11

标签: c#

我是C#的新手,我有一个PowerShell脚本,使用IP地址和用户名将文件发送到多台PC,我在那里使用new-PSDrive。我想在C#中创建相同的程序。

我不知道该怎么做,我经历了一些教程并尝试了它,但坚持使用Windows Impersonate Class。它写在我关注的帖子中:_如果我们想将文件共享到共享文件夹,我们可以使用 File.Copy(destPath,SourcePath),但它不起作用。

这是我正在尝试的代码:

WindowsIdentity idnt = new WindowsIdentity("Administrator", "Test123!");
WindowsImpersonationContext context = idnt.Impersonate();
File.Copy(@"C:\\Sent.txt", @"\\192.xxx.xxx.xxx\\SharedFolder", true);
context.Undo(); 

错误弹出式广告:提供的名称不是正确形成的帐户名称。            WindowsIdentity idnt =新的WindowsIdentity("管理员"," Test123!");

我不知道如何获得正确的名字,我正在尝试这样做: WindowsIdentity idnt =新的WindowsIdentity(用户名,密码);

我也是这个(" \ 192.xxx.xxx.xxx \ WIN-9SMSBCR4V7B \ SharedFolder",密码);

我要复制文件的机器在同一台机器上的Vmware上运行,我可以使用Powershell Script发送。

任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:1)

找到解决方案,这里是使用IP地址,用户名和密码将文件发送到远程PC的完整代码,用于不在同一DOMAIN上的计算机。 Here the Link which explains the use of correct LOGON PROVIDER

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

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

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

        // Test harness.
        // If you incorporate this code into a DLL, be sure to demand FullTrust.
        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public static void Main(string[] args)
        {
            SafeTokenHandle safeTokenHandle;
            try
            {
                string userName, domainName;
                //domainName = Console.ReadLine();
                domainName = ".";

                Console.Write("Enter the login of a user on {0} that you wish to impersonate: ", domainName);
                //provide username of remote machine.
                userName = Console.ReadLine();
                //provide password of remote machine.
                Console.Write("Enter the password for {0}: ", userName);

                //Here's the Catch 
                //LOGON32_PROVIDER_WinNT50 = 3; and LOGON32_LOGON_NewCredentials = 9;
                const int LOGON32_PROVIDER_WinNT50 = 3;
                //This parameter causes LogonUser to create a primary token.
                const int LOGON32_LOGON_NewCredentials = 9;

                // Call LogonUser to obtain a handle to an access token.
                bool returnValue = LogonUser(userName, domainName, Console.ReadLine(),
                    LOGON32_LOGON_NewCredentials, LOGON32_PROVIDER_WinNT50,
                    out safeTokenHandle);

                Console.WriteLine("LogonUser called.");

                if (false == returnValue)
                {
                    int ret = Marshal.GetLastWin32Error();
                    Console.WriteLine("LogonUser failed with error code : {0}", ret);
                    throw new System.ComponentModel.Win32Exception(ret);
                }
                using (safeTokenHandle)
                {
                    Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
                    Console.WriteLine("Value of Windows NT token: " + safeTokenHandle);

                    // Check the identity.
                    Console.WriteLine("Before impersonation: "
                        + WindowsIdentity.GetCurrent().Name);
                    // Use the token handle returned by LogonUser.
                    using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
                    {
                        using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
                        {

                            // Check the identity.
                            Console.WriteLine("After impersonation: "
                                + WindowsIdentity.GetCurrent().Name);
                            //File.Copy(Source File,DestinationFile);
                            File.Copy(@"C:\\Sent.txt", @"\\192.168.xxx.xxx\\Suji\\Sent.txt", true);
                        }
                    }
                    // Releasing the context object stops the impersonation
                    // Check the identity.
                    Console.WriteLine("After closing the context: " + WindowsIdentity.GetCurrent().Name);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception occurred. " + ex.Message);
            }
            Console.ReadLine();
        }
    }
    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);
        }
    }
}

希望这会有所帮助。

答案 1 :(得分:0)

您可能会认为将文件从一个文件夹复制到远程共享(需要用户名/密码)会很简单!但是,它不是!

以下2个链接提供了一些选项:

(1) How to provide user name and password when connecting to a network share

以上链接是关于首先映射网络驱动器然后执行文件复制

(2)copy files with authentication in c#

此选项是关于使用WindowsIdentity类(正如您所尝试的)。上面的链接提供了一种以正确的方式构造对象的方法

在某种程度上,上述两种选择都不是纯粹的.Net解决方案。他们直接调用Win32 API。

另一种选择:

如果您可以先创建一个映射的网络连接(在应用程序之外),那么可以使用简单的文件副本。

在这种情况下,步骤将是:

(1)使用net use命令使用用户名和密码将驱动器映射到共享文件夹

net use Z: /delete
net use Z: \\server name\share name password /user:user name

(2)运行复制程序

File.Copy(sourceFileName, @"Z:\path\to\folder\filename");

(3)删除驱动器映射

net use Z: /delete