メソッドを使用する前に、プロセスが実行されていることを確認する必要があります。
ステートメントは次のとおりです。
Process.Start("popup.exe");
WAITコマンドを実行するか、この値に遅延を設定できますか?
完了するまで待つということですか?次にProcess.WaitForExit
を使用します。
var process = new Process {
StartInfo = new ProcessStartInfo {
FileName = "popup.exe"
}
};
process.Start();
process.WaitForExit();
あるいは、メッセージループに入るのを待っているUIを備えたアプリケーションの場合、次のように言うことができます。
process.Start();
process.WaitForInputIdle();
最後に、これらのどちらも当てはまらない場合は、Thread.Sleep
だけである程度の時間をかけてください:
process.Start();
Thread.Sleep(1000); // sleep for one second
これも一度必要で、プロセスのウィンドウタイトルを確認しました。期待したものであれば、アプリケーションが実行されていることを確認できます。私がチェックしていたアプリケーションは起動に時間がかかり、この方法はうまくいきました。
var process = Process.Start("popup.exe");
while(process.MainWindowTitle != "Title")
{
Thread.Sleep(10);
}
「ChrisG」の答えは正しいのですが、MainWindowTitleを毎回更新する必要があり、空を確認する方が良いでしょう。..このように:
var proc = Process.Start("popup.exe");
while (string.IsNullOrEmpty(proc.MainWindowTitle))
{
System.Threading.Thread.Sleep(100);
proc.Refresh();
}
まず第一に、これはかなり古いことを知っていますが、まだ受け入れられている答えはないので、おそらく私のアプローチは他の誰かを助けるでしょう。 :)
これを解決するために私がしたことは:
process.Start();
while (true)
{
try
{
var time = process.StartTime;
break;
}
catch (Exception) {}
}
プロセスが開始されない限り、関連付けvar time = process.StartTime
は例外をスローします。そのため、一度パスすると、プロセスが実行中であると想定し、それをさらに処理しても安全です。 Javaプロセスが起動するのを待つためにこれを使用しています。時間がかかるためです。この方法では、Thread.Sleep()
を使用するのではなく、アプリケーションが実行されているマシンに依存しません。
これは非常にクリーンなソリューションではないことを理解していますが、パフォーマンスに依存しない唯一のソリューションだと思います。
他の人がすでに言っているように、あなたが何を求めているのかすぐにはわかりません。プロセスを開始し、プロセスが「準備ができた」ときに別のアクションを実行することを想定します。
もちろん、「準備ができている」というのは難しいことです。必要なものによっては、単に待つだけで十分であることがわかります。ただし、より堅牢なソリューションが必要な場合は、名前付き Mutex を使用して2つのプロセス間の制御フローを制御することを検討できます。
たとえば、メインプロセスで名前付きミューテックスを作成し、待機するスレッドまたはタスクを開始できます。その後、2番目のプロセスを開始できます。そのプロセスが「準備ができている」と判断すると、名前付きミューテックスを開き(もちろん同じ名前を使用する必要があります)、最初のプロセスにシグナルを送ることができます。
私はトムに同意します。さらに、Thread.Sleepの実行中にプロセスを確認するには、実行中のプロセスを確認します。何かのようなもの:
bool found = 0;
while (!found)
{
foreach (Process clsProcess in Process.GetProcesses())
if (clsProcess.Name == Name)
found = true;
Thread.CurrentThread.Sleep(1000);
}
子プロセスが開始する前にStart
メソッドが返されますか? Start
は子プロセスを同期的に開始するという印象を受けていました。
子プロセスが何らかの初期化を完了するまで待つ場合は、プロセス間通信が必要です-C#(.NET 2.0)のWindowsのプロセス間通信 を参照してください。
@ChrisGのアイデアを少し拡張するには、process.MainWindowHandleの使用を検討し、ウィンドウメッセージループが応答しているかどうかを確認します。このWin32 APIのp/invokeを使用します: SendMessageTimeout 。そのリンクから:
関数が成功した場合、戻り値はゼロ以外です。 HWND_BROADCASTが使用されている場合、SendMessageTimeoutは個々のウィンドウのタイムアウトに関する情報を提供しません。
関数が失敗またはタイムアウトした場合、戻り値は0です。拡張エラー情報を取得するには、GetLastErrorを呼び出します。 GetLastErrorがERROR_TIMEOUTを返す場合、関数はタイムアウトしました。
ここで、System.Threading.Timer
を使用する実装。多分その目的のために少し。
private static bool StartProcess(string filePath, string processName)
{
if (!File.Exists(filePath))
throw new InvalidOperationException($"Unknown filepath: {(string.IsNullOrEmpty(filePath) ? "EMPTY PATH" : filePath)}");
var isRunning = false;
using (var resetEvent = new ManualResetEvent(false))
{
void Callback(object state)
{
if (!IsProcessActive(processName)) return;
isRunning = true;
// ReSharper disable once AccessToDisposedClosure
resetEvent.Set();
}
using (new Timer(Callback, null, 0, TimeSpan.FromSeconds(0.5).Milliseconds))
{
Process.Start(filePath);
WaitHandle.WaitAny(new WaitHandle[] { resetEvent }, TimeSpan.FromSeconds(9));
}
}
return isRunning;
}
private static bool StopProcess(string processName)
{
if (!IsProcessActive(processName)) return true;
var isRunning = true;
using (var resetEvent = new ManualResetEvent(false))
{
void Callback(object state)
{
if (IsProcessActive(processName)) return;
isRunning = false;
// ReSharper disable once AccessToDisposedClosure
resetEvent.Set();
}
using (new Timer(Callback, null, 0, TimeSpan.FromSeconds(0.5).Milliseconds))
{
foreach (var process in Process.GetProcessesByName(processName))
process.Kill();
WaitHandle.WaitAny(new WaitHandle[] { resetEvent }, TimeSpan.FromSeconds(9));
}
}
return isRunning;
}
private static bool IsProcessActive(string processName)
{
return Process.GetProcessesByName(processName).Any();
}