Как я могу запустить процесс с пользовательским интерфейсом из службы Windows?
Я создал приложение службы, а также приложение формы Windows, теперь я хочу запустить приложение Windows из службы. Я знаю, что в win7 из-за изоляции сервисов вы не можете делать это напрямую, поэтому я использовал метод CreateProcessAsUser метода advapi32.dll, но он может создать процесс, также появляющийся в диспетчере задач, но пользовательский интерфейс не будет отображаться пользователю. Какова причина? кто-нибудь может мне помочь из этого?
Хорошо, позвольте мне дать код, который я написал
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Ansi, EntryPoint = "CreateProcessAsUser")]
public static extern bool CreateProcessAsUser(IntPtr hToken,string lpApplicationName,string lpCommandLine,ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes,bool bInheritHandles,int dwCreationFlags,string lpEnvironment,string lpCurrentDirectory,ref STARTUPINFO lpStartupInfo,ref PROCESS_INFORMATION lpProcessInformation);
void LounchNewApplication()
{
try
{
string strAppName = @"D:\Working\UAC Demo\Tester\bin\Debug\Tester.exe";
string strAppPath = @"D:\Working\UAC Demo\Tester\bin\Debug\";
PROCESS_INFORMATION lpProcessInformation = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES lpProcessAttributes = new SECURITY_ATTRIBUTES();
lpProcessAttributes.nLength = (uint)Marshal.SizeOf(lpProcessAttributes);
STARTUPINFO lpStartupInfo = new STARTUPINFO();
lpStartupInfo.cb = Marshal.SizeOf(lpStartupInfo);
lpStartupInfo.lpDesktop = "WinSta0\\Default";
IntPtr htoken = IntPtr.Zero;
LogonUser("myName", "DomineName", "password", 2, 0, out htoken);
if (!CreateProcessAsUser(htoken, strAppName, null, ref lpProcessAttributes,
ref lpProcessAttributes, true, 0, null, strAppPath, ref lpStartupInfo,
ref lpProcessInformation))
{
eventLogger.WriteEntry("Error in starting application", EventLogEntryType.Error);
}
else
eventLogger.WriteEntry("Application launched successfulll" EventLogEntryType.Information);
//CloseHandle(lpProcessInformation.hThread);
//CloseHandle(lpProcessInformation.hProcess);
}
catch (Exception ex)
{
eventLogger.WriteEntry(ex.Message,
EventLogEntryType.Error);
}
}
Я вызываю метод LounchNewApplication() OnStart службы.
2 ответа
Вы запускаете процесс как пользователь, но в сеансе 0, который не является интерактивным. Не используйте LogonUser для создания токена пользователя. Используйте WTSQueryUserToken, передавая сеанс, в котором вы хотите создать процесс. Этот токен имеет правильный идентификатор сеанса. Вы можете использовать WTSEnumerateSessions для вывода списка всех сеансов на компьютере или обработки уведомлений об изменениях сеансов в обработчике службы.
Технически, сервис должен быть помечен как интерактивный, например. sc config <servicename> type= interact
,
Службы не должны взаимодействовать с консолью, и, безусловно, не должны запускаться. К счастью, это было исправлено после Windows 2003, а в Vista, Windows 2008 и Windows 7 становилось все сложнее и сложнее совершать такое плохое поведение.
Надлежащим способом является разделение вашего приложения на приложение-службу и приложение-монитор. Монитор работает как обычное приложение в сеансе пользователя и связывается со службой через IPC.