windows – 在CMD批处理文件中,我可以确定它是否是从powershell
我有一个
Windows批处理文件,其目的是设置一些环境变量,例如
=== MyFile.cmd === SET MyEnvVariable=MyValue 用户可以在完成需要环境变量的工作之前运行它,例如: C:&; MyFile.cmd C:&; echo "%MyEnvVariable%" <-- outputs "MyValue" C:&; ... do work that needs the environment variable 这大致相当于Visual Studio安装的“Developer命令提示符”快捷方式,它设置了运行VS实用程序所需的环境变量. 但是,如果用户碰巧打开了Powershell提示符,则环境变量当然不会传播回Powershell: PS C:&; MyFile.cmd PS C:&; Write-Output "${env:MyEnvVariable}" # Outputs an empty string 对于在CMD和PowerShell之间切换的用户而言,这可能会造成混淆. 有没有办法可以在我的批处理文件MyFile.cmd中检测到它是从PowerShell调用的,所以我可以,例如,向用户显示警告?这需要在没有任何第三方实用程序的情况下完成.
Your own answer is robust虽然由于需要运行PowerShell进程而通常很慢,但通过优化用于确定调用shell的PowerShell命令,可以大大加快它:
@echo off setlocal CALL :GETPARENT PARENT IF /I "%PARENT%" == "powershell" GOTO :ISPOWERSHELL IF /I "%PARENT%" == "pwsh" GOTO :ISPOWERSHELL endlocal echo Not running from Powershell SET MyEnvVariable=MyValue GOTO :EOF :GETPARENT SET "PSCMD=$ppid=$pid;while($i++ -lt 3 -and ($ppid=(Get-CimInstance Win32_Process -Filter ('ProcessID='+$ppid)).ParentProcessId)) {}; (Get-Process -EA Ignore -ID $ppid).Name" for /f "tokens=*" %%i in ('powershell -noprofile -command "%PSCMD%"') do SET %1=%%i GOTO :EOF :ISPOWERSHELL echo. >&2 echo ERROR: This batch file may not be run from a PowerShell prompt >&2 echo. >&2 exit /b 1 在我的机器上,这个速度大约快3到4倍(YMMV) – 但仍然需要将近1秒. 请注意,我还添加了对进程名称pwsh的检查,以便使解决方案也适用于PowerShell Core. 更快的替代方案 – 虽然不那么强大: 下面的解决方案依赖于以下假设,在默认安装中也是如此: 只有名为PSModulePath的系统环境变量在注册表中持久定义(不是用户特定的). 该解决方案依赖于检测PSModulePath中是否存在特定于用户的路径,PowerShell在启动时会自动添加该路径. @echo off echo %PSModulePath% | findstr %USERPROFILE% >NUL IF %ERRORLEVEL% EQU 0 goto :ISPOWERSHELL echo Not running from Powershell SET MyEnvVariable=MyValue GOTO :EOF :ISPOWERSHELL echo. >&2 echo ERROR: This batch file may not be run from a PowerShell prompt >&2 echo. >&2 exit /b 1 根据需要启动新cmd.exe控制台窗口的替代方法: 在以前的方法的基础上,以下变体只是在检测到它是从PowerShell运行时,在新的cmd.exe窗口中重新调用批处理文件. 这不仅对用户来说更方便,还可以缓解上述解决方案产生误报的问题:从PowerShell启动的交互式cmd.exe会话运行时,上述解决方案将拒绝运行,即使它们应该,正如PetSerAl指出的那样. @echo off REM # Unless already being reinvoked via cmd.exe,see if the batch REM # file is being run from PowerShell. IF NOT %1.==_isNew. echo %PSModulePath% | findstr %USERPROFILE% >NUL REM # If so,RE-INVOKE this batch file in a NEW cmd.exe console WINDOW. IF NOT %1.==_isNew. IF %ERRORLEVEL% EQU 0 start "With Environment" "%~f0" _isNew & goto :EOF echo Running from cmd.exe,setting environment variables... REM # Set environment variables. SET MyEnvVariable=MyValue REM # If the batch file had to be reinvoked because it was run from PowerShell,REM # but you want the user to retain the PowerShell experience,REM # restart PowerShell now,after definining the env. variables. IF %1.==_isNew. powershell.exe GOTO :EOF 在设置所有环境变量之后,请注意最后一个IF语句如何重新调用PowerShell,但是在同一个新窗口中,基于调用用户更喜欢在PowerShell中工作的假设.然后,新的PowerShell会话将看到新定义的环境变量,但请注意,您需要两次连续的退出调用才能关闭窗口. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- windows – Visual Studio 2008中的“符号浏览器”是什么/哪
- WiX获得文化预处理器变量
- windows-server-2008 – 如何在两台Windows 2008服务器之间
- windows-server-2008 – 为什么Windows 2008在断电后重新同
- windows-phone-7 – 在Windows Phone 7.5上集成付款
- windows – Bitvise SSH Git初始目录
- .net – 覆盖嵌入到MSI中的app.config设置?
- windows – 我可以一次打开多少个TCP套接字?
- Windows – 服务器端防病毒与否?
- windows-server-2003 – 尝试更改为Active Directory的其他
- 将函数指针作为参数传递给dll函数并从dll内部调用
- windows-server-2003 – 在Exchange 2003中删除超
- windows-server-2008 – 具有3台服务器的高可用性
- .net – 禁用Windows Mobile 6.5中的菜单栏
- windows – Luasql和SQLite?
- windows-server-2003 – Windows Server到Mac OS
- windows-server-2008 – Active Directory运行状
- windows-service – 如果我没有代理,我可以安全地
- Windows主机和Linux Docker容器之间的通信
- Windows Scripting Host使用的JavaScript版本