2

My (dotNET) application is built (using a Windows Hosted agent), from a build pipeline, and in the subsequent Release pipeline, I provision a 16GB-Win2016 VM (enabling RDP, HTTP, HTTPS, WinRM and SSH), into which I RDP manually (there is a Manual Intervention task here), and configure WinRM (following this article: https://learn.microsoft.com/en-us/azure/marketplace/cloud-partner-portal/virtual-machine/cpp-configure-winrm-after-vm-creation#configure-vm-to-enable-winrm). Everything is fine until here. The next task is a Azure File Copy task, which essentially copies the Build artifacts (from $(System.DefaultWorkingDirectory)) and pastes into a directory I specify. Works like a charm. The next task I have is to create a VHD of this whole VM (essentially after the copying is done).

I know I can manually RDP into the VM (again) and sysprep (with oobe/generalize/shutdown), then maybe go back to the Azure Portal and Disk Export the OS Disk (specifying the SAS URL expiration time at whatever (36000 per the article)) BUT can this all be automated?

So, long story short - I'd like to know if sysprep oobe/generalize/shutdown can be performed remotely preferably over a PS task. I understand the other part of it (exporting the disk and all) can be, but if sysprep can be done remotely nothing like it.

Anonymous Person
  • 1,437
  • 8
  • 26
  • 47

4 Answers4

1

I tried this and got what I wanted:

$sysprep= 'C:\Windows\System32\Sysprep\Sysprep.exe'
$arg1 = '/generalize'
$arg2 = '/oobe'
$arg3 = '/shutdown'
$arg4 = '/quiet'

& $sysprep $arg1 $arg2 $arg3 $arg4 -Wait
Anonymous Person
  • 1,437
  • 8
  • 26
  • 47
  • Very appreciate you shared your solution here. Could you accept it as answer? It would more convenient for some users who has similar puzzle with you can directly know this is a work method:-) – Mengdi Liang Feb 06 '20 at 10:44
1

Make sure you do NOT use Azure custom script extension to run sysprep.

Azure scripts run under the LocalSystem user context: source

Custom Script Extension will run under the LocalSystem Account

This is problematic because sysprep does NOT support running under a system user context: source

Sysprep cannot be run under the context of a System account. Running Sysprep under the context of System account by using Task Scheduler or PSExec, for example, is not supported.

Providing this so that people avoid my mistake :)

m0ntl
  • 21
  • 1
  • 3
0

So, you dont have to configure winrm manually, you can script it\configure it while provisioning the vm. and if\when winrm is working you can just use powershell remoting to issue a command against the vm with:

Invoke-Command -ComputerName dnsname\ipaddress_goes_hehe
    -ScriptBlock { sysprep /shutdown /generalise}

https://github.com/Azure/azure-quickstart-templates/tree/master/201-vm-winrm-windows

4c74356b41
  • 69,186
  • 6
  • 100
  • 141
  • Thanks. So this essentially does what I am doing manually for the WinRM part? Right? – Anonymous Person Jan 25 '20 at 10:26
  • Oh, no. I can't do what's suggested in https://github.com/Azure/azure-quickstart-templates/tree/master/201-vm-winrm-windows. Using `Get-Credential` will pop up the credential window. Since I am doing all this over a Release pipeline, I don't suppose I can implement that. But I am OK with doing that manually - it's just a matter of 3 mins. 5 tops. So at this point it all boils down to this: How can `sysprep` be performed over a PS task in a release pipeline? – Anonymous Person Jan 25 '20 at 10:39
  • you can create credentials object silently: https://github.com/4c74356b41/powershell/blob/master/%23oneliners.ps1#L18. to invoke sysprep just call sysprep from powershell like you normally would. updated the anse – 4c74356b41 Jan 25 '20 at 11:51
0

You can implement this using an Azure custom script extension. There is a github project: https://github.com/jlongo62/AzureVMToImage containing powershell scripts to image a VM. These scripts were built to preserve VM when creating an image, instead of destroying the original VM. The scripts can be called from Azure Devops. There is no need to authenticate against the VM.

The meat of what you need is:

1- create a storageaccount blob containing the following script (the -Wait is very important):

Start-Process -FilePath C:\Windows\System32\Sysprep\Sysprep.exe -ArgumentList '/generalize /oobe /quiet /quit'  -Wait 

2 - invoke it on the VM:

$response = Set-AzureRmVMCustomScriptExtension  `
                -ResourceGroupName  $vm.ResourceGroupName `
                -VMName $vm.Name `
                -Location $vm.Location `
                -Name $ExtensionName  `
                -FileUri $blobUri  `
                -Run $FileName 
jlo-gmail
  • 4,453
  • 3
  • 37
  • 64
  • Hi. Had a follow up question. What's the -Wait for? I understand it "Waits", but sysprep for my machine through the VM itself finishes in 2 - 3 mins (meaning it shuts off). From PowerShell, without the -Wait it takes the same time, but with -Wait, it seems to take forever. So, what's it for? – Anonymous Person Feb 10 '20 at 19:21
  • 1
    When invoking the script via Custom Script Extension, the PS command never gets a response without the -Wait; -Wait forces the Agent to wait for command completion;you gave me an idea: since I am now using C# instead of PS, I can issue command without -Wait; then poll for the machine to Deallocate. – jlo-gmail Feb 10 '20 at 19:33