在什么情况下运行SCCM Powershell检测脚本?

使用AllSigned执行策略在客户端上使用PowerShell检测脚本终于成功了。 (提示:在安装最新的服务包并使用Adam Meltzer的解决方法之后,它开始工作。)

现在,使用PowerShell脚本进行应用程序检测是非常实用的,这让我很想知道以下几点:

  1. SCCM客户端在什么情况下运行PowerShell检测脚本? 系统? 用户?
  2. 上下文依赖于是否在部署types中select“为用户安装”或“为系统安装”?

文档在这个主题上相当稀less。 我发现的SCCM PowerShell检测脚本的最佳资源是Kloud博客文章 ,但在上下文中没有提到 。

实证结果

我编写了一些PowerShell,当作为检测脚本运行时,将检测脚本看到的环境variables转储到日志文件中。 该脚本是在这个答案的结尾。

然后,通过部署具有不同“安装行为”和“login要求”参数的部署types,使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是计算机名称

分析

上述结果令人惊讶,因为检测脚本运行的上下文似乎部分取决于应用程序是部署到用户还是系统。 这足以让我再次进行testing。 结果是一致的。

我们可以暂时从上表中提出以下假设:

  1. 将应用程序部署到用户时,该应用程序的PowerShell检测脚本以该用户身份运行。
  2. 将应用程序部署到系统并为系统安装部署types时,该应用程序的PowerShell检测脚本将作为系统运行。
  3. 将应用程序部署到系统并为用户安装部署types时,该应用程序的PowerShell检测脚本以login用户身份运行。

以上三个假设是由testing结果支持的。 在这些假设不成立的情况下,可能还有其他一些variables没有经过testing。 至less,使用PowerShell检测脚本时,它们是一套很好的初始假设。

不匹配的上下文(小心!)

Jason Sandyslogging了安装环境规则的类似testing。 如果您仔细阅读该文章,您可能会注意到安装上下文和检测脚本上下文的规则并不完全相同。 这是违规的规则:

当应用程序的安装行为被设置为“Install as System”时,安装程​​序将作为系统运行[不pipe是否部署到用户]。

将应用程序部署到用户时,该应用程序的PowerShell检测脚本将以该用户的身份运行[无论安装行为是否设置为“Install as System”)。

这意味着具有安装行为“安装为系统” 部署到用户集合的应用程序将使用系统上下文进行安装,但要使用用户上下文进行检测。

有人为安装行为是“作为系统安装”的应用程序编写检测脚本时要小心,避免依赖系统和用户上下文之间环境的任何部分。 否则,检测部署到系统集合的应用程序可能会成功,同时检测到部署到用户集合的完全相同的应用程序失败。

脚本

 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) }