A new Flexera Community experience is coming on November 25th. Click here for more information.
AdminStudio Enterprise Edition includes a robust set of PowerShell cmdlets that allow for extensive control of the solution which enables powerful automation possibilities that can significantly speed up the process of application packaging and deployment. Saving time and money is great, but of course a solid process also helps with quality– all of which you can realize with the help of the resources outlined in this article.
The Application Readiness process includes the basic areas of effort required for a successful application deployment. It often varies from company to company, but a complete process that mitigates the most risk typically includes the tasks pictured below. The presentation and script found here is intended to help you automate the bulk of the activities necessary in execution of this process.
The AdminStudio documentation includes a reference to the cmdlets as well as a PowerShell example, but until recently we did not have a good real-world implementation of how to leverage this valuable feature to automate the Application Readiness Process.
Below you’ll find two pieces of content to help you unlock the potential of AdminStudio’s PowerShell support: A video of a presentation delivered at the 2018 App Management Event that details a script which can automate the process of importing an application, running tests, automatically fixing detected issues, converting it for virtualization and even publishing to a systems management solution for distribution. The presentation starts by explaining the process, covering some of the key cmdlets that make it possible, and finally a demonstration of the script itself. The script discussed is the second valuable piece of content shared below. To avoid some of the security implications that come with posting a PowerShell script file for download, the script can be found below for copy/paste into your editor of choice (just be sure to paste it as plain text to avoid the HTML that might otherwise come along with it depending on your editor).
(Full credit for the script below goes to Flexera Technical Product Manager, Kiran Mantagi who presented such in the video above)
############################################################### # Environment Settings/Values ############################################################### $DefaultExt = #<list all the package types by extension which monitored for> Eg: @(‘*.msi’,’*.appv’,’*.exe’) $folder = #<Path to a folder which should be monitored for new incoming packages> Eg:”C:\Users\admin_kiran\Desktop\Sample Packages” $global:CatalogName = #<Name of the application catalog> Eg:’MyCatalog’ $ConnectionString = #<Connection string to the SQL Server> Eg: PROVIDER=SQLOLEDB.1;Data Source=<sql server here>; Initial Catalog=’ + $global:CatalogName + ‘;user ID=<Username>;password=<password>’ $SCCMServer = #<SCCM Server> Eg:’10.10.10.10(or FQDN)’ $SCCMServerSiteCode = #<SCCM Site Code> Eg:’ABC’ $SCCMRepositoryPath = #<Content location where the packages from AdminStudio will be copied to distribute to SCCM. It should be a UNC Path> Eg: ‘\\10.10.10.10\Content’ $SCCMTargetGroup = #<Target Group in SCCM where the application should be published> Eg: ‘Applications\Sales’ $SCCMUser = #<SCCM Username. Essentially with admin privileges> Eg: ‘testdomain\admin’ $SCCMPass = #<SCCM User Password> Eg:’Hello’ $sAACProjectFile = #<Path to the aacx project file> Eg:”C:\AppVConversions\Convert.aacx” $VirtualApps = #<Path to the folder where the virtualized apps to be copied> Eg: “C:\Virtualized Apps\” $DistributionName = #<The name of the Distribution Connection like you want it to be set in AdminStudio> Eg: ‘ConfigMgr 2016′ $PluginID = 13 $ShareUser = #<The user account which has access to $SCCMRepositoryPath> Eg:’testdomain\admin’ $SharePwd = #<Password for the user account: $ShareUser> Eg:’Hello’ $IntervalinMins = #<Time in minutes to monitor the $folder for new packages copied in last these many minutes> Eg: 5 (Packages copied in last 5 mins will be picked up for processing) $logfile = #<Log file appended with the time stamp> Eg: “C:\Logs\log $(get-date -f yyyy-MM-dd-hh-mm).txt” ############################################################### # System Settings/Values ############################################################### $shive = “HKLM:\SOFTWARE\Wow6432Node\InstallShield\AdminStudio\16.0\” $slocation = “Product Location” $sAsLoc = (Get-ItemProperty $shive $slocation).$slocation $sCurrentLoc = [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath $sAsLoc = $sAsLoc + “Common\” $global:oPkgArray = @() $global:oPkgArrayError = @() $global:oPkgArrayPass = @() $global:oPkgArrayFail = @() $global:oPkgVirtPass = @() $global:oAppVPkgArrayError = @() $global:oAppVPkgArray = @() ############################################################### # Functions ############################################################### ###****************************** Importing single MSI package ******************************#### function Import ($s) { $f = [System.IO.File]::GetAttributes($s) $d = ($f -band [System.IO.FileAttributes]::Directory) if (!$d) { Write-Host ‘Importing:’ $s -foregroundcolor white Out-File -FilePath $logfile -Append -InputObject “Importing: $s” -Encoding string $obj = Invoke-ASImportPackage -PackagePath $s if ($obj.GetType().FullName -eq ‘AdminStudio.Platform.Helpers.PackageHelper’) { $global:oPkgArray = $global:oPkgArray + $obj } else { Write-Host ‘Failed to import:’ $s -foregroundcolor red Out-File -FilePath $logfile -Append -InputObject “Failed to import: $s” -Encoding string $global:oPkgArrayError = $global:oPkgArrayError + $obj } } } ###****************************** Importing MSI packages from a folder ******************************#### function ImportFolder () { if ($folder) { Write-Host ‘Importing Applications from’ $folder -foregroundcolor yellow Out-File -FilePath $logfile -Append -InputObject “Importing Applications from $folder” -Encoding string Write-Host Out-File -FilePath $logfile -Append -InputObject ” -Encoding string foreach ($file in Get-Childitem -include $DefaultExt -Recurse $folder){ $createtime = $file.CreationTime $nowtime = get-date if (($nowtime – $createtime).totalminutes -lt 5) { Import ($file) } } Write-Host Out-File -FilePath $logfile -Append -InputObject ” -Encoding string Write-Host ‘Packages that Imported Successfully:’ $global:oPkgArray.Count $importedcount = $global:oPkgArray.Count Out-File -FilePath $logfile -Append -InputObject “Packages that Imported Successfully: $importedcount” -Encoding string Write-Host ‘Packages that Failed to Import:’ $global:oPkgArrayError.Count $failedcount = $global:oPkgArrayError.Count Out-File -FilePath $logfile -Append -InputObject “Packages that Failed to Import: $failedcount ” -Encoding string Write-Host Out-File -FilePath $logfile -Append -InputObject ” -Encoding string } } ###****************************** Initial Configurations ******************************#### function LoadDLL ($s) { $FileName = $sAsLoc + $s import-module -name $FileName } function PrepAS () { Set-ExecutionPolicy Unrestricted -Force LoadDLL ‘AdminStudio.Platform.PowerShellExtensions.dll’ LoadDLL ‘AdminStudio.Utilities.dll’ LoadDLL ‘AdminStudio.SCCM.Model.dll’ LoadDLL ‘AdminStudio.SCCM.Integrator.dll’ Set-ASConfigPlatform -ConnectionString $ConnectionString } ###****************************** Run Tests on a Package ******************************#### function Test ($o) { Write-Host ‘Testing Package:’ $o.DisplayedProductName -nonewline -foregroundcolor white Out-File -FilePath $logfile -Append -InputObject “Testing Package: $($o.DisplayedProductName)” -Encoding string Write-Host ‘ RowId:’ $o.RowID -foregroundcolor gray $oTestResults = Test-ASPackage -PackageId $o.RowID $errors = 0; $warn = 0; $fixable=0; foreach ($oTestResult in $oTestResults.Stats) { $errors = $errors + $oTestResult.Errors $warn = $warn + $oTestResult.Warnings $fixable = $fixable + $oTestResult.Fixable } Write-Host-Indent Write-Host ‘Errors:’ $errors -foregroundcolor red Out-File -FilePath $logfile -Append -InputObject “Errors: $($errors)” -Encoding string Write-Host-Indent Write-Host ‘Warnings:’ $warn -foregroundcolor yellow Out-File -FilePath $logfile -Append -InputObject “Warnings: $($warn)” -Encoding string Write-Host-Indent Write-Host ‘Fixables:’ $fixable -foregroundcolor Magenta Out-File -FilePath $logfile -Append -InputObject “Fixables: $($fixable)” -Encoding string Write-Host } ###****************************** Resolve fixable issues for a package**************************### function Resolve ($o) { Write-Host ‘Resolving Package:’ $o.DisplayedProductName -nonewline -foregroundcolor white Out-File -FilePath $logfile -Append -InputObject “Resolving Package: $($o.DisplayedProductName)” -Encoding string Write-Host ‘ RowId:’ $o.RowID -foregroundcolor gray $oTestResults = Resolve-ASPackage -PackageId $o.RowID $errors = 0; $warn = 0; $fixable=0; foreach ($oTestResult in $oTestResults.Stats) { $errors = $errors + $oTestResult.Errors $warn = $warn + $oTestResult.Warnings $fixable = $fixable + $oTestResult.Fixable } Write-Host-Indent Write-Host ‘Errors After Resolve:’ $errors -foregroundcolor red Out-File -FilePath $logfile -Append -InputObject “Errors After Resolve: $($errors)” -Encoding string Write-Host-Indent Write-Host ‘Warnings After Resolve:’ $warn -foregroundcolor yellow Out-File -FilePath $logfile -Append -InputObject “Warnings After Resolve: $($warn)” -Encoding string Write-Host-Indent Write-Host ‘Fixables After Resolve:’ $fixable -foregroundcolor Magenta Out-File -FilePath $logfile -Append -InputObject “Fixables After Resolve: $($fixable)” -Encoding string Write-Host if ($errors -eq 0) { $global:oPkgArrayPass = $global:oPkgArrayPass + $o } else { $global:oPkgArrayFail = $global:oPkgArrayFail + $obj } } ###****************************** Resolve fixable issues for all the imported packages ******************************#### function ResolveImportedPackages ($Array) { $global:oPkgArrayPass = @() $global:oPkgArrayFail = @() foreach ($oPkg in $Array) { Resolve ($oPkg); } } ###****************************** Run Tests on all the imported packages ******************************#### function TestImportedPackages ($Array) { $global:oPkgArrayPass = @() $global:oPkgArrayFail = @() foreach ($oPkg in $Array) { Test ($oPkg); } } ###****************************** Distribute Packages to SCCM ******************************#### function DistributePackage($Array) { New-ASDistributionConnection -Name $DistributionName -PluginID $PluginID -ServerAddress $SCCMServer -SiteCode $SCCMServerSiteCode -DistributionWindowsAuthentication 0 -DistributionUser $SCCMUser -DistributionPassword $SCCMPass -SharePath $SCCMRepositoryPath -ShareWindowsAuthentication 0 -ShareUserName $ShareUser -SharePassword $SharePwd foreach ($oPkg in $Array) { Write-Host ‘Distributing the Package:’ $oPkg.DisplayedProductName -nonewline -foregroundcolor white Out-File -FilePath $logfile -Append -InputObject “Distributing the Package: $($oPkg.DisplayedProductName) RowId: $($oPkg.RowID)” -Encoding string Write-Host ‘ RowId:’ $oPkg.RowID -foregroundcolor gray $oAppID = Get-ASApplicationID -PackageID $oPkg.RowID Invoke-ASPublish -ConnectionName $DistributionName -ApplicationID $oAppID -TargetGroup $SCCMTargetGroup } } ###****************************** Check Virtualization Readiness and Virtualize the MSI Packages ******************************#### function VirtualizeApp($Array) { foreach ($Package in $Array) { $VirtResult = Get-ASVirtualReadiness -PackagePath $Package.FileName -PackageId $Package.RowID if ($VirtResult -eq 0) { Write-Host ‘Converting Package:’ $Package.DisplayedProductName -foregroundcolor white Out-File -FilePath $logfile -Append -InputObject “Converting Package: $($Package.DisplayedProductName)” -Encoding string $virt=Invoke-ASConvertPackageEx -PackageId $Package.RowID -AACSettings $sAACProjectFile -TargetType AppV5 $global:oPkgVirtPass = $global:oPkgVirtPass + $Package } else { Write-Host ‘Skipping Conversion of’ $Package.DisplayedProductName ‘due to Errors/Warnings’-foregroundcolor red Out-File -FilePath $logfile -Append -InputObject “Skipping Conversion of $($Package.DisplayedProductName) due to Errors/Warnings” -Encoding string } } } function Write-Host-Indent () { Write-Host ‘ ‘ -nonewline } function Write-Host-Drawline () { Write-Host ‘**************************************’ -foregroundcolor yellow Out-File -FilePath $logfile -Append -InputObject ‘**************************************’ } ################################################################ # Main Loop ############################################################### cd $sAsLoc Write-Host Out-File -FilePath $logfile -Append -InputObject ” -Encoding string Write-Host-Drawline Write-Host ‘Default Directory =’ $folder -foregroundcolor gray Out-File -FilePath $logfile -Append -InputObject “Default Directory = $folder” -Encoding string Write-Host ‘Catalog Name=’ $global:CatalogName -foregroundcolor gray Out-File -FilePath $logfile -Append -InputObject “Catalog Name= $global:CatalogName” -Encoding string Write-Host-Drawline Write-Host Out-File -FilePath $logfile -Append -InputObject ” PrepAS New-ASCatalog -CatalogName $global:CatalogName ImportFolder TestImportedPackages ($global:oPkgArray) ResolveImportedPackages ($global:oPkgArray) VirtualizeApp ($global:oPkgArray) DistributePackage ($global:oPkgVirtPass) DistributePackage ($global:oPkgArrayPass) Write-Host Out-File -FilePath $logfile -Append -InputObject ” Write-Host “Thank you :-)” Out-File -FilePath $logfile -Append -InputObject “Thank you :-)” Write-Host Out-File -FilePath $logfile -Append -InputObject ” Send-MailMessage -To <“To email addresses list”> -From <“From email address”> -Subject “AdminStudio Automation Test Results” -SmtpServer “smtp.acresso.com” -Attachments $logfile cd $sCurrentLoc