布団が俺を呼んでいる

丘山大一のぶろぐ

他のアプリケーションウィンドウを操作する

この前出した「ぷるまど」の内部実装の話。

やっぱWinAPIだよね

他のアプリケーションを操作する場合、基本的にはウィンドウハンドルをどうやって取得するか、という問題に絞られます。
プロセスが分かっている場合はもちろんプロセスから攻めるわけですが、今回は「ウィンドウ」があるものをを取得したい。
というわけで、それを取得するAPIがEnumWindowsです。

    public class WinAPI
    {
        [DllImport("user32")]
        public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, IntPtr lParam);
        [DllImport("user32")]
        public static extern bool IsWindowVisible(IntPtr hWnd);
        [DllImport("USER32.DLL", SetLastError = true)]
        public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int ProcessId);
    }

みたいな感じでテキトーに定義して、EnumWindowsを呼び出してくるくる回せば色々できます。

        WinAPI.EnumWindows((h, i) =>
        {
            if (WinAPI.IsWindowVisible(h))
            {
                WinAPI.GetWindowThreadProcessId(h,out int id);
                result.Add((h, Process.GetProcessById(id).ProcessName)); //このresultに結果を蓄えているので、後はご随意に
            }
            return true;//Trueを返すと処理が継続する
        },
        IntPtr.Zero);

「WinAPI.IsWindowVisible」を呼び出して、ウィンドウが表示されているかどうかを判定していますが、「ウィンドウは持っているけど表示されない」みたいな例外動作をするアプリケーションもあります。
代表例がexplorerのProgram Manager。
こういった特殊なアプリケーションをどう扱うかは仕様次第だと思います。
「ぷるまど」は汎用的、かつ雑なアプリということもあり、そのあたりはあまり考えないことにしました。「ぷるまど」には、他のアプリケーションの都合が分からないから、とりあえず表示しておけ、てな動作をしています。


ウィンドウ操作系API等

他にはこの辺りを、こんな感じで定義して使っています。

        [DllImport("user32", CharSet = CharSet.Auto)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        [DllImport("user32.dll")]
        public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        public const int SW_RESTORE = 9;  // 画面を元の大きさに戻す
        public const int SW_SHOWNORMAL = 1;
        [DllImport("User32.dll")]
        public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
        [DllImport("user32.dll")]
        public static extern int MoveWindow(IntPtr hwnd, int x, int y, int nWidth, int nHeight, int bRepaint);
        [DllImport("USER32.DLL", CharSet = CharSet.Auto)]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

何をするAPIかは、名前を見てもらえば大体わかるかと……

窓断熱シート マジックミラー フィルム ガラス透明断熱フィルム 建築建物ガラスフィルム 目隠しフィルム 窓のサングラス省エネフィルム めかくしシート 窓フィルム マジックミラー 紫外線カット 飛散防止 ミラー(90cm×200cm, シルバー)

新品価格
¥2,378から
(2018/7/20 17:14時点)

コメントを書く

布団が俺を呼んでいる | サーバの共有フォルダの中身を整理してみた

布団が俺を呼んでいる

丘山大一のぶろぐ

サーバの共有フォルダの中身を整理してみた

梅雨の時期は体調が悪くて……更新さぼってました。
さて、共有の名のもとにカオス化するアレを整理する話。

なぜ整理したか

開発グループの利用の目安が2GB制限だったが、18.5GB使用していた。
ドキュメントが整理されておらず、何がどこにあるか分からない。ドキュメント探索という無駄なコストが発生。
「整理しなきゃ」「整理しなきゃ」と言う人はいるものの、いつまでたっても整理しない。

なぜ整理されないか

必要かもしれない(削除できない)。
自分以外が置いたファイルはよくわからない(削除できない)。

思ったこと

そもそも2GB制限って少なすぎ。サーバ管理者はアホかなんなら適当な1TBハードディスク2~3本買ってきてRAID組めば解決の予感。
削除できない原因は、ようはうっかり必要なファイルを削除していまったときに責任をとりたくないという話。
あとただたんに面倒くさいという話(最大の原因)。

やったこと

全ファイルを容量が空いている他のローカルにバックアップ(複数個所)
ディレクトリリストを出して、削除するファイル一覧を抽出。他のメンバにメールで送りつける(削除するって言ったからね? という予防線)。
なんとなく、「自分だったらこんな感じで整理する」やり方で整理開始。ガンガン削除。
自己基準のみで削除しまくり。

結果

18.5GB から 2.18GB へのスリム化に成功。
もし必要なファイルが後から出てきた場合はバックアップから戻す予定。
そのバックアップは1年後を目安に削除する予定。

共有フォルダとはどうあるべきか

本当にファイルを整理したいなら、それこそ履歴管理できるシステムを導入するべきなわけです。
しかし、共有フォルダにはそれを圧倒的に上回る便利さがある。
それは何より「手軽さ」。
これは何物にも代えがたいメリットなのです。たとえ将来カオス化すると分かっていても。
共有フォルダの問題点の指摘や、それを解消するための枠組みやルールなんかも色々提唱、提案、導入されていますが、2GB程度の容量なら適当でオッケー(今回は10GB超えで制御不能になっていたので整理しちゃいましたけど)。
むしろ下手にルールなんて導入したら、唯一最大のメリットである「手軽さ」が損なわれてしまう。
これは避けたいところです。
というわけで、こんなエントリを書いていますが、共有フォルダはルールではなく、モラルと時々の整理整頓で対応するのが個人的には好きです。



学校では教えてくれない大切なこと 1 整理整頓

新品価格
¥918から
(2016/7/8 23:23時点)

コメントを書く