我終於在具有執行原則的用戶端上成功使用了 PowerShell 檢測腳本AllSigned
。 (提示:安裝後開始工作最新的服務包並使用Adam Meltzer 的解決方法.)
現在使用 PowerShell 腳本進行應用程式偵測已經很實用了,這讓我想知道以下事情:
- SCCM 用戶端在什麼上下文中執行 PowerShell 檢測腳本?系統?用戶?
- 上下文是否取決於您在部署類型中選擇“為使用者安裝”還是“為系統安裝”?
關於這個主題的文檔非常稀疏。我找到的 SCCM PowerShell 檢測腳本的最佳資源是這篇 Kloud 部落格文章然而,它對上下文問題保持沉默。
答案1
實驗結果
我編寫了一些 PowerShell,當作為檢測腳本運行時,會將檢測腳本看到的環境變數轉儲到日誌檔案中。該腳本位於此答案的末尾。
然後,我透過部署具有不同「安裝行為」和「登入要求」參數的部署類型,使 SCCM 用戶端執行此腳本。結果如下表:
Test InstallationBehavior LogonRequirement DeployedTo LoggedOnUser ScriptRunAs
---- -------------------- ---------------- ---------- ------------ -----------
1.1a Install for user Only when a user is logged on un2 un2 un2
1.1b Install for user Only when a user is logged on cn1 un2 un2
1.1c Install for user Only when a user is logged on cn1 un1 un1
1.2a Install for system Only when a user is logged on un2 un2 un2
1.2b Install for system Only when a user is logged on cn1 un2 cn1
1.2c Install for system Only when a user is logged on cn1 un1 cn1
1.3a Install for system Whether or not a user is logged on un2 un2 un2
1.3b Install for system Whether or not a user is logged on cn1 un2 cn1
1.3c Install for system Whether or not a user is logged on cn1 un1 cn1
unX
是使用者名稱cnX
是電腦名稱
分析
上述結果令人驚訝,因為偵測腳本運行的上下文似乎部分取決於應用程式是部署到使用者還是系統。這足以讓我感到驚訝,我第二次進行了測試。結果是一致的。
從上表我們可以初步得出以下假設:
- 當應用程式部署給使用者時,該應用程式的 PowerShell 偵測腳本將以該使用者身分執行。
- 當應用程式部署到系統並為系統安裝部署類型時,該應用程式的 PowerShell 偵測腳本將作為系統執行。
- 當應用程式部署到系統並為使用者安裝部署類型時,該應用程式的 PowerShell 偵測腳本將以登入使用者身分執行。
上述三個假設均得到檢驗結果的支持。很可能還有一些其他變數沒有經過檢驗,而這些假設並不成立。它們至少是使用 PowerShell 檢測腳本時的一組良好的初始假設。
上下文不符(當心!)
Jason Sandys 記錄了安裝上下文規則的類似測試。 如果您仔細閱讀該文章,您可能會注意到安裝上下文和檢測腳本上下文的規則並不完全相同。以下是違規規則:
當應用程式的安裝行為設定為「作為系統安裝」時,安裝程式將作為系統運行[無論部署到使用者]。
當應用程式部署給使用者時,該應用程式的 PowerShell 偵測腳本將以該使用者身分執行 [無論安裝行為是否設定為「作為系統安裝」]。
這意味著具有“安裝為系統”安裝行為的應用程式和部署到使用者集合將使用系統上下文進行安裝,但使用使用者情境進行偵測。
為安裝行為為「作為系統安裝」的應用程式編寫檢測腳本的人應小心避免依賴系統和使用者上下文之間發生變化的環境的任何部分。否則,部署到系統集合的應用程式的偵測可能會成功,而部署到使用者集合的完全相同的應用程式的偵測可能會失敗。
腳本
function Write-EnvToLog
{
$appName = 'script-detect-test'
$logFolderPath = "c:\$appName-$([System.Environment]::UserName)"
if ( -not (Test-Path $logFolderPath -PathType Container) )
{
New-Item -Path $logFolderPath -ItemType Directory | Out-Null
}
if ( -not (Test-Path $logFolderPath -PathType Container ) )
{
return
}
$logFileName = "$appName`__$((Get-Date).ToString("yyyy-MM-dd__HH-mm-ss")).txt"
$fp = "$logFolderPath\$logFileName"
Get-ChildItem Env: | Out-File $fp | Out-Null
return $true
}
try
{
if ( Write-EnvToLog ) { "Detected!" }
[System.Environment]::Exit(0)
}
catch
{
[System.Environment]::Exit(0)
}