12

Automate the complete capturing process using App Volumes Tools

Why?

With the release of App Volumes 2103, an extra option has been added to the installer. Now it is possible to select and install App Volumes Tools on a Windows 10 machine. The new appcapture Command-Line and PowerShell tools can be used to package applications without the App Volumes Manager Console. This command enables customers to automate packaging with silent installers and package in both the VMDK and VHD formats simultaneously.  It also provides other useful tools to convert between VHD and VMDK and work with the  MSIX app attach formatted packages.

I thought it would be fun to try out these Tools. That is why I started automating the capturing process using these tools. For this I made use of the possibility to install the applications with the help of chocolatey. I also used PowerCLI to automate a number of things.

To install App Volumes Tools select “Install App Volumes Tools” and “Install”

App Volumes Tools installs the following Cmdlets:

How?

In this example I want to be able to go through the following steps automatically using a powershell script.

To go through all these steps I need more than just the App Volumes Tools commands. I will also have to use the App Volumes API. Despite the availability of an API explorer, I still had to do some research. I used the tool Fiddler to find out what Rest API calls were made from App Volumes at certain steps.

Prepare the capturing machine

In the following example I installed the App Volumes Tools on a Windows 10 20h2 Operating System. According to the vmware documentation, the machine must meet the following prerequisites:

  • Ensure that you start a new capture every time on a clean virtual machine.
  • Ensure that the User Account Control (UAC) in Windows is disabled.
  • You must run the command-line capture program as an administrator.
  • Ensure that the command-line capture program utility is installed at C:\Program Files (x86)\VMware\AppCapture.
  • Configure WINRM for the communication between the Capturing VM and the machine which will start the script.

In this example I also provided the virtual machine with the following requirements:

  • Autologon for Administrator enabled (to record the entire process)
  • Chocolatey installed
  • PowerCLI installed to Start and Stop the VM and als to revert the VM to the right snapshot

The App Volumes tool is very easy to use. I only needed a few lines of script to start the capture process, install the applications “VLC” and finish the capture process as you can see below.

#Starting, Installing and Finalizing the App Volumes Capture Process 
Write-Host "Capturing, Installing and Finalizing are initiated" -ForegroundColor Green $Destination = "\\" + $AppVolServer + "\C$\Program Files (x86)\CloudVolumes\Manager\ppv\packages_templates" 
Invoke-Command -ComputerName w10-tools -ScriptBlock { Start-AVAppCapture -Name $using:App ; 
                                                      choco install $using:App -y;
                                                      Stop-AVTask } -Credential $WinRMCred

 

Result!

    With this example I would like to show you how easy it is to package an application using the App Volumes Tools and some extra scripting. The total package process of the VLC application including copying to the datastore and importing into the App Volumes Manager only took 5 minutes as you can see in the video below. After filling all the variables I only had to adjust 1 field  ($App) in the PowerShell script.

    The script

    This is the complete PowerShell script I used. You only have to fill the variables and you are ready to go.

    #Application Name (The installation name known by Chocolatey)
    $App              = "vlc" 
    
    #vCenter + VM variables
    $Vcenter          = '<Your_Vcenter_Server>'
    $Vcenter_User     = "<Your_Vcenter_User>"
    $Vcenter_Password = "<Your_Vcenter_Password>"
    $Package_VM       = "<Your_Package_VM>"
    $Snapshot         = "<Your_Snapshot"
    
    #WinRM variables
    $WinRMUser        = "<Your_WinRMUser>" #Domain\User
    $WinRMPassword    = ConvertTo-SecureString "<Your_WinRM_PAssword>" -AsPlainText -Force
    $WinRMCred        = New-Object System.Management.Automation.PSCredential -ArgumentList ($WinRMUser, $WinRMPassword)
    
    #App Volumes variables
    $AppVolServer     = "<Your_App_Volumes_Server>"
    $AppVolUser       = "<Your_App_Volumes_User>"
    $AppVolPassword   = "<Your_App_Volumes_Passwird"
    
    $Datacenter       = '<Your_DataCenter>'
    $Datastore        = '<Your_DataStore>' 
    <#I found the datastore UID by using this command:
     $Body = @{
            _       = 1619177827157 
    }
    $GETDS = Invoke-WebRequest -WebSession $Login -Method get -Uri https://$AppVolServer/cv_api/datastores -Body $Body
    $GETDS.content | ConvertFrom-Json | select package_storage #>
    $file             = 'files[]'
    $files            = 'packages_templates/' + $app +  '_workstation.vmdk'
    
    #Connect to vCenter Server
    Write-Host "Connect to Vcenter Server" -ForegroundColor Green
    Connect-VIServer -Server $Vcenter -User $Vcenter_User  -Password $Vcenter_Password
    
    #Revert capturing VM to package snapshot
    Write-Host "Reverting the capturing VM to the right snapshot" -ForegroundColor Green
    Set-VM -VM $Package_VM -SnapShot $Snapshot -Confirm:$false
    
    #Start- capturing VM
    Write-Host "Starting the capturing VM" -ForegroundColor Green
    Get-VM -Name $Package_VM | Start-VM
    
    #Waiting for WIRM
    Write-Host "Waiting for WINRM" -ForegroundColor Green 
    DO {$svservice = Invoke-Command -ComputerName $Package_VM -ScriptBlock {Get-Service -Name svservice} -Credential $WinRMCred
        }Until($svservice.Status -like "running")
    
    Write-Host "Almost ready to start....." -ForegroundColor Green
    sleep -Seconds 60
    
    #Starting, Installing and Finalizing the App Volumes Capture Process
    Write-Host "Capturing, Installing and Finalizing are initiated" -ForegroundColor Green
    $Destination   = "\\" + $AppVolServer + "\C$\Program Files (x86)\CloudVolumes\Manager\ppv\packages_templates"
    Invoke-Command -ComputerName w10-tools -ScriptBlock  {  Start-AVAppCapture -Name $using:App ;
                                                            choco install $using:App -y;
                                                            Stop-AVTask } -Credential $WinRMCred
    
    
    #Waiting until the VM is available after the reboot
    write-host "VM is restarting and finalizing the Capture Process........" -ForegroundColor Green
    sleep -Seconds 30
    DO {$WinRMService = Invoke-Command -ComputerName $Package_VM -ScriptBlock {Get-Service -Name WinRM} -Credential $WinRMCred | Out-Null
        }Until($WinRMService.status -ne 'running')
    
    #Waiting until the VMDK and JSON files are created
    Write-host "Waiting for VMDK and JSON files are created" -ForegroundColor Green
    $TestPath = "C:\Programdata\VMware\AppCapture\appvhds\" + $app + "_workstation.vmdk"
    Do {$VMDKPresent = Invoke-Command -ComputerName w10-tools -ScriptBlock {Test-Path -Path $using:TestPath} -Credential $WinRMCred
    }While($VMDKPresent -like 'False')
    
    sleep -Seconds 10
    
    #Copy .JSON + .VMDK to App Volumes Management Server
    Write-Host "Copy .JSON + .VMDK to App Volumes Manager" -ForegroundColor Green
    $share  = "\\" + $AppVolServer + "\C$\Program Files (x86)\CloudVolumes\Manager\ppv\packages_templates" 
    Invoke-Command -ComputerName $Package_VM -Credential $WinRMCred -ScriptBlock {
        $drive = New-PSDrive -PSProvider FileSystem -Root $using:share -Name AppVol -Credential $using:winrmcred
        $JSON = "C:\ProgramData\vmware\appcapture\appvhds\" + $using:App + ".json"
        $VMDK = "C:\ProgramData\vmware\appcapture\appvhds\" + $using:App + "_workstation.vmdk"
        Copy-Item  -Path $JSON -Destination AppVol:\ 
        Copy-Item  -Path $VMDK -Destination AppVol:\ 
        Pop-Location
        Remove-PSDrive $drive
    }
    Write-Host ".JSON + .VMDK copied App Volumes Manager" -ForegroundColor Green
    
    #Logging on to App Volumes Server
    Write-Host "Logging in to App Volumes Manager" -ForegroundColor Green
    $Body = @{
            username = $AppVolUser
            password = $AppVolPassword
    }
    
    #Ignore Certificate errors while I am not trusting the default App Volumes certificate
    add-type @"
        using System.Net;
        using System.Security.Cryptography.X509Certificates;
        public class TrustAllCertsPolicy : ICertificatePolicy {
            public bool CheckValidationResult(
                ServicePoint srvPoint, X509Certificate certificate,
                WebRequest request, int certificateProblem) {
                return true;
            }
        }
    "@
    [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
    
    $LoggingIn = Invoke-WebRequest -SessionVariable Login -Method Post -Uri https://$AppVolServer/cv_api/sessions -Body $Body 
    Write-Host $LoggingIn.Content -ForegroundColor Green
    Set-Variable -Name Login -Value $Login -Scope global
    
    #Uploading VMDK and JSON to Datastore
    Write-Host "Uploading VMDK and JSON to Datastore" -ForegroundColor Green
    $Body = @{
            datastore = $Datastore
            $file     = $files  
    }
    $Upload = Invoke-WebRequest -WebSession $Login -Method Post -Uri https://$AppVolServer/cv_api/volumes/preload -Body $Body
    Write-Host $Upload.content -ForegroundColor Green
    
    #Waiting for JSON and VMDK while they are uploading to the App Volumes Manager
    Write-Host ".JSON and .VMDK are being uploaded to the App Volumes Manager" -ForegroundColor Green
    DO {$pending_jobs = ((Invoke-WebRequest -WebSession $Login -Method Get -Uri "https://$AppVolServer/cv_api/jobs/pending").content | ConvertFrom-Json)
        }UNTIL($pending_jobs.pending -eq "0")
    Write-Host "Files are succesfully uploaded" -ForegroundColor Green
    
    #Importing Application/Package from datastore
    write-host "Importing Application/Package from datastore to App Volumes Manager" -ForegroundColor Green
    $AVDatacenter  = 'data[datacenter]'
    $AVDatastore = 'data[datastore]'
    $Path        = 'data[path]' 
    $Delay       = 'data[delay]'
    
    $Body = @{
            $AVDatacenter = $Datacenter
            $AVDatastore  = $Datastore
            $Path         = "appvolumes/packages_templates"
            $Delay        = "true"
            
    }
    $Import = Invoke-WebRequest -WebSession $Login -Method Post -Uri https://$AppVolServer/app_volumes/app_products/import -Body $Body
    Write-Host $Import.Content -ForegroundColor Green
    
    #Importing Application and Package from Datastore
    Write-Host "Application and Package are being imported in App Volumes Manager" -ForegroundColor Green
    DO {$pending_jobs = ((Invoke-WebRequest -WebSession $Login -Method Get -Uri "https://$AppVolServer/cv_api/jobs/pending").content | ConvertFrom-Json)
       }UNTIL($pending_jobs.pending -eq "0")
    write-host "Application and Package are succesfully imported in App Volumes Manager" -ForegroundColor Green
    
    #Removing  .JSON + .VMDK from the App Volumes Management Server 
    Write-Host "Removing .JSON + .VMDK from the App Volumes Manager" -ForegroundColor Green
    $share  = "\\" + $AppVolServer + "\C$\Program Files (x86)\CloudVolumes\Manager\ppv\packages_templates" 
    Invoke-Command -ComputerName $Package_VM -Credential $WinRMCred -ScriptBlock {
        $drive = New-PSDrive -PSProvider FileSystem -Root $using:share -Name AppVol -Credential $using:winrmcred
        $JSON = "AppVol:\" + $using:App + ".json"
        $VMDK = "AppVol:\" + $using:App + "_workstation.vmdk"
        Remove-Item  -Path $JSON  -Force
        Remove-Item  -Path $VMDK  -Force
        Pop-Location
        Remove-PSDrive $drive
    }
    
    #Revert capture VM to capture snapshot
    write-host "Revert capture VM to capture snapshot" -ForegroundColor Green
    Set-VM -VM $Package_VM -SnapShot $Snapshot -Confirm:$false
    
    #Diconnect from vCenter
    write-host "Diconnect from vCenter" -ForegroundColor Green
    Disconnect-VIServer -Server $Vcenter -Confirm:$false
    
    Write-Host "###################################################################################################" -ForegroundColor Green
    Write-Host "###################################################################################################" -ForegroundColor Green
    Write-Host "##    The Application is succesfully captured and is now availabe in the App Volumes Manager     ##" -ForegroundColor Green
    Write-Host "###################################################################################################" -ForegroundColor Green
    Write-Host "###################################################################################################" -ForegroundColor Green

    Roderik de Block

    12 Comments

    1. Great writeup Roderik!
      Have you thought about using esxcli vmkfstools command in your powershell script to clone and convert workstation type of vmdk file into vsphere type ? That might be faster and easier than uploading through ppv folder.

      • Hi Roch, thank you for your feedback. This is definitely worth trying.

    2. Roderik, at first great work … I am just wondering in which phase are you capturing (converting) app into vmdk please? I see you capture it in one step as vhd and then you are waiting for metada and json file created, but how if you end up with vhd file?

      • Hi, The Start-AVAppCapture commands generates a .vmdk, .vhd and .json file by default.

    3. Hi Roderik, how do you manage to create the package into already existing application (in AV console) by this script please?

      • +1 for this.
        I automated the package creation as well but failed to do the import in existing application.

    4. Hi Roderik, can you help with the command/api script to assign AD user/group to appvolumes(4.x) application.

    5. Hello Roderik,
      My team and I are trying to automate application capture using Ansible.
      Only when starting the capture the command timeout. To avoid this the only solution is to connect to the machine and in this case the process can be done. The same goes for stopping the capture.
      Do you know what could cause this?
      The VMware support tells us that this is not supported and can’t give us any more answers…
      Thanks in advance.

      • Hi Pierre,

        I haven’t seen this behaviour before and not sure what is causing your issue.

        Regards, Roderik

      • You need to have an interactive logon.
        Just set autologon in your ansible script, reboot and afterwards start your capture script.

    Leave a Reply

    Your email address will not be published. Required fields are marked *