Wyniki empiryczne
Napisałem PowerShell, który po uruchomieniu jako skrypt wykrywający zrzuca zmienne środowiskowe, które skrypt wykrywa do pliku dziennika. Ten skrypt znajduje się na końcu tej odpowiedzi.
Następnie powoduję, że ten skrypt jest uruchamiany przez klienta SCCM, wdrażając typ wdrożenia z różnymi parametrami „Zachowanie podczas instalacji” i „Wymagania dotyczące logowania”. Wyniki znajdują się w poniższej tabeli:
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
są nazwy użytkownika
cnX
to nazwy komputerów
Analiza
Powyższe wyniki są zaskakujące, ponieważ kontekst, w którym działa skrypt wykrywający, wydaje się częściowo zależeć od tego, czy aplikacja została wdrożona do użytkownika, czy do systemu. To było dość niespodzianką, że przeprowadziłem testy po raz drugi. Wyniki były spójne.
Możemy wstępnie wyciągnąć następujące hipotezy z powyższej tabeli:
- Gdy aplikacja jest wdrażana dla użytkownika, skrypt wykrywający PowerShell dla tej aplikacji jest uruchamiany jako ten użytkownik.
- Gdy aplikacja jest wdrażana w systemie, a typ instalacji jest instalowany w systemie, skrypt wykrywający PowerShell dla tej aplikacji jest uruchamiany jako system.
- Gdy aplikacja jest wdrażana w systemie, a typ instalacji jest instalowany dla użytkownika, skrypt wykrywający PowerShell dla tej aplikacji jest uruchamiany jako zalogowany użytkownik.
Powyższe trzy hipotezy są poparte wynikami testu. Mogą istnieć pewne inne zmienne, które nie zostały przetestowane w przypadku, gdy te hipotezy nie mają zastosowania. Są to przynajmniej dobry zestaw wstępnych założeń podczas korzystania ze skryptów wykrywających PowerShell.
Niedopasowane konteksty (uwaga!)
Jason Sandys udokumentował podobny test reguł w kontekście instalacji. Jeśli dokładnie przeczytasz ten post, możesz zauważyć, że reguły kontekstu instalacji i kontekstu skryptu wykrywania nie są takie same. Oto złe zasady:
Gdy zachowanie instalacyjne aplikacji jest ustawione na „Instaluj jako system”, instalator jest uruchamiany jako system [niezależnie od wdrożenia dla użytkownika].
Gdy aplikacja jest wdrażana dla użytkownika, skrypt wykrywający PowerShell dla tej aplikacji jest uruchamiany jako ten użytkownik [niezależnie od tego, czy zachowanie instalacyjne jest ustawione na „Instaluj jako system”].
Oznacza to, że aplikacja, która zachowuje się podczas instalacji „Zainstaluj jako system” i jest wdrożona w kolekcji użytkowników, będzie używać kontekstu systemu do instalacji, ale kontekstu użytkownika do wykrywania.
Ktoś piszący skrypty wykrywające dla aplikacji, w których zachowanie instalacji brzmi „Zainstaluj jako system”, powinien uważać, aby nie polegać na jakiejkolwiek części środowiska, która zmienia się między kontekstem systemowym a kontekstem użytkownika. W przeciwnym razie wykrycie aplikacji wdrożonej w kolekcji systemowej może się powieść, podczas gdy wykrycie tej samej aplikacji wdrożonej w kolekcji użytkownika zakończy się niepowodzeniem.
Scenariusz
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)
}