none
スタートアップに登録したコンソールアプリケーションが動作しない RRS feed

  • 質問

  • タイトルの通り、スタートアップにアプリケーションのショートカットを配置しています。
    アプリケーションはコンソールアプリです。

    OS起動時にアプリケーションが起動するのですが、稀にコマンドプロンプトが立ち上がるだけで処理が行われず、黒い画面のまま停止することがあります。

    起動に成功した場合はログが画面にばーっと表示されます。
    また、Mainメソッドの中でConsole.Titleを設定していますが、それも反映されずにexeの名前が表示されています。

    現象の原因、できれば解消方法について、ご教示いただけないでしょうか?


    現象が確認できている環境は下記の通りです。
    XP Professional SP2
    .NET Framework2.0 SP1

    class Program
    {
        static void Main(string[] args)
        {
    
            Mutex mu = null;
    
            try
            {
    
                // 2重起動防止
                mu = new Mutex(false, "XXXX");
    
                if (!mu.WaitOne(0, false))
                {
                    System.Windows.Forms.MessageBox.Show(XXXX.Properties.Settings.Default.LOG_MESSAGE, Application.ProductName.ToString());
                    return;
                }
    
                System.Reflection.AssemblyTitleAttribute title = (System.Reflection.AssemblyTitleAttribute)
                    Attribute.GetCustomAttribute(System.Reflection.Assembly.GetExecutingAssembly(),
                    typeof(System.Reflection.AssemblyTitleAttribute));
    
                Console.Title = title.Title;
    
                // 省略
    
            }
            catch (Exception ex)
            {
                // ログ出力_エラー文言
                LogTrace.Trace(ex.Message);
                Console.WriteLine(XXXX.Properties.Settings.Default.CONTINUE);
                Console.ReadKey(false);
            }
            finally
            {
                if (mu != null)
                {
                    mu.Close();
                }
                // ログ出力_終了時
                LogTrace.Trace(XXXX.Properties.Settings.Default.LOG_MESSAGE2);
            }
        }
    }
    2010年1月27日 1:54

回答

  • 直前で、new Mutex( false, "XXXX" )としていますが、既に XXXX のMutexが存在していた場合、このコンストラクタで失敗します。
    # ぶつかる状況において、他のプロセスが XXXX を作成済みなはず。その場合、同じ名前のMutexを複数作成できないため。
    shch さんも指摘されていますが、アクセス権があれば、既存の Mutex に対応するインスタンスが取得できるはずです。
    これは、Win32API の CreateMutex と同じ(か同等)の動作です。

    それとも、「本当にぶつかるとき」というのは、もっと違う、かなり起こしにくいような状況を想定されているのでしょうか?


    # 本題に述べられなくててすみません。
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク shch 2010年2月4日 1:29
    2010年1月27日 14:15
    モデレータ
  • 今回の原因ではないと思いますが、
    WaitOne が true を返す場合は所有権を得ているため、ReleaseMutex が必要です。
    また、別のコンストラクタを使って、以下のようにも処理できると思います。

    bool createdNew;
    using (var mu = new Mutex(false, "mutexName", out createdNew))
    {
        if (createdNew)
        {
            // 処理
        }
    }
    if (!createdNew)
    {
        // 2重起動メッセージ
    }

    止まってしまう箇所の特定のために、さらに多くの場所にログ出力のコードを追加されてはいかがでしょうか?

    • 回答としてマーク shch 2010年2月4日 1:29
    2010年1月31日 9:43
  • しばらく投稿が止まっているみたいなので、可能性の低そうなことでもいいかなー、と思って返信いたします。
    他の(コンソールアプリケーションでない)アプリケーションでは問題が起きていないということですよね?
    もしそうならば、main に [STAThread] を付けた場合の動作はいかがでしょうか?

    ほかに、mutex を使わない場合はどうなのか
    どの処理で止まっているのか、または、main にすら入ってこないのか
    といったあたりがわかると、追求するべき問題を特定しやすくなるかと思います。

    • 回答としてマーク shch 2010年2月4日 1:29
    2010年2月3日 9:14
  • shch さんも指摘されていますが、アクセス権があれば 、既存の Mutex に対応するインスタンスが取得できるはずです。
    これは、Win32API の CreateMutex と同じ(か同等)の動作です。

    それとも、「本当にぶつかるとき」というのは、もっと違う、かなり起こしにくいような状況を想定されているのでしょうか?
    shchさんAzuleanさん、指摘ありがとうございます。
    取得できるはずなのですか…。本当にぶつけるテストをしていて、取得できなかったことがあったので…。

    OpenExistingを使えということなのかと思い、でもあるかないかを確認できない状況においてはオブジェクトの存在確認をする必要があって
    だったらCreateEvent()の成功/失敗をもって排他をすればいいかとか自分の中では納得させてました。

    うまくいくならそれでいいです。前言撤回ということで。
    • 回答としてマーク shch 2010年2月4日 1:28
    2010年2月3日 10:14
  • OS起動時にアプリケーションが起動するのですが、稀にコマンドプロンプトが立ち上がるだけで処理が行われず、黒い画面のまま停止することがあります。
    今回の件に関係あるのかどうかは分かりませんが、XP では conime.exe が衝突することがあるんですよね。
    スタートアップでたまにうまくいかないときに、10 分ほど待って変化があるなら、conime.exe が絡んでるかもしれませんね。
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク shch 2010年2月5日 0:59
    2010年2月4日 13:56
    モデレータ
  • ほとんどの人がこういうMutexの使い方をしていますが、本当にぶつかったとき、実は機能しないんですよね…。

    mu.WaitOne()で多重起動のチェックをしていますが、そのためにはMutexインスタンスmuが必要です。
    直前で、new Mutex( false, "XXXX" )としていますが、既に XXXX のMutexが存在していた場合、このコンストラクタで失敗します。
    # ぶつかる状況において、他のプロセスが XXXX を作成済みなはず。その場合、同じ名前のMutexを複数作成できないため。

    まぁ、この場合であってもログ出力されるのでしょうから、本件はこれが問題ではないとは思いますが。
    • 回答としてマーク shch 2010年2月4日 1:29
    2010年1月27日 2:55
  • ほとんどの人がこういうMutexの使い方をしていますが、本当にぶつかったとき、実は機能しないんですよね…。

    mu.WaitOne()で多重起動のチェックをしていますが、そのためにはMutexインスタンスmuが必要です。
    直前で、new Mutex( false, "XXXX" )としていますが、既に XXXX のMutexが存在していた場合、このコンストラクタで失敗します。
    # ぶつかる状況において、他のプロセスが XXXX を作成済みなはず。その場合、同じ名前のMutexを複数作成できないため。

    まぁ、この場合であってもログ出力されるのでしょうから、本件はこれが問題ではないとは思いますが。

    回答ありがとうございます。
    Mutexについて調べてみました。
    MSDNによると

    "このコンストラクタは、名前付きシステム ミューテックスを表す Mutex オブジェクトを初期化します。同じ名前付きシステム ミューテックスを表す複数の Mutex オブジェクトを作成できます。

    名前付きミューテックスがアクセス制御セキュリティで既に作成されていて、呼び出し元に System.Security.AccessControl.MutexRights.FullControl がない場合は、例外がスローされます。スレッドの動作を同期するために必要な権限でのみ既存の名前付きミューテックスを開く方法については、OpenExisting メソッドに関するトピックを参照してください。"

    となっていて、いいのだか悪いのだかわからないので、もう少し勉強します。
    OpenExistingにtry-catchを張ってチェックするのがよいのですかね。


    本題の件ですが、依然解決できていません。
    PCを長い間落としておいてからの起動時に発生しやすいようです。
    何か原因として考えられる要因があれば、引き続きお願いいたします。

    • 回答としてマーク shch 2010年2月4日 1:29
    2010年1月27日 8:56
  • みなさま回答ありがとうございます。
    結果から言うと、コレという原因はわかっていませんが、現象は発生しなくなりました。

    やったことは「ReleaseMutexを追加」、「[STAThread]を付与」と、コンソールの画面を出さない事になったので、プロジェクトの種類をWindowsアプリケーションに変更しました。

    原因を残せなくて恐縮なのですが、現象が発生しなくなったことで解決済みとしたいと思います。
    個人的にはReleaseMutexが必要だったのではと考えています。

    • 回答としてマーク shch 2010年2月4日 1:29
    2010年2月4日 1:28

すべての返信

  • ほとんどの人がこういうMutexの使い方をしていますが、本当にぶつかったとき、実は機能しないんですよね…。

    mu.WaitOne()で多重起動のチェックをしていますが、そのためにはMutexインスタンスmuが必要です。
    直前で、new Mutex( false, "XXXX" )としていますが、既に XXXX のMutexが存在していた場合、このコンストラクタで失敗します。
    # ぶつかる状況において、他のプロセスが XXXX を作成済みなはず。その場合、同じ名前のMutexを複数作成できないため。

    まぁ、この場合であってもログ出力されるのでしょうから、本件はこれが問題ではないとは思いますが。
    • 回答としてマーク shch 2010年2月4日 1:29
    2010年1月27日 2:55
  • ほとんどの人がこういうMutexの使い方をしていますが、本当にぶつかったとき、実は機能しないんですよね…。

    mu.WaitOne()で多重起動のチェックをしていますが、そのためにはMutexインスタンスmuが必要です。
    直前で、new Mutex( false, "XXXX" )としていますが、既に XXXX のMutexが存在していた場合、このコンストラクタで失敗します。
    # ぶつかる状況において、他のプロセスが XXXX を作成済みなはず。その場合、同じ名前のMutexを複数作成できないため。

    まぁ、この場合であってもログ出力されるのでしょうから、本件はこれが問題ではないとは思いますが。

    回答ありがとうございます。
    Mutexについて調べてみました。
    MSDNによると

    "このコンストラクタは、名前付きシステム ミューテックスを表す Mutex オブジェクトを初期化します。同じ名前付きシステム ミューテックスを表す複数の Mutex オブジェクトを作成できます。

    名前付きミューテックスがアクセス制御セキュリティで既に作成されていて、呼び出し元に System.Security.AccessControl.MutexRights.FullControl がない場合は、例外がスローされます。スレッドの動作を同期するために必要な権限でのみ既存の名前付きミューテックスを開く方法については、OpenExisting メソッドに関するトピックを参照してください。"

    となっていて、いいのだか悪いのだかわからないので、もう少し勉強します。
    OpenExistingにtry-catchを張ってチェックするのがよいのですかね。


    本題の件ですが、依然解決できていません。
    PCを長い間落としておいてからの起動時に発生しやすいようです。
    何か原因として考えられる要因があれば、引き続きお願いいたします。

    • 回答としてマーク shch 2010年2月4日 1:29
    2010年1月27日 8:56
  • 直前で、new Mutex( false, "XXXX" )としていますが、既に XXXX のMutexが存在していた場合、このコンストラクタで失敗します。
    # ぶつかる状況において、他のプロセスが XXXX を作成済みなはず。その場合、同じ名前のMutexを複数作成できないため。
    shch さんも指摘されていますが、アクセス権があれば、既存の Mutex に対応するインスタンスが取得できるはずです。
    これは、Win32API の CreateMutex と同じ(か同等)の動作です。

    それとも、「本当にぶつかるとき」というのは、もっと違う、かなり起こしにくいような状況を想定されているのでしょうか?


    # 本題に述べられなくててすみません。
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク shch 2010年2月4日 1:29
    2010年1月27日 14:15
    モデレータ
  • 今回の原因ではないと思いますが、
    WaitOne が true を返す場合は所有権を得ているため、ReleaseMutex が必要です。
    また、別のコンストラクタを使って、以下のようにも処理できると思います。

    bool createdNew;
    using (var mu = new Mutex(false, "mutexName", out createdNew))
    {
        if (createdNew)
        {
            // 処理
        }
    }
    if (!createdNew)
    {
        // 2重起動メッセージ
    }

    止まってしまう箇所の特定のために、さらに多くの場所にログ出力のコードを追加されてはいかがでしょうか?

    • 回答としてマーク shch 2010年2月4日 1:29
    2010年1月31日 9:43
  • しばらく投稿が止まっているみたいなので、可能性の低そうなことでもいいかなー、と思って返信いたします。
    他の(コンソールアプリケーションでない)アプリケーションでは問題が起きていないということですよね?
    もしそうならば、main に [STAThread] を付けた場合の動作はいかがでしょうか?

    ほかに、mutex を使わない場合はどうなのか
    どの処理で止まっているのか、または、main にすら入ってこないのか
    といったあたりがわかると、追求するべき問題を特定しやすくなるかと思います。

    • 回答としてマーク shch 2010年2月4日 1:29
    2010年2月3日 9:14
  • shch さんも指摘されていますが、アクセス権があれば 、既存の Mutex に対応するインスタンスが取得できるはずです。
    これは、Win32API の CreateMutex と同じ(か同等)の動作です。

    それとも、「本当にぶつかるとき」というのは、もっと違う、かなり起こしにくいような状況を想定されているのでしょうか?
    shchさんAzuleanさん、指摘ありがとうございます。
    取得できるはずなのですか…。本当にぶつけるテストをしていて、取得できなかったことがあったので…。

    OpenExistingを使えということなのかと思い、でもあるかないかを確認できない状況においてはオブジェクトの存在確認をする必要があって
    だったらCreateEvent()の成功/失敗をもって排他をすればいいかとか自分の中では納得させてました。

    うまくいくならそれでいいです。前言撤回ということで。
    • 回答としてマーク shch 2010年2月4日 1:28
    2010年2月3日 10:14
  • みなさま回答ありがとうございます。
    結果から言うと、コレという原因はわかっていませんが、現象は発生しなくなりました。

    やったことは「ReleaseMutexを追加」、「[STAThread]を付与」と、コンソールの画面を出さない事になったので、プロジェクトの種類をWindowsアプリケーションに変更しました。

    原因を残せなくて恐縮なのですが、現象が発生しなくなったことで解決済みとしたいと思います。
    個人的にはReleaseMutexが必要だったのではと考えています。

    • 回答としてマーク shch 2010年2月4日 1:29
    2010年2月4日 1:28
  • OS起動時にアプリケーションが起動するのですが、稀にコマンドプロンプトが立ち上がるだけで処理が行われず、黒い画面のまま停止することがあります。
    今回の件に関係あるのかどうかは分かりませんが、XP では conime.exe が衝突することがあるんですよね。
    スタートアップでたまにうまくいかないときに、10 分ほど待って変化があるなら、conime.exe が絡んでるかもしれませんね。
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク shch 2010年2月5日 0:59
    2010年2月4日 13:56
    モデレータ