我应该如何进行 Powershell 错误处理?

Posted

技术标签:

【中文标题】我应该如何进行 Powershell 错误处理?【英文标题】:How should I do Powershell error handling? 【发布时间】:2021-10-11 08:58:46 【问题描述】:

我有以下代码:

function main 
    #get all content
    [XML]$xml = Get-Content $XMLfile

    $finalObject = $xml.bom.components.component | ForEach-Object 
        $lic = $_.licenses.license.id
        $url = $_.licenses.license.url
        $web = ($_.externalReferences.reference | Where-Object  $_.type -eq 'website' ).url
        [PSCustomObject]@
            'Name'    = if ($web)  '[0](1)' -f $_.Name, $web  elseif ($url)  '[0](1)' -f $_.Name, $url  elseif (!$url)  $_.Name  else 'Unknown'
            'Version' = $_.version
            'License' = if ([string]::IsNullOrWhiteSpace($lic))  'Unknown'  else  $lic 
        
    
    # convert to markdown
    $finalObject | ConvertTo-MarkDownTable  | Out-File -FilePath $saveMdFile


现在我想用 powershell 进行错误处理。例如,如果 XML 不存在或无法保存,我希望有错误日志。然后应将日志单独保存在文件中。我将它们定义如下:

function main 
    #get all content
    [XML]$xml = Get-Content $XMLfile

    Write-Log -Message "No file was found: $($xmlfile)" -Level Info -Path $logpath

    $finalObject = $xml.bom.components.component | ForEach-Object 
        $lic = $_.licenses.license.id
        $url = $_.licenses.license.url
        $web = ($_.externalReferences.reference | Where-Object  $_.type -eq 'website' ).url
        [PSCustomObject]@
            'Name'    = if ($web)  '[0](1)' -f $_.Name, $web  elseif ($url)  '[0](1)' -f $_.Name, $url  elseif (!$url)  $_.Name  else 'Unknown'
            'Version' = $_.version
            'License' = if ([string]::IsNullOrWhiteSpace($lic))  'Unknown'  else  $lic 
        
    
    # convert to markdown
    $finalObject | ConvertTo-MarkDownTable  | Out-File -FilePath $saveMdFile

    Write-Log -Message "No path was found: $($xmlfile)" -Level Info -Path $logpath

到目前为止,我的日志不起作用,并且在发生错误时也不会保存文件。有谁知道我该如何解决这个问题?

【问题讨论】:

可能是try catch? 你没有解释变量 $XMLfile$saveMdFile 来自哪里,也没有解释你的 Write-Log 函数来自哪里。如果您的意思是在Get-Content $XMLfile 因为找不到文件而失败时捕获错误,请先使用Test-Path。 $logpath 来自哪里? 我们还没有收到您的来信.. 我的回答解决了您的问题吗?如果是这样,请通过单击左侧的 图标来考虑accepting。这将帮助其他有类似问题的人更轻松地找到它,并有助于激励其他人回答您将来可能遇到的任何问题。 【参考方案1】:

假设您使用here 中的Write-Log 函数和您之前的问题here 和there 中的ConvertTo-MarkDownTable,您需要做的就是确保变量$XMLfile$saveMdFile$logpath 在您的 main 函数中是已知且有效的。

一种方法是使用Test-Path,我个人会将这些变量设置为带有默认路径的可选参数,这样您就可以接受这些默认值或使用不同的路径调用函数。

类似这样的:

function main 
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false, Position = 0)]
        [string]$xmlFile = 'C:\Users\kraer\Desktop\bom.xml',

        [Parameter(Mandatory = $false, Position = 1)]
        [string]$logpath = 'C:\Users\kraer\Desktop\siteinfo.log',

        [Parameter(Mandatory = $false, Position = 2)]
        [string]$saveMdFile = 'C:\Users\kraer\Desktop\siteinfo.md'
    )

    # try and write to the log
    try 
        Write-Log -Message "Logging started: '$((Get-Date).ToString())'" -Level Info -Path $logpath -ErrorAction Stop
    
    catch 
        Write-Warning "Error from 'Write-Log': $($_.Exception.Message)"
        return   # exit the function
    

    # check if the XML file can be found
    if (!(Test-Path -Path $xmlFile -PathType Leaf)) 
        Write-Warning "Xml file '$xmlFile' not found"
        Write-Log -Message "No file was found: '$xmlfile'" -Level Error -Path $logpath
        return   # exit the function
    

    # get all content. better use this, so you will get the encoding right
    $xml = [System.XML.XMLDocument]::new()
    $xml.Load($xmlFile)
    # assuming this does what you want
    $finalObject = $xml.bom.components.component | ForEach-Object 
        $lic = $_.licenses.license.id
        $url = $_.licenses.license.url
        $web = ($_.externalReferences.reference | Where-Object  $_.type -eq 'website' ).url
        [PSCustomObject]@
            'Name'    = if ($web)  '[0](1)' -f $_.Name, $web  elseif ($url)  '[0](1)' -f $_.Name, $url  elseif (!$url)  $_.Name  else 'Unknown'
            'Version' = $_.version
            'License' = if ([string]::IsNullOrWhiteSpace($lic))  'Unknown'  else  $lic 
        
    
    # convert to markdown
    try 
        $finalObject | ConvertTo-MarkDownTable | Set-Content -Path $saveMdFile -ErrorAction Stop
    
    catch 
        Write-Warning "Could not write to file '$saveMdFile'"
        Write-Log -Message "Could not write to file '$saveMdFile'" -Level Error -Path $logpath
    

【讨论】:

以上是关于我应该如何进行 Powershell 错误处理?的主要内容,如果未能解决你的问题,请参考以下文章

powershell 使用Try / Catch进行Powershell错误处理

Powershell 如何获取异常的名称

powershell 使用多个命令或变量使用Try / Catch进行Powershell错误处理

如何在 PowerShell 中输出内容

如何仅将 SQLPlus 错误保存到文件(从 powershell 调用)

Powershell脚本似乎不应该花费很长时间?