This compares the original cmd
environment (saved to a file) with the current one. You can change the file creation if you need a different check
@echo off
setlocal enableextensions disabledelayedexpansion
rem We need a temporary file to store the original environment
for %%f in ("%temp%\original_%random%%random%%random%.tmp") do (
rem Retrieve the original environment to the temporary file
start /i /wait /min "" "%comspec%" /c">""%%~ff"" set "
rem We need two flag variables. Prepare two names that "should" not collide
for /f "tokens=1,2" %%d in ("_&d&%random%%random%_ _&m&%random%%random%_") do (
rem %%d will be used to determine if we will check for variable deletion
rem on the first inner pass
rem %%e will be used for matching variables between existing/original variables
set "%%d="
rem Retrieve the current environment contents
for /f "delims= eol==" %%a in ('set') do (
rem We have not found matching variables
set "%%e="
rem Search a match in original set of variables
for /f "usebackq delims= eol==" %%o in ("%%~ff") do (
rem If variables match, flag it, else check for variable
rem deletion is this is the first loop over the original file
if %%a==%%o ( set "%%e=1" ) else if not defined %%d (
for /f "delims==" %%V in ("%%~o") do if not defined %%V (echo(%%V=)
)
)
rem If no match found, output changed value
if not defined %%e (echo(%%a)
rem Now all the variable deletion has been checked.
) & if not defined %%d set "%%d=1"
rem Cleanup flag variables
) & set "%%d=" & set "%%e="
rem Cleanup temporary file
) & del "%%~ff"
Not as much code as it seems once we remove the comments
@echo off
setlocal enableextensions disabledelayedexpansion
for %%f in ("%temp%\original_%random%%random%%random%.tmp") do (
start /i /wait /min "" "%comspec%" /c">""%%~ff"" set "
for /f "tokens=1,2" %%d in ("_&d&%random%%random%_ _&m&%random%%random%_") do (
set "%%d="
for /f "delims= eol==" %%a in ('set') do (
set "%%e="
for /f "usebackq delims= eol==" %%o in ("%%~ff") do (
if %%a==%%o ( set "%%e=1" ) else if not defined %%d (
for /f "delims==" %%V in ("%%~o") do if not defined %%V (echo(%%V=)
)
)
if not defined %%e (echo(%%a)
) & if not defined %%d set "%%d=1"
) & set "%%d=" & set "%%e="
) & del "%%~ff"
edited just for completion. As dbenham points the previous code can not handle variables with line feeds in their names or values. This is an hybrid batch file (save as ex. checkEnvironment.cmd
file) that can handle this case.
@if (@This==@IsBatch) @then /* Batch zone ------------------------------------
@echo off
setlocal enableextensions disabledelayedexpansion
call :processCurrentEnvironment "%~f1"
goto :eof
:processCurrentEnvironment
call "%systemroot%\system32\cscript.exe" //nologo //e:JScript "%~f0" /saved:"%~1"
goto :eof
*/ @end
// Javascript zone -----------------------------------------------------------
var environment = WScript.CreateObject('WScript.Shell').Environment('PROCESS');
var savedFileName = WScript.Arguments.Named.Item('saved');
if ( !savedFileName ){
// If no saved file name present, output current environment
for ( var e = new Enumerator(environment); !e.atEnd(); e.moveNext()){
WScript.StdOut.Write( e.item() + '\0\r\n' );
};
} else {
// Retrieve saved environment to compare against current one
var savedEnvironment = retrieveSavedEnvironment( savedFileName );
// For each element in the current environment
for ( var e = new Enumerator(environment); !e.atEnd(); e.moveNext() ) {
// retrieve { variable: , value: } representation of the variable
var buffer = splitEnvironmentVariable( e.item() );
if ( buffer ) {
// if the current variable does not exist in the saved version
// or if the current value does not match the previous one
// then dump the current variable
if (
! savedEnvironment[buffer.variable]
|| savedEnvironment[buffer.variable].value !== buffer.value
) outputVariable( buffer );
// in any case, this is a processed variable
delete savedEnvironment[buffer.variable];
}
};
// any saved variables still present are deleted variables, show them
for (var e in savedEnvironment) outputVariable( e );
};
// - Helper functions ----------------------------------------------------------
// Process the contents of the saved file to generate a { {variable: , value: }, ... }
// representation of the saved environment
function retrieveSavedEnvironment( savedFileName ) {
var savedEnvironment = {};
var buffer = readFile( savedFileName ).split('\0\r\n');
for (var i in buffer) if ( buffer[i] = splitEnvironmentVariable(buffer[i]) ) {
savedEnvironment[buffer[i].variable] = buffer[i];
};
return ( savedEnvironment );
};
// Read the contents of the saved file - FSO can not be used because we are
// writing nulls (ascii 0x00 character) to separate variables
function readFile( savedFileName ){
var buffer = "";
if (
WScript.CreateObject('Scripting.FileSystemObject').FileExists( savedFileName )
){
var stream = WScript.CreateObject('ADODB.Stream');
stream.Open();
stream.Type = 2
stream.Charset = 'ascii';
stream.LoadFromFile( savedFileName );
buffer = stream.ReadText();
stream.Close();
};
return ( buffer );
};
// Convert variable=value to { variable: , value: }
function splitEnvironmentVariable( text ){
text = (/^([\s\S][^=]*)=([\s\S]+)/).exec( text );
return (
text
? { variable : text[1] , value : text[2] }
: text
);
};
// Write the variable with its value or only the variable name
function outputVariable( variable ){
if ( typeof variable === 'object' ) {
WScript.StdOut.WriteLine( variable.variable + '=' + variable.value );
} else {
WScript.StdOut.WriteLine( variable + '=' );
};
};
Placed in the path or in the same folder that your batch files, you can use it as
@echo off
setlocal enableextensions enabledelayedexpansion
(SET LF=^
%=this line is empty=%
)
rem Variables to delete
set "variableToDelete=1"
set "my!lf!var1=my!lf!data"
set "originalEnvironment=%temp%\original_%random%%random%%random%.tmp"
rem save environment
>"%originalEnvironment%" call checkEnvironment.cmd
rem Create new variable2
set "thisIsNew=value"
set "anotherOne=1"
rem Create another problematic variable
set "my!lf!var2=my!lf!data"
rem Delete variables
set "variableToDelete="
set "my!lf!var1="
rem Dump environment changes
call checkEnvironment.cmd "%originalEnvironment%"
rem Remove temporary file
del /q "%originalEnvironment%"
to get an exit as
W:\>testEnv.cmd
anotherOne=1
my
var2=my
data
thisIsNew=value
my
var1=
variableToDelete=
W:\>