Start new cmd.exe and NOT inherit environment?
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...
If you're willing to use powershell, you can use:
Start-Process -UseNewEnvironment powershell
or
Start-Process -UseNewEnvironment cmd
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"