«Неверный массив передан в ...», когда я пытался передать строку в качестве параметра в функцию powershell в Azure Расширение пользовательского сценария - PullRequest
1 голос
/ 25 марта 2020

Мой сценарий: я должен передать строку JSON в качестве параметров для моего Azure пользовательского расширения сценария и выполнить сценарий для обновления настроек моей виртуальной машины. И я получил ошибку вроде ...ExecuteUpdateConfig.ps1 : Invalid array passed in, ']' expected...

Что я пробовал:

  1. Я использую $ variable.GetType (), чтобы убедиться, что все имеет тип string.

  2. Я пытался выполнить свой сценарий, не используя Azure Расширение пользовательского сценария для проверки самого сценария. И это на самом деле работает. Я передаю все строки, откуда берется «Массив»?

    Например:

    . ("D:\Utilities\ExecuteUpdateConfig.ps1") -DsnConfigsAsString $dsnconfigs -WebConfigsAsString $webconfigs
    
  3. Я думаю, что проблема может заключаться в том, как я выполняю свой сценарий и передать параметры. Я попробовал два способа в местном:

a. Точечные работы:

. ("D:\Utilities\ExecuteUpdateConfig.ps1") -DsnConfigsAsString $dsnconfigs -WebConfigsAsString $webconfigs

b. этот синтаксис не работает и выдаст указанную ошибку:

powershell.exe -ExecutionPolicy Unrestricted -Command "D:\Utilities\\ExecuteUpdateConfig.ps1 -DsnConfigsAsString $dsnconfigs -WebConfigsAsString $webconfigs"

Как я сгенерирую свою строку JSON и передам ее в скрипт в расширении собственного скрипта:

$vm = @{ }
$vm | Add-Member WebConfigs @()
$vm | Add-Member WebConfigs @()
$vm | Add-Member WebConfigs @()

$vm.WebConfigs += ([PSCustomObject]@{
    Path           = "C:\WindowsAzure\Packages\CommonAgentConfig.config"
    Node           = "configSections"
    ChildNode      = "section"
    AttributeKey   = "name"
    AttributeValue = "microsoft.windowsAzure.guestAgent.configuration"
    UpdatedValue   = "SamLeong"
    EncryptedValue = $false
})

##convert to json string 
$webconfigs = ConvertTo-Json @($vm.WebConfigs )
$dsnconfigs = ConvertTo-Json @($vm.DsnConfigs)
$registryconfigs = ConvertTo-Json @()

##Generate a VM with custom script extension using ARM template
##dsnConfigs, webconfigs and registryConfigs are my JSON string
##password,fileuri, resourcegorupname not related to the problems are not shown here
New-AzResourceGroupDeployment `
-ResourceGroupName $resourceGroupName `
-TemplateFile ".\customscriptext.json" `
-adminUsername "tester" `
-adminPassword $adminPassword `
-vmName "test16" `
-dsnConfigs $dsnconfigs -webConfigs $webconfigs -FileUrl $fileUrl `  
-dnsLabelPrefix "samtest16"

В своем шаблоне ARM я затем объединяю свои параметры и команду PowerShell в CommandToExecute, я определил их как «строку» в разделе моих параметров в шаблоне ARM:

    {
        "apiVersion": "2018-06-01",
        "type": "Microsoft.Compute/virtualMachines/extensions",
        "location": "[resourceGroup().location]",
        "name": "[concat(parameters('vmName'),'/installcustomscript')]",
        "dependsOn": [
            "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"
        ],
        "tags": {
            "displayName": "config-app"
        },
        "properties": {
            "publisher": "Microsoft.Compute",
            "type": "CustomScriptExtension",
            "typeHandlerVersion": "1.10",
            "autoUpgradeMinorVersion": true,
            "settings": {
                "fileUris": "[parameters('FileUrl')]"
            },
            "protectedSettings": {
                "commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -File ExecuteUpdateConfig.ps1', ' -DsnConfigsAsString ', parameters('dsnConfigs'), ' -WebConfigsAsString ', parameters('webConfigs'))]",
                "storageAccountName": "xxxxxxxxxxxxxxxxxxxxxxxxx",
                "storageAccountKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
            }
        }
    }

И в моем ExecuteUpdateConfig. скрипт ps1:

param([string] $DsnConfigsAsString, [string] $WebConfigsAsString )


try {
    $DsnConfigs = $DsnConfigsAsString | Out-String | ConvertFrom-Json
    $WebConfigs = $WebConfigsAsString | Out-String | ConvertFrom-Json

    #other execution logics follow...
    foreach ($dsn in $DsnConfigs) { ##read the dsn object and update  } 
    foreach ($webConfig in $WebConfigs) { ##read the webconfig object and update }
}catch{
    Write-Error "$($_.Exception.Message)"
    throw "Error in updateAllSettings" 
}

Полная ошибка:

Microsoft.Compute/virtualMachines/extensions 'samtest17/installcustomscript' failed 
with message '{
  "status": "Failed",
  "error": {
    "code": "ResourceDeploymentFailure",
    "message": "The resource operation completed with terminal provisioning state      
'Failed'.",
    "details": [
      {
        "code": "VMExtensionProvisioningError",
        "message": "VM has reported a failure when processing extension
'installcustomscript'. Error message: \"Command execution finished, but failed
because it returned a non-zero exit code of: '1'. The command had an error output of:  
'C:\\Packages\\Plugins\\Microsoft.Compute.CustomScriptExtension\\1.10.5\\Downloads\\0\ 
\\r\nExecuteUpdateConfig.ps1 : Invalid array passed in, ']' expected. (3): [\r\n    + 
CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorExcep \r\n
tion\r\n    + FullyQ...' For more information, check the instance view by executing    
Get-AzVmssVm or Get-AzVm (https://aka.ms/GetAzVm). These commands can be executed      
using CloudShell (https://aka.ms/CloudShell)\"\r\n\r\nMore information on
troubleshooting is available at https://aka.ms/VMExtensionCSEWindowsTroubleshoot "     
      }
    ]
  }
}'
At D:\Scripts\Testing\TestCustomScript.ps1:58 char:1
+ New-AzResourceGroupDeployment `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-AzResourceGroupDeployment], Exce  
   ption
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implem  
   entation.NewAzureResourceGroupDeploymentCmdlet

New-AzResourceGroupDeployment : 10:42:42 AM - VM has reported a failure when 
processing extension 'installcustomscript'. Error message: "Command execution 
finished, but failed because it returned a non-zero exit code of: '1'. The command     
had an error output of:
'C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.10.5\Downloads\0\       
ExecuteUpdateConfig.ps1 : Invalid array passed in, ']' expected. (3): [
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorExcep
   tion
    + FullyQ...' For more information, check the instance view by executing
Get-AzVmssVm or Get-AzVm (https://aka.ms/GetAzVm). These commands can be executed      
using CloudShell (https://aka.ms/CloudShell)"
More information on troubleshooting is available at
https://aka.ms/VMExtensionCSEWindowsTroubleshoot
At D:\Scripts\Testing\TestCustomScript.ps1:58 char:1
+ New-AzResourceGroupDeployment `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-AzResourceGroupDeployment], Exce  
   ption
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implem  
   entation.NewAzureResourceGroupDeploymentCmdlet

New-AzResourceGroupDeployment : 10:42:42 AM - Template output evaluation skipped: at   
least one resource deployment operation failed. Please list deployment operations for  
details. Please see https://aka.ms/DeployOperations for usage details.
At D:\Scripts\Testing\TestCustomScript.ps1:58 char:1
+ New-AzResourceGroupDeployment `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-AzResourceGroupDeployment], Exce  
   ption
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implem  
   entation.NewAzureResourceGroupDeploymentCmdlet

New-AzResourceGroupDeployment : 10:42:42 AM - Template output evaluation skipped: at 
least one resource deployment operation failed. Please list deployment operations for  
details. Please see https://aka.ms/DeployOperations for usage details.
At D:\Scripts\Testing\TestCustomScript.ps1:58 char:1
+ New-AzResourceGroupDeployment `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-AzResourceGroupDeployment], Exce  
   ption
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implem  
   entation.NewAzureResourceGroupDeploymentCmdlet



1 Ответ

1 голос
/ 26 марта 2020

(Дополнено из моего комментария ^^^)

Есть две причины, по которым точечный источник работает с вашим сценарием, но вызывается powershell.exe:

  • dot- Источник сценария означает, что он выполняется в существующем сеансе powershell и передаст значение в ваш сценарий в качестве ссылки на переменную, но вызов powershell.exe предоставит вам возможность разбираться в синтаксическом анализаторе командной строки для интерпретации значения строковой переменной

  • ваша переменная $ dsnConfigs содержит разрывы строк и другие символы (например, " и '), которые не интерпретируются в командной строке вы ожидаете.

Для демонстрации:

PS> Set-Content "myscript.ps1" "param([string] `$JsonString)`r`nwrite-host `$JsonString; `$myVar = ConvertFrom-Json `$JsonString"

PS> $myJson = ConvertTo-Json -InputObject @()
PS> . .\myScript.ps1 $myJson
[

]

PS> powershell .\myscript.ps1 $myJson
[
ConvertFrom-Json : Invalid array passed in, ']' expected. (1): [
At C:\src\scratch\myscript.ps1:2 char:34
+ write-host $JsonString; $myVar = ConvertFrom-Json $JsonString
+                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Вы можете использовать переключатель -Compress с ConvertTo- Json для устранения разрывов строки:

PS> $myJson = ConvertTo-Json -InputObject @() -Compress
PS> powershell .\MyScript.ps1 $myJson
[]

, но это не спасет вас от других проблем с анализатором командной строки:

PS> $myJson = ConvertTo-Json -InputObject @("aaa") -Compress
PS> powershell .\MyScript.ps1 $myJson
[aaa]
ConvertFrom-Json : Invalid JSON primitive: aaa.
At C:\src\scratch\myscript.ps1:2 char:34
+ write-host $JsonString; $myVar = ConvertFrom-Json $JsonString
+                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

За этот ответ - передача JSON строки через командную строку - вы можете base64 кодировать json strin g, передайте строку base64 в качестве параметра и затем декодируйте ее внутри скрипта:

PS> $myJson = ConvertTo-Json -InputObject @("aaa")
PS> $utf8   = [System.Text.Encoding]::UTF8.GetBytes($myJson)
PS> $base64 = [System.Convert]::ToBase64String($utf8)
PS> powershell .\MyScript.ps1 $base64
WyJhYWEiXQ==
["aaa"]

с myscript.ps1, теперь похожим на это, чтобы декодировать строку base64 обратно в исходную json:

myscript.ps1

param([string] $Base64Json)
write-host $Base64Json;

$utf8 = [System.Convert]::FromBase64String($Base64Json);
$json = [System.Text.Encoding]::UTF8.GetString($utf8);
write-host $json

$myVar = ConvertFrom-Json $json

Надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...