系统上下文运行PowerShell脚本创建文件夹后卡死问题
PowerShell在Environment Manager系统上下文下创建目录后卡死故障解决方案
故障复现条件
- 脚本载体:用于应用部署的PowerShell脚本
- 运行环境:通过Environment Manager以域系统用户上下文执行
- 触发代码:
New-Item -Path "$PSScriptRoot\Launcher" -ItemType Directory
- 故障表现:
- 故障场景下
$PSScriptRoot固定为C:\Users\Public,对应Launcher目录可正常创建 - 目录创建完成后脚本直接挂死,不执行后续逻辑、无返回值
- PowerShell运行日志、转录记录无任何错误输出
- 故障场景下
- 对照基线:
- 同脚本以普通域用户身份运行无异常
- 通过PSExec拉起系统上下文PowerShell执行同代码无异常
- 常规系统日志、PowerShell日志无报错线索
核心根因
该故障为Environment Manager注入的文件系统过滤钩子与PowerShell Cmdlet返回逻辑冲突导致:
Environment Manager会向其拉起的所有进程注入钩子DLL,监控公共路径(含C:\Users\Public)的文件创建操作做合规校验;New-Item创建目录完成后,会默认返回DirectoryInfo对象,该对象初始化时会读取目录的扩展属性、安全描述符等信息,该读取操作被EM钩子拦截后,因系统上下文下会话权限隔离导致钩子逻辑死锁,最终表现为PowerShell线程挂起。
PSExec拉起的系统进程不会加载EM的会话级钩子,普通用户上下文下EM钩子的权限校验逻辑不会触发死锁,因此两类对照场景均无异常。
修复方案
按优先级从高到低尝试:
- 屏蔽
New-Item返回值,切断属性读取链路
直接将Cmdlet返回值丢入空流,避免DirectoryInfo对象初始化触发钩子:New-Item -Path "$PSScriptRoot\Launcher" -ItemType Directory -Force | Out-Null - 调用.NET原生接口创建目录,绕过PowerShell Cmdlet逻辑
直接使用基础类库的目录创建方法,不会触发PowerShell的对象封装、模块自动加载等附加逻辑:[System.IO.Directory]::CreateDirectory((Join-Path $PSScriptRoot "Launcher")) | Out-Null - 新增存在性预校验,避免无意义的创建操作
提前判断目录是否存在,仅在目录缺失时执行创建,减少触发钩子的概率:$launcherPath = Join-Path $PSScriptRoot "Launcher" if (-not [System.IO.Directory]::Exists($launcherPath)) { [System.IO.Directory]::CreateDirectory($launcherPath) | Out-Null } - 配置Environment Manager排除规则
在EM控制台将部署脚本的执行进程、C:\Users\Public下的部署临时路径加入文件监控白名单,从根源上避免钩子拦截。
快速验证方法
提前手动在故障环境的C:\Users\Public路径下创建好Launcher目录,再通过EM触发脚本运行,若脚本不再挂死即可确认根因判断正确。
内容的提问来源于stack exchange,提问作者Benjamin
相关产品推荐
相关产品推荐

