LogonUser returns 0 和 GetLastError 也 returns 0
LogonUser returns 0 and GetLastError also returns 0
我正在尝试远程登录到计算机,以便可以在本地复制本地目录。我正在尝试使用在 advapi32 DLL 中找到的 LogonUser 函数调用。当我调用该函数时,它 returns 0(假)但是当我调用 Marshal.GetLastWin32Error() 时它也 returns 0,表明没有错误。我尝试使用的用户名和密码我知道有效,因为我用它来登录计算机。我同时使用了域帐户和本地帐户,return 结果相同。以下是我尝试登录计算机。
[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
Even if an API supports SetLastError/GetLastError, the value returned by GetLastError is only meaningful if the API you just called actually fails. How that failure is indicated depends on the API. Except for a couple of braindead API/situation combinations, like Impersonate* with the new SeImpersonatePrivilege: the API can return a success code even if it fails due to lack of privilege, leaving you with only an identification token. Then you have to call GetLastError () to find out why the nominally-successful API call failed....
我觉得这就是导致我出现问题的原因。我该如何解决这个问题?
所以我过度分析了我的问题和解决方案。显然我可能不需要使用 UserLogon,因为 This answer 在我的测试环境中工作。我用的时候看看能不能用。
编辑:
结果
这一切都对我有用,只需在我的服务器上创建一个具有相同凭据 (username/password) 的用户,并且可以看到工作组
中的其他计算机
我最终使用 windows 登录凭据解决了这个问题。因此,如果 "username/password" 是您的 windows 登录名,那么只需在 "LogonUser" 方法中使用相同的 "username/password"。希望对你有帮助。
我正在尝试远程登录到计算机,以便可以在本地复制本地目录。我正在尝试使用在 advapi32 DLL 中找到的 LogonUser 函数调用。当我调用该函数时,它 returns 0(假)但是当我调用 Marshal.GetLastWin32Error() 时它也 returns 0,表明没有错误。我尝试使用的用户名和密码我知道有效,因为我用它来登录计算机。我同时使用了域帐户和本地帐户,return 结果相同。以下是我尝试登录计算机。
[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
Even if an API supports SetLastError/GetLastError, the value returned by GetLastError is only meaningful if the API you just called actually fails. How that failure is indicated depends on the API. Except for a couple of braindead API/situation combinations, like Impersonate* with the new SeImpersonatePrivilege: the API can return a success code even if it fails due to lack of privilege, leaving you with only an identification token. Then you have to call GetLastError () to find out why the nominally-successful API call failed....
我觉得这就是导致我出现问题的原因。我该如何解决这个问题?
所以我过度分析了我的问题和解决方案。显然我可能不需要使用 UserLogon,因为 This answer 在我的测试环境中工作。我用的时候看看能不能用。
编辑: 结果 这一切都对我有用,只需在我的服务器上创建一个具有相同凭据 (username/password) 的用户,并且可以看到工作组
中的其他计算机我最终使用 windows 登录凭据解决了这个问题。因此,如果 "username/password" 是您的 windows 登录名,那么只需在 "LogonUser" 方法中使用相同的 "username/password"。希望对你有帮助。