我做了很多研究,不知道为什么这不起作用,可能缺少一些简单的东西。该代码确实启动了程序,但它以本地系统用户而不是预期用户的身份启动它。
执行代码的部分服务:
APIProcess.PROCESS_INFORMATION PI = new APIProcess.PROCESS_INFORMATION();
if (!APIProcess.Launch(@"C:\Windows\System32\notepad.exe", ".",
"admin", "test", out string MSG, out PI))
{
logger.Debug(MSG);
}
else
{
logger.Debug(MSG);
logger.Debug(PI.dwProcessID);
}
具有后台功能的部分代码:
public static bool Launch(string appCmdLine, string Domain, string Username, string Password,out string MSG, out PROCESS_INFORMATION pi)
{
MSG = "";
pi = new PROCESS_INFORMATION();
bool ret = false;
IntPtr Token = IntPtr.Zero;
if (LogonUserA(Username,Domain,Password,LogonType.LOGON_NEW_CREDENTIALS,LogonProvider.PROVIDER_WINNT50,ref Token))
{
if (Token != IntPtr.Zero)
{
IntPtr envBlock = GetEnvironmentBlock(Token);
ret = LaunchProcessAsUser(appCmdLine, Token, envBlock, out MSG, out pi);
MSG = string.Join(", ",Token.ToString(),envBlock.ToString());
if (envBlock != IntPtr.Zero)
DestroyEnvironmentBlock(envBlock);
CloseHandle(Token);
}
}
else
{
MSG = "Failed To Logon User";
}
return ret;
}
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUserA(
string Username,
string Domain,
string Password,
LogonType LogonType,
LogonProvider LogonProvider,
ref IntPtr Token);
private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock, out string Error, out PROCESS_INFORMATION pi)
{
bool result = false;
Error = "";
pi = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
saThread.nLength = (uint)Marshal.SizeOf(saThread);
STARTUPINFO si = new STARTUPINFO();
si.cb = (uint)Marshal.SizeOf(si);
si.lpDesktop = @"WinSta0\Default"; //Modify as needed
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
si.wShowWindow = SW_SHOW;
result = CreateProcessAsUser(
token,
null,
cmdLine,
ref saProcess,
ref saThread,
false,
CREATE_UNICODE_ENVIRONMENT,
envBlock,
null,
ref si,
out pi);
if (result == false)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
Error = message;
//Debug.WriteLine(message);
}
return result;
}
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
我有一些日志记录,看起来用户令牌和环境令牌创建得很好。它也确实启动了预期的应用程序,但它以系统用户而不是预期的模拟用户身份启动。如果该用户下已经有一个程序在运行,我可以让它工作。对于示例,我更改了要启动的所需程序以及域/用户名/密码。