locked
Try, Catch, If, Invoke-Command and error handling RRS feed

  • Question

  • I'm still learning Powershell so please take it easy on me. Here is what I am trying to do, find a process called wview.exe on multiple remote computers, if wview.exe exist stop it + log it + increase counter, if it doesn't but computer is up, log it + increase counter, if we can't connect log it + increase counter. I would like to avoid having to test the connection first.

    Here is a sample of what I have:

    Foreach ($Computer in $Computers){
        #Try to connect to the computer
        Try{
            $ProcessCount = Invoke-Command -ComputerName $Computer -ScriptBlock {@(Stop-Process -force -passthru -processname wview).count} -SessionOption (New-PSSessionOption -NoMachineProfile)
            #If we find 1 or more wview.exe let's log it and + counters
            If($ProcessCount -eq 1){
                Write-Host $Computer " Processes killed: $ProcessCount"
                #$Result is an array to store the result to log to a file in the full script
                $Results += $Computer + " Processes killed: $ProcessCount"
                #Counters to store in summary for log file
                $SuccessConnectCount++
                $SuccessKillCount++
            }
                #Else ... no wview processes found, let's log it and + counter
                Else{
                    Write-Host $Computer ": 0 WView processes to kill"
                    $Results += $Computer + ": 0 WView processes to kill"
                    #Counter to store in summary for log file
                    $SuccessConnectCount++
                }
        }   
        #If we get a system error, let's catch it and log it as failed count.
        Catch{
            Write-Host $Computer ": Connection error"
            $Results += $Computer + ": Connection error"
            #Counter to store in summary for log file
            $FailConnectCount++
        }
    }

    I've tried multiple things like erroractions, catching system errors etc, however the script seems to either hit the try statement (if or else, never both) or catch statement and never all 3 (try, if, else and catch) when all 3 scenarios are present.




    Thursday, May 23, 2013 6:30 AM

Answers

  • This an alternative uses WMI:

    $killed=$hasprocess=$contacted=$failed=0
    
    $computers='computerwn0001','computerwd0001','computerwd0000','computerwd0005'
    $computers | ForEach-Object{
        $getprocess=Get-WMIObject Win32_Process -Computer $_ -Filter "Name='notepad.exe'" -ErrorAction SilentlyContinue
        if(-not($?)){$failed++}else{$contacted++}
        If($getprocess){
            $hasprocess++
            $getprocess | ForEach-Object{$_.Terminate() | Out-Null; $killed++}
            }
    
    }
    
    Write-Host "Computers Failed: $failed"
    Write-Host "Computers Contacted: $contacted"
    Write-Host "Computers running process: $hasprocess"
    Write-Host "Tasks killed: $killed"

    Replace notepad.exe with wview.exe

    Inspired by Carlsberg.

    • Marked as answer by NorbertG_TJG Friday, May 24, 2013 1:12 AM
    Friday, May 24, 2013 1:00 AM
  • Here you go (with minimal changes - you could make this a little more efficient):

    $killed=$hasprocess=$contacted=$failed=0
    
    $computers='computerwn0001','computerwn001','computerwd0000','computerwd0005'
    $computers | ForEach-Object {
        $getprocess=Invoke-Command -ComputerName $_ -ScriptBlock {Stop-Process -Name 'notepad' -passthru -ErrorAction SilentlyContinue} -ErrorAction SilentlyContinue
        
        if(-not($?)){$failed++}else{$contacted++}
    
        If($getprocess){
            $hasprocess++
            $getprocess | ForEach{$killed++}
            }
    }
    
    Write-Host "Computers Failed: $failed"
    Write-Host "Computers Contacted: $contacted"
    Write-Host "Computers running process: $hasprocess"
    Write-Host "Tasks killed: $killed"


    Inspired by Carlsberg.

    • Marked as answer by NorbertG_TJG Friday, May 24, 2013 1:45 AM
    Friday, May 24, 2013 1:28 AM

All replies

  • Hi Norbert,

    i search around but it looks live invoke-command dos't throw an exception.

    For a workaround you can try this:

    $ses = New-PSSession -ComputerName $Computer -ErrorAction SilentlyContinue
    if($ses -ne $null)
    {
       Invoke-Command -Session $ses -ScriptBlock {dir}
       Remove-PSSession -Session $ses
    }
    else
    {
        Write-Host "Error"
    }
    

    Greetings Malte
    Thursday, May 23, 2013 8:37 AM
  • How about:

    ForEach ($Computer in $Computers)
        {
        #Try to connect to the computer
        $ProcessCount = Invoke-Command -ComputerName $Computer -ScriptBlock {@(Stop-Process -force -passthru -processname wview).count} -SessionOption (New-PSSessionOption -NoMachineProfile)
        If ($? -EQ $True)
            {
            #If we find 1 or more wview.exe let's log it and + counters
            If($ProcessCount -eq 1)
                {
                Write-Host $Computer " Processes killed: $ProcessCount"
                #$Result is an array to store the result to log to a file in the full script
                $Results += $Computer + " Processes killed: $ProcessCount"
                #Counters to store in summary for log file
                $SuccessConnectCount++
                $SuccessKillCount++
                }
                #Else ... no wview processes found, let's log it and + counter
                Else
                    {
                    Write-Host $Computer ": 0 WView processes to kill"
                    $Results += $Computer + ": 0 WView processes to kill"
                    #Counter to store in summary for log file
                    $SuccessConnectCount++
                    }
            }
        Else
            {
            Write-Host $Computer ": Connection error"
            $Results += $Computer + ": Connection error"
            #Counter to store in summary for log file
            $FailConnectCount++
            }
        }

    The little-known variable $? contains a boolean reporting if the last command executed successfully or not.

    I didn't try the whole script, but I just tried the Invoke-Command and $? does return False if something goes wrong

    PS C:\Windows\SysWOW64\WindowsPowerShell\v1.0> $ProcessCount = Invoke-Command -ComputerName NotExistingComputer -ScriptBlock {@(Stop-Process Excel)}
    "[Test] Connecting to remote server Test failed with the following error message : WinRM cannot process the request. The following error occurred while using Kerberos authentication: Cannot find the
    computer Test. Verify that the computer exists on the network and that the name provided is spelled correctly. For more information, see the about_Remote_Troubleshooting Help topic.
        + CategoryInfo          : OpenError: (Test:String) [], PSRemotingTransportException
        + FullyQualifiedErrorId : NetworkPathNotFound,PSSessionStateBroken"
    PS C:\Windows\SysWOW64\WindowsPowerShell\v1.0> $?
    False
    PS C:\Windows\SysWOW64\WindowsPowerShell\v1.0>
    The problem is indeed, as Malte Brodersen says, that Invoke-Command doesn't throw an exception. I think using $? is easier to implement than his workaround though (you can actually copy/paste my code).


    My grandmother always used to say: "::1: sweet ::1:"





    • Edited by Jelle Janssens Thursday, May 23, 2013 4:17 PM Some formatting
    • Proposed as answer by Jelle Janssens Thursday, May 23, 2013 9:30 PM
    Thursday, May 23, 2013 4:12 PM
  • If a variable contains a boolean value, it does not need to be compared with $True to deterimine if it is true, as the result of that comparison will always be identical to the value of the boolean variable itself (and vice versa). The following three If statements have exactly the same result in all cases:

       a.    if ( $? ) {<whatever>}
       b.    if ( $? -eq $true ) {<whatever>}
       c.    if ( ( $? -eq $true ) -eq $true ) {<whatever>}

    Using form "b" instead of the simpler form "a" makes no more sense than using form "c" instead of form "b".


    Al Dunbar -- remember to 'mark or propose as answer' or 'vote as helpful' as appropriate.

    Thursday, May 23, 2013 7:35 PM
  • You are definitely right, but this way (your 'b') it is easier to understand for someone who is learning PoSh.

    My grandmother always used to say: "::1: sweet ::1:"


    Thursday, May 23, 2013 7:39 PM
  • Thanks for the help thus far guys, but it's still not working. Here is the result I get:

    PS C:\scripts\wView\WIP> C:\scripts\wView\WIP\KillSlips.ps1
    Cannot find a process with the name "wview". Verify the process name and call the cmdlet again.
        + CategoryInfo          : ObjectNotFound: (wview:String) [Stop-Process], ProcessCommandException
        + FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.StopProcessCommand
     
    store-8899-1 : Connection error
    [store-1111-1] Connecting to remote server failed with the following error message : WinRM cannot process the request. The following error occured
     while using Kerberos authentication: The network path was not found.  
     Possible causes are:
      -The user name or password specified are invalid.
      -Kerberos is used when no authentication method and no user name are specified.
      -Kerberos accepts domain user names, but not local user names.
      -The Service Principal Name (SPN) for the remote computer name and port does not exist.
      -The client and remote computers are in different domains and there is no trust between the two domains.
     After checking for the above issues, try the following:
      -Check the Event Viewer for events related to authentication.
      -Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
     Note that computers in the TrustedHosts list might not be authenticated.
       -For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troub
    leshooting Help topic.
        + CategoryInfo          : OpenError: (:) [], PSRemotingTransportException
        + FullyQualifiedErrorId : PSSessionStateBroken
    store-1111-1 : Connection error
    store-8899-1: Connection error store-1111-1: Connection error
    Number of computers successfully killed wview:  0
    Number of computers successfully connected:  0
    Number of computers failed connections:  2
    Number of computers failed wview kill process:  0

    The full code is below:

    <# Scripted by Norbert G
    	
        v1.8 - 20130524 - Fixed issue were script always reported 'kill process failed'
                          Re-wrote the main process
        v1.7 - 20130517 - Change to using QuestAD to get computer names
        v1.6 - 20130508 - Changed encoding method for out-files due to issues.
    	v1.5 - 20130415 - Appended -SessionOption (New-PSSessionOption -NoMachineProfile) to invoke-command.
    					  Some PC's are broken. See SDP #6836 for more info.
    					  http://WEBSERVER:9000/WorkOrder.do?woMode=viewWO&woID=6836&&fromListView=true
        v1.4 - 20130321 - Changed the script to read GetPCNames.ps1 to obtain computer names via domain
                          Removed login creditials, using domain creditials instead
        v1.3 - 20130314 - Made some changes to comments
        v1.2 - 20130214 - Fixed output formating for $TotalConnectCount as output file was returning value on new line
        v1.1 - 20130208 - Removed new line creation from processes killed
                          Change Summary at bottom of log to include Number of computers in front of count    
    	       			  Fixed the count for computers that connect ($SuccessConnectCount + $SuccessKillCount)
        v1.0 - 20130110 - Initial release
    #>
    
    <#
    #Load the Quest Active Directory cmdlets
    Add-PSSnapin Quest.ActiveRoles.ADManagement
    
    #Let's get all store computers, store and sort them
    $Computers = get-QADComputer -SearchRoot 'DOMAIN.com/Stores/Production'  | ForEach-Object {$_.Name} | Sort-Object
    #>
    $Computers = get-content "computers.txt"
    
    ####################
    # Global variables #
    ####################
    $SummaryLog = "summary.log" #SummaryLog file
    $TimeStamp = (Get-Date -format "yyyy/MM/dd hh:mmtt")
    #Counters
    $SuccessKillCount = 0 #Number of wview's killed
    $SuccessConnectCount = 0 #Number of success connects that didn't have to kill wview processes
    $FailConnectCount = 0 #Number of computers failing to connect
    $KillConnectCount = 0 #Number of computers that failed to kill wview
    #Array to store logs in $SummaryLog
    $Results = @()
    
    #Time stamp start time of $SummaryLog
    Write-Output "***** $TimeStamp *****" | Out-File -Encoding ASCII -Append $SummaryLog
    
    ################
    # Main process #
    ################
    
    #Create a remote session, kill and log all wview processes that are terminated
    ForEach ($Computer in $Computers)
        {
        #Try to connect to the computer and kill remote process
        $ProcessCount = Invoke-Command -ComputerName $Computer -ScriptBlock {@(Stop-Process -force -passthru -processname wview).count} -SessionOption (New-PSSessionOption -NoMachineProfile)
        If ($? -EQ $True)
            {
            #If we find 1 or more wview.exe let's log it and + counters
            If($ProcessCount -eq 1)
                {
                Write-Host $Computer " Processes killed: $ProcessCount"
                $Results += $Computer + " Processes killed: $ProcessCount"
                $SuccessConnectCount++
                $SuccessKillCount++
                }
                #Else ... no wview processes found, let's log it and + counter
                Else
                    {
                    Write-Host $Computer ": 0 WView processes to kill"
                    $Results += $Computer + ": 0 WView processes to kill"
                    $SuccessConnectCount++
                    }
            }
        Else
            {
            Write-Host $Computer ": Connection error"
            $Results += $Computer + ": Connection error"
            $FailConnectCount++
            }
        }
    
    #################
    # Count summary #
    #################
    
    #Log the results
    write-host $Results
    write-output $Results | Out-File -Encoding ASCII -Append $SummaryLog
    
    #Formatting
    write-output "`n" | Out-File -Encoding ASCII -Append $SummaryLog
    write-output "Summary: `n" | Out-File -Encoding ASCII -Append $SummaryLog
    
    #Summary report
    write-host "Number of computers successfully killed wview: " $SuccessKillCount 
    write-output "Number of computers successfully killed wview: $SuccessKillCount" | Out-File -Encoding ASCII -Append $SummaryLog
    write-host "Number of computers successfully connected: " $SuccessConnectCount
    write-output "Number of computers successfully connected: $SuccessConnectCount" | Out-File -Encoding ASCII -Append $SummaryLog
    write-host "Number of computers failed connections: " $FailConnectCount
    write-output "Number of computers failed connections: $FailConnectCount" | Out-File -Encoding ASCII -Append $SummaryLog
    write-host "Number of computers failed wview kill process: " $KillConnectCount
    write-output "Number of computers failed wview kill process: $KillConnectCount" | Out-File -Encoding ASCII -Append $SummaryLog
    
    #Put an extra break between this run and the next
    write-output "" | Out-File -Encoding ASCII -Append $SummaryLog

    I'm sure this whole thing can be written better and correctly formatted. I commented out the questAD part and using a simple text file to check against the computers (computers.txt) for testing.

    I think the problem is Invoke-Command returns true or system error, however Stop-Process returns only true if there is a process to kill, if there isn't it returns an error. Here is the result when I left the process running to be killed:

    PS C:\scripts\wView\WIP> C:\scripts\wView\WIP\KillSlips.ps1
    store-8899-1  Processes killed: 1
    [store-1111-1] Connecting to remote server failed with the following error message : WinRM cannot process the request. The following error occured
     while using Kerberos authentication: The network path was not found.  
     Possible causes are:
      -The user name or password specified are invalid.
      -Kerberos is used when no authentication method and no user name are specified.
      -Kerberos accepts domain user names, but not local user names.
      -The Service Principal Name (SPN) for the remote computer name and port does not exist.
      -The client and remote computers are in different domains and there is no trust between the two domains.
     After checking for the above issues, try the following:
      -Check the Event Viewer for events related to authentication.
      -Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
     Note that computers in the TrustedHosts list might not be authenticated.
       -For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troub
    leshooting Help topic.
        + CategoryInfo          : OpenError: (:) [], PSRemotingTransportException
        + FullyQualifiedErrorId : PSSessionStateBroken
    store-1111-1 : Connection error
    store-8899-1 Processes killed: 1 store-1111-1: Connection error
    Number of computers successfully killed wview:  1
    Number of computers successfully connected:  1
    Number of computers failed connections:  1
    Number of computers failed wview kill process:  0

    What I should be getting is the following when I have the following scenario:

    1. pc1 is up and running and has 1 or more processes to kill

    2. pc2 is up and running and has no processes to kill

    3. pc3 is offline

    Number of computers successfully killed wview:  1 <- Should count pc1 only
    Number of computers successfully connected:  2 <- Should count pc1 and pc2
    Number of computers failed connections:  1 <- Should count pc3 only
    Number of computers failed wview kill process:  0 <- this is redundant and I will need to remove from the script.



    Thursday, May 23, 2013 11:26 PM
  • Hi,

    Before we get too far into this, have you stepped through all of the possible causes returned?

    Thursday, May 23, 2013 11:41 PM
  • Hi Mike,

    Sorry I don't know how to run debuggers. I'm very much a novice at scripting.

    Thanks,

    Norbert

    Thursday, May 23, 2013 11:57 PM
  • No worries, no scripting knowledge needed for this part. I'm talking about these 'possible causes':

     Possible causes are:
      -The user name or password specified are invalid.
      -Kerberos is used when no authentication method and no user name are specified.
      -Kerberos accepts domain user names, but not local user names.
      -The Service Principal Name (SPN) for the remote computer name and port does not exist.
      -The client and remote computers are in different domains and there is no trust between the two domains.
     After checking for the above issues, try the following:
      -Check the Event Viewer for events related to authentication.
      -Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
     Note that computers in the TrustedHosts list might not be authenticated.
       -For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troub
    leshooting Help topic.


    Friday, May 24, 2013 12:18 AM
  • I put some debuggers in and here is what happens:

    With a live computer with 0 processes to kill:

    Hits the first if statement ($? -eq $true) then hits the final else statement where it writes out connection error.

    With a offline computer

    Hits the first if statement ($? -eq $true) then hits the final else statement where it writes out connection error.

    Result:

    store-8899-1: Connection error store-1111-1: Connection error
    Number of computers successfully killed wview:  0
    Number of computers successfully connected:  0
    Number of computers failed connections:  2

    ---

    2nd test. With a computer with 2 wview processes open

    Hits the first if statement ($? -eq $true) then If($ProcessCount -eq 1) then first else statement

    Computer that is offline

    Hits the first if statement then final else statement.

    Result:

    store-8899-1: 0 WView processes to kill store-1111-1: Connection error
    Number of computers successfully killed wview:  0
    Number of computers successfully connected:  1
    Number of computers failed connections:  1

    Friday, May 24, 2013 12:19 AM
  • Hey Mike,

    To answer some of your questions, the computer (store-8899-1) is on the same domain, the offline computer name (store-1111-1) I made up so wouldn't be in DNS. Does this matter?

    I have a few other scripts using the invoke-command to do similar things e.g pull down disk error logs from the remote computers and they work correctly under a similar scenario. I think the issue is purely on how to handle errors and what stop-process returns. The disk error script does a test connection first with a try (invoke-command) catch, then look for logs in the try (if with another invoke-command) statement, where as with this script I am trying to eliminate the 2nd invoke command. Hopefully if we can get this right I can fix up the disk error script as well.

    Hopefully this makes sense, what I am trying to do:

    invoke-command to stop the process:

    Can Kill Process -> Yes -> Kill the process -> log as killed, increment counter connected and kill

    Can Kill Process -> No -> no process(but can connect) -> log as connected, increment counter connected

    Can Kill Process -> No -> offline -> log as failed to connect, increment counter failed to connect

    Hope that makes sense.


    IMO the issue is with the return codes for stop-process. It will either return true if it finds a process, false if it doesn't find a process because it doesn't exist or the computer is offline. I guess what I need is a way to trap the 2 possible stop process errors. Trap the error 'Cannot find a process with the name "wview". Verify the process name and call the cmdlet again.' as one type of if error and 'Connecting to remote server failed with the following error message : WinRM cannot process the request. The following error occured' and all other errors as an else error.
    Friday, May 24, 2013 12:32 AM
  • This an alternative uses WMI:

    $killed=$hasprocess=$contacted=$failed=0
    
    $computers='computerwn0001','computerwd0001','computerwd0000','computerwd0005'
    $computers | ForEach-Object{
        $getprocess=Get-WMIObject Win32_Process -Computer $_ -Filter "Name='notepad.exe'" -ErrorAction SilentlyContinue
        if(-not($?)){$failed++}else{$contacted++}
        If($getprocess){
            $hasprocess++
            $getprocess | ForEach-Object{$_.Terminate() | Out-Null; $killed++}
            }
    
    }
    
    Write-Host "Computers Failed: $failed"
    Write-Host "Computers Contacted: $contacted"
    Write-Host "Computers running process: $hasprocess"
    Write-Host "Tasks killed: $killed"

    Replace notepad.exe with wview.exe

    Inspired by Carlsberg.

    • Marked as answer by NorbertG_TJG Friday, May 24, 2013 1:12 AM
    Friday, May 24, 2013 1:00 AM
  • Cheers RiffyRiot, that works as expected.
    Friday, May 24, 2013 1:11 AM
  • My personal preference for no reason at all, would be to use the invoke-command over using wmi. If anyone is able to trap the 3+ types of output stop-process gives, I would still love it to be posted.
    Friday, May 24, 2013 1:14 AM
  • Here you go (with minimal changes - you could make this a little more efficient):

    $killed=$hasprocess=$contacted=$failed=0
    
    $computers='computerwn0001','computerwn001','computerwd0000','computerwd0005'
    $computers | ForEach-Object {
        $getprocess=Invoke-Command -ComputerName $_ -ScriptBlock {Stop-Process -Name 'notepad' -passthru -ErrorAction SilentlyContinue} -ErrorAction SilentlyContinue
        
        if(-not($?)){$failed++}else{$contacted++}
    
        If($getprocess){
            $hasprocess++
            $getprocess | ForEach{$killed++}
            }
    }
    
    Write-Host "Computers Failed: $failed"
    Write-Host "Computers Contacted: $contacted"
    Write-Host "Computers running process: $hasprocess"
    Write-Host "Tasks killed: $killed"


    Inspired by Carlsberg.

    • Marked as answer by NorbertG_TJG Friday, May 24, 2013 1:45 AM
    Friday, May 24, 2013 1:28 AM
  • Thanks, that is what I am looking for :)
    Friday, May 24, 2013 1:45 AM
  • How would I pass the computer name through the if and else statements?

    So I have:

    computerwn0001 failed to connect

    computerwn0002 killed 5 processes

    computerwn0003 no processes to kill

    Computers Failed: 1
    Computers Contacted: 2
    Computers running process: 1
    Tasks killed: 0

    ---

    I will be dealing with over 170 computers and would like to log each computers result.

    Thanks.

    Edit worked it out, I can pass $_ to get the name.


    Friday, May 24, 2013 2:17 AM
  • I'd put the results in an object array

    Reason: easier to analyse.

    $failed=$hasprocess=$false $computers='pcwn0001','pcwd0001','pcwd0000','pcwd0005' $output=@() $computers | ForEach-Object { $getprocess=Invoke-Command -ComputerName $_ -ScriptBlock {Stop-Process -Name 'notepad' -passthru -ErrorAction SilentlyContinue} -ErrorAction SilentlyContinue #if(-not($?)){$failed=$false}else{$failed=$true} $output+=New-Object PSobject -Property @{ 'Computer'=$_ 'Contacted'=$? 'RunningProcess'=[bool]$getprocess 'Killed'=$getprocess.Count } } $output | Select Computer,Contacted,RunningProcess,Killed | Format-Table -AutoSize

    Write-Host "Computers Contacted: "$($output | Where{$_.Contacted}).count""
    Write-Host "Computers Running Process: "$(@($output | Where{$_.RunningProcess})).Count""
    Write-Host "Processes Killed: "$($output | Measure-Object Killed -Sum).Sum""

    Output:

    Computer Contacted RunningProcess Killed
    -------- --------- -------------- ------
    pcwn0001      True           True      1
    pcwd0001      True           True      1
    pcwd0000     False          False      0
    pcwd0005     False          False      0



    Inspired by Carlsberg.





    • Edited by RiffyRiot Friday, May 24, 2013 3:00 AM
    Friday, May 24, 2013 2:38 AM
  • I have a working code, output isn't 'pretty' but it works :)

    <# Scripted by Norbert G
    	
        v1.8 - 20130524 - Script re-write
                          Fixed issue were script always reported 'kill process failed'
                          Re-wrote the main process - http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/d534adac-0278-4cf8-87c8-b9fc479d8b14
        v1.7 - 20130517 - Change to using QuestAD to get computer names
        v1.6 - 20130508 - Changed encoding method for out-files due to issues.
    	v1.5 - 20130415 - Appended -SessionOption (New-PSSessionOption -NoMachineProfile) to invoke-command.
    					  Some PC's are broken. See SDP #6836 for more info.
    					  http://vsweb01:9000/WorkOrder.do?woMode=viewWO&woID=6836&&fromListView=true
        v1.4 - 20130321 - Changed the script to read GetPCNames.ps1 to obtain computer names via domain
                          Removed login creditials, using domain creditials instead
        v1.3 - 20130314 - Made some changes to comments
        v1.2 - 20130214 - Fixed output formating for $TotalConnectCount as output file was returning value on new line
        v1.1 - 20130208 - Removed new line creation from processes killed
                          Change Summary at bottom of log to include Number of computers in front of count    
    	       			  Fixed the count for computers that connect ($SuccessConnectCount + $SuccessKillCount)
        v1.0 - 20130110 - Initial release
    #>
    
    #Load the Quest Active Directory cmdlets
    Add-PSSnapin Quest.ActiveRoles.ADManagement
    
    #Let's get all store computers, store and sort them
    $Computers = get-QADComputer -SearchRoot 'zamserv.com/Stores/Production'  | ForEach-Object {$_.Name} | Sort-Object
    
    ####################
    # Global variables #
    ####################
    $SummaryLog = "summary.log" #SummaryLog file
    $TimeStamp = (Get-Date -format "yyyy/MM/dd hh:mmtt")
    #Array to store logs in $SummaryLog
    $Results = @()
    
    #Time stamp start time of $SummaryLog
    Write-Output "***** $TimeStamp *****" | Out-File -Encoding ASCII -Append $SummaryLog
    
    ################
    # Main process #
    ################
    
    $hasprocess=$contacted=$failed=0
    
    $computers | ForEach-Object {
        $killed = 0
        $getprocess=Invoke-Command -ComputerName $_ -ScriptBlock {
            Stop-Process -force -Name 'wview' -passthru -ErrorAction SilentlyContinue
            } -SessionOption (New-PSSessionOption -NoMachineProfile) -ErrorAction SilentlyContinue
        
        if(-not($?)){
            $failed++
            Write-Host "$_ failed to connect"
            $Results += "$_ failed to connect"
        }else{
            $contacted++
            Write-Host "$_ has connected"
            $Results += "$_ has connected"
            }
        If($getprocess){
            Write-Host "$_ has wview processes to kill"
            $hasprocess++
            $getprocess | ForEach{
                $killed++
                Write-Host "$_ killed wview process(s)"
                $Results += "$_ killed wview process(s)"
                }
        }else{
            Write-Host "$_ no wview process to kill"
            $Results += "$_ no wview process to kill"
            }
    }
    
    #################
    # Count summary #
    #################
    
    #Log the results
    write-host $Results
    write-output $Results | Out-File -Encoding ASCII -Append $SummaryLog
    
    #Formatting
    write-output "`n" | Out-File -Encoding ASCII -Append $SummaryLog
    write-output "Summary: `n" | Out-File -Encoding ASCII -Append $SummaryLog
    
    #Summary report
    Write-Host "Computers Failed: $failed"
    Write-Output "Computers Failed: $failed" | Out-File -Encoding ASCII -Append $SummaryLog
    Write-Host "Computers Contacted: $contacted"
    Write-Output "Computers Contacted: $contacted" | Out-File -Encoding ASCII -Append $SummaryLog
    Write-Host "Computers running process: $hasprocess"
    Write-Output "Computers running process: $hasprocess" | Out-File -Encoding ASCII -Append $SummaryLog
    
    #Put an extra break between this run and the next
    write-output "" | Out-File -Encoding ASCII -Append $SummaryLog

    Thanks everyone for there help :)

    Friday, May 24, 2013 4:08 AM
  • Cheers, looking good but the result's isn't right and isn't returning failed totals:

    Computer     Contacted RunningProcess Killed
    --------     --------- -------------- ------
    store-8899-1      True           True       
    store-5577-2      True          False       
    store-5341-1     False          False       


    Computers Contacted:  2
    Computers Running Process:    <- Should be 1
    Processes Killed:  0                  <- Not really worried about it and only works when total >= 2

    --

    The only changes I made to your was add -force after stop-process and -SessionOption (New-PSSessionOption -NoMachineProfile) after the script block.

    Sorry, I edited the write-host command a little but to fix that. I forgot, the count property returns null when there is 1 unless you force the object being counted to an array.

    Write-Host "Computers Contacted: "$($output | Where{$_.Contacted}).count""

    Write-Host "Computers Failed: "$($output | Where{-not($_.Contacted)}).count""

    Write-Host "Computers Running Process: "$(@($output | Where{$_.RunningProcess})).Count""



    Inspired by Carlsberg.


    • Edited by RiffyRiot Friday, May 24, 2013 4:36 AM rephrase
    Friday, May 24, 2013 4:34 AM
  • if(-not($?)){$failed++}else{$contacted++} works for me.


    Shinish Sasidharan

    Thursday, November 28, 2019 3:33 PM