Powershell のカスタム Set-Window スクリプトを使用してウィンドウのエクスプローラーのサイズを設定する

Powershell のカスタム Set-Window スクリプトを使用してウィンドウのエクスプローラーのサイズを設定する

この回答で提供されているスクリプトを使用しようとしています PowerShell 5 および 6 でウィンドウのサイズと位置を設定する

複数の Windows エクスプローラー ウィンドウの高さとサイズを設定します。インターネット エクスプローラーではなく、「エクスプローラー」と呼ばれるファイル ブラウザーです。

「メモ帳」プログラムでは動作しますが、「エクスプローラ」プログラムでは動作しません。

#works
Set-Window -ProcessName notepad-X 400 -Y 400 -Width 400 -Height 700 

#doesnt work
Set-Window -ProcessName explorer -X 400 -Y 400 -Width 400 -Height 700

理想的には、次のようなスクリプトを用意したいです:

  1. エクスプローラーウィンドウを3つ開きます。
  2. ファイルパスA、B、Cへ移動
  3. 各ウィンドウを画面上の特定の位置にサイズ変更する

追加のソフトウェアをインストールせずに、生の PowerShell だけを使用してこれを行うにはどうすればよいですか?

編集: harrymc の提案を使用した後、問題の半分を解決しました。ウィンドウを移動することはできますが、3 つのエクスプローラー子プロセスのハンドルを取得する方法を理解する必要があります...

$MethodDefinition = @'
[DllImport("user32.dll")]
public extern static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);
'@

$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -Namespace 'Win32' -PassThru

# How do I get 3 child explorer IDs here?
# i can't pass in 'explorer' name because that references the parent process running the whole GUI
$Handle = (Get-Process -Name "notepad").MainWindowHandle

$Return = [Window]::MoveWindow($Handle, 10, 20, 400, 400,$True)

編集2:

Start-Process 関数を使用してエクスプローラー ウィンドウを取得しようとしましたが、エラーが発生します。

$er3 = (Start-Process explorer -passthru)

PS C:\> (Get-Process -Id $er3.Id).MainWindowHandle
Get-Process : Cannot find a process with the process identifier 10572.At line:1 char:2
+ (Get-Process -Id $er3.Id).MainWindowHandle
+  ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (10572:Int32) [Get-Process], ProcessCommandException
    + FullyQualifiedErrorId : NoProcessFoundForGivenId,Microsoft.PowerShell.Commands.GetProcessCommand

終了したと表示されますが、エクスプローラーのファイル ブラウザー ウィンドウは開いたままです。何が起こっているのかわかりません。メモ帳で試してみると、うまくいきます...

$er4 = (Start-Process notepad -passthru)
PS C:\> (Get-Process -Id $er4.Id).MainWindowHandle
9899994

編集 3: ComObject を使用して item(0) にアクセスする方法を見つけました。

$ex4 = New-Object -ComObject Shell.Application
$ex4.open("C:\")
# $ex4.windows()[0].Width = 400       # breaks
$ex5 = $ex4.Windows()[0]
$ex6 = $ex5.Item(0)              # not sure why i need to do this extra step
$ex6.Width = 400 
$ex6.Navigate("file:///C:/Folder1/Folder2")                                                   

答え1

ネイティブの Windows API を使用すれば可能になるはずです。次のようになります。

[DllImport("User32.dll")]
public extern static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);
...
$Handle = (Get-Process -Id $ProcessId).MainWindowHandle
$Return = [Window]::MoveWindow($Handle, $x, $y, $Width, $Height,$True)

この一般的なコードは Explorer では機能しないため、代替の解決策を次に示します (テスト済み)。

$ex1 = New-Object -ComObject Shell.Application
$ex1.open("C:\")
$ex1.windows()[0].Top = 10
# also assignable : Left, Width, Height
# if required : $handle = $ex1.windows()[0].HWND

答え2

PowerShell は実際には UI 自動化ツールではありません。ご指摘のとおり、単に使用しないのはなぜでしょうか...

オートメーション

$w = Get-UIAWindow -ProcessName notepad
$w.Move(100, 100)

プロジェクトの説明

UIAutomation モジュールは、GUI テストの作業時にソフトウェア テストの自動化を簡素化します。このモジュールは、.Net Framework 3.0 以降の一部である UI Automation ライブラリに基づいており、ソフトウェア エンジニアの作業を可能な限り容易にすることを目的としています。

ワスプ

WASP は、ウィンドウやコントロールの選択、マウスやキーボードのイベントの送信などの Windows 自動化タスク用の PowerShell スナップインです。Select-Window、Select-Control、Send-Keys、Send-Click、Get-WindowPosition、Set-WindowPosition、Set-WindowActive、Remove-Window などのコマンドレットがあります。

注: これらはメンテナンスされなくなりましたが、設計どおりに動作し、メンテナンスされたことも、今後もメンテナンスされる予定もないサンプル コードを使用しています。

完全にメンテナンスされたこのソリューションも参照してください:

オートIT

AutoIt スクリプト言語の最新バージョンには、PowerShell ユーザー向けのボーナスが付属しています。ネイティブ PowerShell コマンドレットのセットです。これにより、AutoIt のユニークな機能 (ウィンドウ操作とキーストロークのシミュレーション) を通常の PowerShell スクリプトに追加できます。さらに、AutoIt PowerShell コマンドレットとアセンブリはデジタル署名されているため、より厳格な実行ポリシーで使用できます。コマンドレットは、PowerShell の x86 および x64 バージョンでもネイティブに実行されます。

関連情報