我应该如何进行 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 使用多个命令或变量使用Try / Catch进行Powershell错误处理