Запустить новый cmd.exe и НЕ наследовать среду? - PullRequest
27 голосов
/ 24 ноября 2011

Если я запускаю новую оболочку CMD из существующей оболочки, новая оболочка наследует существующую среду.Есть ли способ запустить новую оболочку, но инициализировать ее по умолчанию в системе и не наследовать?

Текущий результат:

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

[обновление] Решением для этого является start /i cmd, как и dbenham, ниже .Однако это не помогает в ситуации, когда текущая оболочка уже второго поколения.Пример:

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!

Ответы [ 6 ]

14 голосов
/ 27 ноября 2011

У рецепта Андерса есть подробный контроль над новой средой, и я оставляю это как принятый ответ из-за этого контроля глубины.Однако одна фраза в этом ответе привела меня к методу, который я на самом деле буду использовать для конкретной проблемы, которая вызвала этот запрос. «среда, равная исходной среде explorer.exe» .Ой!Я знаю, как сделать , что !

start /i "%windir%\explorer.exe" "%windir%\system32\cmd.exe"

Примечание: первоначально это было просто start /i explorer ..., но оказывается, что это не работает надежно, и полный путь должен бытьиспользуется для обеих частей.Если все, что вам нужно, это решение, у вас есть все сейчас и вы можете игнорировать все остальное.


Следуя комментарию Андер ниже о предупреждении о безопасности, которое я тестировал на 4 компьютерах Win7, сочетание Pro, Home и Enterprise, 32 и 64-разрядных.Я возился с контролем учетных записей, все время вверх и вниз.Также протестирован с командной оболочкой без прав администратора.Все они работали без ошибок и предупреждений.

На сервере 2003, вошедшем в систему как локальный администратор, я получаю всплывающее диалоговое окно «Загрузка файла - Предупреждение безопасности: вы хотите запустить или сохранить этот файл?» с кнопками для запуска, сохранения и отмены.Нажатие [run] приводит к дополнительному диалоговому окну, «Проводник Windows - Предупреждение безопасности: издатель не может быть проверен. Вы уверены, что хотите запустить это программное обеспечение?» .Повторное нажатие [run] в конечном итоге приводит к использованию командной оболочки.Очевидно, существует некоторая странная логика, которая приводит к тому, что Internet Explorer заменяется на Windows Explorer без полного пути к исполняемому файлу.

Это даже странно: использование start с заголовком (некоторые советуют всегда включать title) приводит к предупреждениям безопасности независимо от полного пути.Другие параметры, такие как начальный каталог, кажутся нормальными.

:: 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"
4 голосов
/ 02 февраля 2016

Если вы хотите использовать powershell, вы можете использовать:

Start-Process -UseNewEnvironment powershell

или

Start-Process -UseNewEnvironment cmd

4 голосов
/ 25 ноября 2011

Некоторые переменные инициализируются при входе в систему и не сохраняются вместе с другими записями реестра, поэтому, если вы хотите создать среду, равную исходной среде 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), но перед этим убедитесь, что вывод 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...

3 голосов
/ 25 ноября 2011

Я не знаю, как сделать это в том же окне.Но вы можете выполнить задачу в отдельном окне, используя

start /i cmd

Если вы хотите, чтобы текущий сеанс cmd ожидал окончания нового сеанса, вы можете добавить параметр /wait

EDIT

Я исправлен, благодаря комментарию Ромарио.Вы можете добавить опции /B and /WAIT для создания нового сеанса cmd.exe в том же окне.

start /i /b /wait cmd

Обратите внимание, что новый cmd.exe наследует исходную среду, которая существовала при запуске родительского файла.Это может быть не среда по умолчанию, если родительский элемент был сам запущен из другой среды cmd.exe.

0 голосов
/ 17 мая 2019

Пример ниже, как я понял, что это работает для меня.

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

ECHO SetVar : %VAR1%
PAUSE
SETX VAR1 "Random Value"
WMIC PROCESS CALL CREATE "%SELF%"
EXIT 0
0 голосов
/ 24 июля 2013

Это похоже на старый пост, но это то, что я пробовал:

start / i

эта ссылка содержит больше информации: http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/start.mspx?mfr=true

Эта команда должнаоткройте новое окно, которое похоже на среду запуска cmd.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...