Windows Vista Forums

Error Handling
  1. #1


    Jacob Guest

    Error Handling

    Hi all,
    I am having some trouble understanding how to use error control in Powershell.

    In VBSCript I use to do something like:
    If Err Then
    Wscript.Echo Err.Description
    Exit Function
    End If

    In Powershell I am trying to do this:
    function Get-RemotePNP ([string]$computer=$(throw "You must specifiy list of
    computers to query computer to query")){

    trap {
    #Some code do write error to a file.
    break;
    }

    #attempt to ping this first.
    $PNPEntity = Get-WmiObject "Win32_PnPEntity" -ComputerName $computer
    -ErrorAction "silentlycontinue"

    #More statements below

    }

    For some reason my script continue to execute even when there is an error
    with the Get-WmiObject. Should the break in the trap statement stop the
    function from proceeding.

    How do I achieve what the vbscript sample achieves?



    --
    **********************
    Jacob


      My System SpecsSystem Spec

  2. #2


    Jeff Guest

    Re: Error Handling

    On Oct 2, 8:25 am, Jacob <jacob(AT)hfws.net.nospam> wrote:

    > Hi all,
    > I am having some trouble understanding how to use error control in Powershell.
    >
    > In VBSCript I use to do something like:
    > If Err Then
    > Wscript.Echo Err.Description
    > Exit Function
    > End If
    >
    > In Powershell I am trying to do this:
    > function Get-RemotePNP ([string]$computer=$(throw "You must specifiy list of
    > computers to query computer to query")){
    >
    > trap {
    > #Some code do write error to a file.
    > break;
    > }
    >
    > #attempt to ping this first.
    > $PNPEntity = Get-WmiObject "Win32_PnPEntity" -ComputerName $computer
    > -ErrorAction "silentlycontinue"
    >
    > #More statements below
    >
    > }
    >
    > For some reason my script continue to execute even when there is an error
    > with the Get-WmiObject. Should the break in the trap statement stop the
    > function from proceeding.
    >
    > How do I achieve what the vbscript sample achieves?
    >
    > --
    > **********************
    > Jacob
    Control is only transferred to the body of a trap statement when a
    terminating error occurs, which isn't what you get from your call to
    Get-WmiObject. There are probably many ways to do what you want to
    do; this is one:

    # your statements...

    if ( $? )
    {
    # all is well
    }
    else
    {
    # an error occurred
    }

    $? is a Boolean value that holds the status of the last operation:
    success or failure. You might also want to look at $LASTEXITCODE; it
    actually contains the exit code of the last command.

    For more information about these and other automatic variables, type
    "Get-Help about_automatic_variables".

    Good luck.

    Jeff


      My System SpecsSystem Spec

  3. #3


    Jacob Guest

    Re: Error Handling

    Hi Jeff,
    Thanks for your reply.

    I'm still struggling with this. I have it sort of working for Get-WmiObject
    but when i run this line:
    $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',
    $computer)

    It just outputs the red text.

    In VBScript I've always had a logging class that I used to make log file of
    errors when i script is running.

    Is there a way to do this in powershell. Intercept the error, Don't display
    it to the console, and write it to a log file.

    Sure there is a powershell equivalent to:
    If Err Then
    LogEntrySub "Something went wrong."
    Exit Function
    End If

    Thanks for your help.


    --
    **********************
    Jacob



    "Jeff" wrote:

    > On Oct 2, 8:25 am, Jacob <jacob(AT)hfws.net.nospam> wrote:

    > > Hi all,
    > > I am having some trouble understanding how to use error control in Powershell.
    > >
    > > In VBSCript I use to do something like:
    > > If Err Then
    > > Wscript.Echo Err.Description
    > > Exit Function
    > > End If
    > >
    > > In Powershell I am trying to do this:
    > > function Get-RemotePNP ([string]$computer=$(throw "You must specifiy list of
    > > computers to query computer to query")){
    > >
    > > trap {
    > > #Some code do write error to a file.
    > > break;
    > > }
    > >
    > > #attempt to ping this first.
    > > $PNPEntity = Get-WmiObject "Win32_PnPEntity" -ComputerName $computer
    > > -ErrorAction "silentlycontinue"
    > >
    > > #More statements below
    > >
    > > }
    > >
    > > For some reason my script continue to execute even when there is an error
    > > with the Get-WmiObject. Should the break in the trap statement stop the
    > > function from proceeding.
    > >
    > > How do I achieve what the vbscript sample achieves?
    > >
    > > --
    > > **********************
    > > Jacob
    >
    > Control is only transferred to the body of a trap statement when a
    > terminating error occurs, which isn't what you get from your call to
    > Get-WmiObject. There are probably many ways to do what you want to
    > do; this is one:
    >
    > # your statements...
    >
    > if ( $? )
    > {
    > # all is well
    > }
    > else
    > {
    > # an error occurred
    > }
    >
    > $? is a Boolean value that holds the status of the last operation:
    > success or failure. You might also want to look at $LASTEXITCODE; it
    > actually contains the exit code of the last command.
    >
    > For more information about these and other automatic variables, type
    > "Get-Help about_automatic_variables".
    >
    > Good luck.
    >
    > Jeff
    >
    >

      My System SpecsSystem Spec

  4. #4


    Brandon Shell Guest

    Re: Error Handling

    In your trap try this

    Trap { Write-Ouput $_ | out-file Error.log -app -enc ascii ; continue}

    "Jacob" <jacob(AT)hfws.net.nospam> wrote in message
    news:4BFB3036-91EB-4EEE-9707-0D47A7A74715@xxxxxx

    > Hi Jeff,
    > Thanks for your reply.
    >
    > I'm still struggling with this. I have it sort of working for
    > Get-WmiObject
    > but when i run this line:
    > $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',
    > $computer)
    >
    > It just outputs the red text.
    >
    > In VBScript I've always had a logging class that I used to make log file
    > of
    > errors when i script is running.
    >
    > Is there a way to do this in powershell. Intercept the error, Don't
    > display
    > it to the console, and write it to a log file.
    >
    > Sure there is a powershell equivalent to:
    > If Err Then
    > LogEntrySub "Something went wrong."
    > Exit Function
    > End If
    >
    > Thanks for your help.
    >
    >
    > --
    > **********************
    > Jacob
    >
    >
    >
    > "Jeff" wrote:
    >

    >> On Oct 2, 8:25 am, Jacob <jacob(AT)hfws.net.nospam> wrote:

    >> > Hi all,
    >> > I am having some trouble understanding how to use error control in
    >> > Powershell.
    >> >
    >> > In VBSCript I use to do something like:
    >> > If Err Then
    >> > Wscript.Echo Err.Description
    >> > Exit Function
    >> > End If
    >> >
    >> > In Powershell I am trying to do this:
    >> > function Get-RemotePNP ([string]$computer=$(throw "You must specifiy
    >> > list of
    >> > computers to query computer to query")){
    >> >
    >> > trap {
    >> > #Some code do write error to a file.
    >> > break;
    >> > }
    >> >
    >> > #attempt to ping this first.
    >> > $PNPEntity = Get-WmiObject "Win32_PnPEntity" -ComputerName
    >> > $computer
    >> > -ErrorAction "silentlycontinue"
    >> >
    >> > #More statements below
    >> >
    >> > }
    >> >
    >> > For some reason my script continue to execute even when there is an
    >> > error
    >> > with the Get-WmiObject. Should the break in the trap statement stop the
    >> > function from proceeding.
    >> >
    >> > How do I achieve what the vbscript sample achieves?
    >> >
    >> > --
    >> > **********************
    >> > Jacob
    >>
    >> Control is only transferred to the body of a trap statement when a
    >> terminating error occurs, which isn't what you get from your call to
    >> Get-WmiObject. There are probably many ways to do what you want to
    >> do; this is one:
    >>
    >> # your statements...
    >>
    >> if ( $? )
    >> {
    >> # all is well
    >> }
    >> else
    >> {
    >> # an error occurred
    >> }
    >>
    >> $? is a Boolean value that holds the status of the last operation:
    >> success or failure. You might also want to look at $LASTEXITCODE; it
    >> actually contains the exit code of the last command.
    >>
    >> For more information about these and other automatic variables, type
    >> "Get-Help about_automatic_variables".
    >>
    >> Good luck.
    >>
    >> Jeff
    >>
    >>

      My System SpecsSystem Spec

  5. #5


    Jeff Guest

    Re: Error Handling

    On Oct 2, 9:46 am, Jacob <jacob(AT)hfws.net.nospam> wrote:

    > Hi Jeff,
    > Thanks for your reply.
    >
    > I'm still struggling with this. I have it sort of working for Get-WmiObject
    > but when i run this line:
    > $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',
    > $computer)
    >
    > It just outputs the red text.
    >
    > In VBScript I've always had a logging class that I used to make log file of
    > errors when i script is running.
    >
    > Is there a way to do this in powershell. Intercept the error, Don't display
    > it to the console, and write it to a log file.
    >
    > Sure there is a powershell equivalent to:
    > If Err Then
    > LogEntrySub "Something went wrong."
    > Exit Function
    > End If
    >
    > Thanks for your help.
    I don't think I'm familiar enough with VBScript to give you a
    PowerShell example that is exactly equivalent to your VBScript
    example. If you don't want to see the red error messages in the
    console while your script is running, but you want the errors written
    to a file, you can use redirection:

    PS$ .\SomeScriptWithErrors.ps1 "argument1" "argument2" 2> "errors.log"

    Normal output from your script will still go to the console, but the
    '>2' operator redirects errors to "errors.log". For other
    combinations of regular results and errors, see the "Redirection
    Operators" section in "about_operators".

    Jeff


      My System SpecsSystem Spec

  6. #6


    Jeff Guest

    Re: Error Handling

    On Oct 2, 9:46 am, Jacob <jacob(AT)hfws.net.nospam> wrote:

    > Hi Jeff,
    > Thanks for your reply.
    >
    > I'm still struggling with this. I have it sort of working for Get-WmiObject
    > but when i run this line:
    > $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',
    > $computer)
    >
    > It just outputs the red text.
    >
    > In VBScript I've always had a logging class that I used to make log file of
    > errors when i script is running.
    >
    > Is there a way to do this in powershell. Intercept the error, Don't display
    > it to the console, and write it to a log file.
    >
    > Sure there is a powershell equivalent to:
    > If Err Then
    > LogEntrySub "Something went wrong."
    > Exit Function
    > End If
    >
    > Thanks for your help.
    >
    One more thing that might get you closer to what you want with your
    last example:

    & {
    $ErrorActionPreference = "SilentlyContinue"

    trap
    {
    "Error!"
    # log your error, exit, or whatever
    }

    $hive = "LocalMachine"
    $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hive, `
    $computer)
    }

    OpenRemoteBaseKey does throw an exception, so you can use a trap
    statement here. I am setting the $ErrorActionPreference variable in a
    scriptblock so its old value will be restored outside of the
    scriptblock's scope.

    Good luck.

    Jeff


      My System SpecsSystem Spec

  7. #7


    Jacob Guest

    Re: Error Handling

    My Script is below. It seems to work but I don't get an xml file at the end???


    #
    //***************************************************************************
    # // ***** Script Header *****
    # //
    # // File: Get-PNPInfo.ps1
    # //
    # // Purpose: Given a list of Computers will query for PNP Device IDS
    # //
    # // Usage: powershell .\Get-PNPInfo.ps1 [collection of computers]
    # //
    # // Notes:
    #
    //***************************************************************************
    Param
    (
    [array]$computers =$(throw "You must specify an array of computers")
    )
    $ErrorActionPreference="SilentlyContinue"

    for ($i=0;$i -le $computers.length; $i++) {
    [int]$progress = ($i * 100) / $computers.Length
    Write-Progress -activity "Querying Remote PNP Information" -Status
    "Currently Querying $($computers[$i])" -perc $progress

    #Attempt to ping the machine
    Write-Progress -activity "Details for $($computers[$i])" -id 1 -status
    "Trying to ping workstation." -perc 16
    $response = Get-WmiObject -query "Select * From Win32_PingStatus Where
    Address='$($computers[$i])'"

    if( ($response -eq $null) -or ($response.StatusCode -ne 0)) {
    Write-Progress -activity "Details for $($computers[$i])" -id 1 -status
    "Could not ping workstation" -perc 100
    } else {
    Write-Progress -activity "Details for $($computers[$i])" -id 1 -status
    "Getting remote WMI and Registry" -perc 32
    $PNPEntity = Get-WmiObject "Win32_PnPEntity" -ComputerName $computers[$i]
    $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',
    $computer)

    #if $reg or wmi action action failed then don't continue.
    if ($?)
    {
    #Create the XML File
    $XMLFile = [xml]'<?xml version="1.0"
    encoding="utf-8"?><SystemAudit><Devices></Devices></SystemAudit>'
    $XMLDevices = $XMLFile.PSBase.SelectSingleNode("//Devices")

    foreach ( $device in $PNPEntity) {
    $deviceID = $device.PNPDeviceID
    Write-Progress -activity "Details for $($computers[$i])" -id 1
    -status "Found Key: $deviceID" -perc 48
    #create a new entry in the xml file.
    $XMLDevice = $XMLFile.CreateElement("Device")
    $id = $XMLFile.CreateAttribute("Id")
    $id.psbase.Value = $deviceID
    $return = $XMLDevice.SetAttributeNode($id)

    Write-Progress -activity "Details for $($computers[$i])" -id 1
    -status "Getting hardware IDs" -perc 64
    #Get HardwareIds and Compatible IDS
    #trap{continue}
    $devEnum = $reg.OpenSubKey("SYSTEM\CurrentControlSet\Enum\$deviceID")
    $hwids = $devEnum.GetValue("HardwareID")
    $compatIDs = $devEnum.GetValue("CompatibleIDs")

    #List HardwareIDs
    if ( -not ($hwids -eq $null) ) {
    foreach ($hwid in $hwids) {
    $XMLHwid = $XMLFile.CreateElement("HwId")
    $attribute = $XMLFile.CreateAttribute("Id")
    $attribute.psbase.Value = $hwid
    $return = $XMLHwid.SetAttributeNode($attribute)
    $return = $XMLDevice.AppendChild($XMLHwid)
    }
    }

    Write-Progress -activity "Details for $($computers[$i])" -id 1
    -status "Getting Driver Information" -perc 80
    #Get Driver Information
    $driver =
    $reg.OpenSubKey("SYSTEM\CurrentControlSet\Control\Class\$($devEnum.GetValue('Driver'))")

    #XML Element and Attributes for Driver Information
    $installedDriver = $XMLFile.CreateElement("InstalledDriver")

    $MatchingDeviceId = $XMLFile.CreateAttribute("MatchingDeviceId")
    $MatchingDeviceId.psbase.Value = $driver.GetValue("MatchingDeviceId")
    $return = $installedDriver.SetAttributeNode($MatchingDeviceId)

    $DriverDesc = $XMLFile.CreateAttribute("DriverDesc")
    $DriverDesc.psbase.Value = $driver.GetValue("DriverDesc")
    $return = $installedDriver.SetAttributeNode($DriverDesc)

    $DriverVerDate = $XMLFile.CreateAttribute("DriverVerDate")
    $DriverVerDate.psbase.Value = $driver.GetValue("DriverDate")
    $return = $installedDriver.SetAttributeNode($DriverVerDate)

    $DriverVerVersion =$XMLFile.CreateAttribute("DriverVerVersion")
    $DriverVerVersion.psbase.Value = $driver.GetValue("DriverVersion")
    $return = $installedDriver.SetAttributeNode($DriverVerVersion)

    $Class = $XMLFile.CreateAttribute("Class")
    $Class.psbase.Value = $devEnum.GetValue("Class")
    $return = $installedDriver.SetAttributeNode($Class)

    $Manufacturer = $XMLFile.CreateAttribute("Manufacturer")
    $Manufacturer.psbase.Value = $devEnum.GetValue("Mfg")
    $return = $installedDriver.SetAttributeNode($Manufacturer)

    $Provider = $XMLFile.CreateAttribute("Provider")
    $Provider.psbase.Value = $driver.GetValue("ProviderName")
    $return = $installedDriver.SetAttributeNode($Provider)

    $Model = $XMLFile.CreateAttribute("Model")
    $Model.psbase.Value = $driver.GetValue("DriverDesc")
    $return = $installedDriver.SetAttributeNode($Model)

    #Add the installedDrivers to the Device Node
    $return = $XMLDevice.AppendChild($installedDriver)

    #add this device to the XML File
    $return = $XMLDevices.AppendChild($XMLDevice)
    }
    Write-Progress -activity "Details for $($computers[$i])" -id 1 -status
    "Writing XML File" -perc 100
    $XMLFile.Save("output.xml")
    }
    }
    }




    --
    **********************
    Jacob



    "Jeff" wrote:

    > On Oct 2, 9:46 am, Jacob <jacob(AT)hfws.net.nospam> wrote:

    > > Hi Jeff,
    > > Thanks for your reply.
    > >
    > > I'm still struggling with this. I have it sort of working for Get-WmiObject
    > > but when i run this line:
    > > $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',
    > > $computer)
    > >
    > > It just outputs the red text.
    > >
    > > In VBScript I've always had a logging class that I used to make log file of
    > > errors when i script is running.
    > >
    > > Is there a way to do this in powershell. Intercept the error, Don't display
    > > it to the console, and write it to a log file.
    > >
    > > Sure there is a powershell equivalent to:
    > > If Err Then
    > > LogEntrySub "Something went wrong."
    > > Exit Function
    > > End If
    > >
    > > Thanks for your help.
    > >
    >
    > One more thing that might get you closer to what you want with your
    > last example:
    >
    > & {
    > $ErrorActionPreference = "SilentlyContinue"
    >
    > trap
    > {
    > "Error!"
    > # log your error, exit, or whatever
    > }
    >
    > $hive = "LocalMachine"
    > $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hive, `
    > $computer)
    > }
    >
    > OpenRemoteBaseKey does throw an exception, so you can use a trap
    > statement here. I am setting the $ErrorActionPreference variable in a
    > scriptblock so its old value will be restored outside of the
    > scriptblock's scope.
    >
    > Good luck.
    >
    > Jeff
    >
    >

      My System SpecsSystem Spec

  8. #8


    Jeff Guest

    Re: Error Handling

    On Oct 2, 12:24 pm, Jacob <jacob(AT)hfws.net.nospam> wrote:

    > My Script is below. It seems to work but I don't get an xml file at the end???
    Try this, if you want output.xml to end up in your current directory:

    $XMLFile.Save("$(Get-Location)\output.xml")

    Your file is likely ending up in your $home directory. Type "Set-
    Location $HOME", and you will probably find your XML file.

    Jeff


      My System SpecsSystem Spec

  9. #9


    Keith Hill [MVP] Guest

    Re: Error Handling

    "Jacob" <jacob(AT)hfws.net.nospam> wrote in message
    news9E432AF-B7C5-4D01-AA99-0F71CFAE3E82@xxxxxx

    > Hi all,
    > I am having some trouble understanding how to use error control in
    > Powershell.
    >
    > In VBSCript I use to do something like:
    > If Err Then
    > Wscript.Echo Err.Description
    > Exit Function
    > End If
    >
    > In Powershell I am trying to do this:
    > function Get-RemotePNP ([string]$computer=$(throw "You must specifiy list
    > of
    > computers to query computer to query")){
    >
    > trap {
    > #Some code do write error to a file.
    > break;
    > }
    >
    > #attempt to ping this first.
    > $PNPEntity = Get-WmiObject "Win32_PnPEntity" -ComputerName $computer
    > -ErrorAction "silentlycontinue"
    >
    > #More statements below
    >
    > }
    >
    > For some reason my script continue to execute even when there is an error
    > with the Get-WmiObject. Should the break in the trap statement stop the
    > function from proceeding.
    That is because Get-WmiObject errors are normally "non-terminating".
    PowerShell has the concept of terminating errors (usually program logic
    errors like deferencing $null in a .NET method call or integer divide by
    zero or you use the throw statemement) and non-terminating errors
    Get-WmiObject failed to complete for some reason. The trap statement only
    traps terminating errors to get Get-WmiObject to throw a terminating error
    do either:

    Get-WmiObject -errorAction Stop ...

    or

    Get-WmiObject -errorAction SilentlyContinue ...
    if (!$?) {
    # If previous command failed, throw the last error
    throw $error[0]
    }

    Of course the second version is essentially doing the same thing as the
    first but I point it out in case you wanted to throw a different type of
    error or perhaps your own error message e.g.:

    if (!$?) { throw "Errored finding WMI Object" }

    --
    Keith



      My System SpecsSystem Spec

Error Handling problems?

Similar Threads
Thread Thread Starter Forum Replies Last Post
Graceful error handling... Jake VB Script 1 21 Oct 2009
Re: error handling Pegasus [MVP] VB Script 9 22 Aug 2009
WMI Error Handling Pete Zerger (MVP) PowerShell 3 09 Aug 2009
error handling MaxMad PowerShell 3 18 Dec 2007
Crash Course in Error Handling? greatbarrier86 PowerShell 1 12 Nov 2007