4

I copied this PowerShell code from some site, that show the current position of the mouse:

[Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null
$control = [System.Windows.Forms.Control]
$mouseX = $control::MousePosition.X
$mouseY = $control::MousePosition.Y
Write-Host 'MousePosition:' $mouseX $mouseY

I reviewed the System.Windows.Forms.Control class documentation and discovered several properties that are "sisters" of MousePosition (like Bottom, Bounds, Left, Location, Right or Top), that contain measures about the "control" in pixels, so I tried to also report the Location property values this way:

[Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null
$control = [System.Windows.Forms.Control]
$mouseX = $control::MousePosition.X
$mouseY = $control::MousePosition.Y
Write-Host 'MousePosition:' $mouseX $mouseY
$locationX = $control::Location.X
$locationY = $control::Location.Y
Write-Host 'Location:' $locationX $locationY

However this code don't works: no error is reported, but the Location values don't appear:

MousePosition: 368 431
Location:

Why the MousePosition property can be correctly accessed, but the Location one not?

The purpose of this code is to get the dimensions and position in pixels of the cmd.exe window in which the PowerShell script run. What is the right way to get these values in PowerShell?

Aacini
  • 65,180
  • 12
  • 72
  • 108
  • 3
    `MousePosition` is static, `Location` is not (since it's per instance of a control). You'll have to instantiate a `Control` object from the window handle if you want its location – Mathias R. Jessen Apr 16 '16 at 16:29

1 Answers1

3

The purpose of this code is to get the dimensions and position in pixels of the cmd.exe window in which the PowerShell script run. What is the right way to get these values in PowerShell?

If so, System.Windows.Forms.Control is not what you want - the console host is not a Windows Forms control.

You can get these values from the Win32 API (user32.dll) with the GetWindowRect function:

$WindowFunction,$RectangleStruct = Add-Type -MemberDefinition @'
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}
'@ -Name "type$([guid]::NewGuid() -replace '-')" -PassThru

$MyWindowHandle = Get-Process -Id $PID |Select -ExpandProperty MainWindowHandle
$WindowRect = New-Object -TypeName $RectangleStruct.FullName
$null = $WindowFunction::GetWindowRect($MyWindowHandle,[ref]$WindowRect)

The $WindowRect variable now has the location coordinates of the Window:

PS C:\> $WindowRect.Top
45
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • Thanks a lot for your promptly answer! I copy-pasted your code into `test.ps1` file and just added `Write-Host 'Left,Top,Right,Bottom:' $WindowRect.Left $WindowRect.Top $WindowRect.Right $WindowRect.Bottom` line at end. I executed it from the command-line with this command: `powershell Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process; .\test.ps1`; the output was: `Left,Top,Right,Bottom: 0 0 0 0` – Aacini Apr 16 '16 at 18:43
  • In that situation, you would need to get the `MainWindowHandle` of the *parent* process (ie. the cmd.exe process) rather than the current running instance of PowerShell – Mathias R. Jessen Apr 16 '16 at 18:46
  • Easiest thing would be something like `(Get-Process -Id (Get-WmiObject Win32_Process -Filter "ProcessId=$PID").ParentProcessId).MainWindowHandle` – Mathias R. Jessen Apr 16 '16 at 18:51
  • It works now! Thanks a lot! A last question: in order to write the first definition in just one long line, what changes I would need to do? I tried this mod, but it marked an error at the `@'[DllImport...` part. I also tried to remove the apostrophes and the at-signs, but as I said before: I am a PoSh novice user and really don't know what to do... – Aacini Apr 16 '16 at 19:15
  • Just remove the line breaks and the `@`'s - `@` is only for here-string (multi-line strings) – Mathias R. Jessen Apr 16 '16 at 19:16