Question

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."
Was it helpful?

Solution

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\"");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top