启动新的 cmd.exe 而不是继承环境? [英] Start new cmd.exe and NOT inherit environment?

查看:16
本文介绍了启动新的 cmd.exe 而不是继承环境?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我从现有的 shell 启动一个新的 CMD shell,新的 shell 会继承现有的环境.有没有办法启动一个新的 shell,但将它初始化为系统默认值而不是继承?

If I start a new CMD shell from an existing shell, the new shell inherits the existing environment. Is there a way to start a new shell but have it initialized to the system defaults and not inherit?

当前结果:

B:>set _test=blooharky

B:>cmd
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

B:>set _
_test=blooharky

想要的结果:

B:>set _test=blooharky

B:>cmd /env=default
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

B:>set _
Environment variable _ not defined

[update] 解决方案是 start/i cmd,由 dbenham 分享,下面.但是,在当前 shell 已经是第二代的情况下,它无济于事.示例:

[update] Solution for this is start /i cmd, as shared by dbenham, below. However it doesn't help in the situation where the current shell is already second generation. Example:

d:>set _
Environment variable _ not defined

d:>set _test=blooharky

d:>cmd /k

:: some work done using _test here...
:: ...but after we need a new clean shell:

d:>start /i cmd

d:>set _
_test=blooharky

:: uhoh, our shell isn't clean!

推荐答案

有些变量在登录时初始化,不与其他注册表项一起存储,因此如果您想要一个与初始 explorer.exe 环境相同的环境您需要将这些项目列入白名单,并希望它们没有被任何人更改:

Some of the variables are initialized at logon and are not stored with the other registry entries so if you want a environment that is equal to the initial explorer.exe environment you need to white-list those items and hope they have not been changed by anyone:

@echo off
setlocal ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION
goto main

:SetFromReg
FOR /F "tokens=2,*" %%A IN ('REG query "%~1" /v "%~2"^|find /I "REG_"') DO (
    call set %~3=%%B
)
goto :EOF

:GetRegEnv
FOR /F %%A IN ('REG query "%~1" /s^|find /I "REG_"') DO (
    if /I not "%%~A"=="Path" call :SetFromReg "%~1" "%%~A" "%%~A"
)
goto :EOF

:InheritOrDelete
for %%A in (save_TEMP Path SystemRoot SystemDrive ProgramFiles CommonProgramFiles ALLUSERSPROFILE COMPUTERNAME LOGONSERVER USERNAME USERDOMAIN HOMEDRIVE HOMEPATH USERPROFILE APPDATA) do if /I "%%~A"=="%~1" goto :EOF
set %~1=
goto :EOF

:main
REM Save temp
set save_TEMP=%temp%
if not defined save_TEMP set save_TEMP=%tmp%

for /F "delims==" %%A in ('set') do call :InheritOrDelete "%%~A"
call :GetRegEnv "HKLMSYSTEMCurrentControlSetControlSession ManagerEnvironment"
call :GetRegEnv "HKCUEnvironment"

REM Special handling for Path
call :SetFromReg "HKLMSYSTEMCurrentControlSetControlSession ManagerEnvironment" Path Path
setlocal
set u=
call :SetFromReg "HKCUEnvironment" Path u
endlocal&if not "%Path%"=="" if not "%u%"=="" set Path=%Path%;%u%

REM Restore TEMP/TMP
set TEMP=%save_TEMP%
set save_TEMP=
set TMP=%TEMP%

REM start some command...
start cmd /d /k set

reg.exe 的输出在每个 Windows 版本上都不相同,因此您必须确保它在您的目标系统上工作(如果变量的名称包含空格,它也会出现问题,您可以修复通过将 "tokens=2,*" 替换为 "tokens=2,* delims=" (delims equals tab) 但在此之前请确保 reg.exe 输出总是使用制表符作为分隔符)

The output from reg.exe is not the same on every windows version so you would have to make sure that it works on your target system (It will also have problems if the name of a variable contains a space, you could fix that by replacing "tokens=2,*" with "tokens=2,* delims= " (delims equals tab) but before you do that make sure that the reg.exe output always uses tab as the separator)

您可以通过使用 Windows 脚本宿主脚本而不是批处理文件来解决这些问题:

You can work around these issues by using a windows scripting host script instead of a batch file:

'orgenvshell.vbs:
Set WShl = CreateObject( "WScript.Shell" )
Set FSO = CreateObject("Scripting.FileSystemObject")

Function CanInherit(n)
    CanInherit = False
    w = Split("SystemRoot SystemDrive ProgramFiles CommonProgramFiles ALLUSERSPROFILE COMPUTERNAME LOGONSERVER USERNAME USERDOMAIN HOMEDRIVE HOMEPATH USERPROFILE APPDATA")
    For Each i In w
        If 0 = StrComp(i,n,1) Then
            CanInherit = True
            Exit Function
        End If
    Next
End Function

Function GetShortFolderPath(p)
    GetShortFolderPath = p
    On Error Resume Next
    GetShortFolderPath = FSO.GetFolder(p).ShortPath
End Function

Sub E(dst,src)
    set envs = WShl.Environment(src)
    For Each i In envs
        t = Split(i,"=")
        n = t(0)
        If n = "" Then n = "="&t(1)
        If IsNull(dst) Then
            If not CanInherit(n) Then envs.Remove n
        Else
            v = Mid(i,Len(n)+2)
            envd = dst
            If "X" = dst Then
                v = WShl.ExpandEnvironmentStrings(v)
                envd = src
                If 0 = StrComp(n,"TMP",1) Then v = GetShortFolderPath(v)
                If 0 = StrComp(n,"TEMP",1) Then v = GetShortFolderPath(v)
            End If
            WShl.Environment(envd)(n) = v
        End If
    Next
End Sub

E Null,"PROCESS"
E "PROCESS","SYSTEM"
E "PROCESS","USER"
E "X","PROCESS"

'Special hack for Path
s = WShl.Environment("SYSTEM")("Path")
u = WShl.Environment("USER")("Path")
If Len(u) Then s = s&";"&u
WShl.Environment("PROCESS")("Path") = WShl.ExpandEnvironmentStrings(s)

'Test a command
WShl.Run "cmd /d /k set ",1

您可能可以通过查询 WMI 和使用其他 WSH 方法来删​​除很多列入白名单的项目...

You could probably remove a lot of the white-listed items by querying WMI and using other WSH methods...

这篇关于启动新的 cmd.exe 而不是继承环境?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆