Is there an equivalent source command in Windows CMD as in bash or tcsh? - windows

I know that in the unix world, if you edit your .profile or .cshrc file, you can do a source ~/.profile or source ~/.cshrc to get the effect on your current session. If I changed something in the system variable on Windows, how can I have it effect the current command prompt session without exiting the command prompt session and opening another command prompt session?

In the usual Windows command prompt (i.e. cmd.exe), just using call mybat.bat did what I wanted. I got all the environment variables it had set.

The dos shell will support .bat files containing just assignments to variables that, when executed, will create the variables in the current environment.
c:> type EnvSetTest.bat
set TESTXYZ=XYZ
c:> .\EnvSetTest.bat
c:> set | find "TESTX"
TESTXYZ=XYZ
c:>
IHTH.

Following example will help you to solve your problem.
env.bat This file is for setting variables. Its contents are given blow.
set name="test3"
test.bat Our main batch file.
call env.bat
call print.bat
pause
Now print.bat batch file to print variables. Its contents given below
echo %name%

I am afraid not, but you can start using Powershell, which does support dot sourcing. Since powershell window is really based on cmd so all your dos command will continue to work, and you gain new power, much more power.

The only way I have found this to work is to launch a new cmd window from my own config window. eg:
#echo off
echo Loading...
setlocal enabledelayedexpansion
call 1.cmd
call 2.bat
...
...
if "%LocalAppData%"=="" set LocalAppData=%UserProfile%\Local Settings\Application Data
SET BLAHNAME=FILE:%LocalAppData%\BLAH
call blah blah
cmd
The last cmd will launch a new cmd prompt with the desired settings exported to the command window.

Here's a workaround for some limited use-cases. You can read-in a file of commands and execute them in-line. For example the calling command file looks like:
echo OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:
echo. ----------------
echo. set-up java
echo. ----------------
echo.
rem call %DEV_SCRIPTS%\setup-java
for /F "tokens=*" %%A in ( %DEV_SCRIPTS%\setup-java.bat ) do (
%%A
)
call %DEV_SCRIPTS%\show-java
:
In the setup-java.bat file you can't use % expansion. You need to use !; e.g.:
set JRE_HOME=!JRE_08!
rem
set JRE_TARGET=!JRE_HOME!
So you are litterally source-ing commands from a text file. You will need to test which commands sourced in this way. It took a few trials just to set some environment variables.
I don't think we can do logic or loops because the command processor scans the file at the start. I am OK just having a simple workaround to reuse shared things like environment definitions. Most other things won't need an actual source command (I am hoping). Good luck.

For example to set VC# vars
C:\Windows\System32\cmd.exe /k "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"

Use git bash for windows, it works totally fine!

Related

How do I loop over the output of `pushd` in Windows Command Processor?

The following illustrates a problem I found using for /f %l in ('<command>') do #(echo %l). (/f is the for command's parameter for "iterating and file parsing.") This works as expected when <command> is cd or chdir, but not when <command> is pushd:
C:\>cd
C:\
C:\>for /f %l in ('cd') do #(echo %l)
C:\
C:\>chdir
C:\
C:\>for /f %l in ('chdir') do #(echo %l)
C:\
C:\>pushd Windows
C:\Windows>pushd
C:\
C:\Windows>for /f %l in ('pushd') do #(echo %l)
C:\Windows>pushd > nul
C:\Windows>
I would expect the last command to print C:\ but it does not execute the do block at all. I added pushd > nul to check that pushd prints to stdout.
How can I process the output of pushd in a for /f loop?
Information about command processing by FOR /F
The usage of a for /F loop with a command enclosed in ' or in ` on using usebackq results in starting in background one more command process using %ComSpec% /c and the command appended as additional argument(s).
The usage of for /f %l in ('pushd') do #(echo %l) results in background execution of:
C:\Windows\System32\cmd.exe /c pushd
That can be seen by downloading, extracting and running the free Windows Sysinternals tool Process Monitor as administrator which logs the execution of two cmd.exe processes with different process identifiers on running the commands as posted in the question. There must be double clicked on any line in log of Process Monitor of second cmd.exe in the middle of the log to open the Event Properties window and selected the second tab Process to see the Command Line which was used by first cmd.exe to start the second cmd.exe for the execution of the command pushd.
There cannot be executed just a single command with a for /F loop. There can be executed an entire command line which can even have multiple commands. But it is necessary to take into account all the information given by the usage help of cmd output on running cmd /? in a command prompt window on using a complex command line with for /F and processing its output as written to handle STDOUT of in background started cmd.exe.
Command operators like &, && and || as well as redirection operators like |, 2> and 2>&1 in the command line to execute by for /F are processed by two cmd.exe, first the one executing the entire for /F loop and another one started in background with the command line of which output is of interest. That is the reason why many for /F loops with a complex command line are with the escape character ^ left to each & and | and > in the command line to get these characters interpreted literally by cmd.exe parsing and executing the entire for /F loop while being interpreted as command/redirection operators by the second cmd.exe started in background which is really executing the command line.
Information about output of PUSHD
The Windows command PUSHD outputs on execution without any directory path the list of directory paths pushed on stack of current command process.
There can be executed in a command prompt window following commands:
cd /D %SystemDrive%\
pushd %SystemRoot%
pushd inf
pushd
popd
popd
The fifth command pushd results usually for typical Windows installations in the output:
C:\Windows
C:\
But there is nothing output by using as fifth command instead of pushd the command line:
for /F "delims=" %I in ('pushd') do #echo %I
The reason is the execution of pushd by one more cmd.exe started in background which has no directory paths pushed on its stack. The internal command PUSHD does not output anything at all for that reason to handle STDOUT of in background started cmd.exe.
The command process running for /F cannot capture any output text. The for /F loop cannot process therefore any line after cmd.exe started in background finished the execution of pushd and closed itself.
How to process the directory paths pushed on stack?
It would be necessary to use the following command lines in the command prompt window to process the directory paths pushed on stack of the current command process:
pushd >"%TEMP%\DirectoryList.tmp"
if exist "%TEMP%\DirectoryList.tmp" for /F "usebackq delims=" %I in ("%TEMP%\DirectoryList.txt") do #echo %I
del "%TEMP%\DirectoryList.tmp" 2>nul
The redirection of the output of PUSHD executed by the command process which executed also the two pushd command lines before into a temporary file makes it possible to process the directory paths pushed on stack of current command process.
The for /F option usebackq is necessary to get the string inside " interpreted as file name of which lines to process by the FOR loop and not as string to process.
The for /F option delims= is necessary to define an empty list of string delimiters as a directory path can contain one or more spaces. There is by default split up a line into substrings using normal space and horizontal tab as string delimiters and assigned to the loop variable is just the first space/tab delimited string instead of the entire directory path. The line splitting is turned off by the definition of an empty list of delimiters. The entire directory path is assigned therefore always to the loop variable in this case with processing always full directory paths never starting with the default end of line character ; as the first character is always either a drive letter or a backslash in case of a UNC directory path.
Why does the command CD work with a FOR /F loop?
The command CD works also with for /F "delims=" %I in ('cd') do #echo %I because of cmd.exe calls the Windows kernel library function CreateProcess on starting the additional command process for execution of a command specified as set of a for /F loop with value NULL for the function parameter lpCurrentDirectory. The current directory of in background started cmd.exe is set by CreateProcess for that reason with the current directory of the command process executing the for /F command line. Both running command processes have the same current directory during the execution of the command of a for /F loop.
Information about environment variable ComSpec
ComSpec is an environment variable defined by default with %SystemRoot%\system32\cmd.exe (with s at beginning of System32 instead of S as the folder name is in real by default) as system environment variable stored in Windows registry under the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment.
It is really not advisable to ever modify or even delete the environment variable ComSpec neither in local environment of a running process nor in the Windows registry. That would cause a lot of programs to stop working normally as lots of executables depend internally on the correct definition of this environment variable including cmd.exe itself.
The reason is that many applications and scripts use internally the function system which uses the environment variable ComSpec to start on Windows cmd.exe for execution of a command line.
There are many batch files running internal command ver of cmd.exe to get the Windows version like:
for /F "tokens=2 delims=[]" %%G in ('ver') do for /F "tokens=2" %%H in ("%%G") do echo %%H
That works only for Windows NT based Windows versions using cmd.exe as command processor and not for older Windows versions using COMMAND.COM like Windows 95/98/ME for processing a batch file. It works only with enabled command extensions which are enabled by Windows default, but can be disabled by command setlocal DisableExtension in a batch file, on starting cmd.exe with /E:OFF or by a registry value which should be really never used and therefore not written here. The command ver must be really executed by %SystemRoot%\System32\cmd.exe because of in real is output the version of cmd.exe and not the version of Windows.
However, that command line is very good to demonstrate what happens on usage of for /F if the environment variable ComSpec is not defined in environment of cmd.exe on running the batch file with the two for /F loops.
ComSpec usage by cmd.exe on Windows XP
On Windows XP is always called C:\WINDOWS\system32\cmd.exe /c ver even on doing following:
Copying cmd.exe to the directory F:\Temp\system32.
Starting F:\Temp\system32\cmd.exe with a double click in Windows Explorer.
Running set ComSpec=F:\Temp\system32\cmd.exe and set SystemRoot=F:\Temp and set SystemDrive=F: and set windir=F:\Temp.
Verifying with echo %__APPDIR__% that F:\Temp\system32\ is output.
Running the batch file with the command line as posted above.
That can be seen with Process Monitor v3.61 on Windows XP x86.
There can be even modified the local environment variable PATH to begin with F:\Temp\system32 instead of C:\WINDOWS\system32 or the local environment variable ComSpec is deleted with set ComSpec=. The Windows Command Processor of Windows XP in directory F:\Temp\system32 calls nevertheless always C:\WINDOWS\system32\cmd.exe with the option /c and the command ver on running the batch file immediately after closing the batch file containing just the single command line in the text editor.
There cannot be seen in Process Monitor even a Windows registry access by cmd.exe of Windows XP to get any directory path.
Please read further why cmd.exe of Windows XP in a different directory than %SystemRoot%\System32\cmd.exe calls nevertheless the command processor executable in Windows system directory even after modification of local environment variable ComSpec or its deletion.
ComSpec usage of cmd.exe on Windows Vista/7/8/8.1/10/11
The same procedure as described above for Windows XP can be executed also on Windows 7 x64 and newer 64-bit Windows versions.
The double clicked 64-bit F:\Temp\system32\cmd.exe copied from C:\Windows\System32 outputs on Windows 7 and currently latest Windows 11 22H2 first:
The system cannot find message text for message number 0x2350 in the message file for Application.
(c) Microsoft Corporation. All rights reserved.
Note: The copyright message line depends on version of cmd.exe. The output above is from cmd.exe of version 10.0.22621.963 (Windows 11 22H2).
The Windows Command Processor cmd.exe of version 6.1.7601 of Windows 7 outputs additionally the line:
Not enough storage is available to process this command.
The execution of the internal command ver executed in the command prompt window opened with a double click on F:\Temp\System32\cmd.exe fails on Windows 7 and all later Windows versions up to currently latest Windows 11 22H2 which is the reason for the strange output on starting F:\Temp\System32\cmd.exe with a double click.
There can be redefined also the environment variables as described above and done on German Windows XP by me on my tests. A verification of the output of echo %__APPDIR__% works and shows F:\Temp\system32\ as expected. So, it works to access the string value of the internal dynamic variable of cmd.exe even on executed cmd.exe is not in the directory %SystemRoot%\System32.
But the batch file execution from within the command prompt of F:\Temp\system32\cmd.exe as on Windows XP results in no output at all.
In log of Process Monitor v3.70 or a newer Process Monitor version can be seen that on Windows 7 and Windows 11 22H2 is executed F:\Temp\System32\cmd.exe /c ver. That means it is indeed possible that another cmd.exe is executed instead of C:\Windows\System32\cmd.exe on Windows 7 and newer Windows versions.
But why is no version output?
Well, the execution of ver results in the output of the error message:
The system cannot find message text for message number 0x2350 in the message file for Application.
64-bit cmd.exe is not working in F:\Temp\system32 at all.
The usage of 32-bit cmd.exe copied from C:\Windows\SysWOW64 to F:\Temp\system32 makes no difference. The same error messages are output already on starting F:\Temp\system32\cmd.exe and on running next ver or the batch file after modification of local environment variable ComSpec.
Conclusion: cmd.exe of Windows Vista and newer versions are not fully working on being stored outside the appropriate system directory %SystemRoot%\System32 or %SystemRoot%\SysWOW64 while cmd.exe of Windows XP works fine in any directory.
Caching of ComSpec value
I found out with lots of further tests that the string value of the environment variable ComSpec is indeed used to find cmd.exe to run command ver on execution of the batch file with the for /F loop. But there is a caching mechanism on Windows Vista and newer Windows versions.
There must be run immediately set ComSpec=F:\Temp\system32\cmd.exe after starting F:\Temp\system32\cmd.exe before running the batch file. This results in calling F:\Temp\system32\cmd.exe /c ver. If there is next executed set ComSpec=C:\Windows\System32\cmd.exe to redefine the variable with correct value and run the batch file once again, there is nevertheless run now not working F:\Temp\system32\cmd.exe /c ver.
The same caching mechanism can be seen on starting F:\Temp\system32\cmd.exe, then running the batch file resulting in calling in background C:\Windows\System32\cmd.exe /c ver, next running set ComSpec=F:\Temp\system32\cmd.exe and running now the batch file again. There is executed once again C:\Windows\System32\cmd.exe /c ver although the value of the environment variable ComSpec is now F:\Temp\system32\cmd.exe.
It looks like cmd.exe of Windows Vista/7/8/8.1/10/11 reads the value of ComSpec only once and keeps its value in memory for further usage without reading the environment variable a second time on string value for the default command interpreter being already in its internal memory.
That is quite clever in my opinion. The string value of ComSpec is read only once from the environment variable on first usage and then is used that string internally on further usage because of the value of the environment variable ComSpec changes usually never as long as cmd.exe is running.
It looks like cmd.exe of Windows XP has nearly the same caching mechanism for the string value of the environment variable ComSpec. The difference is that cmd.exe of Windows XP reads the value of ComSpec already on starting it and not on first usage and so all changes done on local environment variable ComSpec of an already running cmd.exe have no effect on the execution of one more cmd.exe on processing a for /F loop with a command line to execute, capturing the output and processing it as I could find out with further tests on German Windows XP.

How to set an env variable with multiline file content in windows command prompt

I have a file say my-file.dat which has multiple lines. I want to set an env variable say MYVAR that will contain the content of my-file.dat.
That is, in windows command prompt, the output of type my-file.dat be same as the output of echo %MYVAR% and with new-line preserved.
In RHEL/MAC, it is typically done like this export MYVAR=$(cat my-file.dat), but how do I do the similar in windows command prompt (not really interested in powershell, but feel free to share examples it might be my backup option)
Following the answer of this Stackoverflow question Multiline text file, how to put into an environment variable I could get a variable to hold the content of my-file.dat. But this variable's scope seems to be the batch file. Even though I run the batch file from the command prompt, I don't see the batch-file's variable is available in the command prompt.
I tried set /P MYVAR=<my-file.dat , but this sets only the first line whereas I want all lines when I echo MYVAR
Pls help.
The technique you use requires delayed expansion, which is not enabled by default. So the code issues setlocal enableDelayedExpansion. But that localizes environment changes. When the script ends there is an implicit endlocal, and the environment is restored to what existed before the setlocal.
The simplest solution is to run the script in a session where delayed expansion is already enabled so that you can remove setlocal enableDelayedExpansion. You can do this simply by running
cmd /v:on from your command line before executing your script.
There is another simple, but ugly option. The implicit endlocal does not occur if your script has a fatal syntax error (I consider this to be a bug in cmd.exe). So you can put the following at the end of your script:
:: Your current script goes here.
:: I'm assuming your script falls through to the end and does not use EXIT /B
call :fatalErr 2>nul
:fatalErr
if
But I discourage you from using this technique if you might be executing your script multiple times - your dead environments will begin to pile up.
Also - please remember that variables are limited to ~8191 characters - your script will fail if the file you are trying to capture exceeds the limit. This is a hard limit of cmd.exe
Update
You could put the cmd /v:on command within your script if you add the /K option. The IF statement tests if delayed expansion is enabled or not. If not, then it reruns the script via cmd.exe with the /K option and /V:ON.
#echo off
if "!!" neq "" cmd /v:on /k "%~f0"
:: rest of your script goes here.

Windows CMD Start and wait for the default application in a batch file

I am trying to start the default application for a file, wait for it to complete, and then continue with my batch file. The problem is that start, when used below simply creates another command prompt window with the example.doc in the title bar. I can use call instead of start, but then call does not wait for the program to finish before going to the next line. It appears that start needs to have an executable name and will not work with the default application system in windows.
Any ideas how I can make this happen without having to hardcode the windows application in the batch file as well?
set filename=example.doc
start /wait %filename%
copy %filename% %filename%.bak
How do I start the default application for a file, wait for completion, then continue?
It appears that start needs to have an executable name and will not work with the default application system in windows.
start, when used below simply creates another command prompt window with the example.doc in the title bar
start /wait %filename%
The above command won't work because %filename% is used as the window title instead of a command to run.
Always include a TITLE this can be a simple string like "My Script" or just a pair of empty quotes ""
According to the Microsoft documentation, the title is optional, but depending on the other options chosen you can have problems if it is omitted.
Source start
Try the following command instead:
start "" /wait %filename%
Alternative solution using the default open command
Any ideas how I can make this happen without having to hardcode the
windows application in the batch file as well?
One way is to use assoc and ftype to get the default open command used for the file then execute that command.
The following batch file does that for you (so no hard coding of windows applications is needed).
Open.cmd:
#echo off
setlocal enabledelayedexpansion
set _file=example.doc
rem get the extension
for %%a in (%_file%) do (
set _ext=%%~xa
)
rem get the filetype associated with the extension
for /f "usebackq tokens=2 delims==" %%b in (`assoc %_ext%`) do (
set _assoc=%%b
)
rem get the open command used for files of type filetype
for /f "usebackq tokens=2 delims==" %%c in (`ftype %_assoc%`) do (
set _command=%%c
rem replace %1 in the open command with the filename
set _command=!_command:%%1=%_file%!
)
rem run the command and wait for it to finish.
start "" /wait %_command%
copy %_file% %_file%.bak 1>nul
endlocal
Further Reading
An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
assoc - Display or change the association between a file extension and a fileType
enabledelayedexpansion - Delayed Expansion will cause variables to be expanded at execution time rather than at parse time.
for - Conditionally perform a command several times.
for /f - Loop command against the results of another command.
ftype - Display or change the link between a FileType and an executable program.
start - Start a program, command or batch script (opens in a new window).
variable edit/replace - Edit and replace the characters assigned to a string variable.
Simply use the filename directly as command, unless that filename is a batch file, in which case use call.
In a batch file invocation of a GUI subsystem executable is blocking, unlike for an interactive command.
Use the start command when you don't want blocking execution.
There is a subtle point about “default application”, namely that a file type can have a registered default application for the graphical shell, e.g. its “Open with…”, without having an assoc/ftype association, or different from that association.
I'm not entirely sure of which registry entries are used for this. I've always had to look it up and research it each time. As I recall it's not well-documented.
But hopefully you're OK with just the assoc/ftype scheme.
A further subtle point about “default application”: on the laptop I'm writing this on the ftype association for text files is to open them in Notepad:
[H:\forums\so]
> assoc .txt
.txt=txtfile
[H:\forums\so]
> ftype txtfile
txtfile=%SystemRoot%\system32\NOTEPAD.EXE %1
[H:\forums\so]
> _
And this is what the graphical shell (Windows Explorer) will do.
But cmd.exe looks inside files, and if it finds an executable signature then it tries to run the text file as an executable, even in Windows 10:
[H:\forums\so]
> echo MZ bah! >oops.txt
[H:\forums\so]
> oops.txt
This version of H:\forums\so\oops.txt is not compatible with the version of Windows you're running. Check your computer's system information and then contact the software publisher.
[H:\forums\so]
> _

Environment Variable not expanding

Platform: Windows Vista Service Pack 2 (x86)
I was messing around with batch scripts and realized that they could act as the command prompt(yes I know batch scripts run threw the command prompt) I mean that a batch script could prompt the user for a command and then call the command.
SET command=
SET /P command=%cd%^>
ECHO(
%command%
ECHO(
The only problem is that when I type in for example cd %windir% I get an error message telling me that the system cannot find the path specified. So I typed echo %windir% and echo printed %windir% exactly it wasn't expanded at all. I am wondering if the problem is because I have the environment variable nested inside the %command% variable but from what I understand CMD.exe does support nested environment variables. I tried using Delayed Expansion but the variable still didn't expand.
Add a call or cmd /c to evaluate variables that way.
#echo off
setlocal
SET /P command=%cd%^>
call %command%
ECHO;

Pausing a batch file when double-clicked but not when run from a console window?

Is there a way for a batch file (in this case, running on Windows XP) to determine whether it was launched from a command line (i.e. inside a console window) or launched via the shell (e.g. by double-clicking)?
I have a script which I'd like to have pause at certain points when run via the shell, but not when run at a command line. I've seen a similar question on SO, but am unable to use the same solution for two reasons: first, whether or not it pauses needs to be dependent on multiple factors, only one of which is whether it was double-clicked. Second, I'll be distributing this script to others on my team and I can't realistically ask all of them to make registry changes which will affect all scripts.
Is this possible?
Found one :-) – After desperately thinking of what cmd might do when run interactively but not when launching a batch file directly ... I finally found one.
The pseudo-variable %cmdcmdline% contains the command line that was used to launch cmd. In case cmd was started normally this contains something akin to the following:
"C:\Windows\System32\cmd.exe"
However, when launching a batch file it looks like this:
cmd /c ""C:\Users\Me\test.cmd" "
Small demo:
#echo off
for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" set DOUBLECLICKED=1
if defined DOUBLECLICKED pause
This way of checking might not be the most robust, though, but /c should only be present as an argument if a batch file was launched directly.
Tested here on Windows 7 x64. It may or may not work, break, do something weird, eat children (might be a good thing) or bite you in the nose.
A consolidated answer, derived from much of the information found on this page (and some other stack overflow pages with similar questions). This one does not rely on detecting /c, but actually checks for the name of the script in the command line. As a result this solution will not pause if you double-clicked on another batch and then called this one; you had to double-click on this particular batch file.
:pauseIfDoubleClicked
setlocal enabledelayedexpansion
set testl=%cmdcmdline:"=%
set testr=!testl:%~nx0=!
if not "%testl%" == "%testr%" pause
The variable "testl" gets the full line of the cmd processor call, stripping out all of the pesky double quotes.
The variable "testr" takes "testl" and further strips outs the name of the current batch file name if present (which it will be if the batch file was invoked with a double-click).
The if statement sees if "testl" and "testr" are different. If yes, batch was double-clicked, so pause; if no, batch was typed in on command line (or called from another batch file), go on.
Edit: The same can be done in a single line:
echo %cmdcmdline% | findstr /i /c:"%~nx0" && set standalone=1
In plain English, this
pipes the value of %cmdcmdline% to findstr, which then searches for the current script name
%0 contains the current script name, of course only if shift has not been called beforehand
%~nx0 extracts file name and extension from %0
>NUL 2>&1 mutes findstr by redirecting any output to NUL
findstr sets a non-zero errorlevel if it can't find the substring in question
&& only executes if the preceding command returned without error
as a consequence, standalone will not be defined if the script was started from the command line
Later in the script we can do:
if defined standalone pause
One approach might be to create an autoexec.nt file in the root of c:\ that looks something like:
#set nested=%nested%Z
In your batch file, check if %nested% is "Z" - if it is "Z" then you've been double-clicked, so pause. If it's not "Z" - its going to be "ZZ" or "ZZZ" etc as CMD inherits the environment block of the parent process.
-Oisin
A little more information...
I start with a batch-file (test.cmd) that contains:
#echo %cmdcmdline%
If I double-click the "test.cmd" batch-file from within Windows Explorer, the display of echo %cmdcmdline% is:
cmd /c ""D:\Path\test.cmd" "
When executing the "test.cmd" batch-file from within a Command Prompt window, the display of
echo %cmdcmdline% depends on how the command window was started...
If I start "cmd.exe" by clicking the "Start-Orb" and "Command Prompt" or if I click "Start-Orb" and execute "cmd.exe" from the search/run box. Then I execute the "test.cmd" batch-file, the display of echo %cmdcmdline% is:
"C:\Windows\system32\cmd.exe"
Also, for me, if I click "Command Prompt" from the desktop shortcut, then execute the "test.cmd" batch-file, the display of echo %cmdcmdline% is also:
"C:\Windows\system32\cmd.exe"
But, if I "Right-Click" inside a Windows Explorer window and select "Open Command Prompt Here", then execute the "test.cmd" batch-file, the display of echo %cmdcmdline% is:
"C:\Windows\System32\cmd.exe" /k ver
So, just be careful, if you start "cmd.exe" from a shortcut that contains a "/c" in the "Target" field (unlikely), then the test in the previous example will fail to test this case properly.

Resources