Емпіричні результати
Я написав 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.
Невідповідні контексти (будьте обережні!)
Джейсон Сенді задокументував аналогічний тест правил встановлення контексту. Якщо ви уважно прочитали цю публікацію, ви можете помітити, що правила для контексту встановлення та контекст сценарію виявлення не зовсім однакові. Ось кривдні правила:
Коли поведінка програми встановлення програми встановлено на "Встановити як система", інсталятор запускається як система [незалежно від розгортання до користувача].
Коли додаток розгорнуто до користувача, сценарій виявлення 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)
}