Начать новую среду cmd.exe и НЕ наследовать?
Если я запустил новую оболочку 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!
Ответы
Ответ 1
Некоторые из переменных инициализируются при входе в систему и не сохраняются вместе с другими записями реестра, поэтому, если вы хотите, чтобы среда, равная исходной среде 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 равно tab), но прежде чем вы это сделаете, убедитесь, что вывод reg.exe всегда использует вкладку в качестве разделителя)
Вы можете обойти эти проблемы с помощью хоста Windows scripting script вместо пакетного файла:
'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...
Ответ 2
Рецепт Андерса имеет подробный контроль над новой средой, и я оставляю это как принятый ответ из-за этого контроля глубины. Однако одна фраза в этом ответе привела ко мне метод, который я фактически использую для конкретной проблемы, вызвавшей этот запрос. "Окружающая среда, которая равна исходной среде explorer.exe". Ой! Я знаю, как это сделать!
start /i "%windir%\explorer.exe" "%windir%\system32\cmd.exe"
Примечание: первоначально это было просто start /i explorer ...
, но оказалось, что это не работает надежно, и полный путь должен использоваться для обеих частей. Если все, что вам нужно, это решение, у вас есть все, и вы можете игнорировать остальные.
Следующее сообщение Ander о предупреждении безопасности, которое я тестировал на четырех компьютерах Win7, представляет собой сочетание Pro, Home и Enterprise, 32 и 64 бит. Я возился с контролем учетных записей пользователей, полностью и полностью вниз. Также протестирован с оболочкой командной строки без администратора. Все они работали без ошибок или предупреждений.
На сервере 2003, входящем в систему как локальный администратор, я получаю всплывающее диалоговое окно "Загрузка файла - предупреждение безопасности: вы хотите запустить или сохранить этот файл?" с кнопками для запуска, сохранения и отмены. При нажатии [run] появляется дополнительное диалоговое окно "Проводник Windows - предупреждение о безопасности: издатель не может быть проверен. Вы уверены, что хотите запустить это программное обеспечение?". Повторное нажатие [run] приводит к использованию полезной командной оболочки. По-видимому, существует какая-то странная логика, которая приводит к замене Internet Explorer на проводник Windows без полного пути к exe.
Это становится еще более странным: используя 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"
Ответ 3
Если вы хотите использовать powershell, вы можете использовать:
Start-Process -UseNewEnvironment powershell
или
Start-Process -UseNewEnvironment cmd
Ответ 4
Я не знаю, как это сделать в том же окне. Но вы можете выполнить задачу в отдельном окне, используя
start /i cmd
Если вы хотите, чтобы текущий сеанс cmd дождался окончания нового сеанса, вы можете добавить опцию /wait
ИЗМЕНИТЬ
Я исправляюсь, благодаря замечанию Ромарио. Вы можете добавить опции /B and /WAIT
, чтобы создать новый сеанс cmd.exe в том же окне.
start /i /b /wait cmd
Обратите внимание, что новый cmd.exe наследует начальную среду, существовавшую при запуске родителя. Это может быть не среда по умолчанию, если родитель сам запускался из другой среды cmd.exe.
Ответ 5
Пример ниже о том, как я получил это работает для меня.
@ECHO OFF
TITLE Test
SET SELF=%~dp0%~n0%~x0
ECHO SetVar : %VAR1%
PAUSE
SETX VAR1 "Random Value"
WMIC PROCESS CALL CREATE "%SELF%"
EXIT 0
Ответ 6
Это похоже на старый пост, но это то, что я пробовал:
start/i
У этой ссылки есть дополнительная информация:
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/start.mspx?mfr=true
Эта команда должна открыть новое окно, которое похоже на среду cmd запуска.