-1

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"
webprogrammer
  • 2,393
  • 3
  • 21
  • 27
bangi
  • 3
  • 1
  • -1: there is no question, just a critic about some random code. Assuming you have a defined need, you should research about selecting Win32 processes (which is not PowerShell-specific). – AntoineL Feb 18 '20 at 11:58

3 Answers3

1

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"

}
T-Me
  • 1,814
  • 1
  • 9
  • 22
0

If more than one windowhandle, do a loop:

$processList = [object[]]@( Get-Process |where {$_.mainWindowTItle }|where {$_.Name -like "$proc"} )

foreach( $p in $processList ) {

    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

        [WinAp]::SetForegroundWindow($h) | Out-Null

        [WinAp]::ShowWindow($h,3) | Out-Null


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

        #[void]$wshell.SendKeys('~')

        [void]$wshell.SendKeys('%fx')

        sleep 1 | Out-Null

        [void]$wshell.SendKeys('N')
    }
}
f6a4
  • 1,684
  • 1
  • 10
  • 13
0

The Get-Process will return all the processes that match your criteria which means it will return multiple objects to the variable $p.

So you need to iterate over them you can simply use foreach loop

foreach($process in $p){
    if (($process -eq $null) -and ($adm -ne ""))

    {

        Start-Process "$proc" -Verb runAs

    }

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

    {

        Start-Process "$proc" #-Verb runAs

    }

    else

    {

        $h = $process.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')


    }
}
DevX
  • 308
  • 5
  • 16