LogonUser返回0,GetLastError也返回0

时间:2015-04-09 17:40:34

标签: c# interop remote-access dllimport

我尝试远程登录计算机,以便在本地复制本地目录。我试图使用advapi32 DLL中的LogonUser函数调用。当我调用该函数时,它返回0(false)但是当我调用Marshal.GetLastWin32Error()时也返回0,表示没有错误。我尝试使用的用户名和密码我知道有效,因为我用它来登录计算机。我已经使用了域帐户和本地帐户,并且都返回了相同的结果。以下是我尝试登录计算机。

[DllImport("advapi32.DLL", SetLastError = true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLongonType, int dwLogonProvider, ref IntPtr phToken);

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

[DllImport("kernel32.DLL", CharSet = CharSet.Auto)]
public static extern string GetLastError();

private static void CopyDirectory(string computerName, string localPath, string remotePath)
{
    WindowsImpersonationContext impersonationContext = null;
    IntPtr userHandle = IntPtr.Zero;
    string username = @"testing";
    string password = @"testing";

    string fullRemotePath = string.Format("{0}\\{1}", computerName, remotePath);

    try
    {

        bool Logon = LogonUser(username, computerName, password, 2, 0, ref userHandle);
        if (!Logon)
        {
            Console.WriteLine("Error Logging in");
            int errorCode = Marshal.GetLastWin32Error();
            Console.WriteLine(string.Format("Error Code: {0}", errorCode));
            Console.WriteLine(new Win32Exception(errorCode).Message);
        }

        else
        {
            WindowsIdentity user = new WindowsIdentity(userHandle);
            impersonationContext = user.Impersonate();

            System.IO.File.Copy(localPath, fullRemotePath, true);
        }

    }

    catch (Exception ex)
    {
        int errorCode = Marshal.GetLastWin32Error();
        Console.WriteLine(string.Format("Error Code: {0}", errorCode));
        Console.WriteLine(ex.Message);
    }

    finally
    {
        if(impersonationContext != null)
            impersonationContext.Undo();

        if(userHandle != IntPtr.Zero)
            CloseHandle(userHandle);

    }
}

你能帮助我找到我的缺陷吗?

编辑: 我找到了以下评论here

  

即使API支持SetLastError / GetLastError,GetLastError返回的值仅在您刚调用的API实际失败时才有意义。如何指示失败取决于API。除了一些脑卒中API /情境组合,例如Impersonate *和新的SeImpersonatePrivilege:即使由于缺少权限而失败,API也可以返回成功代码,只留下一个识别令牌。然后你必须调用GetLastError()来找出名义上成功的API调用失败的原因....

我有一种感觉,这就是导致我出现问题的原因。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

所以我在分析我的问题和解决方案。显然我可能不需要使用UserLogon,因为This answer在我的测试环境中有效。让我们看看它在使用时是否有效。

编辑: 结果 这一切对我来说只需要在我的服务器上创建一个具有相同凭据(用户名/密码)的用户,并且可以看到工作组上的其他计算机

答案 1 :(得分:0)

我最终通过使用Windows登录凭据解决了这个问题。因此,如果“用户名/密码”是您的Windows登录,那么只需在“LogonUser”方法中使用相同的“用户名/密码”。希望它有所帮助。