Festlegen der Fenstergröße und -position in PowerShell 5 und 6

3386
Bewc

Problem : Wir haben einen großen Fernseher, den wir für Präsentationen verwenden, also nicht exakt 1920 × 1080 Pixel. Es ist aus und ich kann es nicht kontrollieren. Was ich kontrollieren kann, ist mein Windows-Laptop, an den ich mich anschließe. Ich habe nach Möglichkeiten gesucht, alles anzuzeigen, was ich brauche, um zum Projektor zu gelangen, eine Position zu setzen, die versetzt ist, um auf dem Fernseher gut auszusehen, und die Breite / Höhe für denselben Wert einstellen.

Was wurde getan : Ich kann das Get-Window-Skript von Boe Prox verwenden ( https://blogs.technet.microsoft.com/heyscriptingguy/2015/12/26/weekend-scripter-manage-window-placement-by-using-pinvoke/ ), und das hat gut funktioniert, um die Dimensionen und den Offset zu bekommen, die ich brauche. Allerdings sind seine Set-Window-Fehler sowohl bei WinPosh 5 als auch bei Posh 6 mit und ohne Admin-Privilegien auf mich zurückzuführen. Andere mögliche Lösungen führten zu ähnlichen Fehlern. Daher entschied ich mich, bei Prox 'Skript zu bleiben, da er für meine Ansprüche ein Experte ist.

Ich bewerte die hier genannten Lösungen, https://stackoverflow.com/questions/10392620/how-can-a-batch-file-run-a-program-and-set-the-position-and-size-of-the- -fenster / als mögliche Problemumgehungen . Ideal wäre jedoch eine PowerShell-Lösung ohne Abhängigkeiten von Drittanbietern.

Die Frage ist: Hat jemand gelöst, wie man entweder das Set-Window von Mr. Prox oder irgendetwas anderes dazu bringt, die Position und Größe eines Fensters in Straight V5 oder V6 PowerShell festzulegen?

Fehlermeldung in Posh 5:

Cannot convert argument "hWnd", with value: "System.Object[]", for "GetWindowRect" to type "System.IntPtr": "Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.IntPtr"." At Z:\scripts\Set-Window.ps1:90 char:9 + $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument 

Fehlermeldungen in Posh 6:

PS C:\> Set-Window -ProcessName notepad -X 1911 -Y "-369" -Width 266 -Height 113 Method invocation failed because [Window] does not contain a method named 'MoveWindow'. At Z:\scripts\Set-Window.ps1:98 char:13 + $Return = [Window]::MoveWindow($Handle, $x, $y, $Width, $ ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound   PS C:\> Set-Window -ProcessName firefox -X "-9" -Y "-9" -Width "1938" -Height "1050" Cannot convert argument "hWnd", with value: "System.Object[]", for "GetWindowRect" to type "System.IntPtr": "Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.IntPtr"." At Z:\scripts\Set-Window.ps1:90 char:9 + $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument 

Hinweis: Diese Fehler treten in Windows 7 auf (vorübergehend kein Zugriff auf Win10).

Update: Ich hatte die Fenstergröße / -position von Set (Many) Programs bemerkt, aber das UIAutomation-Modul wird nicht verwaltet (Codeplex wird archiviert und der letzte Blogbeitrag des Autors dafür war Feb. 2014).

1

2 Antworten auf die Frage

2
JosefZ

Standardmäßig gibt das Get-ProcessCmdlet ein System.Diagnostics.ProcessObjekt zurück - oder ein Array eines solchen Objekts, wenn mehrere übereinstimmende Prozesse vorhanden sind. Leider ist das ursprüngliche Set-Window.ps1Skript nicht das letztere Szenario widerspiegeln.

Ausgabe mit verbessertem Skript:

PS D:\PShell> Get-Process -ProcessName notepad  Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName ------- ------ ----- ----- ------ -- -- ----------- 505 29 12104 41232 2,05 4208 1 notepad 231 14 3068 13212 0,09 6732 1 notepad  PS D:\PShell> . D:\PShell\Downloaded\WindowManipulation\Set-Window.ps1  PS D:\PShell> Set-Window -ProcessName notepad -X 11 -Y 11 -Width 1200 -Height 900 -Passthru  ProcessName Size TopLeft BottomRight ----------- ---- ------- ----------- notepad 1200,900 11,11 1211,911 notepad 1200,900 11,11 1211,911   PS D:\PShell> 

Verbessertes Skript (Änderungen kommentiert):

Function Set-Window { <# .SYNOPSIS Sets the window size (height,width) and coordinates (x,y) of a process window.  .DESCRIPTION Sets the window size (height,width) and coordinates (x,y) of a process window.  .PARAMETER ProcessName Name of the process to determine the window characteristics  .PARAMETER X Set the position of the window in pixels from the top.  .PARAMETER Y Set the position of the window in pixels from the left.  .PARAMETER Width Set the width of the window.  .PARAMETER Height Set the height of the window.  .PARAMETER Passthru Display the output object of the window.  .NOTES Name: Set-Window Author: Boe Prox Version History 1.0//Boe Prox - 11/24/2015 - Initial build 1.1//JosefZ (https://superuser.com/users/376602/josefz) - 19.05.2018 - treats more process instances of supplied process name properly  .OUTPUT System.Automation.WindowInfo  .EXAMPLE Get-Process powershell | Set-Window -X 2040 -Y 142 -Passthru  ProcessName Size TopLeft BottomRight ----------- ---- ------- ----------- powershell 1262,642 2040,142 3302,784   Description ----------- Set the coordinates on the window for the process PowerShell.exe  #> [OutputType('System.Automation.WindowInfo')] [cmdletbinding()] Param ( [parameter(ValueFromPipelineByPropertyName=$True)] $ProcessName, [int]$X, [int]$Y, [int]$Width, [int]$Height, [switch]$Passthru ) Begin { Try{ [void][Window] } Catch { Add-Type @" using System; using System.Runtime.InteropServices; public class Window { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);  [DllImport("User32.dll")] public extern static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw); } public struct RECT { public int Left; // x position of upper-left corner public int Top; // y position of upper-left corner public int Right; // x position of lower-right corner public int Bottom; // y position of lower-right corner } "@ } } Process { $Rectangle = New-Object RECT $Handles = (Get-Process -Name $ProcessName).MainWindowHandle ### 1.1//JosefZ foreach ( $Handle in $Handles ) { ### 1.1//JosefZ if ( $Handle -eq [System.IntPtr]::Zero ) { Continue } ### 1.1//JosefZ $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle) If (-NOT $PSBoundParameters.ContainsKey('Width')) {  $Width = $Rectangle.Right - $Rectangle.Left  } If (-NOT $PSBoundParameters.ContainsKey('Height')) { $Height = $Rectangle.Bottom - $Rectangle.Top } If ($Return) { $Return = [Window]::MoveWindow($Handle, $x, $y, $Width, $Height,$True) } If ($PSBoundParameters.ContainsKey('Passthru')) { $Rectangle = New-Object RECT $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle) If ($Return) { $Height = $Rectangle.Bottom - $Rectangle.Top $Width = $Rectangle.Right - $Rectangle.Left $Size = New-Object System.Management.Automation.Host.Size -ArgumentList $Width, $Height $TopLeft = New-Object System.Management.Automation.Host.Coordinates -ArgumentList $Rectangle.Left, $Rectangle.Top $BottomRight = New-Object System.Management.Automation.Host.Coordinates -ArgumentList $Rectangle.Right, $Rectangle.Bottom If ($Rectangle.Top -lt 0 -AND $Rectangle.LEft -lt 0) { Write-Warning "Window is minimized! Coordinates will not be accurate." } $Object = [pscustomobject]@{ ProcessName = $ProcessName Size = $Size TopLeft = $TopLeft BottomRight = $BottomRight } $Object.PSTypeNames.insert(0,'System.Automation.WindowInfo') $Object  } } } } } 
Das funktioniert erfolgreich in v5 und v6. Danke, dass Sie mir etwas beigebracht haben! Bewc vor 5 Jahren 0
Ich musste auch "User32.dll" in "user32.dll" unter Windows 10 / PowerShell ändern: `` [DllImport ("User32.dll")] public extern static bool MoveWindow (IntPtr-Handle, int x, int y, int width, int height, bool redraw); } `` `to (Kleinbuchstabe u beachten)` `[[DllImport (" user32.dll ")] public extern static bool MoveWindow (IntPtr-Handle, int x, int y, int Breite, int Höhe, bool neu zeichnen); } `` ` Tuure Laurinolli vor 5 Jahren 0
0
Tuure Laurinolli

Ich musste unter Windows 10 / PowerShell auch "User32.dll" in "user32.dll" ändern:

[DllImport("User32.dll")] public extern static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw); } 

zu (Kleinschreibung u beachten)

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