问题
I'trying to automatize the process of deploying to azure cloud. My powershell script that do that, works like a charm when executing it from azure powershell commandline. When I try to invoke the same script from c # application it fails .
This is my code:
internal void RunPowerShellScript(string scriptPath, Dictionary<string, string> 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());
}
}
I followed other threads as well , like this one : Execute PowerShell Script from C# with Commandline Arguments and this one : passing parameters to powershell from c#
But nothing seems to work. I get the following error :
Cannot validate argument on parameter 'PublishSettingsFile'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
The script:
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."
回答1:
I believe that the way you are passing the publishsettings file is causing the problem. When passing the publishsettings file, you must add the quotes and if there are no quotes you will hit the exception.
Following is the code which is based on your code and I tested it by passing publishsetting file with quotes using (\") and it works fine:
private void button1_Click(object sender, EventArgs e)
{
Dictionary<string, string> myDict= new Dictionary<string, string>();
myDict.Add("-subscriptionDataFile", "\"C:\\InstallBox\\asc.publishsettings\"");
RunPowerShellScript("C:\\InstallBox\\testcode.ps1", myDict);
}
internal void RunPowerShellScript(string scriptPath, Dictionary<string, string> 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)
{
.........
}
}
And my testcode.ps1 is as below:
Param( [string]$subscriptionDataFile)
Import-Module Azure
Import-AzurePublishSettingsFile subscriptionDataFile
Get-AzureSubscription
To make sure I can see your problem, if i change the dictionary key value pair to as below (without quotes) I get exact same error as you described:
myDict.Add("-subscriptionDataFile", "C:\\InstallBox\\asc.publishsettings");
So the correct way to pass PublishSettings file is as below:
myDict.Add("-subscriptionDataFile", "\"C:\\InstallBox\\asc.publishsettings\"");
来源:https://stackoverflow.com/questions/14568665/call-azure-powershell-cmdlet-from-c-sharp-application-fails