![Powershell:为同一进程名称的多个应用程序设置窗口大小和位置](https://linux22.com/image/1569359/Powershell%EF%BC%9A%E4%B8%BA%E5%90%8C%E4%B8%80%E8%BF%9B%E7%A8%8B%E5%90%8D%E7%A7%B0%E7%9A%84%E5%A4%9A%E4%B8%AA%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E8%AE%BE%E7%BD%AE%E7%AA%97%E5%8F%A3%E5%A4%A7%E5%B0%8F%E5%92%8C%E4%BD%8D%E7%BD%AE.png)
我正在使用来自在 PowerShell 5 和 6 中设置窗口大小和位置,这对于仅一个应用程序来说效果很好,但我需要打开同一进程的多个窗口,并且每次调用它们时,我都会将它们设置为某个位置。而不是将它们全部转到一个指定位置。
解决了: 最后确定了如何让它在服务器上工作。添加了参数 $ProcessTitle 以及 $UserSessionID,使其能够正常工作,但有时它在尝试将窗口移动到位时无法快速获得 $ProcessID,并且会出错。为了解决这个问题,我在 $ProcessID 为空时添加了 Start-Sleep,并在运行命令后将其重置回 $null。
While ($ProcessID -eq $Null){
$ProcessID = (Get-Process -name $ProcessName | Where-Object -property SI -eq $UserSessionID |where {$_.MainWindowTitle -eq $ProcessTitle}).Id
Start-Sleep -Milliseconds 50}
功能脚本:
Function Set-Window {
[OutputType('System.Automation.WindowInfo')]
[cmdletbinding()]
Param (
[parameter(ValueFromPipelineByPropertyName=$True)]
$ProcessName,
[int]$UserSessionID,
[string]$ProcessTitle,
[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
While ($ProcessID -eq $Null){
$ProcessID = (Get-Process -name $ProcessName | Where-Object -property SI -eq $UserSessionID |where {$_.MainWindowTitle -eq $ProcessTitle}).Id
Start-Sleep -Milliseconds 50}
$Handle = (Get-Process -id $ProcessID).MainWindowHandle
#$Handles = (Get-Process -Name $ProcessName).MainWindowHandle
#foreach ( $Handle in $Handles ) {
if ( $Handle -eq [System.IntPtr]::Zero ) { Continue }
$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
}
}
$ProcessID = $Null
}
}
按钮点击
$btnPingFrame_Click = {
$Per = $RestID + 'per'
$Cer = $RestID + "cer"
$R = $RestID + 'r'
Get-Process |Where-Object {$_.MainWindowTitle -eq "PER - PROVIDER EDGE ROUTER"} | Stop-Process
start-process cmd -ArgumentList "/C","mode con:cols=75 lines=19 && COLOR 0b && title PER - PROVIDER EDGE ROUTER&& ping $Per -t"
Set-Window -ProcessName cmd -processtitle 'PER - PROVIDER EDGE ROUTER' -x 1 -y 1 -Width 615 -Height 345 -UserSessionID $UserSessionID -Passthru
Get-Process |Where-Object {$_.MainWindowTitle -eq "CER - CUSTOMER EDGE ROUTER"} | Stop-Process
start-process cmd -ArgumentList "/C","mode con:cols=75 lines=19 && COLOR 0a && title CER - CUSTOMER EDGE ROUTER&& ping $Cer -t"
Set-Window -ProcessName cmd -processtitle 'CER - CUSTOMER EDGE ROUTER' -x 1 -y 335 -Width 615 -Height 345 -UserSessionID $UserSessionID -Passthru
Get-Process |Where-Object {$_.MainWindowTitle -eq "R - AGGREGATED NETWORK"} | Stop-Process
start-process cmd -ArgumentList "/C","mode con:cols=75 lines=19 && COLOR 0c && title R - AGGREGATED NETWORK&& ping $R -t"
Set-Window -ProcessName cmd -processtitle 'R - AGGREGATED NETWORK' -x 1 -y 670 -Width 615 -Height 345 -UserSessionID $UserSessionID -Passthru
}
答案1
我不会尝试改变窗口大小或位置。但是,至于这个...
有什么方法可以让我创建脚本来指向最新的进程 ID?
...当我弹出记事本以显示命令中的文本时,我做了类似的事情。代码找到最后一个最近的记事本实例,激活它并将输出粘贴在那里。
# Get-Process | Clip
Get-WmiObject -Class Win32_OperatingSystem | Clip
[void] [System.Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
& "$env:WinDir\Notepad.exe"
Start-Sleep -Seconds 1
$a = Get-Process `
| Where-Object {$_.Name -eq "Notepad"} `
| Select -Last 1
Start-Sleep -Seconds 1
[Microsoft.VisualBasic.Interaction]::AppActivate($a.ID)
[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
[System.Windows.Forms.SendKeys]::SendWait("%EP")