Automating the Application Readiness Process with PowerShell

bkelly
Moderator Moderator
Moderator
2 5 2,537

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.

app-ready-process.png

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
Tags (1)
5 Comments
Latest Articles