azure-docs
azure-docs copied to clipboard
Doesn't work with Windows 11 VHD
Hello, Thanks for the wonderful examples here and on the Azure pages, many have been very helpful. We have been using this example script almost verbatim for a while now with Windows 10 and it works beautifully. We just created our first Windows 11 vhd and the script generates a custom image without error, however that image will not boot. Will not even get to the point where you can ping it or do any diagnostics of the VM. Presumably this is because there is nothing to specify that it needs to create a HyperV Gen 2 disk/VM, which uses different boot logic. Any ideas on what needs to change in the example to allow it to work for Windows 11? Following the steps in the Portal work like a charm, so I guess those must be using different calls.
Create the custom image.
New-AzResourceGroupDeployment -ResourceGroupName $lab.ResourceGroupName -Name CreateCustomImage -TemplateUri 'https://raw.githubusercontent.com/Azure/azure-devtestlab/master/samples/DevTestLabs/QuickStartTemplates/201-dtl-create-customimage-from-vhd/azuredeploy.json' -TemplateParameterObject $parameters
Thanks, Brian
Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
- ID: a96b4af7-04e1-763b-90a4-d43e85cb0787
- Version Independent ID: b05aa41c-61a6-50ef-2644-d04459e23348
- Content: Create a custom image from VHD file by using Azure PowerShell - Azure DevTest Labs
- Content Source: articles/devtest-labs/devtest-lab-create-custom-image-from-vhd-using-powershell.md
- Service: devtest-lab
- GitHub Login: @j-martens
- Microsoft Alias: juliako
@briancovingtonhsv Thank you for reaching out to us! We are reviewing this and will get back to you shortly.
Thanks for the feedback! I have assigned the issue to the content author to investigate further and update the document as appropriate.
@Karishma-Tiwari-MSFT Is there some way I can get the correct template (or URL to a template) that I should be calling? We have a product release in 2022 Q2 which would need to be certified on Windows 11 and this is a huge hurdle in accomplishing that. Thanks, Brian
Hi @briancovingtonhsv,
I'm part of the DevTest Labs product team, I'm bringing the issue to our team and will get back to you soon.
Thanks for reaching out.
The ARM template doesn't seem to be the problem as it just creates a custom image in DTL through ARM. It seems like the issue is something in the VHD. In the VM. We would like to know how you prepared the VM, what parameters you are passing, and what is different between the Win10 image and the Win11 image in that process. Did you sysprep the VM? How? Was it successfully sysprepped?
Thanks
Jose,
We would like to know how you prepared the VM, what parameters you are passing, and what is different between the Win10 image and the Win11 image in that process. For the Windows 11 which has failed for us several times, it is a pristine Marketplace Windows 11 Enterprise image which has been domain joined to our domain and had our domain user added. We disabled UAC and then started our PowerShell script to produce the custom image. At the point the deployment step is done, we would have other scripts on the machine to proceed further but we do not get that far, as the machine doesn't boot.
Windows 10 VM is much the same. We started with a marketplace image and loaded and configured much of the software, then we run the function below. For Windows 10, this generates a running VM, which then has a script in the RunOnce registry entry which takes care of the sysprep step, which is the normal "%WINDIR%\system32\sysprep\sysprep.exe /generalize /shutdown /oobe".
Did you sysprep the VM? No, we have not run sysprep yet, as it does not boot. How? Was it successfully sysprepped? The function from our script is below: (NOTE: we had some issues with random failures to the CLI calls, so most functions are wrapped in separate functions that have retry options)
Function Copy-HALVMToTempCustomImage() { param ( [Parameter(Mandatory=$true)][ValidateNotNull()][HALLab]$Lab, [Parameter(Mandatory=$True)][ValidateNotNull()][string]$VMName, [Parameter(Mandatory=$true)][ValidateNotNull()][string]$TempImageName )
try
{
Log "Copy-HALVMToTempCustomImage" Log "Lab:$($Lab.Name)" Log "VMName:$VMName" Log "TempImageName:$TempImageName"
[string]$destContainer = 'importvhds' [string]$labVhdFileName=(Get-Date).ToUniversalTime().ToString('yyyy-MM-dd-HHmmss.\v\h\d')
Get access to the VM disk
$VMResource = Get-HALPsVMResource -VMName $VMName
$VM = Get-HALPsVirtualMachine -VMResource $VMResource
$Access = Grant-HALPsDiskAccess -VM $VM
# Get the storage account
Log "Lab default Storage Account: $($lab.DefaultStorageAccount)"
$labStorageAccount = Get-HALPsResourceById -ResourceID $lab.DefaultStorageAccount
$labStorageAccountKey = Get-HALPsStorageAccountKey -StorageAccountResource $labStorageAccount
# Setup Destination container
$destContext = New-AzStorageContext -StorageAccountName $labStorageAccount.Name -StorageAccountKey $labStorageAccountKey
New-AzStorageContainer -Context $destContext -Name $destContainer -ErrorAction Ignore
Log "Created new container $destContainer"
# Copy from the export URL to a blob endpoint
$BlobCopy = Start-AzStorageBlobCopy -AbsoluteUri $Access.AccessSAS -DestContainer $destContainer -DestBlob $labVhdFileName -DestContext $destContext -Force
$labVhdUri = $BlobCopy.ICloudBlob.Uri
$status = $BlobCopy | Get-AzStorageBlobCopyState
if ($status.Status -eq "Pending")
{
[datetime]$dtStart = $(Get-Date)
Log "Starting blob copy."
Log "Total to copy: $(DisplayInBytes($status.TotalBytes))"
While ($status.Status -eq "Pending")
{
Start-Sleep 300
$status = $BlobCopy | Get-AzStorageBlobCopyState
if ($status.TotalBytes -ne 0)
{
[timespan]$tsDelta = $(Get-Date) - $dtStart
Log ("Percent complete {0:p2} after {1}" -f ($status.BytesCopied/$status.TotalBytes), $tsDelta.ToString("h' hours 'm' minutes'"))
}
}
}
if ($status.Status -eq "Failed")
{
Log "AzureStorageBlobCopy failed"
Log "Status.Description: $($status.StatusDescription)"
Throw "Copy-HALVMToTempCustomImage: AzureStorageBlobCopy failed"
}
Log "$labVhdFileName successfully copied to storage"
$Global:Error.Clear()
Log "Create new image $TempImageName"
# Create the custom image.
$deployName = 'deploy-' + $TempImageName
# Set up the parameters object.
$parameters = @{existingLabName="$($lab.Name)"; existingVhdUri=$labVhdUri; imageOsType='windows'; isVhdSysPrepped=$false; imageName=$TempImageName; imageDescription='Temporary Image used for teamplate gen'}
$deployHandle = New-AzResourceGroupDeployment -ResourceGroupName $lab.ResourceGroupName -Name $deployName -TemplateUri 'https://raw.githubusercontent.com/Azure/azure-devtestlab/master/samples/DevTestLabs/QuickStartTemplates/201-dtl-create-customimage-from-vhd/azuredeploy.json' -TemplateParameterObject $parameters
if($deployHandle.ProvisioningState -ne "Succeeded")
{
Throw "Copy-HALVMToTempCustomImage: Image deploy failed. We should stop now"
}
Log "Deleting copied vhd"
Remove-AzStorageBlob -Context $destContext -Container $destContainer -Blob $labVhdFileName -ErrorAction SilentlyContinue
Log "Remove group deployment"
Remove-AzResourceGroupDeployment -ResourceGroupName $lab.ResourceGroupName -Name $deployName -ErrorAction SilentlyContinue | Out-Null
Revoke-HALPsDiskAccess -VM $VM } catch { Log "Caught an exception in Copy-HALVMToTempCustomImage" LogException $_.Exception
try
{
Log "Clean up after failure"
Revoke-HALPsDiskAccess -VM $VM
Remove-AzStorageBlob -Context $destContext -Container $destContainer -Blob $labVhdFileName -ErrorAction SilentlyContinue
Remove-AzResourceGroupDeployment -ResourceGroupName $lab.ResourceGroupName -Name $deployName -ErrorAction SilentlyContinue | Out-Null
}
catch
{
Log "Caught an exception in Copy-HALVMToTempCustomImage cleanup after failure exception handler"
LogException $_.Exception
}
Throw $_.Exception
}
}
#assign:@josegallardo
#reassign:@rosehjm
Hi @briancovingtonhsv, Thank you for taking the time to contact us. Unfortunately, at this time we have been unable to resolve your issue in a timely manner and we sincerely apologize for the delayed response.
I've consulted with @josegallardo, and he's confirmed that the configuration you describe isn't currently supported.
Given the timeline you mention above, we are closing this issue for now. If you feel that it's still a concern, please respond and let us know. If you determine another possible update to our documentation, please don't hesitate to reach out again.
#please-close