0

バックグラウンドでコンソール アプリケーションを起動する Windows フォームがあります (CreateNoWindow = rue、WindowStyle = ProcessWindowStyle.Hidden)。

Windows フォームでは、いつでもコンソール アプリケーションを停止できます。しかし、コンソール アプリケーション内で何らかの形でクローズ メッセージを処理したいと考えています。私は次のようなフックを使用しようとしました:

    [DllImport("Kernel32")]
    public static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool add);

    // A delegate type to be used as the handler routine 
    // for SetConsoleCtrlHandler.
    public delegate bool HandlerRoutine(CtrlTypes ctrlType);

    // An enumerated type for the control messages
    // sent to the handler routine.
    public enum CtrlTypes
    {
        CTRL_C_EVENT = 0,
        CTRL_BREAK_EVENT,
        CTRL_CLOSE_EVENT,
        CTRL_LOGOFF_EVENT = 5,
        CTRL_SHUTDOWN_EVENT
    }

    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
    {
        StaticLogger.Instance.DebugFormat("Main: ConsoleCtrlCheck: Got event {0}.", ctrlType);
        if (ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
        {
            // Handle close stuff
        }
        return true;
    }

    static int Main(string[] args)
    {
        // Subscribing
        HandlerRoutine hr = new HandlerRoutine(ConsoleCtrlCheck);
        SetConsoleCtrlHandler(hr, true);
        // Doing stuff
    }

しかし、コンソールウィンドウが作成された場合にのみ ConsoleCtrlCheck 内にメッセージが表示されます。しかし、ウィンドウが非表示の場合、メッセージは表示されません。

コンソール アプリケーション プロセスを閉じるための Windows フォームでは、proc.CloseMainWindow(); を使用します。コンソール ウィンドウにメッセージを送信します。

PS AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; - また、役に立たない

この状況を処理する別の方法はありますか?ありがとう。

4

1 に答える 1

1

これはうまくいくかもしれません。環境をクリーンアップするために NUnit テストで使用しました。残念ながら、呼び出されることは保証されていません。それを機能させるには、そのインスタンスを作成し、シャットダウン時に呼び出されるコールバック関数を渡す必要があります。

    /// <summary>
    /// Detects the moment when environment is about to be shutdown.
    /// <remarks>
    ///     For usage just create single instance of it.
    ///     Each time when GC calles Finilize a '~ShutdownDetector' will be called.
    /// </remarks>
    /// </summary>
    public sealed class ShutdownDetector
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="T:ShutdownDetector"/> class.
        /// </summary>
        /// <param name="notifier">The notifier</param>
        public ShutdownDetector(Notifier notifier)
        {
            if (notifier == null) throw new ArgumentNullException("notifier");
            _notifier = notifier;
        }

        /// <summary>
        /// Releases unmanaged resources and performs other cleanup operations before the
        /// <see cref="T:CQG.PDTools.Common.ShutdownDetector"/> is reclaimed by garbage collection.
        /// </summary>
        ~ShutdownDetector()
        {
            if (Environment.HasShutdownStarted)
            {
                onShutdown();
            }
            else
            {
                new ShutdownDetector(_notifier);
            }
        }

        /// <summary>
        /// Called when component needs to signal about shutdown.
        /// </summary>
        private void onShutdown()
        {
            if (_notifier != null)
            {
                _notifier();
            }
        }

        Notifier _notifier;
        public delegate void Notifier();
    }
于 2011-03-02T18:00:17.790 に答える