{"id":2679,"date":"2017-08-16T16:40:14","date_gmt":"2017-08-16T20:40:14","guid":{"rendered":"https:\/\/www.tmurgent.com\/TmBlog\/?p=2679"},"modified":"2017-08-16T17:04:26","modified_gmt":"2017-08-16T21:04:26","slug":"life-with-the-app-v-autosequencer","status":"publish","type":"post","link":"https:\/\/www.tmurgent.com\/TmBlog\/?p=2679","title":{"rendered":"Life with the App-V AutoSequencer"},"content":{"rendered":"<table style=\"border: 0px white;\">\n<tbody>\n<tr>\n<td style=\"border: 0px white;\" width=\"250\"><img decoding=\"async\" src=\"\/TMBlog\/wp-content\/uploads\/2017\/Tim2.jpg\" width=\"250\" \/><\/td>\n<td style=\"border: 0px white;\" width=\"5\"><\/td>\n<td style=\"border: 0px white; vertical-align: top;\" valign=\"top\">It&#8217;s summer.\u00a0 Who should work all that hard anyway? I&#8217;m letting the AutoSequencer do the work for me.<\/p>\n<p>With the March 2017 release of Microsoft Windows also came the 1703 version of the Windows ADK. The ADK contains a number of tools used by both developers and IT Pros and is generally updated with each OS release. When you go to get the ADK you almost always want to get the latest version &#8211; it supports features in that release but most of the time also supports prior OS releases as well.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The two major new items in the 1703 ADK were both App-V related, however these only work with Windows 10 1607 and Windows 16, or later, operating systems.<\/p>\n<p>The first new item is the App-V Sequencer. With the App-V Client moving directly into the operating system, the ADK is now the release vehicle for the Sequencer. The primary reason that you cannot install this sequencer on Windows 7 is that it depends on some of the dlls in place for the in-box App-V client (which is present but not enabled by default).<\/p>\n<p>The second new component is the App-V AutoSequencer. I <a href=\"https:\/\/www.tmurgent.com\/TmBlog\/?p=2620\" target=\"blank\">wrote about the tool when it was released here<\/a> but basically the AutoSequencer is a component that would be used on a Hyper-V enabled machine to control a virtual machine that has the App-V Sequencer installed. Great for that package you have to touch each month if you are an IT Pro, or for an ISV to output an App-V package right from Visual Studio. You probably don&#8217;t use the command line sequencer, but in addition to the wizard based GUI sequencer interface, the sequencer also has a command-line sequencing capability that can automatically create an App-V package from an unattended installation script. So the AutoSequencer manages the VM state, copies installers into the VM, runs the command-line sequencer and finally collects the output package.<\/p>\n<p>I have been using this tool since late last fall when Microsoft made some prerelease versions available to me. Even using one of my Intel NUCs I can pump out about 6 packages per hour (assuming that I already did the work for a proper silent installation of the app).\u00a0 <img decoding=\"async\" src=\"\/TMBlog\/wp-content\/uploads\/2017\/Nucs.jpg\" width=\"400\" align=\"right\" \/>Heck, I have a set of nearly 50 apps that I can package with a single line of powershell &#8211; just enough time for a round of golf and a beer afterwards. The process I use includes two installers per package, one for dependencies and one for the main install. I use the <a href=\"https:\/\/github.com\/TimMangan\/silent-install\" target=\"blank\">Silent-Install open-source framework up on GitHub<\/a>for writing these unattended installations. Working with the improvement scripts output by AppV_Manage, these installations are better than from the vendor and optimized.<\/p>\n<p>As the bulk of the AutoSequencer tool is PowerShell based, I have been working on my own fixes to the tool to make it more useful. Last Winter I recommended a bunch of these changes to the tool to the Microsoft App-V dev team; a couple of which made it into the 1703 release version, but there has been no word on plans for the others (<em>Update: The Windows Insiders&#8217; build this week included an updated ADK, and although the AutoSequencer is a new build, all of the PowerShell is identical to the 1703 version<\/em>). After months of pleading with Microsoft this spring\/summer to make that PowerShell open source, I am resigned to the idea that we are unlikely to see this happen.<\/p>\n<p>But the AutoSequencer is a really useful tool with the fixes, so how do I make those available to you?\u00a0 While the PowerShell doesn&#8217;t contain a copyright notice, there is that pesky click-through license you agree to when you download the bits. So I am not comfortable in just posting the updated files. Yet if you are going to use the AutoSequencer you really want these changes. So I will post the changes here and try to make it easy for you to build your own &#8220;fixed version&#8221;. On each file below, I suggest that you edit using changes from the end of the list and work backwards &#8212; that way the line numbers I reference will work out.<\/p>\n<p>There are four files to change, although as you will see many of these changes are cosmetic.\u00a0 After installing the AutoSequencer, you will find these files in the folder:<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"font-size: 10pt;\"><strong><span style=\"font-family: times new roman,times,serif;\">C:\\Program Files (x86)\\Windows Kits\\10\\Microsoft Application Virtualization\\AutoSequencer<\/span><\/strong><\/span><\/p>\n<h6>Part 1: Updates to VMSetup\\Runner.ps1<\/h6>\n<p><strong>WHAT IT IS:<\/strong><\/p>\n<p>Runner.PS1 is a powershell file that is executed within the Sequencer VM to run commands. The file is copied into the VM as part of the VM creation process and is kicked off by a windows scheduled task that triggers upon login of the sequencer user.<\/p>\n<p><strong>WHY I MODIFY IT:<\/strong><br \/>\n1) The script assumes that the &#8220;installer&#8221; is a file that you include in the folder to be copied and that your file reference is a relative reference to that folder, so it plunks &#8220;C:\\users\\public\\Documents\\&#8221; in front of your reference. I modify this to detect a colon in the path and when detected use it as an absolute reference. Thus I can use &#8220;<span style=\"font-family: times new roman,times,serif;\">C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\PowerShell.exe<\/span>&#8221; as the installer and give it a ps1 file as an argument.<br \/>\n2) The script does not allow for the use of Template files. I added in support for a template file. I did not modify the input XML syntax so you don&#8217;t have to reference the file there, but if you include a file ending in the &#8220;<span style=\"font-family: times new roman,times,serif;\">.appvt<\/span>&#8221; file extension in the folder for the installer the script will detect and apply the template.<br \/>\n3) Remove the digital signature since we modified the file. (For extra credit you can sign the file with your own certificate, but I just disable the signature checking on PowerShell instead).<\/p>\n<p><strong>CHANGES:<\/strong><br \/>\n1) On Line 19 Replace:<\/p>\n<table style=\"font-family: CourierNew; font-size: 6px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">$installer = &#8220;$publicDocFolder\\ProductInstaller\\$installer&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 10px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">if (!($installer -like &#8220;?:\\*&#8221;) -and !($installer -like &#8220;`&#8221;?:\\*`&#8221;&#8221;))<\/span><br \/>\n<span style=\"font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $installer = &#8220;$publicDocFolder\\ProductInstaller\\$installer&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> }<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>2) On line 16, Insert:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\"># Check if template file is present<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $templatefile = Get-Item &#8220;$publicDocFolder\\ProductInstaller\\*.appvt&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>3) Lines 73-76 replace:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">log &#8220;Start the sequencing process&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $local:cmd = &#8220;New-AppvSequencerPackage -name `&#8221;$appName`&#8221; -Installer `&#8221;$installer`&#8221; -InstallerOptions `&#8221;$installerOptions`&#8221; -FullLoad -Path `&#8221;$productFolder`&#8221;&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> log $local:cmd<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Invoke-Expression &#8220;$local:cmd -ErrorVariable sequencerError&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 10px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">if ($templatefile)<\/span><br \/>\n<span style=\"font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> log &#8220;Start the sequencing process using $templatefile&#8221;<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $local:cmd = &#8220;New-AppvSequencerPackage -name `&#8221;$appName`&#8221; -Installer `&#8221;$installer`&#8221; -InstallerOptions `&#8221;$installerOptions`&#8221; -TemplateFilePath `&#8221;$templatefile`&#8221; -FullLoad -Path `&#8221;$productFolder`&#8221;&#8221;<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> log $local:cmd<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> Invoke-Expression &#8220;$local:cmd -ErrorVariable sequencerError&#8221;<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\n<span style=\"padding-left: 30px;\">log &#8220;Start the sequencing process&#8221;<\/span><br \/>\n<span style=\"padding-left: 30px;\">$local:cmd = &#8220;New-AppvSequencerPackage -name `&#8221;$appName`&#8221; -Installer `&#8221;$installer`&#8221; -InstallerOptions `&#8221;$installerOptions`&#8221; -FullLoad -Path `&#8221;$productFolder`&#8221;&#8221;<\/span><br \/>\n<span style=\"padding-left: 30px;\">log $local:cmd<\/span><br \/>\n<span style=\"padding-left: 30px;\">Invoke-Expression &#8220;$local:cmd -ErrorVariable sequencerError&#8221;<\/span><br \/>\n}<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h6>Part 2 New-AppVSequencerVM\\New-AppVSequencerVM.ps1:<\/h6>\n<p><strong>WHAT IT IS:<\/strong><br \/>\nScript that is used to create the Sequencer VM.<\/p>\n<p><strong>WHY I MODIFY IT:<\/strong><br \/>\nThe changes are mostly cosmetic for debugging, but I improve some error situations and change a couple of settings on the VM for improved operations.<\/p>\n<p><strong>CHANGES:<\/strong><br \/>\n1) <em>Improvements to logging. <\/em>Modify Line 121 Replace:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-Host &#8220;Failed to mount image: $VhdPath&#8221; -BackgroundColor Red<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 10px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-Host &#8220;Failed to mount image: $VhdPath onto folder $local:UnattendXml:MountRoot&#8221; -BackgroundColor Red<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>2) <em>Improvements to logging.<\/em> Insert on line 124:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">else<\/span><br \/>\n<span style=\"font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> Write-host &#8220;VHD Image mounted onto folder $local:UnattendXml:MountRoot&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> }<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>3) <em>Improvements to logging and error handling.<\/em> On line 149 Replace:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">}<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 10px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"padding-left: 30px; font-size: 10pt;\">Write-Host &#8220;Modified unattend written into Panther folder of mounted drive for VHD.&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> }<\/span><br \/>\n<span style=\"font-size: 10pt;\"> else<\/span><br \/>\n<span style=\"font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 10px; font-size: 10pt;\"> Write-Host &#8220;Failed to create $local:UnattendXml:TargetDirectory folder: $local:DismResult&#8221; -BackgroundColor Red<\/span><br \/>\n<span style=\"padding-left: 10px; font-size: 10pt;\"> handleDismErrorAndStop $local:UnattendXml:MountRoot<\/span><br \/>\n<span style=\"font-size: 10pt;\"> }<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>4) <em>Improvements to logging.<\/em> On line 251 insert :<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;VM Parameter Set detected, using an existing VM.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>5) <em>Improvements to logging.<\/em> On line 83 Replace :<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">start-vm $vm<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 10px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;Starting VM..&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> start-vm $vm<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Write-host &#8220;VM Started.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>6) <em>Improvements to logging.<\/em> On line 302 insert :<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;VM Session found.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>7) <em>Improvements to logging.<\/em> On line 305 insert :<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;Remote command invoked.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>8) <em>Improvements to logging.<\/em> On line 313 insert :<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;Provisioned.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>9) <em>Improvements to logging<\/em>. On line 316 insert :<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;VHD Parameter Set detected, use existing VHD to create VM.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>10) <em>Improvements to logging<\/em>. On line 373 insert :<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">else<\/span><br \/>\n<span style=\"font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> Write-host &#8216;VM Created.&#8217;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> }<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>11) <em>Improvements to VM Settings. Use standard checkpoint types and ensure VM does not start when Hypervisor starts.<\/em> On line 400 insert :<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\"># Added this line to prevent VM from starting up automatically when the hyper-v host is rebooted.<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Set-VM $VMName -AutomaticStartAction Nothing -CheckpointType Standard<\/span><br \/>\n<span style=\"font-size: 10pt;\"> # &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>12) <em>Improvements to logging.<\/em> On line 373 insert :<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;VM started.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>13) I<em>mprovements to give a second chance to connect to console<\/em>. On line 434-5, Replace:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host $failedGetVMSession -BackgroundColor Red<\/span><br \/>\n<span style=\"font-size: 10pt;\"> onCmdletStop<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 10px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host $failedGetVMSession -BackgroundColor Yellow<\/span><br \/>\n<span style=\"font-size: 10pt;\"> #Try again from the top<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $local:vmSession = GetVmSession $VMName $local:VmComputerName ([REF]$local:cred) $false $SessionSetupTimeout $reportFilePath<\/span><br \/>\n<span style=\"font-size: 10pt;\"> if (!$local:vmSession)<\/span><br \/>\n<span style=\"font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $failedGetVMSession = &#8220;Failed to get VM session 2nd time&#8221;<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> LogNewAppVSequencerVMStatus -TelemetryId $telemetryId -Message $failedGetVMSession<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> Write-host $failedGetVMSession -BackgroundColor Red<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> onCmdletStop<\/span><br \/>\n<span style=\"font-size: 10pt;\"> }<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>14) <em>Improvements to logging.<\/em> On line 437 Insert:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;VM Session found.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>15) <em>Improvements to logging.\u00a0<\/em> On line 442 Insert:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;VM provisioning completed&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>16) <em>Improvements to logging.<\/em> On line 460 Insert:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;Snapshot created.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>17) Remove Digital Signature<\/p>\n<h6>Part 3 New-BatchAppVSequencerPackages\\New-BatchAppVSequencerPackages.ps1:<\/h6>\n<p><strong>WHAT IT IS:<\/strong><br \/>\nThis script is called to start a run of autosequencing; it is run on the hypervisor.<\/p>\n<p><strong>WHY I MODIFY IT:<\/strong><br \/>\nMost of changes are all cosmetic. They provide information on the elapsed time per-package, and it modifies the titlebar on the VM to include the name of the package being sequenced so you can more easily tell how far along you are.<\/p>\n<p>The one substantive change is to revert the VM immediately after completion of a package and saving it off.<\/p>\n<p><strong>CHANGES:<\/strong><br \/>\n1) On line 256, Replace:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;&#8211; Start sequencing $appName &#8211;&#8220;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 30px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">$start_time = Get-Date<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $timeout = $app.TimeoutInMinutes<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Write-host &#8220;&#8211; $start_time &#8212; Start sequencing $appName &#8212; &#8220;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Write-host &#8220;Timeout is set to $timeout minutes&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>2) On line 284, Replace:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;Scheduling sequencing task..&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 30px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Write-host &#8220;Scheduling the dependencies and sequencing task..&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>3) On line 341, Insert:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Update-RDSClientWindowTitle $appname $procMstsc.Id<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>4) On line 348, Replace:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">$ret = Invoke-Command -session $s -ScriptBlock ${function:WaitForTaskComplete} -argumentlist $timeoutInMinutes<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 30px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">$ret = Invoke-Command -session $s -ScriptBlock ${function:WaitForTaskComplete} -argumentlist $timeoutInMinutes, $procMstsc.Id, &#8220;$appname&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>5) On line 361 , Insert<br \/>\n#Give a good opportunity to explore the VM before destroying it when there is an issue.<br \/>\nstart-sleep 600<br \/>\n6) On line 388 , Replace<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">$doneSequencing = &#8220;&#8211; Done sequencing $appName &#8211;&#8220;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> LogNewBatchAppVSequencerPackagesStatus -TelemetryId $telemetryId -Message $doneSequencing<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Write-host $doneSequencing<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"padding-left: 10px;\">With:<\/span><\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">$end_time = Get-Date<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $time_span = $end_time &#8211; $start_time<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $doneSequencing = &#8220;&#8211; $end_time &#8212; Done sequencing $appName &#8212; ($time_span)&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> LogNewBatchAppVSequencerPackagesStatus -TelemetryId $telemetryId -Message $doneSequencing<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Write-host $doneSequencing<\/span><br \/>\n<span style=\"font-size: 10pt;\"> writeToReport $reportFilePath $doneSequencingWrite-Host &#8220;Terminating session&#8230;&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> closeSession $s<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Write-Host &#8220;Session to $VMName removed.&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Write-host &#8220;Rolling back to checkpoint&#8230;&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> RollbackVM $VMName $VMCheckpoint<\/span><br \/>\n<span style=\"font-size: 10pt;\"> Write-host &#8220;$VMName rollback to checkpoint $VMCheckpoint complete.&#8221;<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>7) On line 406, Insert:<\/p>\n<table style=\"font-family: CourierNew; font-size: 10px; margin-left: 30px;\" bgcolor=\"#e0e0e8\">\n<tbody>\n<tr>\n<td><span style=\"font-size: 10pt;\">Function Update-RDSClientWindowTitle($appname, $proc_Id)<\/span><br \/>\n<span style=\"font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $global:timerito = New-Object System.Timers.Timer<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $global:timerito.Interval = 1000<\/span><br \/>\n<span style=\"font-size: 10pt;\"> <span style=\"padding-left: 30px;\">$global:timerito.AutoReset = $true<\/span><span style=\"padding-left: 30px;\">#write-host &#8220;before register&#8221;<\/span><\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> # Make variables global so thery are available to Action<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $global:proc_ID = $proc_Id<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $global:app_Name = $appname<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $global:source_identifier = Get-Random<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $global:UpdateCounter = 0<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $xx = Register-ObjectEvent -InputObject $timerito -SourceIdentifier $global:source_identifier -EventName Elapsed -Action {<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> #Write-host &#8220;Timerito time $($global:proc_ID)&#8221;<\/span><span style=\"padding-left: 50px; font-size: 10pt;\">Add-Type -TypeDefinition @&#8221;<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> using System;<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> using System.Runtime.InteropServices;<\/span><span style=\"padding-left: 50px; font-size: 10pt;\">public static class Win32 {<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> [DllImport(&#8220;User32.dll&#8221;, EntryPoint=&#8221;SetWindowText&#8221;)]<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> public static extern int SetWindowText(IntPtr hWnd, string strTitle);<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> }<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> &#8220;@<\/span><span style=\"padding-left: 30px; font-size: 10pt;\"># fix up window name on rdp session so we know which app is being done $process = Get-Process -Id $procId<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $match = &#8220;*$($global:app_Name)&#8221;<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> $process = Get-Process -Id $global:proc_ID<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> if ($process)<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> if ($process.mainWindowTitle -notlike &#8220;$($match)&#8221; )<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> #Write-host &#8220;Changing window title&#8221;<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> [Win32]::SetWindowText($process.mainWindowHandle, &#8220;$($process.mainWindowTitle) Sequencing $($global:app_Name)&#8221;)<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> $global:UpdateCounter = $global:UpdateCounter + 1<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> #$timerito.Stop()<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> #$timerito.Disose()<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> #Unregister-Event $global:source_identifier<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> }<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> if ($global:UpdateCounter -ge 2)<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> #Write-host &#8220;Setting Window Title&#8221;<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> #Unregister-Event $global:source_identifier<\/span><br \/>\n<span style=\"padding-left: 70px; font-size: 10pt;\"> #Write-host &#8220;after stop&#8221;<\/span><br \/>\n<span style=\"padding-left: 50px; font-size: 10pt;\"> }<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> }<\/span><br \/>\n<span style=\"font-size: 10pt;\"> }<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $timerito.Enabled = $true<\/span><br \/>\n<span style=\"font-size: 10pt;\"> #$timerito.Start()<\/span><br \/>\n<span style=\"font-size: 10pt;\"> #Write-host &#8220;after register&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $tempcounter = 0<\/span><br \/>\n<span style=\"font-size: 10pt;\"> while ($tempcounter -lt 60)<\/span><br \/>\n<span style=\"font-size: 10pt;\"> {<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> Start-Sleep 1<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> #Write-host &#8220;sleep check&#8221;<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> if ($global:UpdateCounter -ge 2) { $tempcounter = 60 }<\/span><br \/>\n<span style=\"padding-left: 30px; font-size: 10pt;\"> else { $tempcounter = $tempcounter + 1 }<\/span><br \/>\n<span style=\"font-size: 10pt;\"> }<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $global:timerito.Stop()<\/span><br \/>\n<span style=\"font-size: 10pt;\"> $global:timerito.Dispose()<\/span><br \/>\n<span style=\"font-size: 10pt;\"> #Write-host &#8220;after sleeps&#8221;<\/span><br \/>\n<span style=\"font-size: 10pt;\"> }<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>8) Remove digital signature<\/p>\n<h6>Part 4 sample_config.xml:<\/h6>\n<p><strong>WHAT IT IS:<\/strong><br \/>\nThis is a sample file that you edit to define your sequence packaging. The example file is INCORRECT in that is uses an element named &#8220;Name&#8221; for the package name when it should be &#8220;AppName&#8221; to match the config.xsd schema.<\/p>\n<h6>An optional addition\u2026<\/h6>\n<p>The dependencies assume that you will have a file called &#8220;run.cmd&#8221; as the installer for the dependencies. The config.xml file only lists the folder for dependencies. It is possible to edit the schema to add a new element, the new-BatchAppvSequencingPackages.ps1, scheduler.ps1, and runner.ps1 files to support it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s summer.\u00a0 Who should work all that hard anyway? I&#8217;m letting the AutoSequencer do the work for me. With the March 2017 release of Microsoft Windows also came the 1703 version of the Windows ADK. The ADK contains a number of tools used by both developers and IT Pros and is generally updated with each&hellip; <a class=\"more-link\" href=\"https:\/\/www.tmurgent.com\/TmBlog\/?p=2679\">Continue reading <span class=\"screen-reader-text\">Life with the App-V AutoSequencer<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2679","post","type-post","status-publish","format-standard","hentry","category-uncategorized","entry"],"_links":{"self":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts\/2679","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2679"}],"version-history":[{"count":11,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts\/2679\/revisions"}],"predecessor-version":[{"id":2690,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts\/2679\/revisions\/2690"}],"wp:attachment":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2679"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2679"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2679"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}