从C#应用程序调用蔚蓝的PowerShell命令失败 [英] Call azure powershell cmdlet from c# application fails

查看:170
本文介绍了从C#应用程序调用蔚蓝的PowerShell命令失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

I'trying以使自动化部署到Azure云的过程。我的PowerShell脚本,做到这一点,从湛蓝的PowerShell命令行执行时,它就像一个魅力。当我尝试从C#应用程序调用相同的脚本失败。

这是我的code:

 内部空隙RunPowerShellScript(字符串SCRIPTPATH​​,字典<字符串,字符串>参数)
    {
        RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
        运行空间运行空间= RunspaceFactory.CreateRunspace(runspaceConfiguration);
        runspace.Open();
        RunspaceInvoke scriptInvoker =新RunspaceInvoke(运行空间);
        管道管道= runspace.CreatePipeline();
        //这里是你如何添加一个新的脚本参数
        命令myCommand =新司令部(SCRIPTPATH​​,真);
      的foreach(在参数VAR参数)
        {
            myCommand.Parameters.Add(新CommandParameter(argument.Key,argument.Value));
        }
        pipeline.Commands.Add(myCommand);
        变种结果= pipeline.Invoke();
        的foreach(在结果VAR psObject)
        {
            _view.PrintOutput(psObject.ToString());
        }
    }

我跟着其他线程为好,像这样的:<一href=\"http://stackoverflow.com/questions/527513/execute-powershell-script-from-c-sharp-with-commandline-arguments\">Execute PowerShell脚本从C#与命令行参数的
而这其中:<一href=\"http://stackoverflow.com/questions/2594587/passing-parameters-to-powershell-from-c-sharp\">passing参数从C# PowerShell的

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

不能在参数PublishSettingsFile验证的说法。参数为空。提供一个参数不是null或空,然后再次尝试命令。

脚本:

 参数($服务名=,
    $ storageAccountName =,
    $ packageLocation =,
    $ cloudConfigLocation =,
    $环境=,
    $ deploymentLabel =,
    $ timeStampFormat =G,
    $ alwaysDeleteExistingDeployments = 1,
    $ enableDeploymentUpgrade = 1,
    $ selectedsubscription =默认,
    $ subscriptionDataFile =
 ) 功能发布()
{
#设置-ExecutionPolicy RemoteSigned就是
SET-AzureSubscription -SubscriptionName的Windows Azure MSDN - Visual Studio的专业-CurrentStorageAccount $ storageAccountName
$部署= GET-AzureDeployment -ServiceName $服务名-Slot $插槽-ErrorVariable一个-ErrorAction silentlycontinue
如果($ A [0] -ne $空)
{
    写输出$(获取最新-f $ timeStampFormat) - 未检测到部署创建一个新的部署。
}
#检查现有的部署,然后要么升级,删除+部署,或取消根据$ alwaysDeleteExistingDeployments和$ enableDeploymentUpgrade布尔变量
如果($ deployment.Name -ne $空)
{
    开关($ alwaysDeleteExistingDeployments)
    {
        1
        {
            开关($ enableDeploymentUpgrade)
            {
                1 #UPDATE部署就地(通常更快,更便宜,不会破坏VIP)
                {
                    写输出$(获取最新-f $ timeStampFormat) - 部署在$服务名升级部署的存在。
                    UpgradeDeployment
                }
                0 #DELETE然后创建新的部署
                {
                    写输出$(获取最新-f $ timeStampFormat) - 部署存在于$ SERVICENAME删除的部署。
                    DeleteDeployment
                    CreateNewDeployment                }
            }#开关($ enableDeploymentUpgrade)
        }
        0
        {
            写输出$(获取最新-f $ timeStampFormat) - 错误:部署存在于$服务名脚本执行取消。
            出口
        }
    } #switch($ alwaysDeleteExistingDeployments)
}其他{
        CreateNewDeployment
}
SwapVip
}
 功能DeleteDeployment()
{
写进度-id 2 -activity删除部署 - 状态进行中
写输出$(获取最新-f $ timeStampFormat) - 删除部署:在进步指令#warning - 总是用武力删除
$ removeDeployment =删除-AzureDeployment -Slot $插槽-ServiceName $服务名-Force写进度-id 2 -activity删除部署:完成-completed -Status $ removeDeployment
写输出$(获取最新-f $ timeStampFormat) - 删除部署:完成
}功能StartInstances()
{
写进度-id 4 -activity启动实例-status进行中
写输出$(获取最新-f $ timeStampFormat) - 启动实例:在进步$部署= GET-AzureDeployment -ServiceName $服务名-Slot $插槽
$ runstatus = $ deployment.Status如果($ runstatus -ne'运行')
{
    $ RUN =设置AzureDeployment -Slot $插槽-ServiceName $服务名-Status运行
}
$部署= GET-AzureDeployment -ServiceName $服务名-Slot $插槽
$ oldStatusStr = @()* $ deployment.RoleInstanceList.Count而(-not(AllInstancesRunning($ deployment.RoleInstanceList)))
{
    $ I = 1
    的foreach($ roleInstance在$ deployment.RoleInstanceList)
    {
        $实例= $ roleInstance.InstanceName
        $ instanceStatus = $ roleInstance.InstanceStatus        如果($ oldStatusStr [$ I - 1] -ne $ roleInstance.InstanceStatus)
        {
            $ oldStatusStr [$ I - 1] = $ roleInstance.InstanceStatus
            写输出$(获取最新-f $ timeStampFormat) - 启动实例$实例:$ instanceStatus
        }        写进度-id(4 + $ I)-activity启动实例$实例'-status$ instanceStatus
        $ I = $ I + 1
    }    睡眠-Seconds 1    $部署= GET-AzureDeployment -ServiceName $服务名-Slot $插槽
}$ I = 1
的foreach($ roleInstance在$ deployment.RoleInstanceList)
{
    $实例= $ roleInstance.InstanceName
    $ instanceStatus = $ roleInstance.InstanceStatus    如果($ oldStatusStr [$ I - 1] -ne $ roleInstance.InstanceStatus)
    {
        $ oldStatusStr [$ I - 1] = $ roleInstance.InstanceStatus
        写输出$(获取最新-f $ timeStampFormat) - 启动实例$实例:$ instanceStatus
    }    $ I = $ I + 1
}$部署= GET-AzureDeployment -ServiceName $服务名-Slot $插槽
$ OPSTAT = $ deployment.Status写进度-id 4 -activity启动实例-completed -status $ OPSTAT
写输出$(获取最新-f $ timeStampFormat) - 启动实例:$ OPSTAT
}
功能AllInstancesRunning($ roleInstanceList)
{
的foreach($ roleInstance在$ roleInstanceList)
{
    如果($ roleInstance.InstanceStatus -neReadyRole)
    {
        返回$假
    }
}返回$真
}
功能SwapVip()
{
 写输出$(获取最新-f $ timeStampFormat) - 交换生产和分期为$服务名。
 布展AzureDeployment -ServiceName $ SERVICENAME
}
功能CreateNewDeployment()
{
写进度-id 3 -activity创建新的部署 - 状态进行中
写输出$(获取最新-f $ timeStampFormat) - 创建新的部署:在进步$ OPSTAT =新AzureDeployment -Slot $插槽-package $ packageLocation -configuration $ cloudConfigLocation -label $ deploymentLabel -ServiceName $服务名$ completeDeployment = GET-AzureDeployment -ServiceName $服务名-Slot $插槽
$ completeDeploymentID = $ completeDeployment.deploymentid写进度-id 3 -activity创建新部署-completed -Status完整
写输出$(获取最新-f $ timeStampFormat) - 创建新的部署:完整,部署ID:$ completeDeploymentIDStartInstances
}功能UpgradeDeployment()
{
写进度-id 3 -activity升级部署 - 状态进行中
写输出$(获取最新-f $ timeStampFormat) - 升级部署:在进步#执行更新部署
$ setdeployment =设置AzureDeployment -Upgrade -Slot $插槽-package $ packageLocation -configuration $ cloudConfigLocation -label $ deploymentLabel -ServiceName $服务名-Force$ completeDeployment = GET-AzureDeployment -ServiceName $服务名-Slot $插槽
$ completeDeploymentID = $ completeDeployment.deploymentid写进度-id 3 -activity升级部署-completed -Status完整
写输出$(获取最新-f $ timeStampFormat) - 升级部署:完整,部署ID:$ completeDeploymentID
}
导入模块的Azure
$ pubsettings = $ subscriptionDataFile
进口AzurePublishSettingsFile $ pubsettings
设置AzureSubscription -CurrentStorageAccount $ storageAccountName -SubscriptionName $ selectedsubscription#SET其余环境变量的Azure的cmdlet
$认购= GET-AzureSubscription $ selectedsubscription
$ subscriptionname = $ subscription.subscriptionname
$ subscriptionid = $ subscription.subscriptionid
$ SLOT = $环境
写输出$(获取最新-f $ timeStampFormat) - Azure的云服务部署脚本启动。
写输出$(获取最新-f $ timeStampFormat) - $ deploymentLabel的preparing部署$与订阅ID $ subscriptionid subscriptionname。发布$部署= GET-AzureDeployment -Slot $插槽-ServiceName $ SERVICENAME
$ deploymentUrl = $ deployment.Url写输出$(获取最新-f $ timeStampFormat) - 创建云服务与网址$ deploymentUrl。
写输出$(获取最新-f $ timeStampFormat) - Azure的云服务部署脚本完成了。


解决方案

我相信你传递publishsettings文件的方式引起该问题。当传递publishsettings文件,则必须加引号,如果没有引号,你会打的异常。

以下是code这是根据你的code和我使用过publishsetting文件以引号(\\)测试,它工作得很好:

 私人无效的button1_Click(对象发件人,EventArgs的发送)
{
  字典&LT;字符串,字符串&GT; myDict =新词典&LT;字符串,字符串&GT;();
  myDict.Add( - subscriptionDataFile,\\C:\\\\ \\\\ InstallBox asc.publishsettings \\);
  RunPowerShellScript(C:\\\\ \\\\ InstallBox测试code.ps1,myDict);
}内部空隙RunPowerShellScript(字符串SCRIPTPATH​​,字典&LT;字符串,字符串&GT;参数)
 {
   RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
   运行空间运行空间= RunspaceFactory.CreateRunspace(runspaceConfiguration);
   runspace.Open();
   RunspaceInvoke scriptInvoker =新RunspaceInvoke(运行空间);
   管道管道= runspace.CreatePipeline();
   //这里是你如何添加一个新的脚本参数
   命令myCommand =新司令部(SCRIPTPATH​​);
   的foreach(在参数VAR参数)
   {
      myCommand.Parameters.Add(新CommandParameter(argument.Key,argument.Value));
   }
   pipeline.Commands.Add(myCommand);
   变种结果= pipeline.Invoke();
   的foreach(在结果VAR psObject)
    {
      .........
    }
   }

和我的测试code.ps1是如下:

 参数([字符串] $ subscriptionDataFile)
导入模块的Azure
进口AzurePublishSettingsFile subscriptionDataFile
GET-AzureSubscription

要确保我可以看到你的问题,如果我的字典键值对改为如下(不带引号),你描述的,我得到确切的同样的错误:

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

所以要通过PublishSettings文件正确的方法是如下:

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

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."

解决方案

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\"");

这篇关于从C#应用程序调用蔚蓝的PowerShell命令失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆