Search code examples
powershellsendkeysshowwindowsetforegroundwindow

Powershell newcomer


I am a total new comer to powershell so please forgive me if my question sounds stupid. I found the script below from Yuri Posidelov which I tweaked to activate a process and show the window and send keystrokes to shut down the process which works great. However it fails if there are two process with the same name can anyone help me with this.

Orignal code by Yuriy Posidelov

param([string] $proc="SBDDesktop", [string]$adm)

cls


Add-Type @"

  using System;

  using System.Runtime.InteropServices;

  public class WinAp {

     [DllImport("user32.dll")]

     [return: MarshalAs(UnmanagedType.Bool)]

     public static extern bool SetForegroundWindow(IntPtr hWnd);


     [DllImport("user32.dll")]

     [return: MarshalAs(UnmanagedType.Bool)]

     public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

  }


"@

$p = Get-Process |where {$_.mainWindowTItle }|where {$_.Name -like "$proc"}


if (($p -eq $null) -and ($adm -ne ""))

{

    Start-Process "$proc" -Verb runAs

}

elseif (($p -eq $null) -and ($adm -eq ""))

{

    Start-Process "$proc" #-Verb runAs

}

else

{

    $h = $p.MainWindowHandle


    [void] [WinAp]::SetForegroundWindow($h)

    [void] [WinAp]::ShowWindow($h,3);


    $wshell = New-Object -ComObject wscript.shell;

    #$wshell.SendKeys('~')

    $wshell.SendKeys('%fx')

    sleep 1

    $wshell.SendKeys('N')


}


#|format-table id,name,mainwindowtitle –AutoSize

# static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

# powershell.exe -windowstyle hidden -file *.ps1 -adm "a"

Solution

  • The problem is that the line $p = Get-Process |where {$_.mainWindowTItle }|where {$_.Name -like "$proc"} will create an object of type array if it's more than one process. Else it will create an object of type System.ComponentModel.Component. You can test this with:

    $p.GetType()
    

    To compensate this you can execute your code foreach process in the array even if there is only one element in that array:

    ...
    [array]$array = Get-Process |where {$_.mainWindowTItle }|where {$_.Name -like "$proc"}
    
    foreach ($p in $array){
    
    
        if (($p -eq $null) -and ($adm -ne ""))
    
        {
    
            Start-Process "$proc" -Verb runAs
    
        }
    
        elseif (($p -eq $null) -and ($adm -eq ""))
    
        {
    
            Start-Process "$proc" #-Verb runAs
    
        }
    
        else
    
        {
    
            $h = $p.MainWindowHandle
    
    
            [void] [WinAp]::SetForegroundWindow($h)
    
            [void] [WinAp]::ShowWindow($h,3);
    
    
            $wshell = New-Object -ComObject wscript.shell;
    
            #$wshell.SendKeys('~')
    
            $wshell.SendKeys('%fx')
    
            sleep 1
    
            $wshell.SendKeys('N')
    
    
        }
    
    
        #|format-table id,name,mainwindowtitle –AutoSize
    
        # static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
        # powershell.exe -windowstyle hidden -file *.ps1 -adm "a"
    
    }