C#/。NET:プログラムがサービスとして実行されているか、コンソールアプリケーションとして実行されているかを検出する[複製]
質問
この質問にはすでに回答があります:
- サービスとして実行していますか 12答え
コンソールアプリケーションとしてもサービスとしても実行できるC#/。NETプログラムがあります。 現在、コンソールアプリケーションとして起動するコマンドラインオプションを指定していますが、それを避けたいと思います。
プログラムがサービスとして開始されているかどうかをプログラムで検出することはできますか?
純粋なWin32の場合、StartServiceCtrlDispatcherでサービスとして開始して、ERROR_FAILED_SERVICE_CONTROLLER_CONNECTが返された場合はコンソールにフォールバックできますが、失敗した場合はSystem.ServiceProcess.ServiceBase.Run()がerrordialogをポップアップし、プログラムにエラーを通知します。
アイデアはありますか
解決
Rasmus、これは以前の質問です。
回答から、最も一般的な方法は、単純なコマンドラインオプションを使用するか、try catchブロックでコンソールオブジェクトにアクセスすることです(サービスでは、コンソールはプロセスに接続されず、アクセスしようとするとスローされます)例外)。
またはサービスのテスト/デバッグに問題がある場合は、コードを別のdllアセンブリに移動し、別のテストハーネス(winforms / consoleなど)を作成します。
(ジョナサンが質問の最後に自分の解決策を追加したことに気付いた。)
他のヒント
Environment.UserInteractive が魔法を行います。
ProcessオブジェクトのSessionIdプロパティを試してください。私の経験では、プロセスがサービスを実行している場合、SessionIdは0に設定されます。
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
const int STD_OUTPUT_HANDLE = -11;
IntPtr iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (iStdOut == IntPtr.Zero)
{
app.RunAsWindowsService = true;
}
// Run as Service
if (runAsWindowsService)
{
// .....
ServiceBase.Run(myService);
}
else
{
// Run as Console
// Register Ctrl+C Handler...
}
親プロセスの検索に関するこの回答のParentProcessUtilities構造体を使用して、これを行うことができます。
static bool RunningAsService() {
var p = ParentProcessUtilities.GetParentProcess();
return ( p != null && p.ProcessName == "services" );
}
親プロセスのプロセス名には、拡張子「.exe」が含まれていないことに注意してください。
試したことはありませんが、 Process.GetCurrentProcess が役立ちます-コンソールモードではプロセス名は実行可能ファイルと同じになりますが、サービスとして実行する場合は異なることが予想されます(また、確認してください!)。
これが機能するかどうかはわかりませんが、このコードと、親が" services.exe"かどうかを確認します。
Console.IsErrorRedirected 。 " false"を返しましたコンソールアプリの場合、および「true」テストした非コンソールアプリの場合。 IsOutputRedirected も使用できます。
これらが正確ではない状況があると思いますが、これは私にはうまくいきました。