SendKeys

Hi Team,
I wan to maximize one window by using send keys in powershell. The below code is not working. Please help me asap pls.
**
$wshShell = new-object -com wscript.shell
$wshShell.SendKeys(“%{space}x”) #not working…

$wshShell.SendKeys(“% x”) #not working… :frowning:

Using SendKeys is always a pretty fragile operation (since it depends on the correct window having the active focus). If you do need to do some GUI automation of that sort, I’d highly recommend that you check out AutoIT sometime; it has a nice scripting language, a COM interface, and can be written to interact with specific windows and user controls without depending on keystrokes or focus.

As far as I know, your second usage of SendKeys should be correct, so long as the window that you want to maximize has focus. It worked for me when I pasted it into a file in the ISE and ran it, at any rate (the ISE was maximized.)

Hey Vidya,

SendKeys is really best left as a last resort when all else fails. Mention of it has been known to cause some programmers and scripters to collapse in shock at hearing such bad language. :wink:

It’s a bit more involved than using SendKeys, but the Win32API has several funtions we can combine to achieve this. I’ve put together a couple of cmdlets that can be combined to get what you need. Run them, and you can then use the cmdlet like the example below.

What it does is get the MainWindowHandle value for the process you specify from Get-Process. This is then fed into the two API functions, which perform the operations required. First, it brings the window to the front, and then maximizes it. You can find out a bit more about these functions on MSDN.

It will fail for if you specify a process to the cmdlet that has more than one instance open (e.g. notepad running twice), but you can easily add extra validation for this if you want to take that into account.

Example use :

Set-WindowMaximized -Name notepad
Function Get-Hwnd
{
  [CmdletBinding()]
    
  Param
  (
    [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] [string] $ProcessName
  )
    
  Process
  { $ErrorActionPreference = 'Stop'
    Try 
    {
      $hwnd = Get-Process -Name $ProcessName | Select-Object -ExpandProperty MainWindowHandle
    }
    Catch 
    {
      $hwnd = $null
    }
    $hash = @{
      ProcessName = $ProcessName
      Hwnd        = $hwnd
    }
        
    New-Object -TypeName PsObject -Property $hash
  }
}

function Set-WindowMaximized
{
  [CmdletBinding()]
    
  Param
  (
    [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] [string] $Name
   
        
  )
    
  Process
  {
    $memberDefinition = @'
    [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll", SetLastError = true)] public static extern bool SetForegroundWindow(IntPtr hWnd);

'@

    Add-Type -MemberDefinition $memberDefinition -Name Api -Namespace User32
    $hwnd = Get-Hwnd -ProcessName $Name | Select-Object -ExpandProperty Hwnd
    If ($hwnd) 
    {
      $onTop = New-Object -TypeName System.IntPtr -ArgumentList (0)
      [User32.Api]::SetForegroundWindow($hwnd)
      [User32.Api]::ShowWindow($hwnd, 3)
    }
    Else 
    {
      [string] $hwnd = 'N/A'
    }

    $hash = @{
      Process = $Name
      Hwnd    = $hwnd
    }
        
    New-Object -TypeName PsObject -Property $hash
  }
}

Hi Tim Pringle,
That was a mind blowing job. Honestly I am in vain to understand the code but you given is the perfect solution of my requirement and that worked fine for me.
But still I am not clear why “$wshShell.SendKeys(”% x")" is not working for powershell.exe (but fine for ISE)? any reason?

I’m happy to give extra information on the script if you want on it mate,no worries.

I’m been playing around with SendKeys for the last 15 minutes or so, and experiencing exactly the same situation. It almost seems like ALT is not processed at all. The SendKeys equivalent of ALT+SPACE does not work for example. Also tried it with .NET’s [System.Windows.Forms.SendKeys]::Send method and get similar results.

All I can think of at the moment is that the behavior is different at some level because it is command line based. In vbscript previously for example, you would normally use cscript.exe for running vbs files within a command prompt session, and wscript.exe for form based apps. Thats me just thinking aloud there though, nothing to confirm this is why.

Will keep digging though, it’s an interesting one. :slight_smile:

Hey Tim,
I just modified your code as per my requirement. The below code is working very fine but the issue is after running the command it is echoing the Boolean values which I don’t want. Can you tell me how to avoid this?


function Set-WindowMaximized
{
Process
{
$temp_PSCal1=$Host.UI.RawUI.MaxPhysicalWindowSize
$temp_PSCal1.Width-=3
$temp_PSCal1.Height=9999
$Host.UI.RawUI.BufferSize=$temp_PSCal1
$temp_PSCal2=$Host.UI.RawUI.WindowSize
$temp_PSCal2.Width=$temp_PSCal1.Width-=3
$Host.UI.RawUI.WindowSize=$temp_PSCal2
$memberDefinition = @’
[DllImport(“user32.dll”)] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport(“user32.dll”, SetLastError = true)] public static extern bool SetForegroundWindow(IntPtr hWnd);

'@

Add-Type -MemberDefinition $memberDefinition -Name Api -Namespace User32
[int]$hwnd = Get-Process -Id $PID | Select-Object -ExpandProperty MainWindowHandle
If ($hwnd) 
{
  $onTop = New-Object -TypeName System.IntPtr -ArgumentList (0)
  [User32.Api]::SetForegroundWindow($hwnd)
  [User32.Api]::ShowWindow($hwnd, 3)
}

}
}

Yes, that’ll be the API functions, forgot about that.

Try this :

$null = [User32.Api]::SetForegroundWindow($hwnd)
$null = [User32.Api]::ShowWindow($hwnd, 3)

great. that worked bro for me. Thanks a lot.

Tim, I am very interested to learn about this sort of coding. what language is this?

[DllImport(“user32.dll”)] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow)

any resourced to learn pls?

Great topic! While I’m out digging on my own, I’m hoping you can point towards the modules/functions that would allow me to write to the console command line.
(I’m trying to build a facility to allow recall and editing of previous commands. I have a version working with SendKeys, but it is pretty wobbly with almost all shifted keystrokes – ‘$’, for instance.)

Thanks –