我正在尝试在.NET控制台应用程序中模拟用户帐户,当它到达我调用Impersonate()方法的位置时,应用程序似乎立即退出。方法调用是在try-catch块中,但它甚至从未到达'catch'块,所以我看不出错误是什么!
以下是相关代码:
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
然后在我的申请开始时:
bool returnValue = LogonUser(user, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref m_tokenHandle);
if (!returnValue)
{
int ret = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(ret);
}
// Impersonate
WindowsIdentity _identity = new WindowsIdentity(m_tokenHandle);
EmailHelper.SendErrorMessage("Windows Identity Created!", string.Format("Created at: {0}", DateTime.Now.ToLongTimeString()));
try
{
m_impersonatedUser = _identity.Impersonate();
EmailHelper.SendErrorMessage("Impersonation Complete...", string.Format("Impersonation at: {0}", DateTime.Now.ToLongTimeString()));
}
catch
{
int ret = Marshal.GetLastWin32Error();
EmailHelper.SendErrorMessage("Error impersonating user!", string.Format("Error: {0}", ret));
}
finally
{
EmailHelper.SendErrorMessage("Finally block executed?!", "What is going on?");
}
我正在获取最初的“Windows身份创建”电子邮件,但不是其他任何人!有谁知道我怎么能找出我的潜在错误是什么以及为什么我的模仿不起作用?
谢谢!
编辑:
我尝试了这篇MSDN文章中的代码:http://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).aspx,唯一的修改就是在模仿时尝试创建文件。
修改改变了这段代码:
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
{
// Check the identity.
Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);
}
要:
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
{
// Check the identity.
Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);
System.IO.File.CreateText(@"Test.txt");
}
我作为“标准”用户运行exe时得到的输出表明LogonUser成功,WindowsIdentity.GetCurrent()。Name返回模拟的用户名,但创建文件失败,错误代码为1346,根据MSDN ,是:
ERROR_BAD_IMPERSONATION_LEVEL 1346(0x542) 未提供所需的模拟级别,或者提供的模拟级别无效。
这是什么意思?谷歌尚未对此有所了解......
编辑2:
我可以使用此代码冒充另一个标准用户帐户,但是当我尝试模拟我的管理员帐户时,它会失败。是否有可能以某种方式更改代码以允许运行此exe的标准用户模拟管理员帐户?
答案 0 :(得分:0)
当我运行您的代码时,我用Console.WriteLine
替换了所有发送电话的电子邮件,并使用我的UPN创建了Windows身份。这导致调用try块,然后调用finally块,如预期的那样。
您的电子邮件发送方式可能存在问题。我会看到你用Console.WriteLine()
替换后得到的结果相同。
另外,请尝试在最后添加Console.ReadLine()
,这样您就可以在不退出应用程序的情况下查看正在发生的事情。这可能是因为这是正常的,你只是没有收到电子邮件。如果电子邮件工作正常,如果在该电子邮件之后没有可以调用的行,应用程序将立即退出,但您仍然会收到电子邮件。
答案 1 :(得分:0)
您是否测试了m_tokenHandle
?
if (m_tokenHandle != IntPtr.Zero)
{
// continue on
您是否测试过_identity
?它也没有测试。
if (_identity != null)
{
// continue on
无论try例程是否成功,finally块都将执行。
答案 2 :(得分:0)
可悲的是,这似乎仍然不起作用,我有一种预感,试图冒充使用WindowsIdentity的管理员帐户可能不受支持,或者我的方法存在缺陷。无论哪种方式,相当具有讽刺意味,我决定完全采用不同的方法,将我想作为管理员运行的代码放入一个单独的可执行文件中,然后使用管理员凭据启动该exe作为一个新进程。
System.Diagnostics.Process.Start(myExecutablePath, args, adminUsername, adminPassword, domainName);
这样可以正常工作,因此遇到此问题的任何人也许也可以使用此解决方法。