我已经做了大量研究,不确定为什么它不起作用,可能缺少一些简单的东西。该代码确实启动了该程序,但它以本地系统用户而不是预期用户的身份启动了该程序。
执行代码的服务部分:
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);
我有一些日志记录,看起来用户令牌和环境令牌创建得很好。它也确实启动了预期的应用程序,但是它以系统用户而不是预期的模拟用户启动。如果该用户下已有程序正在运行,我可以使其工作。对于该示例,我将所需的程序更改为启动,还更改了域/用户名/密码。
答案 0 :(得分:2)
问题在于在对LogonUser的调用中使用了LOGON_NEW_CREDENTIALS类型。来自the documentation:
此登录类型允许调用方克隆其当前令牌并为出站连接指定新的凭据。 新的登录会话具有相同的本地标识符,但对其他网络连接使用不同的凭据。
尝试改用LOGON32_LOGON_BATCH。