Automating the Application Readiness Process with PowerShell

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

Categories: Application Compatibility, Application Readiness, Application Virtualization, General

Leave a Reply

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