none
特定のプロセスを非表示化または最小化したい RRS feed

  • 質問

  • 動作中の、アプリケーションウィンドウを持つプロセス(例:notepad.exe)を探し、アプリケーションウィンドウを非表示にする方法を知りたいです。
    MicroSoft Excelがメモリーに残り、Marshal.FinalReleaseComObject(obj)を使って終了させるという解決法がありますが、表面上これと同じ状況(プロセスは動作中だがタスクバーに現れない)を作り出したいです。
    これが無理ならば、プロセスを最小化する方法でも構いません。
    VB.netまたはc#による解決方法を教えて下さい。
    2020年3月18日 9:09

回答

  • メモ帳以外でのテストはしていません。

    そのプロセスが持つトップレベルウィンドウを無条件で Hide / Show するコードになっているので、本来操作すべきではないウィンドウまで操作されてしまうという問題がありました。使うのは notepad.HideWindows(); だけの方が良いかも。

    メモ帳で「ファイルを開く」ダイアログを出している最中に notepad.Showindows(); を呼び出したところ、コンボボックスのドロップダウン部やオートコンプリート項目まで強制表示されるというカオスな状況になりました。どのウィンドウを対象にするのかどうかという追加条件を加える必要がありそうです。

    • 回答としてマーク huahi11112 2020年3月19日 8:31
    2020年3月18日 15:39

すべての返信

  • API を使って処理するのなら、ShowWinow API を使うことで、特定の画面を非表示・最小化・最大化・元のサイズに復元などができます。

    手動操作での一時的な話なら、Windows 10 の仮想デスクトップ機能を使って他のデスクトップに追いやってしまえば、現在のデスクトップ上から隠すことが出来るでしょう。
    2020年3月18日 9:24
  • Process クラスに対する拡張メソッドとして作ってみました。
    使い方はこんな感じです。メモ帳以外でのテストはしていません。

    private void button1_Click(object sender, EventArgs e)
    {
        foreach (var notepad in Process.GetProcessesByName("notepad"))
        {
            notepad.HideWindows();
        }
    }
    
    private void button2_Click(object sender, EventArgs e)
    {
        foreach (var notepad in Process.GetProcessesByName("notepad"))
        {
            notepad.ShowWindows();
        }
    }

    以下、拡張メソッドのコードです。

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    
    public static class ProcessExtensions
    {
        internal enum WindowStyle
        {
            Hide = 0,
            Normal = 1,
            ShowMinimized = 2,
            ShowMaximized = 3,
            ShowNoActivate = 4,
            Show = 5,
            Minimize = 6,
            ShowMinNoActive = 7,
            ShowNA = 8,
            Restore = 9,
            ShowDefault = 10,
            ForceMinimize = 11,
        }
    
        public static void HideWindows(this Process proc)
        {
            Array.ForEach(proc.GetWindows(), w => SetStyle(w, WindowStyle.Hide));
        }
        public static void ShowWindows(this Process proc)
        {
            Array.ForEach(proc.GetWindows(), w => SetStyle(w, WindowStyle.Show));
        }
        public static IntPtr[] GetWindows(this Process proc)
        {
            var finder = new WindowFinder();
            return finder.GetWindows(proc);
        }
        internal static void SetStyle(this IntPtr window, WindowStyle style)
        {
            if (!Enum.IsDefined(typeof(WindowStyle), style))
            {
                throw new ArgumentOutOfRangeException(nameof(style));
            }
            if (window == IntPtr.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(window));
            }
            NativeMethods.ShowWindow(window, (int)style);
        }
    
        private class WindowFinder
        {
            private int processId;
            private List<IntPtr> hWndList;
            public IntPtr[] GetWindows(Process proc)
            {
                processId = proc.Id;
                hWndList = new List<IntPtr>();
                NativeMethods.EnumWindowsDelegate callback = this.EnumWindowsCallback;
                NativeMethods.EnumWindows(callback, IntPtr.Zero);
                GC.KeepAlive(callback);
                return hWndList.ToArray();
            }
            private bool EnumWindowsCallback(IntPtr handle, IntPtr extraParameter)
            {
                int processId;
                NativeMethods.GetWindowThreadProcessId(new HandleRef(this, handle), out processId);
                if (processId == this.processId)
                {
                    hWndList.Add(handle);
                }
                return true;
            }
        }
    
        private class NativeMethods
        {
            public delegate bool EnumWindowsDelegate(IntPtr hWnd, IntPtr lparam);
            [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern int EnumWindows(EnumWindowsDelegate lpEnumFunc, IntPtr extraData);
            [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern int GetWindowThreadProcessId(HandleRef handle, out int processId);
            [DllImport("user32", ExactSpelling = true, CharSet = CharSet.Auto)]
            public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        }
    }



    2020年3月18日 15:25
  • メモ帳以外でのテストはしていません。

    そのプロセスが持つトップレベルウィンドウを無条件で Hide / Show するコードになっているので、本来操作すべきではないウィンドウまで操作されてしまうという問題がありました。使うのは notepad.HideWindows(); だけの方が良いかも。

    メモ帳で「ファイルを開く」ダイアログを出している最中に notepad.Showindows(); を呼び出したところ、コンボボックスのドロップダウン部やオートコンプリート項目まで強制表示されるというカオスな状況になりました。どのウィンドウを対象にするのかどうかという追加条件を加える必要がありそうです。

    • 回答としてマーク huahi11112 2020年3月19日 8:31
    2020年3月18日 15:39
  • 御回答誠にありがとうございました。

    特定のプロセスに対し、enum WindowStyleのメンバーを指定してShowWindow()の操作ができることを確認しました。
    VBで書き直そうとしたのですが、API宣言とデリゲートでそれぞれシグネチャーが合わないコンパイルエラーが解決できず諦めました。
    VS2019で、VBとC#の混在言語で実験したのは初めてでしたが、C#の扱い方については良い学習になりました。また機会がありましたら御支援をお願い致します。
    2020年3月19日 8:45