Unified Application Management: Shell Apps Overview and Usage

Unified Application Management: Shell Apps Overview and Usage

The versatile Shell Apps feature offers the ability to create complex scripted deployment for Unified Application Management (UAM) deployment. Administrators can deploy multiple components via PowerShell and use the detection script feature to report success or failure information back to the UAM policy console for review.

This feature is intended for use with large or complex applications, or where deployment via Winget is not practical or desirable. Because the feature makes use of native PowerShell scripts, Winget can be called as part of an installation script if required.

Applications deployed using the Shell Apps feature are deployed exclusively in the device system context, avoiding the need for any service account.

This feature functions in a similar way to Nerdio Manager Scripted actions. If you are making use of scripted actions, there should be no complications when adopting the Shell Apps feature.

Prerequisites

PowerShell remoting (WSMan) must be enabled for the target devices.

Limitations

The Shell Apps feature is currently only supported for AVD hosts.

Because this is a preview feature, the items noted below are not currently available. These are planned for future releases.

  • Secure variable support: As with scripted actions, secure variables provide the ability to deliver obfuscated, predefined items into the script.

  • SCCM integration: The ability to ingest scripted installations with their associated binaries from connected SCCM environments.

Getting Started

In Nerdio Manager, navigate to ApplicationsShell Apps to work with the Shell Apps feature. See Unified Application Management: Manage Shell Apps for details.

  • Notepad ++ (.EXE) and 7-Zip (MSI) are included when you get started.

  • Deployments are split into the following script areas: Detection, Install and Uninstall. All components are required to form a valid application package.

  • Each application package contains a switch labeled Public. This controls the application’s visibility within the UAM unified catalog page. It is recommended that this switch remains Off until you have completed your scripts, to avoid any potential deployment issues.

Please refer to the guidance below to understand how these example scripts function, and how you can reuse these to deploy your own applications using the Shell Apps feature.

Example: Notepad ++ (.EXE)

Detection Script

The detection script function provides the ability to create a ruleset that returns a positive or negative value for a specific query. We provide an example below of the detection script for a specific application (Notepad ++).

In this example, the PowerShell script efficiently checks for the existence of a specific program by verifying the existence of its installation folder and the program executable file within that folder.

Script Body

$basePath = $env:ProgramFiles

$programFolderName = "Notepad++"

$programFolderFullPath = Join-Path $basePath $programFolderName

 

$programFolderExists = Test-Path $programFolderFullPath

if (!$programFolderExists) {

return $false

}

 

$programFileName = 'notepad++.exe'

$programFileFullPath = Join-Path $programFolderFullPath $programFileName

 

return Test-Path $programFileFullPath

Components Breakdown

  1. Variables:

    • $basePath: Stores the path of the Program Files directory retrieved from the system environment variables ($env:ProgramFiles).

    • $programFolderName: Specifies the name of the program folder (in this case, "Notepad++").

    • $programFolderFullPath: Combines $basePath and $programFolderName using Join-Path to get the full path of the program folder.

  2. Checking Program Folder Existence:

    $programFolderExists = Test-Path $programFolderFullPath if (!$programFolderExists) { return $false }

    • Test-Path: Cmdlet used to determine whether a file or directory exists at a specified path.

    • $programFolderExists: Stores the result of the existence check for the program folder.

    • If the program folder doesn't exist (!$programFolderExists), the script returns $false, indicating that the program is not installed.

  3. Constructing Program File Path:

    $programFileName = 'notepad++.exe' $programFileFullPath = Join-Path $programFolderFullPath $programFileName

    • $programFileName: Specifies the name of the program executable file.

    • $programFileFullPath: Combines $programFolderFullPath and $programFileName using Join-Path to get the full path of the program executable file.

  4. Checking Program File Existence:

    return Test-Path $programFileFullPath

    • Checks if the program executable file exists at the specified path.

    • The script returns the result of this existence check, which indicates whether the program is installed ($true) or not ($false).

Installation Script

The installation script installs and configures all required components for the successful deployment of the application.

In this example, the PowerShell script automates the installation of Notepad++ by downloading the installer, executing it silently (/S argument), and cleaning up afterward.

Script Body

$basePath = $env:TEMP

$installerFolderName = "Notepad $(New-Guid)"

$installerFolderFullPath = Join-Path $basePath $installerFolderName

 

$installerFolderExists = Test-Path $installerFolderFullPath

if ($installerFolderExists) {

Remove-Item $installerFolderFullPath -Recurse -Force -ErrorAction Stop

}

 

New-Item -Path $basePath -Name $installerFolderName -ItemType Directory -Force | Out-Null

 

$installerName = 'installer.exe'

$installerFullPath = Join-Path $installerFolderFullPath $installerName

 

$installerUrl = "https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v8.6/npp.8.6.Installer.x64.exe"

Invoke-WebRequest -URI $installerUrl -OutFile $installerFullPath

 

Start-Process "$installerFullPath" -Wait -ArgumentList "/S"

 

Remove-Item $installerFolderFullPath -Recurse -Force

 

$Context.Log('Install script completed')

Components Breakdown

  1. Variables:

    • $basePath: Stores the path of the temporary directory retrieved from the system environment variables ($env:TEMP).

    • $installerFolderName: Specifies the name of the folder for the Notepad++ installer. It includes a dynamically-generated GUID to ensure uniqueness.

    • $installerFolderFullPath: Combines $basePath and $installerFolderName using Join-Path to get the full path of the installer folder.

  2. Checking and Creating Installer Folder:

    $installerFolderExists = Test-Path $installerFolderFullPath if ($installerFolderExists) { Remove-Item $installerFolderFullPath -Recurse -Force -ErrorAction Stop } New-Item -Path $basePath -Name $installerFolderName -ItemType Directory -Force | Out-Null

    • Checks if the installer folder already exists. If it does, it removes it recursively and forcefully to ensure a clean installation environment.

    • Creates a new directory for the installer using New-Item cmdlet.

  3. Downloading Installer:

    $installerUrl = "https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v8.6/npp.8.6.Installer.x64.exe" Invoke-WebRequest -URI $installerUrl -OutFile $installerFullPath

    • Specifies the URL of the Notepad++ installer.

    • Downloads the installer executable using Invoke-WebRequest and saves it to the specified path.

  4. Starting Installation Process:

    Start-Process "$installerFullPath" -Wait -ArgumentList "/S"

    • Initiates the installation process by starting the installer executable. The -Wait parameter ensures that the script waits for the installation to complete before proceeding.

  5. Cleaning Up:

    Remove-Item $installerFolderFullPath -Recurse -Force

    • Removes the installer folder and its contents after the installation is complete, ensuring a clean environment.

  6. Logging:

    $Context.Log('Install script completed')

    • Logs a message indicating that the installation script has completed. This function can also log a message which is later available on the Policy Details page. This can be used as $Context.Log(string $message).

Uninstall Script

The uninstall script provides the ability to remove a specified application as part of the policy assessment process. The detection script is re-used to confirm the specified detection items are not present.

In this example, the PowerShell script automates the uninstallation of Notepad++ by checking for the existence of both the program folder and the uninstaller executable. If both are found, it executes the uninstaller silently (/S argument).

Script Body

$basePath = $env:ProgramFiles

$programFolderName = "Notepad++"

$programFolderFullPath = Join-Path $basePath $programFolderName

 

$programFolderExists = Test-Path $programFolderFullPath

if (!$programFolderExists) {

throw "Notepad++ is not found"

}

 

$uninstallerFileName = 'uninstall.exe'

$uninstallerFileFullPath = Join-Path $programFolderFullPath $uninstallerFileName

 

$uninstallerFileExists = Test-Path $uninstallerFileFullPath

if (!$uninstallerFileExists) {

throw "Notepad++ uninstaller is not found"

}

 

Start-Process "$uninstallerFileFullPath" -Wait -ArgumentList "/S"

 

$Context.Log('Uninstall script completed')

Components Breakdown

  1. Variables:

    • $basePath: Stores the path of the Program Files directory retrieved from the system environment variables ($env:ProgramFiles).

    • $programFolderName: Specifies the name of the program folder (in this case, "Notepad++").

    • $programFolderFullPath: Combines $basePath and $programFolderName using Join-Path to get the full path of the program folder.

  2. Checking Program Folder Existence:

    $programFolderExists = Test-Path $programFolderFullPath if (!$programFolderExists) { throw "Notepad++ is not found" }

    • Test-Path: Cmdlet used to determine whether a file or directory exists at a specified path.

    • Throws an error if the Notepad++ program folder doesn't exist, indicating that Notepad++ is not installed.

  3. Checking Uninstaller File Existence:

    $uninstallerFileName = 'uninstall.exe' $uninstallerFileFullPath = Join-Path $programFolderFullPath $uninstallerFileName $uninstallerFileExists = Test-Path $uninstallerFileFullPath if (!$uninstallerFileExists) { throw "Notepad++ uninstaller is not found" }

    • Constructs the full path to the Notepad++ uninstaller executable (uninstall.exe).

    • Checks if the uninstaller executable exists. If it doesn't, throws an error indicating that the uninstaller is not found.

  4. Starting Uninstallation Process:

    Start-Process "$uninstallerFileFullPath" -Wait -ArgumentList "/S"

    • Initiates the uninstallation process by starting the uninstaller executable. The -Wait parameter ensures that the script waits for the uninstallation to complete before proceeding.

  5. Logging:

    $Context.Log('Uninstall script completed')

    • Logs a message indicating that the uninstallation script has completed. This function can also log a message which is later available on the Policy Details page. This can be used as $Context.Log(string $message).

Example: 7-Zip (.MSI)

Detection Script

The detection script function provides the ability to create a ruleset which returns a positive or negative value for a specific query. We provide an example below of the detection script for a specific application (7-Zip). This PowerShell script checks for the existence of a specific program by verifying the presence of its uninstall information in the Windows Registry.

Script Body

$basePath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"

$productCode = '{23170F69-40C1-2702-2201-000001000000}'

$programRegistryPath = Join-Path $basePath $productCode

 

return Test-Path $programRegistryPath

Components Breakdown

  1. Variables:

    • $basePath: Stores the base path in the Windows Registry where the uninstall information for installed programs is typically stored. In this case, it points to HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, which is the registry location for installed programs for all users.

    • $productCode: Specifies the unique product code associated with the program being checked. This code is typically a GUID (Globally Unique Identifier) and is used to identify the program in the registry.

    • $programRegistryPath: Combines the base path ($basePath) and the product code ($productCode) using Join-Path to form the full registry path to the program's uninstall information.

  2. Checking Program Registry Key Existence:

    return Test-Path $programRegistryPath

    • Test-Path: Cmdlet used to determine whether a file, directory, or in this case, a registry key exists at a specified path.

    • The script returns the result of this existence check, which indicates whether the program is installed (registry key exists) or not.

Installation Script

The installation script installs and configures all required components for the successful deployment of the application. This PowerShell script automates the installation of 7-Zip by downloading the installer MSI file, executing it silently (/qn argument), and cleaning up afterward.

Script Body

$basePath = $env:TEMP

$installerFolderName = "7zip $(New-Guid)"

$installerFolderFullPath = Join-Path $basePath $installerFolderName

 

$installerFolderExists = Test-Path $installerFolderFullPath

if ($installerFolderExists) {

Remove-Item $installerFolderFullPath -Recurse -Force -ErrorAction Stop

}

 

New-Item -Path $basePath -Name $installerFolderName -ItemType Directory -Force | Out-Null

 

$installerName = 'installer.msi'

$installerFullPath = Join-Path $installerFolderFullPath $installerName

 

$installerUrl = "https://7-zip.org/a/7z2201-x64.msi"

Invoke-WebRequest -URI $installerUrl -OutFile $installerFullPath

 

Start-Process msiexec -ArgumentList "/i `"$installerFullPath`" /qn" -Wait

 

Remove-Item $installerFolderFullPath -Recurse -Force

 

$Context.Log('Install script completed')

Components Breakdown

  1. Variables:

    • $basePath: Stores the path of the temporary directory retrieved from the system environment variables ($env:TEMP).

    • $installerFolderName: Specifies the name of the folder for the 7-Zip installer. It includes a dynamically generated GUID to ensure uniqueness.

    • $installerFolderFullPath: Combines $basePath and $installerFolderName using Join-Path to get the full path of the installer folder.

  2. Checking and Creating Installer Folder:

    $installerFolderExists = Test-Path $installerFolderFullPath if ($installerFolderExists) { Remove-Item $installerFolderFullPath -Recurse -Force -ErrorAction Stop } New-Item -Path $basePath -Name $installerFolderName -ItemType Directory -Force | Out-Null

    • Checks if the installer folder already exists. If it does, it removes it recursively and forcefully to ensure a clean installation environment.

    • Creates a new directory for the installer using New-Item cmdlet.

  3. Downloading Installer:

    $installerName = 'installer.msi' $installerFullPath = Join-Path $installerFolderFullPath $installerName $installerUrl = "https://7-zip.org/a/7z2201-x64.msi" Invoke-WebRequest -URI $installerUrl -OutFile $installerFullPath

    • Specifies the URL of the 7-Zip installer.

    • Downloads the installer MSI file using Invoke-WebRequest and saves it to the specified path.

  4. Starting Installation Process:

    Start-Process msiexec -ArgumentList "/i `"$installerFullPath`" /qn" -Wait

    • Initiates the installation process by starting the msiexec utility with the /i (install) flag and the path to the MSI installer file ($installerFullPath). The /qn parameter installs silently without displaying any user interface.

  5. Cleaning Up:

    Remove-Item $installerFolderFullPath -Recurse -Force

    • Removes the installer folder and its contents after the installation is complete, ensuring a clean environment.

  6. Logging:

    $Context.Log('Install script completed')

    • Logs a message indicating that the installation script has completed. This function can also log a message which is later available on policy Details page. This can be used as $Context.Log(string $message).

Uninstall Script

The uninstall script provides the ability to remove a specified application as part of the policy assessment process. The detection script can be re-used to confirm the specified detection items are not present. This example PowerShell script automates the uninstallation of 7-Zip by checking for the existence of its uninstallation registry key and initiating the uninstallation process silently.

Script Body

$basePath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"

$productCode = '{23170F69-40C1-2702-2201-000001000000}'

$programRegistryPath = Join-Path $basePath $productCode

 

$programExists = Test-Path $programRegistryPath

if (!$programExists) {

throw "7zip is not found"

}

 

Start-Process msiexec -ArgumentList "/x `"$productCode`" /qn" -Wait

 

$Context.Log('Uninstall script completed')

Components Breakdown

  1. Variables:

    • $basePath: Stores the base path in the Windows Registry where uninstall information for installed programs is typically stored. In this case, it points to HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, which is the registry location for installed programs for all users.

    • $productCode: Specifies the unique product code associated with 7-Zip. This code is typically a GUID (Globally Unique Identifier) and is used to identify the program in the registry.

    • $programRegistryPath: Combines the base path ($basePath) and the product code ($productCode) using Join-Path to form the full registry path to the program's uninstall information.

  2. Checking Program Registry Key Existence:

    $programExists = Test-Path $programRegistryPath if (!$programExists) { throw "7zip is not found" }

    • Test-Path: Cmdlet used to determine whether a registry key exists at a specified path.

    • Throws an error if the registry key for 7-Zip doesn't exist, indicating that 7-Zip is not installed.

  3. Starting Uninstallation Process:

    Start-Process msiexec -ArgumentList "/x `"$productCode`" /qn" -Wait

    • Initiates the uninstallation process by starting the msiexec utility with the /x (uninstall) flag and the product code ($productCode). The /qn parameter uninstalls silently without displaying any user interface.

  4. Logging:

    $Context.Log('Uninstall script completed')

    • Logs a message indicating that the uninstallation script has completed. This function can also log a message which is later available on the Policy Details page. This can be used as $Context.Log(string $message).

Was this article helpful?

0 out of 0 found this helpful
Have more questions? Submit a request

Comments (0 comments)

Please sign in to leave a comment.