93205


例えば、メモ帳のエディット（文字入力）部分や、任意のアプリの特定のフォームに表示されている文字列を、powershellから取得できるでしょうか？

環境：  
Powershell 5.1  
Windows 10  
※spy++等は使えません。  
※何かをダウンロードすることはできず、Windows標準で付属している機能のみ使えます。


CC BY-SA 4.0
2023-01-04T19:07:41.897
93187
2023-01-06T02:20:09.790
56253
question
powershell
Powershellで、他アプリのフォームの値を取得できますか？


できます。  
ただし下記のサンプルコードでは、任意のアプリのクラス名と特定のフォームのコントロール名をあらかじめ把握しておく必要があります。

**サンプルコード**

起動しているメモ帳のエディットから文字列を読み取る例です。  
任意のアプリの特定のコントロールを読み取る場合は、コード末尾の`"notepad"`と`"Edit"`を適切な値に書き換えてください。

[code]

    $Win32 = &{
    Add-Type -Assembly "System.Runtime" 
    # ========= C#言語によるWin32Api関数定義(ここから) =========
    $cscode = @" 
    
    [DllImport("user32.dll")]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr hwndParent,IntPtr hwndChildafter,string lpszClass,string lpszWindow);
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wparam, System.Text.StringBuilder lparam);
    
    public static IntPtr FindWindowByClass(string lpClassName) {
        return FindWindow(lpClassName, null);
    }
    
    public static string GetText(IntPtr hwndParent, string lpszClass) {
        int WM_GETTEXT = 0x000D;
        int WM_GETTEXTLENGTH = 0x000E;
        var hwnd = FindWindowEx(hwndParent, IntPtr.Zero, lpszClass, "");  // コントロールのハンドル
        Console.WriteLine(hwnd);
        var length = SendMessage(hwnd, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);  // コントロールの文字数
        Console.WriteLine(length);
        var sb = new System.Text.StringBuilder(length); /* length分のバッファサイズを確保 */
        SendMessage(hwnd, WM_GETTEXT, new IntPtr(length+1), sb);
        return sb.ToString();
    }
    "@
    # ========= C#言語によるWin32Api関数定義(ここまで) =========
    
        return (add-type -memberDefinition $cscode -name "Win32ApiFunctions" -passthru)
    }
    # クラス名からメモ帳のハンドルを取得
    $notepad = $Win32::FindWindowByClass("notepad")
    # エディットコントロールの文字列を取得
    $s = $Win32::GetText($notepad, "Edit")
    # 表示
    $s
    
[/code]

**参考資料**

  * [powershellでWin32 APIを利用する（powershell 2.0以上）](https://qiita.com/y-takano/items/cb752ad6a10e550ec92f)
  * [C#で他のアプリケーションの値を読み取る。](https://kobazlab.tech/2015/10/01/c%E3%81%A7%E4%BB%96%E3%81%AE%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E5%80%A4%E3%82%92%E8%AA%AD%E3%81%BF%E5%8F%96%E3%82%8B%E3%80%82/)
  * [SendMessageのWM_GETTEXTとWM_GETTEXTLENGTHで大幅に文字数が異なる](https://ja.stackoverflow.com/q/38214)


CC BY-SA 4.0
2023-01-06T02:20:09.790
93205
2023-01-06T02:20:09.790
9820
93187
answer