Dastechguy
Dastechguy

Reputation: 3

Error handling in the pipeline

This function gets a list of installed software on a remote PC. What is special about this function is the conversion of the date from yyyyMMdd to MM/dd/yyyy. While the function works, it is dropping objects that have no InstallDate. I get this error:

Exception calling "ParseExact" with "3" argument(s).

function Get-Software {
    param ( [string[]]$ComputerName )

    [scriptblock]$code = {
        $keys = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
                'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'

        Get-ItemProperty -Path $keys |
            Where-Object { $_.DisplayName -ne $null } |
            Where-Object { $_.DisplayName -notlike '*update*' } |
            sort DisplayName |
            ForEach-Object {
                [PSCustomObject]@{
                    Display   = $_.DisplayName;
                    Installed = Get-Date ([DateTime]::ParseExact($_.InstallDate, 'yyyyMMdd', $null)) -format d
                }
            }
    }
    Invoke-Command -ScriptBlock $code -ComputerName $ComputerName -ArgumentList * |
        ft Display, Installed -AutoSize |
        Out-File "$Env:USERPROFILE\Desktop\SWinv.txt"
}

Get-Software RemotePC

What can I do to return all objects?

Upvotes: 0

Views: 418

Answers (3)

Esperento57
Esperento57

Reputation: 17472

Because install date can be null, try this

     function Get-Software {
         param ( [string[]]$ComputerName )

         [scriptblock]$code = {
             $keys = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
                     'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'

             Get-ItemProperty -Path $keys |
                 Where-Object { $_.DisplayName -ne $null -and $_.DisplayName -notlike '*update*' } |
                 sort DisplayName |
                 ForEach-Object {
                     [PSCustomObject]@{
                         Display   = $_.DisplayName;
                         Installed =if ($_.InstallDate -ne $null) { Get-Date ([DateTime]::ParseExact($_.InstallDate, 'yyyyMMdd', $null)) -format d} else {$null}
                     }
                 }
         }
         Invoke-Command -ScriptBlock $code -ComputerName $ComputerName -ArgumentList * |
             ft Display, Installed -AutoSize |
             Out-File "$Env:USERPROFILE\Desktop\SWinv.txt"
     }

     Get-Software RemotePC

Upvotes: 1

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200393

Do the date parsing in a try..catch, assign the result to a variable, and use that variable when creating the object:

... | ForEach-Object {
    $date = try {
      [DateTime]::ParseExact($_.InstallDate, 'yyyyMMdd', $null).ToString('d')
    } catch {
      ''  # default value to assign if date is invalid
    }
    [PSCustomObject]@{
        Display   = $_.DisplayName;
        Installed = $date
    }
}

Upvotes: 1

BenH
BenH

Reputation: 10044

You could put a simple if/else check.

Assuming that $_.InstallDate is null when you get the error:

ForEach-Object { 
    if ($null -ne $_.InstallDate) {
        [PSCustomObject]@{Display = $_.DisplayName; Installed = Get-Date ([datetime]::ParseExact($_.InstallDate,'yyyyMMdd',$null)) -format d}
    } else {
        [PSCustomObject]@{Display = $_.DisplayName; Installed = "Not Available"}
    }
}

Upvotes: 1

Related Questions