UAM: Shell Apps の概要と使い方
多用途なShell Apps機能を使うと、統合アプリケーション管理(UAM)での展開向けに、複雑なスクリプトを用いた展開を作成できます。管理者は、PowerShell経由で複数のコンポーネントを展開し、検出スクリプト機能を使用して成功または失敗情報をUAMポリシーコンソールにレポートすることができます。
この機能は、大規模または複雑なアプリケーションでの使用、またはWinget経由での展開が実用的または望ましくない場合を想定しています。この機能はネイティブのPowerShellスクリプトを利用するため、必要に応じてインストールスクリプトの一部としてWinGetを呼び出すことができます。
Shell Apps機能を使用して展開されたアプリケーションは、デバイスのシステムコンテキスト内でのみ展開され、サービスアカウントの必要がありません。
この機能はNerdio ManagerScripted Actionsと同様の方法で機能します。Scripted Actionsを利用している場合、Shell Apps機能を採用しても問題は発生しません。
前提条件
PowerShellリモーティング(WSMan)は、ターゲットデバイスに有効にする必要があります。
制限事項
Shell Appsには、Secure Variablesを含む場合、Intuneデバイスに割り当てることはできません。
これはプレビュー機能であるため、以下に記載されている項目は現在利用できません。これらは将来のリリースで提供される予定です。
Secure Variablesサポート: Scripted Actionsと同様に、Secure Variablesは難読化された事前定義済みの項目をスクリプトに配信できます。
SCCM 統合: 接続された SCCM 環境から、関連バイナリ付きのスクリプトによるインストールを取り込む機能。
はじめに
Nerdio Managerで、アプリ > Shell Appsに移動して、Shell Apps機能を操作します。詳細については、UAM: シェルアプリを管理するを参照してください。
Notepad ++ (.EXE) と 7-Zip (MSI) は、ご利用開始時に含まれています。
展開は、以下のスクリプト領域に分割されます: 検出、インストール、アンインストール。有効なアプリケーションパッケージを作成するには、すべてのコンポーネントが必要です。
各アプリケーションパッケージには、Publicとラベル付けされたスイッチが含まれています。これは、UAM統合カタログページ内でアプリケーションの可視性を制御します。スクリプト完了までは、このスイッチをオフのままにしてください。そうすることで、展開時の問題を回避できます。
以下のガイダンスを参照し、サンプルスクリプトの動作や、Shell Apps機能を使った独自アプリの展開方法を確認してください。
ファイルパッケージ
Shell Appsは、必要に応じてパッケージファイルをアップロードすることをサポートしています。これは、インストーラー ファイルを含めたい場合や、インストール処理でインターネット上からファイルをダウンロードしないようにしたい場合に便利です。UAMがサポートするすべてのアプリは、Shell Appsでのインストールにも対応します。
使用状況
アップロードされたインストールパッケージを使用している場合、スクリプト内で組み込み変数$Context.GetAttachedBinary()を用いて呼び出せます。たとえば、添付されたインストールパッケージをインストールしたい場合、次のコマンドを使用できます:
Start-Process $Context.GetAttachedBinary() -Wait -ArgumentList "/S" |
ZIPアーカイブのサポート
Nerdio Managerのv6.2以降、Shell Appsでは、インストールプロセスの一環として、.ZIPアーカイブを利用し、複数のファイルをデスクトップに展開できます。オプションとして、これらの.ZIPアーカイブはアプリ展開タスク用に自動で抽出されることもあります。
使用状況
Shell Appsの「ファイル」ページで.ZIPアーカイブをインポートする際に、追加の「解凍」オプションが利用可能です。選択された場合、スクリプトは自動的に圧縮ファイルをターゲットデスクトップのC:\Windows\Tempの一時フォルダーに抽出します。
抽出後、スクリプトのコンテキストは自動的に作成された一時ディレクトリに設定されるため、すべてのインストールタスクはスクリプト内で相対パスを使用して完了できます。たとえば、Shell AppsインストールスクリプトからファイルEXAMPLE.MSIを呼び出すには、インストール処理の一部として、コマンド.\EXAMPLE.MSIではなく、コマンド.\EXAMPLE.MSI(実際は「.\EXAMPLE.MSI」)を使用してください。必要に応じて引数を追加できます。さらに、変換などの他のファイルやタスクも相対パスから呼び出すことができます。
例:Notepad ++ (.EXE)
検出スクリプト
検出スクリプト機能では、特定の問い合わせに対して正または負の値を返すルールセットを作成できます。特定のアプリケーション(Notepad ++)のための検出スクリプトの例を以下に示します。
この例では、PowerShellスクリプトが、プログラムのインストールフォルダーとその中の実行ファイルの存在を確認することで、対象プログラムの有無を効率的にチェックします。
$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 |
-
<# Variables:
$basePath: システム環境変数から取得したプログラムファイルディレクトリのパスを格納します ($env:ProgramFiles)。$programFolderName: プログラムフォルダーの名前を指定します(この場合は「Notepad++」)。$programFolderFullPath:$basePathと$programFolderNameをJoin-Pathで組み合わせ、プログラムフォルダーの完全なパスを取得します。
-
プログラムフォルダーの存在確認:
$programFolderExists = Test-Path $programFolderFullPath
if (!$programFolderExists) {
return $false
}
Test-Path: 指定されたパスにファイルまたはディレクトリが存在するかどうかを判断するために使用されるCmdletです。$programFolderExists: プログラムフォルダーの存在チェックの結果を格納します。プログラムフォルダーが存在しない場合(
!$programFolderExists)、スクリプトは$falseを返し、プログラムがインストールされていないことを示します。
-
プログラムファイルパスの構築:
$programFileName = 'notepad++.exe'
$programFileFullPath = Join-Path $programFolderFullPath $programFileName
$programFileName: プログラム実行ファイルの名前を指定します。$programFileFullPath:$programFolderFullPathと$programFileNameをJoin-Pathで組み合わせ、プログラム実行ファイルのフルパスを取得します。
-
プログラムファイルの存在確認:
return Test-Path $programFileFullPath
指定されたパスにプログラム実行ファイルが存在するかどうかを確認します。
スクリプトは、この存在チェックの結果を返し、プログラムがインストールされているか(
$true)、インストールされていないか($false)を示します。
インストールスクリプト
インストールスクリプトは、アプリの展開を成功させるために必要なすべてのコンポーネントをインストールし、構成します。
この例では、PowerShellスクリプトがNotepad++のインストーラーをダウンロードし、サイレントで実行し(/S引数)、その後クリーンアップを行うことでインストールを自動化します。
$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') |
-
<# Variables:
$basePath: システム環境変数から取得した一時ディレクトリのパスを格納します($env:TEMP)。$installerFolderName: Notepad++インストーラーのフォルダー名を指定します。一意性を確保するために、動的に生成されたGUIDが含まれています。$installerFolderFullPath:$basePathと$installerFolderNameをJoin-Pathで組み合わせ、インストーラーフォルダーのフルパスを取得します。
-
インストーラーフォルダーの確認と作成:
$installerFolderExists = Test-Path $installerFolderFullPath
if ($installerFolderExists) {
Remove-Item $installerFolderFullPath -Recurse -Force -ErrorAction Stop
}
New-Item -Path $basePath -Name $installerFolderName -ItemType Directory -Force | Out-Null
インストーラーフォルダーがすでに存在するかどうかを確認します。存在する場合は、クリーンなインストール環境を確保するために、再帰的かつ強制的に削除します。
New-Itemcmdletを使用してインストーラー用の新しいディレクトリを作成します。
-
インストーラーのダウンロード:
$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
Notepad++インストーラーのURLを指定します。
Invoke-WebRequestを使用してインストーラー実行ファイルをダウンロードし、指定されたパスに保存します。
-
インストールプロセスの開始:
Start-Process "$installerFullPath" -Wait -ArgumentList "/S"
インストーラー実行ファイルを起動することでインストールプロセスを開始します。
-Waitパラメータは、スクリプトがインストールの完了を待つことを保証します。
-
クリーンアップ:
Remove-Item $installerFolderFullPath -Recurse -Force
インストールが完了した後、インストーラーフォルダーとその内容を削除し、クリーンな環境を確保します。
-
ログ記録:
$Context.Log('Install script completed')
インストールスクリプトが完了したことを示すメッセージをログに記録します。この関数は、後でポリシー詳細ページで利用可能なメッセージをログに記録することもできます。これは
$Context.Log(string $message)として使用できます。
アンインストールスクリプト
アンインストールスクリプトは、ポリシー評価プロセスの一環として指定されたアプリを削除する機能を提供します。検出スクリプトは再利用され、指定された検出項目が存在しないことを確認します。
この例では、PowerShellスクリプトがプログラムフォルダーとアンインストーラー実行ファイルの両方の存在を確認することでNotepad++のアンインストールを自動化します。両方が見つかった場合、アンインストーラーをサイレントで実行します(/S引数)。
$basePath = $env:ProgramFiles |
$programFolderName = "Notepad++" |
$programFolderFullPath = Join-Path $basePath $programFolderName |
$programFolderExists = Test-Path $programFolderFullPath |
if (!$programFolderExists) { |
throw "Notepad++が見つかりません" |
} |
$uninstallerFileName = 'uninstall.exe' |
$uninstallerFileFullPath = Join-Path $programFolderFullPath $uninstallerFileName |
$uninstallerFileExists = Test-Path $uninstallerFileFullPath |
if (!$uninstallerFileExists) { |
throw "Notepad++アンインストーラーが見つかりません" |
} |
Start-Process "$uninstallerFileFullPath" -Wait -ArgumentList "/S" |
$Context.Log('Uninstall script completed') |
-
<# Variables:
$basePath: システム環境変数から取得したプログラムファイルディレクトリのパスを格納します ($env:ProgramFiles)。$programFolderName: プログラムフォルダーの名前を指定します(この場合は「Notepad++」)。$programFolderFullPath:$basePathと$programFolderNameをJoin-Pathで組み合わせ、プログラムフォルダーのフルパスを取得します。
-
プログラムフォルダーの存在確認:
$programFolderExists = Test-Path $programFolderFullPath
if (!$programFolderExists) {
throw "Notepad++が見つかりません"
}
Test-Path: 指定されたパスにファイルまたはディレクトリが存在するかどうかを判断するために使用されるCmdletです。Notepad++プログラムフォルダーが存在しない場合、エラーをスローし、Notepad++がインストールされていないことを示します。
-
アンインストーラーファイルの存在確認:
$uninstallerFileName = 'uninstall.exe'
$uninstallerFileFullPath = Join-Path $programFolderFullPath $uninstallerFileName
$uninstallerFileExists = Test-Path $uninstallerFileFullPath
if (!$uninstallerFileExists) {
throw "Notepad++のアンインストーラーが見つかりません"
}
Notepad++のアンインストーラー実行ファイルへのフルパスを構築します (
uninstall.exe)。アンインストーラー実行ファイルが存在するかどうかを確認します。存在しない場合、アンインストーラーが見つからないことを示すエラーをスローします。
-
アンインストールプロセスの開始:
Start-Process "$uninstallerFileFullPath" -Wait -ArgumentList "/S"
アンインストーラー実行ファイルを起動することによってアンインストールプロセスを開始します。
-Waitパラメータは、スクリプトがアンインストールの完了を待つことを保証します。
-
ログ記録:
$Context.Log('Uninstall script completed')
アンインストールスクリプトが完了したことを示すメッセージをログに記録します。この関数は、後でポリシー詳細ページで利用可能なメッセージをログに記録することもできます。これは
$Context.Log(string $message)として使用できます。
例:7-Zip (.msi)
検出スクリプト
検出スクリプト機能は、特定のクエリに対して正または負の値を返すルールセットを作成する能力を提供します。特定のアプリ(7-Zip)の検出スクリプトの例を以下に示します。このPowerShellスクリプトは、Windowsレジストリにおけるアンインストール情報の存在を確認することによって特定のプログラムの存在をチェックします。
$basePath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" |
$productCode = '{23170F69-40C1-2702-2201-000001000000}' |
$programRegistryPath = Join-Path $basePath $productCode |
return Test-Path $programRegistryPath |
-
<# Variables:
$basePath:インストールされたプログラムのアンインストール情報が通常保存されるWindowsレジストリのベースパスを格納します。この場合、すべてのユーザーのインストールされたプログラムのレジストリの場所であるHKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstallを指します。$productCode:確認対象のプログラムに関連付けられたユニークな製品コードを指定します。このコードは通常 GUID(Globally Unique Identifier)であり、レジストリ内でプログラムを識別するために使用されます。$programRegistryPath:ベースパス($basePath)と製品コード($productCode)をJoin-Pathで組み合わせ、プログラムのアンインストール情報へのレジストリのフルパスを形成します。
-
プログラムレジストリキーの存在確認:
return Test-Path $programRegistryPath
Test-Path:指定されたパスにファイル、ディレクトリ、またはこの場合はレジストリキーが存在するかどうかをテストするために使用されるコマンドレットです。
スクリプトは、この存在テストの結果を返し、プログラムがインストールされているか(レジストリキーが存在する)どうかを示します。
インストールスクリプト
インストールスクリプトは、アプリの正常な展開に必要なすべてのコンポーネントをインストールおよび設定します。このPowerShellスクリプトは、インストーラーMSIファイルをダウンロードし、サイレントで実行し(/qn引数)、その後クリーンアップすることで7-Zipのインストールを自動化します。
$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') |
-
<# Variables:
$basePath: システム環境変数から取得した一時ディレクトリのパスを格納します($env:TEMP)。$installerFolderName:7-Zipインストーラーのフォルダー名を指定します。一意性を確保するために、動的に生成されたGUIDが含まれています。$installerFolderFullPath:$basePathと$installerFolderNameをJoin-Pathで結合し、インストーラーフォルダーの完全なパスを取得します。
-
インストーラーフォルダーの確認と作成:
$installerFolderExists = Test-Path $installerFolderFullPath
if ($installerFolderExists) {
Remove-Item $installerFolderFullPath -Recurse -Force -ErrorAction Stop
}
New-Item -Path $basePath -Name $installerFolderName -ItemType Directory -Force | Out-Null
インストーラーフォルダーがすでに存在するかどうかを確認します。存在する場合は、クリーンなインストール環境を確保するために、再帰的かつ強制的に削除します。
New-Itemcmdletを使用してインストーラー用の新しいディレクトリを作成します。
-
インストーラーのダウンロード:
$installerName = 'installer.msi'
$installerFullPath = Join-Path $installerFolderFullPath $installerName
$installerUrl = "https://7-zip.org/a/7z2201-x64.msi"
Invoke-WebRequest -URI $installerUrl -OutFile $installerFullPath
7-ZipインストーラーのURLを指定します。
Invoke-WebRequestを使用してインストーラーMSIファイルをダウンロードし、指定されたパスに保存します。
-
インストールプロセスの開始:
Start-Process msiexec -ArgumentList "/i `"$installerFullPath`" /qn" -Wait
msiexecユーティリティを/i(インストール)フラグとMSIインストーラーファイルのパス($installerFullPath)で起動することによって、インストールプロセスを開始します。/qnパラメーターは、ユーザーインターフェースを表示せずにサイレントでインストールします。
-
クリーンアップ:
Remove-Item $installerFolderFullPath -Recurse -Force
インストールが完了した後、インストーラーフォルダーとその内容を削除し、クリーンな環境を確保します。
-
ログ記録:
$Context.Log('Install script completed')
インストールスクリプトが完了したことを示すメッセージをログに記録します。この関数は、後でポリシーの詳細ページで利用可能なメッセージをログに記録することもできます。これは
$Context.Log(string $message)として使用できます。
アンインストールスクリプト
アンインストールスクリプトは、ポリシー評価プロセスの一環として指定されたアプリケーションを削除する機能を提供します。検出スクリプトは、指定された検出項目が存在しないことを確認するために再利用できます。この例のPowerShellスクリプトは、7-Zipのアンインストールレジストリキーの存在を確認し、サイレントでアンインストールプロセスを開始することによって、7-Zipのアンインストールを自動化します。
$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 "7-Zipが見つかりません" |
} |
Start-Process msiexec -ArgumentList "/x `"$productCode`" /qn" -Wait |
$Context.Log('Uninstall script completed') |
-
<# Variables:
$basePath:インストールされたプログラムのアンインストール情報が通常保存されるWindowsレジストリ内の基本パスを格納します。この場合、すべてのユーザーのインストールされたプログラムのレジストリの場所であるHKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstallを指します。$productCode:7-Zipに関連付けられている一意の製品コードを指定します。このコードは通常GUID(Globally Unique Identifier)であり、レジストリ内でプログラムを識別するために使用されます。$programRegistryPath:ベースパス($basePath)と製品コード($productCode)をJoin-Path使用して組み合わせ、プログラムのアンインストール情報への完全なレジストリのパスを形成します。
-
プログラムレジストリキーの存在確認:
$programExists = Test-Path $programRegistryPath if (!$programExists) {
throw "7-Zipが見つかりません"
}
Test-Path:指定されたパスにレジストリキーが存在するかどうかを判断するために使用されるコマンドレットです。レジストリキーが存在しない場合、エラーをスローし、7-Zipがインストールされていないことを示します。
-
アンインストールプロセスの開始:
Start-Process msiexec -ArgumentList "/x `"$productCode`" /qn" -Wait
msiexecユーティリティを/x(アンインストール用)フラグと製品コード($productCode)で起動して、アンインストールプロセスを開始します。/qnパラメータは、ユーザーインターフェイスを表示せずにサイレントでアンインストールします。
-
ログ:
$Context.Log('Uninstall script completed')
アンインストールスクリプトが完了したことを示すメッセージをログします。この関数は、後でポリシー詳細ページで利用可能なメッセージをログすることもできます。これは
$Context.Log(string $message)として使用できます。
バージョン管理
Nerdio Manager v6.6以降、Shell Appsはバージョン管理をサポートしています。このセクションでは、ユーザーインターフェイス内でアプリのバージョンを作成および使用するためのガイダンスを提供します。
バージョン設定の UI とフローの例
バージョン設定ユーザーインターフェイスおよびフローの例については、UAM: Shell Apps 技術リファレンスガイドを参照してください。
バージョン管理の例
以下の例は、Shell Apps内でバージョンを管理するための提案されたアプローチとして提供されています。これは非常に柔軟な機能であり、顧客はパッケージのインストール状況を判断するために、さまざまな検出された環境条件を利用することができます。この例では、ファイルバージョンを検出ルールとして使用しますが、この機能はレジストリ キー、ファイル、およびフォルダーにも同様に適用されます。
検出スクリプト
以下の検出スクリプトは、指定されたパスの実行可能ファイルを検査し、製品バージョン情報を返します。
注意: 検出スクリプトは、バージョン形式x.x.x.xで結果を返すように構成する必要があります。特定のバージョンの場合、バージョンプロパティ内のNameの値は、関連付けられたポリシーがアプリの状態を評価するために、検出スクリプトが返す値と一致している必要があります。
$nppDirPath = Join-Path $env:ProgramFiles "Notepad++" $exePath = Join-Path $nppDirPath 'notepad++.exe' if (!(Test-Path $exePath)) { return $null # 何もインストールされていません } # .exeメタデータからバージョンを取得 return (Get-Item $exePath).VersionInfo.ProductVersion |
インストールスクリプト
以下のインストールスクリプトは、UAMポリシーで定義され、スクリプト内で$Context.TargetVersionとして利用可能なアプリのターゲットバージョンをインストールします。
$installerTempDir = Join-Path $env:TEMP "Notepad $(New-Guid)" |
$installerPath = Join-Path $installerTempDir 'installer.exe' |
# Tempフォルダーにディレクトリを作成 |
New-Item -Path $installerTempDir -ItemType Directory -Force | Out-Null |
# ターゲットバージョンに基づいて動的にURLを生成 |
# デプロイメントポリシーで構成 |
$version = $Context.TargetVersion |
$installerUrl = "https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v$version/npp.$version.Installer.x64.exe" |
# ファイルをダウンロードし、サイレントスイッチでインストールを実行 |
Invoke-WebRequest -URI $installerUrl -OutFile $installerPath |
Start-Process "$installerPath" -Wait -ArgumentList "/S" |
# 自分たちの後始末 |
Remove-Item $installerTempDir -Recurse -Force |
アンインストールスクリプト
以下のアンインストールスクリプトは、検出ルールの条件が満たされている場合に、定義されたルーチンを使用してアプリを単純にアンインストールします。
$nppDirPath = Join-Path $env:ProgramFiles "Notepad++" |
$uninstallerPath = Join-Path $nppDirPath 'uninstall.exe' |
Start-Process "$uninstallerPath" -Wait -ArgumentList "/S" |
コメント (0件のコメント)