从c#应用程序调用azure powershell cmdlet失败

我正在自动化部署到azure云的过程。 我的powershell脚本就是这样做的,当从azure powershell命令行执行它时,它就像一个魅力。 当我尝试从c#应用程序调用相同的脚本时,它失败了。

这是我的代码:

internal void RunPowerShellScript(string scriptPath, Dictionary arguments) { RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create(); Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration); runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace); Pipeline pipeline = runspace.CreatePipeline(); //Here's how you add a new script with arguments Command myCommand = new Command(scriptPath, true); foreach (var argument in arguments) { myCommand.Parameters.Add(new CommandParameter(argument.Key, argument.Value)); } pipeline.Commands.Add(myCommand); var results = pipeline.Invoke(); foreach (var psObject in results) { _view.PrintOutput(psObject.ToString()); } } 

我也跟着其他线程,就像这样: 使用命令行参数从C#执行PowerShell脚本 ,这个: 从c#传递参数到powershell

但似乎没有任何效果。 我收到以下错误:

无法validation参数’PublishSettingsFile’的参数。 参数为null或空。 提供非null或空的参数,然后再次尝试该命令。

剧本:

 Param( $serviceName = "", $storageAccountName = "", $packageLocation = "", $cloudConfigLocation = "", $environment = "", $deploymentLabel = "", $timeStampFormat = "g", $alwaysDeleteExistingDeployments = 1, $enableDeploymentUpgrade = 1, $selectedsubscription = "default", $subscriptionDataFile = "" ) function Publish() { #Set-ExecutionPolicy RemoteSigned Set-AzureSubscription -SubscriptionName "Windows Azure MSDN – Visual Studio Professional" -CurrentStorageAccount $storageAccountName $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot -ErrorVariable a -ErrorAction silentlycontinue if ($a[0] -ne $null) { Write-Output "$(Get-Date –f $timeStampFormat) - No deployment is detected. Creating a new deployment. " } #check for existing deployment and then either upgrade, delete + deploy, or cancel according to $alwaysDeleteExistingDeployments and $enableDeploymentUpgrade boolean variables if ($deployment.Name -ne $null) { switch ($alwaysDeleteExistingDeployments) { 1 { switch ($enableDeploymentUpgrade) { 1 #Update deployment inplace (usually faster, cheaper, won't destroy VIP) { Write-Output "$(Get-Date –f $timeStampFormat) - Deployment exists in $servicename. Upgrading deployment." UpgradeDeployment } 0 #Delete then create new deployment { Write-Output "$(Get-Date –f $timeStampFormat) - Deployment exists in $servicename. Deleting deployment." DeleteDeployment CreateNewDeployment } } # switch ($enableDeploymentUpgrade) } 0 { Write-Output "$(Get-Date –f $timeStampFormat) - ERROR: Deployment exists in $servicename. Script execution cancelled." exit } } #switch ($alwaysDeleteExistingDeployments) } else { CreateNewDeployment } SwapVip } function DeleteDeployment() { write-progress -id 2 -activity "Deleting Deployment" -Status "In progress" Write-Output "$(Get-Date –f $timeStampFormat) - Deleting Deployment: In progress" #WARNING - always deletes with force $removeDeployment = Remove-AzureDeployment -Slot $slot -ServiceName $serviceName -Force write-progress -id 2 -activity "Deleting Deployment: Complete" -completed -Status $removeDeployment Write-Output "$(Get-Date –f $timeStampFormat) - Deleting Deployment: Complete" } function StartInstances() { write-progress -id 4 -activity "Starting Instances" -status "In progress" Write-Output "$(Get-Date –f $timeStampFormat) - Starting Instances: In progress" $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot $runstatus = $deployment.Status if ($runstatus -ne 'Running') { $run = Set-AzureDeployment -Slot $slot -ServiceName $serviceName -Status Running } $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot $oldStatusStr = @("") * $deployment.RoleInstanceList.Count while (-not(AllInstancesRunning($deployment.RoleInstanceList))) { $i = 1 foreach ($roleInstance in $deployment.RoleInstanceList) { $instanceName = $roleInstance.InstanceName $instanceStatus = $roleInstance.InstanceStatus if ($oldStatusStr[$i - 1] -ne $roleInstance.InstanceStatus) { $oldStatusStr[$i - 1] = $roleInstance.InstanceStatus Write-Output "$(Get-Date –f $timeStampFormat) - Starting Instance '$instanceName': $instanceStatus" } write-progress -id (4 + $i) -activity "Starting Instance '$instanceName'" -status "$instanceStatus" $i = $i + 1 } sleep -Seconds 1 $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot } $i = 1 foreach ($roleInstance in $deployment.RoleInstanceList) { $instanceName = $roleInstance.InstanceName $instanceStatus = $roleInstance.InstanceStatus if ($oldStatusStr[$i - 1] -ne $roleInstance.InstanceStatus) { $oldStatusStr[$i - 1] = $roleInstance.InstanceStatus Write-Output "$(Get-Date –f $timeStampFormat) - Starting Instance '$instanceName': $instanceStatus" } $i = $i + 1 } $deployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot $opstat = $deployment.Status write-progress -id 4 -activity "Starting Instances" -completed -status $opstat Write-Output "$(Get-Date –f $timeStampFormat) - Starting Instances: $opstat" } function AllInstancesRunning($roleInstanceList) { foreach ($roleInstance in $roleInstanceList) { if ($roleInstance.InstanceStatus -ne "ReadyRole") { return $false } } return $true } function SwapVip() { Write-Output "$(Get-Date –f $timeStampFormat) - Swap production and staging for $servicename." Move-AzureDeployment -ServiceName $servicename } function CreateNewDeployment() { write-progress -id 3 -activity "Creating New Deployment" -Status "In progress" Write-Output "$(Get-Date –f $timeStampFormat) - Creating New Deployment: In progress" $opstat = New-AzureDeployment -Slot $slot -Package $packageLocation -Configuration $cloudConfigLocation -label $deploymentLabel -ServiceName $serviceName $completeDeployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot $completeDeploymentID = $completeDeployment.deploymentid write-progress -id 3 -activity "Creating New Deployment" -completed -Status "Complete" Write-Output "$(Get-Date –f $timeStampFormat) - Creating New Deployment: Complete, Deployment ID: $completeDeploymentID" StartInstances } function UpgradeDeployment() { write-progress -id 3 -activity "Upgrading Deployment" -Status "In progress" Write-Output "$(Get-Date –f $timeStampFormat) - Upgrading Deployment: In progress" # perform Update-Deployment $setdeployment = Set-AzureDeployment -Upgrade -Slot $slot -Package $packageLocation -Configuration $cloudConfigLocation -label $deploymentLabel -ServiceName $serviceName -Force $completeDeployment = Get-AzureDeployment -ServiceName $serviceName -Slot $slot $completeDeploymentID = $completeDeployment.deploymentid write-progress -id 3 -activity "Upgrading Deployment" -completed -Status "Complete" Write-Output "$(Get-Date –f $timeStampFormat) - Upgrading Deployment: Complete, Deployment ID: $completeDeploymentID" } Import-Module Azure $pubsettings = $subscriptionDataFile Import-AzurePublishSettingsFile $pubsettings Set-AzureSubscription -CurrentStorageAccount $storageAccountName -SubscriptionName $selectedsubscription #set remaining environment variables for Azure cmdlets $subscription = Get-AzureSubscription $selectedsubscription $subscriptionname = $subscription.subscriptionname $subscriptionid = $subscription.subscriptionid $slot = $environment Write-Output "$(Get-Date –f $timeStampFormat) - Azure Cloud Service deploy script started." Write-Output "$(Get-Date –f $timeStampFormat) - Preparing deployment of $deploymentLabel for $subscriptionname with Subscription ID $subscriptionid." Publish $deployment = Get-AzureDeployment -slot $slot -serviceName $servicename $deploymentUrl = $deployment.Url Write-Output "$(Get-Date –f $timeStampFormat) - Created Cloud Service with URL $deploymentUrl." Write-Output "$(Get-Date –f $timeStampFormat) - Azure Cloud Service deploy script finished." 

我相信你传递publishsettings文件的方式导致了问题。 传递publishsettings文件时,必须添加引号,如果没有引号,则会触发exception。

以下是基于您的代码的代码,我通过使用(\“)引号传递publishsetting文件来测试它,它工作正常:

 private void button1_Click(object sender, EventArgs e) { Dictionary myDict= new Dictionary(); myDict.Add("-subscriptionDataFile", "\"C:\\InstallBox\\asc.publishsettings\""); RunPowerShellScript("C:\\InstallBox\\testcode.ps1", myDict); } internal void RunPowerShellScript(string scriptPath, Dictionary arguments) { RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create(); Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration); runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace); Pipeline pipeline = runspace.CreatePipeline(); //Here's how you add a new script with arguments Command myCommand = new Command(scriptPath); foreach (var argument in arguments) { myCommand.Parameters.Add(new CommandParameter(argument.Key, argument.Value)); } pipeline.Commands.Add(myCommand); var results = pipeline.Invoke(); foreach (var psObject in results) { ......... } } 

我的testcode.ps1如下:

 Param( [string]$subscriptionDataFile) Import-Module Azure Import-AzurePublishSettingsFile subscriptionDataFile Get-AzureSubscription 

为了确保我能看到你的问题,如果我将字典键值对更改为如下(没有引号),我会得到与你描述的完全相同的错误:

 myDict.Add("-subscriptionDataFile", "C:\\InstallBox\\asc.publishsettings"); 

因此,传递PublishSettings文件的正确方法如下:

 myDict.Add("-subscriptionDataFile", "\"C:\\InstallBox\\asc.publishsettings\"");