Я использую функцию из « Установка размера и положения окна в PowerShell 5 и 6», которая прекрасно работает только для одного приложения, но мне нужно иметь несколько открытых окон одного и того же процесса, и каждый раз, когда я вызываю их, я устанавливаю их в определенное место. Вместо них все собираются в одно указанное место.

Решено: окончательно определился, как заставить его работать на сервере. Добавлен параметр $ ProcessTitle, а также $ UserSessionID, который позволяет ему работать должным образом, но иногда он не будет иметь $ ProcessID так быстро, как при попытке переместить окно в нужное положение и с ошибкой. Чтобы решить эту проблему, я добавил Start-Sleep, когда $ ProcessID равен null, и сбросил его до $ 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 ответ1

0

Я не пытаюсь изменить размер окна и / или положение. Однако, что касается этого ...

Есть ли способ, которым я мог бы создать сценарий, чтобы указать на самый последний идентификатор процесса?

... Я делаю что-то похожее, когда выхожу в блокнот для отображения текста из команд. Код находит последний последний экземпляр блокнота, активирует его и вставляет туда вывод.

# 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")

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .