Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 是否启动新cmd.exe而不继承环境?_Batch File_Cmd - Fatal编程技术网

Batch file 是否启动新cmd.exe而不继承环境?

Batch file 是否启动新cmd.exe而不继承环境?,batch-file,cmd,Batch File,Cmd,如果从现有shell启动新CMD shell,则新shell将继承现有环境。有没有办法启动一个新的shell,但将其初始化为系统默认值而不是继承 当前结果: B:\>set _test=blooharky B:\>cmd Microsoft Windows [Version 6.1.7600] Copyright (c) 2009 Microsoft Corporation. All rights reserved. B:\>set _ _test=blooharky

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

当前结果:

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]解决方案是dbenham共享的
start/i cmd
。然而,在当前的shell已经是第二代的情况下,这并没有帮助。例如:

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!

我不知道在同一个窗口中做这件事的方法。但是,您可以在单独的窗口中使用

start /i cmd
如果希望当前cmd会话等待新会话结束,可以添加
/wait
选项

编辑

多亏了罗马里奥的评论,我得到了纠正。您可以添加
/B和/WAIT
选项,在同一窗口中创建新的cmd.exe会话

start /i /b /wait cmd

请注意,新cmd.exe继承启动父级时存在的初始环境。如果父项本身是从另一个cmd.exe环境启动的,则它可能不是默认环境。

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

@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 "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
call :GetRegEnv "HKCU\Environment"

REM Special handling for Path
call :SetFromReg "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" Path Path
setlocal
set u=
call :SetFromReg "HKCU\Environment" 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输出始终使用tab作为分隔符)

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

'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方法,您可能会删除许多列在白名单上的项目…

Anders的配方对新环境有详细的控制,由于深度控制,我将此作为可接受的答案。然而,这个答案中的一个短语让我想到了我将实际用于解决这个问题的方法,这个问题引发了这项调查。“等于初始explorer.exe环境的环境”。哦我知道怎么做

注意:最初这只是
start/i explorer…
,但事实证明它不能可靠地工作,两个部分都应该使用完整的路径。如果你所需要的只是一个解决方案,那么你现在拥有了一切,可以忽略其余的


下面是Ander关于我在4台Win7电脑上测试的安全警告的评论,这台电脑是Pro、Home和Enterprise的混合,32位和64位。我摆弄着用户帐户控制,一路上上下下。还使用非管理员命令提示符shell进行了测试。这些都没有错误或警告

在以本地管理员身份登录的Server 2003上,我会看到一个弹出对话框“文件下载-安全警告:是否要运行或保存此文件?”以及“运行”、“保存”和“取消”按钮。按[run]会出现另一个对话框,“Windows资源管理器-安全警告:无法验证发布服务器。是否确实要运行此软件?”。再次按[run]最终生成一个可用的命令shell。显然,有一些奇怪的逻辑导致Internet Explorer被Windows Explorer取代,而没有exe的完整路径

但它变得更加奇怪:使用带有标题的
start
(有些人建议这样做)会导致安全警告,而不管完整路径如何。其他参数(如启动目录)似乎没有问题

:: security warning
start "clean shell" /i "%windir%\explorer.exe" "%windir%\system32\cmd.exe"

:: is okay
start /i  /d x:\ "%windir%\explorer.exe" "%windir%\system32\cmd.exe"

这看起来像是一篇旧文章,但这是我尝试的:

开始/i

此链接包含更多信息:


该命令将打开一个新窗口,类似于startup cmd环境。

如果您愿意使用powershell,可以使用:

启动流程-使用NewEnvironment powershell


启动流程-使用newEnvironment cmd

下面的示例介绍了我是如何让它为我工作的

@ECHO OFF
TITLE Test
SET SELF=%~dp0%~n0%~x0

ECHO SetVar : %VAR1%
PAUSE
SETX VAR1 "Random Value"
WMIC PROCESS CALL CREATE "%SELF%"
EXIT 0

好吧,这对我来说是一个局部的解决方案,一个新的窗口不是一个交易破坏者。但这确实表明,我最初的问题并没有包含足够的信息。我需要启动一个干净的系统默认环境,我的父shell不是系统默认环境,并且在
start/I cmd
shell中继承了不应该继承的设置。我将相应地更新Q。您可以使用
/b
开关将它放在同一个窗口中。@Romário-当然!我不知道为什么我没有考虑将
/I
/B
选项结合起来。但是您可能也需要
/WAIT
选项,否则共享控制台会变得非常混乱。
start/i cmd
仍然保留父cmd窗口的原始%path%,不是吗?这不是问题想要的。@Pacerier-路径变量与任何其他变量没有区别。新的cmd会话将忽略父会话的当前环境,而是使用启动父会话时存在的值。我已经承认这并不是OP想要的,因为父会话可能没有使用默认值启动。但这个答案是朝着正确的方向迈出的一步,在许多情况下都是足够的。投票结束了这个问题,我很好奇为什么。那么它又如何呢?投票结束您的问题的用户只是建议它在这里是离题的,属于是的,那是我,我认为它在超级用户方面会更好。很明显,我被否决了!:)这是不受支持的浏览器语法AFAIK,当我尝试它时,我得到了一个安全警告。这个解决方案真的需要
/I
选项吗?我认为explorer.exe将启动默认值eit
@ECHO OFF
TITLE Test
SET SELF=%~dp0%~n0%~x0

ECHO SetVar : %VAR1%
PAUSE
SETX VAR1 "Random Value"
WMIC PROCESS CALL CREATE "%SELF%"
EXIT 0