我在使用Process.Start()+ Impersonation从文件服务器执行文件时遇到问题。请帮我解决我的问题。还有另一种方法吗?
这是按钮点击事件。
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
newUser = cls.ImpersonateUser("username", "domain", "password");
string fileName = @"\\network_computer\Test\Test.doc";
System.Diagnostics.Process.Start(fileName);
}
catch (Exception ex) { throw ex; }
finally
{
if (newUser != null)
newUser.Undo();
}
}
这是假冒课程。
public class clsImpersonate
{
#region 'Impersonation'
// group type enum
public enum SECURITY_IMPERSONATION_LEVEL : int
{
SecurityAnonymous = 0,
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3
}
// obtains user token
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
// closes open handes returned by LogonUser
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
// creates duplicate token handle
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
private System.Security.Principal.WindowsImpersonationContext newUser;
public WindowsImpersonationContext ImpersonateUser(string sUsername, string sDomain, string sPassword)
{
// initialize tokens
IntPtr pExistingTokenHandle = new IntPtr(0);
IntPtr pDuplicateTokenHandle = new IntPtr(0);
pExistingTokenHandle = IntPtr.Zero;
pDuplicateTokenHandle = IntPtr.Zero;
// if domain name was blank, assume local machine
if (sDomain == "")
sDomain = System.Environment.MachineName;
try
{
string sResult = null;
const int LOGON32_PROVIDER_DEFAULT = 0;
// create token
const int LOGON32_LOGON_INTERACTIVE = 2;
//const int SecurityImpersonation = 2;
// get handle to token
bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);
// did impersonation fail?
if (false == bImpersonated)
{
int nErrorCode = Marshal.GetLastWin32Error();
sResult = "LogonUser() failed with error code: " + nErrorCode + "\r\n";
// show the reason why LogonUser failed
//MessageBox.Show(sResult, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// Get identity before impersonation
sResult += "Before impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n";
bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle);
// did DuplicateToken fail?
if (false == bRetVal)
{
int nErrorCode = Marshal.GetLastWin32Error();
CloseHandle(pExistingTokenHandle); // close existing handle
sResult += "DuplicateToken() failed with error code: " + nErrorCode + "\r\n";
// show the reason why DuplicateToken failed
//MessageBox.Show(sResult, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
else
{
// create new identity using new primary token
WindowsIdentity newId = new WindowsIdentity(pDuplicateTokenHandle);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
// check the identity after impersonation
sResult += "After impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n";
//MessageBox.Show(sResult, "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
return impersonatedUser;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
// close handle(s)
if (pExistingTokenHandle != IntPtr.Zero)
CloseHandle(pExistingTokenHandle);
if (pDuplicateTokenHandle != IntPtr.Zero)
CloseHandle(pDuplicateTokenHandle);
}
}
#endregion
}
答案 0 :(得分:2)
如果您进行调试,您会在
中看到任何错误bool bImpersonated = LogonUser(sUsername, sDomain, sPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);
或
bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle);
在按钮点击事件中,尝试添加Using
声明:
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
using (newUser = cls.ImpersonateUser("username", "domain", "password"))
{
string fileName = @"\\network_computer\Test\Test.doc";
System.Diagnostics.Process.Start(fileName);
}
}
catch (Exception ex) { throw ex; }
finally
{
if (newUser != null)
newUser.Undo();
}
}
答案更新(#01):
请尝试以下代码:
public class clsImpersonate
{
#region 'Impersonation'
// obtains user token
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
// closes open handes returned by LogonUser
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
public IntPtr ImpersonateUser(string sUsername, string sDomain, string sPassword)
{
// initialize token
IntPtr pExistingTokenHandle = new IntPtr(0);
// if domain name was blank, assume local machine
if (sDomain == "")
sDomain = System.Environment.MachineName;
try
{
string sResult = null;
const int LOGON32_PROVIDER_DEFAULT = 0;
// create token
const int LOGON32_LOGON_INTERACTIVE = 2;
// get handle to token
bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);
// did impersonation fail?
if (false == bImpersonated)
{
int nErrorCode = Marshal.GetLastWin32Error();
sResult = "LogonUser() failed with error code: " + nErrorCode + "\r\n";
// show the reason why LogonUser failed
//MessageBox.Show(sResult, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// Get identity before impersonation
sResult += "Before impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n";
return pExistingTokenHandle;
}
catch (Exception ex)
{
throw ex;
}
}
public bool FreeImpersonationResource(IntPtr _token)
{
// close handle(s)
if (_token != IntPtr.Zero)
return CloseHandle(_token);
else return true;
}
#endregion
}
然后,按钮点击事件:
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
IntPtr token = cls.ImpersonateUser("username", "domain", "password");
using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(token))
{
string fileName = @"\\network_computer\Test\Test.doc";
System.Diagnostics.Process.Start(fileName);
}
cls.FreeImpersonationResource(token);
}
catch (Exception ex) { throw ex; }
}
注意:
- 如果在LogonUser函数中使用LOGON32_LOGON_INTERACTIVE
,则无需复制令牌,因为您获得的句柄是可以立即使用的主令牌。 (看看this MSDN page)
- 如果您为模拟上下文使用using
语句,则不需要Undo
,因为它会在using
的末尾“自动撤消”。
- 如果仍然无效,请尝试使用服务器的IP地址而不是其域名
- 如果它仍然不起作用,我可以建议的最后一件事是获取原始代码并在按钮单击事件中移动整个方法ImpersonateUser
,然后立即执行原始指令System.Diagnostics.Process.Start(fileName);
指令System.Diagnostics.Process.Start(fileName);
。
我希望这个答案中至少有一部分会有所帮助:)
更新(#02):
我自己尝试了这个并且它正在运行,使用我之前编辑中的代码进行了以下修改:
clsImpersonate
中,您必须将LogonUser
函数的类型更改为LOGON32_LOGON_NEW_CREDENTIALS
:
// create token
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
// get handle to token
bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);
在按钮单击事件中,您必须更改使用Process.Start()的方式。 另请在{。3}}上查看Process.Start功能
上的一些示例private void button1_Click(object sender, EventArgs e)
{
try
{
IntPtr token = cls.ImpersonateUser("username", "domain", "password");
using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(token))
{
string fileName = @"Winword.exe"; // the name of the sw you will use to open your file, I suppose MS Word
string argument = @"\\network_computer\Test\Test.doc"; // the path pf the file you want to open
Process process = new Process();
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = fileName;
info.Arguments = argument;
process.StartInfo = info;
process.Start();
}
cls.FreeImpersonationResource(token);
}
catch (Exception ex) { throw ex; }
}