在两个存储帐户之间进行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
}
}
}
05-08 08:45