Я должен быть в состоянии запустить процессы (и консоль и оконный) без него, крадя фокус. Единственный путь в платформе.NET, которую я нашел, чтобы сделать, это - Microsoft. VisualBasic. Взаимодействие. Shell с Microsoft. VisualBasic. AppWinStyle. [Minimized|Normal]NoFocus (которые отображаются на SW_SHOWMINNOACTIVE/SW_SHOWMA, передаваемый до ShellExecute).
В текущей версии моего кода (который действительно крадет фокус), я использую Систему. Диагностика. Процесс, и полагающийся на часть функциональности, которая дает мне, который Взаимодействие. Метод Shell не делает.
2 вопроса (одно серьезное, и одна вентиляция моего разочарования, что я действительно не ожидаю хороший ответ на),
1.) Я корректен, что у меня нет выбора, кроме как обертывать CreateProcess или ShellExecuteEx самого, или я пропускаю некоторое другое решение? Я действительно надеялся избежать этого, поскольку Процесс является такой полной и полезной оберткой кроме этого контроля, и была бы такая функциональность для реализации, P/Invoke призывает к отладке и всем видам различной боли.
2.) Почему был бы одна команда в Microsoft создавать такую (в других отношениях) полную обертку и затем исключать половину возможных значений из ProcessWindowStyle, в то время как другая команда создала подобную обертку, которая была намного менее завершена, но обеспечила все полезные стили окна?
Команда VB.NET сделала гораздо больше, чтобы облегчить вещи для разработчика относительно инструментарии Windows, и я не вижу проблем с добавлением ссылки на VB DLL и использовать это в вашей программе C #.
Это две команды с различным фокусом, вот и все. И вы не должны чувствовать себя плохо использование Microsoft.visualBasic.interaction.shell, если это решает вашу проблему.
Вы также можете использовать отражатель, чтобы увидеть фактическую реализацию и внедрить код самостоятельно, если вы не хотите ссылаться на DLL.
[РЕДАКТИРОВАНИЕ - Добавлен пример кода После комментариев, чтобы показать, что можно комбинировать взаимодействие. Shell и Process]
int pid = Interaction.Shell("notepad.exe", AppWinStyle.NormalFocus);
Process p = Process.GetProcessById(pid);
p.Exited += ((o, e) => Console.WriteLine("Exit"));
p.EnableRaisingEvents = true;
Console.ReadLine();
Здесь я использую метод оболочки, чтобы запустить процесс, получите ручку в процессе из PID, и крючок на событиях. Вы можете даже сделать P.kill (), чтобы прервать процесс.
[Редактировать - обходной путь для CMD.exe]
Это начинает становиться немного взломанным на мой вкус, но он работает. Замените «NewWindow» со случайным руководством или что-то, чтобы сделать его уникальным.
Microsoft.VisualBasic.Interaction.Shell(@"cmd.exe /c ""start cmd.exe /k title NEWWINDOW""", AppWinStyle.NormalFocus);
foreach (var process in Process.GetProcessesByName("cmd"))
{
if (process.MainWindowTitle.EndsWith("NEWWINDOW"))
{
process.Exited += ((o, e) => Console.WriteLine("Exit"));
process.EnableRaisingEvents = true;
}
}
Посмотрите здесь:
System.Diagnostics.ProcessStartInfo procInfo = new System.Diagnostics.ProcessStartInfo(); procInfo.CreateNoWindow = true; procInfo.UseShellExecute = true; procInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo = procInfo; proc.EnableRaisingEvents = true; proc.Exited += new EventHandler(proc_Exited); proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived); proc.Start(...) // Do something with proc.Handle... void proc_OutputDataReceived(object sender, DataReceivedEventArgs e) { /* Do something here... */ } void proc_Exited(object sender, EventArgs e) { /* Do something here... */ }
Редактировать: Я модифицировал код, чтобы показать средства для подъема событий и обрабатывающих их, также, я показал использование свойства
это ручка процесса, который работает.