Подтвердить что ты не робот

Начать новую среду 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!
4b9b3361

Ответ 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