【发布时间】:2017-12-11 18:21:07
【问题描述】:
更新 1: 最初,我发布了这个标题:“脚本忽略 PowerShell 模块中的错误处理”,因为这是当前的问题,但它似乎更像是一个模块问题,所以我重命名了标题。
更新 2:
在发表让我质疑 Azure cmdlet 的评论之后,我使用最基本的脚本(添加到模块)进行了测试,结果是相同的,因为错误没有传递给调用脚本,但是添加了 @987654321 @ to Get-Service 确实返回了一些我可以用来处理错误的东西(WriteErrorException 除外):
function Test-MyError($Variable)
{
Try
{
Get-Service -Name $variable -ErrorAction Stop -ErrorVariable bar
#Get-AzureRmSubscription -SubscriptionName $variable -ErrorAction Stop
}
Catch
{
Write-Error $error[0]
$bar
}
}
返回:
Test-MyError "Foo"
Test-MyError : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
At line:3 char:1
+ Test-MyError "Foo"
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-MyError
The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: Cannot find any service with service name 'foo'.
但是,如果我在 ISE 中运行“Test-MyError”,然后调用该函数,我会得到:
Test-MyError "Foo"
Test-MyError : Cannot find any service with service name 'Foo'.
At line:3 char:1
+ Test-MyError "Foo"
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-MyError
The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: Cannot find any service with service name 'Foo'.
所以我不确定在 ISE 中运行“Test-MyError”并调用它时会发生什么,反对它在 PSM1 文件中被点源化然后调用它?
我现在必须使用-ErrorVariable 并处理它吗?
原问题:
我在一个模块中有两个函数:Get-Subscription 和 Get-AllSubscriptions。每个函数都位于其自己的 PS1 文件中,并且 PSM1 文件对它们进行点源。该模块看起来不错,因为可以使用 intelisense 访问模块脚本并且模块加载没有问题。我在很多模块中都使用过这种结构,之前没有遇到过这个问题。 (虽然我想知道 MS 是否改变了模块在 PS 5.1 中的工作方式,因为我注意到使用 FunctionsToExport='x','y','Z' 和 Export-ModuleMember 的行为似乎与以前不同。)
Get-AllSubscriptions 调用 Get-Subscription。
如果我没有登录到 Azure,Get-Subscription 应该抛出一个错误,并提示我登录。如果我从 Get-Subscription.ps1 调用 Get-Subscription,这将按预期工作。
但是,当我从新的 PS1 文件 Get-AllSubscriptions 或 powershell 控制台调用 Get-Subscription 时,它不起作用。它一直遍历 do..until 循环,而没有像我期望的那样“处理”错误。在每次迭代中,它似乎都会抛出一个通用错误:
Get-Subscription : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
但是,我确实看到了最后一个错误,Get-Subscription : Unable to find requested subscription after 3 login attempts.
如果我在 ISE 中执行 Get-Subscription,然后在新 PS1 文件中或从 Get-AllSubscriptions 中调用 Get-Subscription,它会按预期工作,但是,一旦我重新导入模块 (Import-Module AzureVnetTools -Force -Verbose),它就会运行回到不正确的行为。
如果我在调用者脚本中点源获取订阅,它可以工作,但为什么呢?这就是模块的 PSM1 应该发生的情况。
谁能帮我找出我做错了什么?
(PS 5.1,Windows 7)
获取订阅:
function Get-Subscription
{
[cmdletbinding()]
Param
(
[string]$SubscriptionName,
[string]$UserName,
[string]$code
)
$c=1
Write-Verbose "Checking access to '$SubscriptionName' with user '$UserName'..."
Do
{
Write-Verbose "Attempt $c"
Try
{
$oSubscription = Get-AzureRmSubscription -SubscriptionName $SubscriptionName -ErrorAction Stop -WarningAction SilentlyContinue
Write-Verbose "Subscription found: $($oSubscription.SubscriptionName)."
}
Catch
{
if($error[0].Exception.Message -like "*Please verify that the subscription exists in this tenant*")
{
Write-Verbose "Cannot find subscription '$SubscriptionName' with provided credentials."
$account = Login-AzureRmAccount -Credential (Get-Credential -UserName $Username -Message "Subscription '$SubscriptionName' user' password:")
}
elseif($error[0].Exception.Message -like "*Run Login-AzureRmAccount to login*")
{
Write-Verbose "No logged in session found. Please log in."
$account = Login-AzureRmAccount -Credential (Get-Credential -UserName $Username -Message "Subscription '$SubscriptionName' user' password:")
}
else
{
Write-Error $error[0]
}
}
$c++
}
until(($oSubscription) -or ($c -eq 4))
if($c -eq 4)
{
Write-Error "Unable to find requested subscription after $($c-1) login attempts."
break
}
$oSubscription | Add-Member -MemberType NoteProperty -Name Code -Value $code
$oSubscription
}
获取所有订阅:
function Get-AllSubscriptions
{
[cmdletbinding()]
param
(
[string]$MasterSubscription,
[string]$MasterSubscriptionCode,
[string]$MasterSubscriptionUsername,
[string]$ChildSubscription,
[string]$ChildSubscriptionCode,
[string]$ChildSubscriptionUsername
)
Write-Verbose "Getting all subscriptions..."
$oAllSubscriptions = @()
$oMasterSubscription = Get-Subscription -SubscriptionName $MasterSubscription -UserName $MasterSubscriptionUsername -code $MasterSubscriptionCode -Verbose
$oChildSubscription = Get-Subscription -SubscriptionName $ChildSubscription -UserName $ChildSubscriptionUsername -code $ChildSubscriptionCode -Verbose
$oAllSubscriptions = ($oMasterSubscription,$oChildSubscription)
$oAllSubscriptions
}
测试:
$splat2 = @{
SubscriptionName = "SomeSubscription"
Code = "S02"
Username = "some.user@somewhere.com"
}
#Write-Output "Dot-source:"
#. "D:\Temp\PS.Modules\AzureVnetTools\functions\public\Get-Subscription.ps1"
Get-Subscription @splat2 -verbose
输出:
Get-Subscription @splat2 -verbose
VERBOSE: Checking access to 'SomeSubscription' with user 'some.user@somewhere.com'...
VERBOSE: Attempt 1
Get-Subscription : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
At line:7 char:1
+ Get-Subscription @splat2 -verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Subscription
VERBOSE: Attempt 2
Get-Subscription : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
At line:7 char:1
+ Get-Subscription @splat2 -verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Subscription
VERBOSE: Attempt 3
Get-Subscription : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
At line:7 char:1
+ Get-Subscription @splat2 -verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Subscription
Get-Subscription : Unable to find requested subscription after 3 login attempts.
At line:7 char:1
+ Get-Subscription @splat2 -verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Subscription
AzureVnetTools.psm1
#Get public and private function definition files.
$Public = @( Get-ChildItem -Path $PSScriptRoot\Functions\Public\*.ps1 -ErrorAction SilentlyContinue )
$Private = @( Get-ChildItem -Path $PSScriptRoot\Functions\Private\*.ps1 -ErrorAction SilentlyContinue )
#Dot source the files
Foreach($import in @($Public + $Private))
{
#write-error $import.fullname
Try
{
#Write-Host "Dot-sourcing file: $($import.fullname)."
. $import.fullname
}
Catch
{
Write-Error -Message "Failed to import function $($import.fullname): $_"
}
}
Export-ModuleMember -Function $Public.Basename
AzureVnetTools.psd1(相关部分):
FunctionsToExport = '*'
【问题讨论】:
-
听起来像
Write-Error $Error[0]正在评估由于未处理的异常。更改为Write-Host $Error[0]看看是否会打印一些有用的东西。 -
@woter324 您的帐户是什么类型的? Microsoft 帐户或 Azure AD 帐户?你检查你的订阅名称正确吗?
-
@gms0ulman 谢谢,尝试了你的建议,但没有区别。
-
@walter - MSFT 这是一个 AAD 帐户,但我认为这不是问题所在。订阅正确。
-
@woter324 您的 Azure PowerShell 版本是什么?我在我的实验室测试你的脚本,我没有遇到你的错误。您可以使用
Get-Module -ListAvailable -Name Azure -Refresh检查您的 Azure PowerShell 版本。最新版本是 4.10。
标签: powershell azure-powershell