簡體   English   中英

啟動流程而不會竊取焦點(C#)

[英]Starting a process without stealing focus (C#)

我需要能夠啟動進程(控制台和窗口)而不會竊取焦點。 我發現在.NET框架中執行此操作的唯一方法是使用Microsoft.VisualBasic.AppWinStyle的Microsoft.VisualBasic.Interaction.Shell。[Minimized | Normal] NoFocus(映射到SW_SHOWMINNOACTIVE / SW_SHOWMA傳遞給ShellExecute)。

在我的代碼的當前版本(它確實竊取焦點),我使用System.Diagnostics.Process,並依賴於我提供的一些功能,Interaction.Shell方法沒有。

2個問題(一個嚴重,一個讓我感到沮喪,我真的不希望得到一個好的答案)

1.)我是否正確,我別無選擇,只能自己包裝CreateProcess或ShellExecuteEx,或者我錯過了其他一些解決方案? 我真的希望避免這種情況,因為除了這種疏忽之外,Process是一個完整而有用的包裝器,並且會有很多功能要實現,P / Invoke調試調用以及各種各樣的痛苦。

2.)為什么Microsoft的一個團隊會創建這樣一個(否則)完整的包裝器,然后從ProcessWindowStyle中排除一半可能的值,而另一個團隊創建了一個類似的包裝器,它不太完整,但提供了所有有用的窗口樣式?

VB.Net團隊已經做了很多工作來為開發人員提供有關Windows工具的簡化方法,我發現添加VB dll的引用並在C#程序中使用它沒有問題。

這是兩支不同重點的球隊,就是這樣。 如果它解決了你的問題,你應該對使用Microsoft.VisualBasic.Interaction.Shell感到不舒服。

如果您不想引用dll,也可以使用Reflector查看實際實現並自己實現代碼。

[編輯 - 在評論后添加代碼示例,表明您可以組合Interaction.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();

在這里,我使用Shell方法啟動進程,從pid獲取進程的句柄,並掛鈎事件。 您甚至可以執行p.Kill()以中止該過程。

[編輯 - cmd.exe的解決方法]

它開始變得有點像我的味道,但它的作用。 用隨機guid或其他東西替換“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... */
}

編輯:我已修改代碼以顯示引發事件和處理它們的方法,另外,我已經顯示了Handle屬性的用法,它是正在運行的進程的句柄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM