Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start new cmd.exe and NOT inherit environment?

Tags:

batch-file

cmd

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?

Current result:

B:\>set _test=blooharky  B:\>cmd Microsoft Windows [Version 6.1.7600] Copyright (c) 2009 Microsoft Corporation.  All rights reserved.  B:\>set _ _test=blooharky 

Desired result:

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] 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! 
like image 466
matt wilkie Avatar asked Nov 24 '11 18:11

matt wilkie


People also ask

How do I set environment variable in cmd?

To set (or change) a environment variable, use command " set varname=value ". There shall be no spaces before and after the '=' sign. To unset an environment variable, use " set varname= ", i.e., set it to an empty string.

Is cmd.exe the same as command prompt?

Windows Command Prompt (also known as the command line, cmd.exe or simply cmd) is a command shell based on the MS-DOS operating system from the 1980s that enables a user to interact directly with the operating system.


2 Answers

Anders' recipe has detailed control over a new environment, and I'm leaving that as the accepted answer because of that depth control. However one phrase in that answer led to me the method I'll actually be using for the particular problem which prompted this enquiry. An "environment that is equal to the initial explorer.exe environment". Oh! I know how to do that!

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

Note: originally this was simply start /i explorer ..., but it turns out that doesn't work reliably, and a full path should be be used for both parts. If all you need is a solution, you have everything now and can ignore the rest.


Following Ander's comment below about a security warning I tested on 4 Win7 computers, a mix of Pro, Home, and Enterprise, 32 and 64bit. I fiddled with User Account Control, all the way up and all the way down. Also tested with a non-administrator Command Prompt shell. These all worked without error or warning.

On Server 2003, logged on as local administrator, I get a popup dialog "File Download - Security Warning: do you want to run or save this file?" with buttons for run,save, and cancel. Pressing [run] results in an additional dialog, "Windows Explorer - Security Warning: the publisher could not be verified. Are you sure you want to run this software?". Pressing [run] again finally results in a usable command shell. Apparently there is some weird logic that results in Internet Explorer being substituted for Windows Explorer without the full path to the exe.

It gets even stranger though: using start with a title, (some advise to always include a title) results in the security warnings regardless of full path. Other parameters like starting directory seem to be okay.

:: 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" 
like image 156
matt wilkie Avatar answered Oct 10 '22 10:10

matt wilkie


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 "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 

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)

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 

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

like image 40
Anders Avatar answered Oct 10 '22 09:10

Anders