【问题标题】:Invoke PowerShell from cmd, context gets lost when that PowerShell calls into another module从 cmd 调用 PowerShell,当 PowerShell 调用另一个模块时,上下文会丢失
【发布时间】:2018-01-26 05:13:35
【问题描述】:

我有一个 PowerShell 脚本,它调用 ServiceFabricSDK PowerShell 模块来触发 Azure Service Fabric 应用程序部署。当我直接调用该 PowerShell 时,一切正常,但如果我使用 powershell 命令从 cmd 文件调用它,事情就会变得一团糟,看起来我的 PowerShell 脚本和它调用的模块之间的某些上下文丢失了。

这就是我的意思:

我的 PowerShell 脚本采用应用程序名称和几个参数,导入 ServiceFabricSDK.psm1,运行 Connect-ServiceFabricCluster 以连接到本地 Service Fabric 集群,并最终调用 Publish-NewServiceFabricApplication 开始部署:

param (
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]
    $applicationName,

    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]
    $repoTargetPath,

    [Switch]
    $retail,

    [Parameter()]
    [ValidateNotNullOrEmpty()]
    $targetEnvironment = "dev.local"
)

# Load ServiceFabricSDK first
Write-Output "Loading Service Fabric SDK module"
Import-Module "$ENV:ProgramFiles\Microsoft SDKs\Service Fabric\Tools\PSModule\ServiceFabricSDK\ServiceFabricSDK.psm1"

# Connect to the local cluster
Write-Output "Connecting to local Service Fabric cluster"
Connect-ServiceFabricCluster | Out-Null
Write-Output "Successfully connected to local Service Fabric cluster"

$repoTargetPath = $repoTargetPath.TrimEnd('\')
$target = if($retail.IsPresent) { "retail" } Else { "debug" }
$applicationTargetBasePath = "$repoTargetPath\distrib\$target\applications\$applicationName"
$applicationPackagePath = "$applicationTargetBasePath\package\"
$applicationParametersFilePath = "$applicationTargetBasePath\applicationParameters\$applicationName.$targetEnvironment.xml"

Write-Output "Deploying application $applicationName to local Service Fabric cluster"

# Deploy the application
Publish-NewServiceFabricApplication -ApplicationPackagePath $applicationPackagePath -ApplicationParameterFilePath $applicationParametersFilePath -ApplicationName "fabric:/$applicationName" -OverwriteBehavior Always -Verbose -SkipPackageValidation

如果我直接运行它一切正常:

PS G:\repo> .\build\scripts\Deploy-Application.ps1 -applicationName HelloWorld -targetEnvironment "dev.local" -repoTargetPath G:\repo\target\
Loading Service Fabric SDK module
Connecting to local Service Fabric cluster
WARNING: Cluster connection with the same name already existed, the old connection will be deleted
Successfully connected to local Service Fabric cluster
Validating the package and application parameters
Deploying application HelloWorld to local Service Fabric cluster
An application with name 'fabric:/HelloWorld' already exists in the cluster with Application Type 'HelloWorldType' and Version '1.0.20170816-seed-1    207928760'. Removing it.
Remove application instance succeeded
Unregister application type succeeded.
Copying application to image store...
Copy application package succeeded
Registering application type...
Register application type succeeded
Removing application package from image store...
Remove application package succeeded
Creating application...

ApplicationName        : fabric:/HelloWorld
ApplicationTypeName    : HelloWorldType
ApplicationTypeVersion : 1.0.20170816-seed-1207928760
ApplicationParameters  : { "HelloWorldServiceType_InstanceCount" = "2" }

Create application succeeded.

我还有 appStart.cmd 文件,它调用了那个 PowerShell:

@if "%_echo%"=="" echo off

pushd
cd %BaseDir%

if "%1" == "" goto error

echo powershell %ScriptsPath%\Deploy-Application.ps1 -applicationName "%1" -repoTargetPath "%BaseDir%\\target\\" -targetEnvironment "dev.local"
call powershell %ScriptsPath%\\Deploy-Application.ps1 -applicationName "%1" -repoTargetPath "%BaseDir%\\target\\" -targetEnvironment "dev.local"

GOTO :EOF

无非就是调用那个 PowerShell,但不幸的是部署失败,因为模块看不到集群连接:

G:\repo>appStart HelloWorld
powershell G:\repo\build\scripts\Deploy-Application.ps1 -applicationName "HelloWorld" -repoTargetPath "G:\repo\\target\\" -targetEnvironment "dev.local"
Loading Service Fabric SDK module
Connecting to local Service Fabric cluster
Successfully connected to local Service Fabric cluster
Validating the package and application parameters
Deploying application HelloWorld to local Service Fabric cluster
VERBOSE: System.NullReferenceException: Cluster connection instance is null
WARNING: Unable to Verify connection to Service Fabric cluster.
Get-ServiceFabricClusterConnection : Cluster connection instance is null
At C:\Program Files\Microsoft SDKs\Service
Fabric\Tools\PSModule\ServiceFabricSDK\Publish-NewServiceFabricApplication.ps1:144 char:1
+ Get-ServiceFabricClusterConnection
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [Get-ServiceFabricClusterConnection], NullReferenceException
    + FullyQualifiedErrorId : GetClusterConnectionErrorId,Microsoft.ServiceFabric.Powershell.GetClusterConnection

我玩过它,Connect-ServiceFabricCluster 的结果可以通过Get-ServiceFabricClusterConnection 来检查,这就是Publish-NewServiceFabricApplication.ps1 正在做的事情。我可以在调用Publish-NewServiceFabricApplication.ps1 之前在我的PowerShell 中运行它,它会返回正确的连接数据,即使从appStart.cmd 运行也是如此。 为什么在脚本中调用时会丢失连接?

【问题讨论】:

  • 根据您运行的 PowerShell 版本,添加-MTA or -STA 参数时会发生什么情况:call powershell -MTA %ScriptsPath%\\Deploy-Application.ps1 -applicationName "%1" -repoTargetPath "%BaseDir%\\target\\" -targetEnvironment "dev.local"
  • @iRon 没有区别。
  • 尝试模式:powershell -Command { %ScriptsPath%\\Deploy-Application.ps1 -applicationName \"%1\" -repoTargetPath \"%BaseDir%\\target\\\" -targetEnvironment \"dev.local\" }
  • @MaxBurlik 没用,现在我没有将 PowerShell 脚本的输出通过管道返回到常规命令行,所以我看不到错误消息是什么。
  • 当您导入 ServiceFabricSDK.psm1 模块时,您是否有任何其他配置要说连接到服务结构集群?如果它通常是您个人资料的一部分,并且您使用从未连接过的新帐户运行它,那么这可能是您的问题。

标签: powershell azure-service-fabric


【解决方案1】:

您可以尝试将集群连接放入Connect-ServiceFabricCluster之后的全局变量中:

$global:clusterConnection = $clusterConnection  

更多信息在这里How do I deploy service fabric application from VSTS release pipeline?

【讨论】:

    猜你喜欢
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多