我尝试远程登录计算机,以便在本地复制本地目录。我试图使用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调用失败的原因....
我有一种感觉,这就是导致我出现问题的原因。我该如何解决这个问题?
答案 0 :(得分:0)
所以我在分析我的问题和解决方案。显然我可能不需要使用UserLogon,因为This answer在我的测试环境中有效。让我们看看它在使用时是否有效。
编辑: 结果 这一切对我来说只需要在我的服务器上创建一个具有相同凭据(用户名/密码)的用户,并且可以看到工作组上的其他计算机
答案 1 :(得分:0)
我最终通过使用Windows登录凭据解决了这个问题。因此,如果“用户名/密码”是您的Windows登录,那么只需在“LogonUser”方法中使用相同的“用户名/密码”。希望它有所帮助。