在两个存储帐户之间进行blob拷贝,在客户端,使用Azue PowerShell脚本, 用存储帐户上下文(New-AzureStorageContext)来获取某个StorageAccount中的Container。进而,我们想使用Azure Portal的自动化(Automation), 在Runbook中运行同样的脚本,就出现了如下的错误:
5/25/2015 9:49:19 AM, Error: Get-AzureStorageContainer : Cannot bind parameter 'Context'. Cannot convert the
"Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext" value of type
"Deserialized.Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext" to type
"Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext".
At storageAccountCopy:28 char:28
从网上查询问题原因,有人说是这样的,即Automation中运行的是PowerShell Workflow,其中返回的类型是deserialized, 而在PowerShell中返回的类型是非deserialized,所以你不能将Deserialized类型的AzueStorageContext转换为AzureStorageContext:解决方法是在脚本中使用关键字InlineScript包裹这些代码,使得他们仍然返回AzureStorageContext,而不是PowerShell Workflow中默认的Deserialized AzureStorageContext.
原话如下:
This is due to PowerShell Workflow returning values in deserialized form. See http://social.msdn.microsoft.com/Forums/windowsazure/en-US/1adec597-964c-402e-b1f1-b195d00a20be/exception-calling-azureprovisioningconfig?forum=azureautomation for more details.
The workaround is to just use an InlineScript within the workflow to run these commands in the PowerShell context instead of the PowerShell Workflow context.
示例代码如下:(这段代码所实现的是在同一个Subscription中,将源存储帐户中的blob文件拷贝到目标存储帐户中)
workflow storageAccountCopy { #Script by LeX (Qijie Xue) #sign in Azure Subscription $Credential = Get-AutomationPSCredential -Name "PSCredential" $SubscriptionName = Get-AutomationVariable -Name "SubscriptionName" #connect to Azure using PowerShell Credential Add-AzureAccount -Credential $Credential #Select the Azure subscription to use in this workflow Select-AzureSubscription -SubscriptionName $SubscriptionName inlinescript{ #source Storage Account $srcStorageAccountName = "" $srcStorageKey="" #target Storage Account $trgStorageAccountName="" $trgStorageKey ="" # storage context, source and target $srcContext = New-AzureStorageContext -StorageAccountName $srcStorageAccountName -StorageAccountKey $srcStorageKey $trgContext = New-AzureStorageContext -StorageAccountName $trgStorageAccountName -StorageAccountKey $trgStorageKey # all containers in source Storage Account $containers = Get-AzureStorageContainer -Context $srcContext ForEach($container in $containers) { $trgContainers = Get-AzureStorageContainer -Context $trgContext $exists=0 ForEach($item in $trgContainers) { if($item.Name -eq $container.Name) { $exists=1 } } if($exists -eq 0) { New-AzureStorageContainer $container.Name -Permission Container -Context $trgContext } # do the copy blob for the current container $blobs = Get-AzureStorageBlob -Container $container.Name -Context $srcContext $blobs | Start-AzureStorageBlobCopy -DestContainer $container.Name -DestContext $trgContext -Force } } }