Я провел много исследований и не уверен, почему это не работает, возможно, упустил что-то простое. Код запускает программу, но запускает ее как пользователь локальной системы, а не как предполагаемый пользователь.
Часть службы, которая выполняет код:
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);
У меня есть запись в журнал, и похоже, что токен пользователя и токен окружения созданы просто отлично. Он также запускает намеченное приложение, но запускается как системный пользователь вместо предполагаемого пользователя олицетворения. Я могу заставить его работать, если под этим пользователем уже запущена программа. Для примера я изменил нужную программу для запуска, а также домен / имя пользователя / пароль.