Windows batch files: .bat vs .cmd? - windows

As I understand it, .bat is the old 16-bit naming convention, and .cmd is for 32-bit Windows, i.e., starting with NT. But I continue to see .bat files everywhere, and they seem to work exactly the same using either suffix. Assuming that my code will never need to run on anything older than NT, does it really matter which way I name my batch files, or is there some gotcha awaiting me by using the wrong suffix?

From this news group posting by Mark Zbikowski himself:
The differences between .CMD and .BAT as far as CMD.EXE is concerned
are: With extensions enabled, PATH/APPEND/PROMPT/SET/ASSOC in .CMD
files will set ERRORLEVEL regardless of error. .BAT sets ERRORLEVEL
only on errors.
In other words, if ERRORLEVEL is set to non-0 and then you run one of those commands, the resulting ERRORLEVEL will be:
left alone at its non-0 value in a .bat file
reset to 0 in a .cmd file.

Here is a compilation of verified information from the various answers and cited references in this thread:
command.com is the 16-bit command processor introduced in MS-DOS and was also used in the Win9x series of operating systems.
cmd.exe is the 32-bit command processor in Windows NT (64-bit Windows OSes also have a 64-bit version). cmd.exe was never part of Windows 9x. It originated in OS/2 version 1.0, and the OS/2 version of cmd began 16-bit (but was nonetheless a fully fledged protected mode program with commands like start). Windows NT inherited cmd from OS/2, but Windows NT's Win32 version started off 32-bit. Although OS/2 went 32-bit in 1992, its cmd remained a 16-bit OS/2 1.x program.
The ComSpec env variable defines which program is launched by .bat and .cmd scripts. (Starting with WinNT this defaults to cmd.exe.)
cmd.exe is backward compatible with command.com.
A script that is designed for cmd.exe can be named .cmd to prevent accidental execution on Windows 9x. This filename extension also dates back to OS/2 version 1.0 and 1987.
Here is a list of cmd.exe features that are not supported by command.com:
Long filenames (exceeding the 8.3 format)
Command history
Tab completion
Escape character: ^ (Use for: \ & | > < ^)
Directory stack: PUSHD/POPD
Integer arithmetic: SET /A i+=1
Search/Replace/Substring: SET %varname:expression%
Command substitution: FOR /F (existed before, has been enhanced)
Functions: CALL :label
Order of Execution:
If both .bat and .cmd versions of a script (test.bat, test.cmd) are in the same folder and you run the script without the extension (test), by default the .bat version of the script will run, even on 64-bit Windows 7. The order of execution is controlled by the PATHEXT environment variable. See Order in which Command Prompt executes files for more details.
References:
cmd.exe
command.com
wikipedia: Comparison of command shells

These answers are a bit too long and focused on interactive use. The important differences for scripting are:
.cmd prevents inadvertent execution on non-NT systems.
.cmd enables built-in commands to change Errorlevel to 0 on success.
Not that exciting, eh?
There used to be a number of additional features enabled in .cmd files, called Command Extensions. However, they are now enabled by default for both .bat and .cmd files under Windows 2000 and later.
Bottom line: in 2012 and beyond, I recommend using .cmd exclusively.

No - it doesn't matter in the slightest. On NT the .bat and .cmd extension both cause the cmd.exe processor to process the file in exactly the same way.
Additional interesting information about command.com vs. cmd.exe on WinNT-class systems from MS TechNet (http://technet.microsoft.com/en-us/library/cc723564.aspx):
This behavior reveals a quite subtle
feature of Windows NT that is very
important. The 16-bit MS-DOS shell
(COMMAND.COM) that ships with Windows
NT is specially designed for Windows
NT. When a command is entered for
execution by this shell, it does not
actually execute it. Instead, it
packages the command text and sends it
to a 32-bit CMD.EXE command shell for
execution. Because all commands are
actually executed by CMD.EXE (the
Windows NT command shell), the 16-bit
shell inherits all the features and
facilities of the full Windows NT
shell.

RE: Apparently when command.com is invoked is a bit of a complex mystery;
Several months ago, during the course of a project, we had to figure out why some programs that we wanted to run under CMD.EXE were, in fact, running under COMMAND.COM. The "program" in question was a very old .BAT file, that still runs daily.
We discovered that the reason the batch file ran under COMMAND.COM is that it was being started from a .PIF file (also ancient). Since the special memory configuration settings available only through a PIF have become irrelevant, we replaced it with a conventional desktop shortcut.
The same batch file, launched from the shortcut, runs in CMD.EXE. When you think about it, this makes sense. The reason that it took us so long to figure it out was partially due to the fact that we had forgotten that its item in the startup group was a PIF, because it had been in production since 1998.

Still, on Windows 7, BAT files have also this difference : If you ever create files TEST.BAT and TEST.CMD in the same directory, and you run TEST in that directory, it'll run the BAT file.
C:\>echo %PATHEXT%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
C:\Temp>echo echo bat > test.bat
C:\Temp>echo echo cmd > test.cmd
C:\Temp>test
C:\Temp>echo bat
bat
C:\Temp>

Since the original post was regarding the consequences of using the .bat or .cmd suffix, not necessarily the commands inside the file...
One other difference between .bat and .cmd is that if two files exist with the same file name and both those extensions, then:
entering filename or filename.bat at the command line will run the .bat file
to run the .cmd file, you have to enter filename.cmd

everything working in a batch should work in a cmd; cmd provides some extensions for controlling the environment.
also, cmd is executed by in new cmd interpreter and thus should be faster (not noticeable on short files) and stabler as bat runs under the NTVDM emulated 16bit environment

.cmd and .bat file execution is different because in a .cmd errorlevel variable it can change on a command that is affected by command extensions. That's about it really.

I believe if you change the value of the ComSpec environment variable to %SystemRoot%system32\cmd.exe(CMD) then it doesn't matter if the file extension is .BAT or .CMD. I'm not sure, but this may even be the default for WinXP and above.

The extension makes no difference.
There are slight differences between COMMAND.COM handling the file vs CMD.EXE.

a difference:
.cmd files are loaded into memory before being executed. .bat files execute a line, read the next line, execute that line...
you can come across this when you execute a script file and then edit it before it's done executing. bat files will be messed up by this, but cmd files won't.

Related

How to prevent use of 8.3 names in HKCR open commands?

I tried to modify the open default command for .bat and .cmd files on Windows in order to open the Windows terminal instead of the legacy cmd.exe.
My modification to the user registry was:
(I had to use TotalReg from Pavel Yosifovitch to change the default value to REG_EXPAND_SZ).
The same default value was used for the batfile class.
The above definitions work almost properly.
There is a little issue though: when I now run a .bat or a .cmd file, the command line for wt.exe uses “legacy DOS 8.3 paths”, as well as the current working directory.
If my definition for the open command simply uses wt.exe instead of "%localappdata%\Microsoft\WindowsApps\wt.exe", then the problem disappears.
Is there a way to use the absolute path and still get the non-8.3 behavior?
When using %1, the shell tries to guess if the target supports long filenames. If you use %L, the shell always uses the long filename if the target is 32 or 64-bit. 16-bit applications presumably still get the short name?
%L is not officially documented anywhere but a Microsoft employee listed them in a comment here...

Converting .ps1 to .bat doesn't cause cmd.exe to hit max character length - but why?

Based on a related question and some Googling/testing, it is pretty clear that the maximum length of a command line in cmd.exe is 8,191 characters. However...my script seems to successfully exceed that length, and I can't figure out why it works.
So I have:
A script written/saved as a .ps1
I'm converting it to a .bat using the method from Converting PowerShell to Batch
If I run the .bat - there don't seem to be any issues
If I try to echo the $encoded command or just remove #echo off before running the .bat - it is easy to see that the length/content of $encoded has been truncated...yet it works as expected
I realize this is a bit of a strange question since I'm trying to ascertain some kind of hidden truth about something that works vs. something that is broken, but I'd like to understand why it is working!
Note:
The primary reason I'm creating a .bat for my script is because I have a number of small 'programs' that I need to run on my work computer and share with others. Our company's execution policies don't allow running scripts, and it is much easier for others to use something I've written if it is a .bat since they won't need to understand/use PowerShell. They can just place the .bat in the right place, give it two clicks, and then sit back and relax until something happens.
EDIT: Here's the truncated command in the cmd.exe window. If I convert from Base64 back to readable text, it is clearly missing about half of the script. Yet - I'm not noticing any problems
The 8191-character limit applies to the interactive command line and calls to cmd.exe's CLI (via cmd /c)
It does not apply to commands invoked from batch files - there the limit is close to[1] 32KiB (32,768) characters.
However, it still seems to apply selectively to cmd.exe's internal commands, such as echo; by contrast, a call to an external program such as powershell.exe is not affected (though it is possible for specific external programs to have their own, lower limits).
As an aside:
As clever as the linked method of converting PowerShell scripts to batch files is, the resulting batch files lack support for arguments to be passed through to the PowerShell code, and adding support for that would be impractical (it would require Base64-encoding the arguments too, at invocation time, which isn't possible from a batch file except with the help of non-built-in utilities).
If your script / batch file is written to either require no arguments on invocation or to prompt for them interactively (as in your case), this limitation is not a concern.
However, you may want argument support for any of the following reasons:
To allow calling the batch file from cmd.exe (Command Prompt) with arguments.
To allow calling with arguments from other environments that support passing arguments, notably Task Scheduler and the Windows Run dialog (WinKey-R).
To make the batch file support drag-and-drop (which implicitly passes the dropped files' paths as arguments).
As for the overall reason to wrap PowerShell code in batch files:
Batch files (.cmd, .bat) can be launched directly, as if they were executables, system-wide.
By contrast, this is not supported for PowerShell scripts (.ps1), which from outside PowerShell must be invoked via an explicit call to the PowerShell CLI; note that systems may be configured to categorically prevent execution of .ps1 scripts - see next section.
If you do need argument support in your batch file, the best - but inconvenient - solution is to distribute two files:
the original *.ps1 file...
and a companion batch file, with the same base file name, to be placed in the same directory - which can be invoked from outside PowerShell - whose sole purpose is to invoke the *.ps1 file via powershell.exe with pass-through arguments.
E.g. foo.cmd would accompany foo.ps1, with the following - invariant - content:
#powershell.exe -NoProfile -File "%~dpn0.ps1" %*
Note:
Important: The above assumes that the effective PowerShell execution policy allows execution of script files (.ps1).
If you cannot make this assumption, place -ExecutionPolicy RemoteSigned before -NoProfile above (or, to deactivate all checks, -ExecutionPolicy Bypass), but note that an execution policy based on GPO (Group Policy Objects) may still prevent script execution.
To call PowerShell (Core) 7+ instead, use pwsh.exe instead of powershell.exe.
%~dpn0 expands to the full path of the enclosing batch file itself without its filename extension; appending .ps1 therefore targets the companion PowerShell script in the same directory; run cmd /c call /? for an explanation of the syntax.
%* passes any and all arguments received by the batch file on.
[1] In practice, the limits appear to be: 32,767 characters in batch files, and - lower by 3 chars. - 32,764 for Powershell (both on the command line / via the CLI and in *.ps1 scripts). In PowerShell, the limit may in practice be even lower than that, because PowerShell expands the names of executables it locates via $env:PATH to their full paths in the command lines constructed behind the scenes, which cmd.exe doesn't do.

Trying to open programs with bat file but always comes back invalid

I am a streamer and I need a few programs to stream. It's annoying to open all of them so I tried putting them in a batch file. I looked up the process and followed it,but every time I run the batch file it comes back invalid.
This is what my batch file looks like:
#echo off
cd C:\Program Files "(x86)\obs-studio\bin\64bit"
start obs64.exe
#echo off
cd "C:\Program Files\HexChat"
start hexchat.exe
#echo off
cd "C:\Program Files (x86)\Nightbot"
start nightbot.exe
exit
Cmd gives me an error saying it cannot find the file. When I put this into cmd by itself it opens the program.
Also is there a way to add applications from chrome to the file?
Open a command prompt window and run from within this window start /? which outputs the help for this command and explaining all options.
Following batch file most likely works:
#echo off
start "" "%ProgramFiles(x86)%\obs-studio\bin\64bit\obs64.exe"
start "" "%ProgramFiles%\HexChat\hexchat.exe"
start "" "%ProgramFiles(x86)%\Nightbot\nightbot.exe"
This batch file starts the three applications with current directory on execution of the batch file being also the current directory for the 3 started applications.
But the following batch file should be used if it is really necessary that each application is started with the application's directory as current directory:
#echo off
start "" /D"%ProgramFiles(x86)%\obs-studio\bin\64bit" obs64.exe
start "" /D"%ProgramFiles%\HexChat" hexchat.exe
start "" /D"%ProgramFiles(x86)%\Nightbot" nightbot.exe
With parameter /D and path of application's folder the Start In directory is set first like when using command CD. So for example hexchat.exe is started with current directory being C:\Program Files\HexChat for this application.
The two double quotes after command START are necessary as this command interprets first double quoted string as title for the process. By using "" an empty title string is explicitly specified resulting in rest of command line being correct interpreted as expected. I suppose those three applications are all GUI applications and not console applications and therefore a real title string being useful on running a console application in an new command process for the console window is not really necessary.
%ProgramFiles% references the predefined environment variable ProgramFiles containing path to standard program files folder for 64-bit applications on 64-bit Windows when batch file is started with 64-bit cmd.exe as default on 64-bit Windows and is replaced by Windows command interpreter before execution of the command line on your Windows computer by C:\Program Files.
%ProgramFiles(x86)% references the predefined environment variable ProgramFiles(x86) containing always path to standard program files folder for 32-bit applications on 64-bit Windows and is replaced by Windows command interpreter before execution of the command line on your Windows computer by C:\Program Files (x86).
It is of course also possible to use the real paths in your computer instead of the environment variable references if this batch file is never shared with other people.
Extra hint:
Run in a command prompt window the command you want to use with /? as parameter to get displayed the help for this command. Other sources for help on commands and predefined environment variables displayed all on running in a command prompt window set are:
SS64.com - A-Z index of the Windows CMD command line
Microsoft's command-line reference
Windows Environment Variables and WOW64 Implementation Details

How to run VBScript from command line without Cscript/Wscript

I am a beginner in VBScript. I googled it & got to know that we can run VBScript from command line by executing below command:
For Example my vbscript name is Converter.vbs & it's present in folder D:\VBS.
I can run it through following methods:
CScript "D:\VBS\Converter.vbs"
OR
WScript "D:\VBS\Converter.vbs"
Now I would like to execute above VBScript without Cscript or Wscript command by simply typing the name of VBscript name i.e. Converter.
I DON'T WANT TO SPECIFY THE FULL PATH OF VBSCRIPT EVERYTIME.
Can anyone please guide me on how to do that ?
I'll break this down in to several distinct parts, as each part can be done individually. (I see the similar answer, but I'm going to give a more detailed explanation here..)
First part, in order to avoid typing "CScript" (or "WScript"), you need to tell Windows how to launch a * .vbs script file. In My Windows 8 (I cannot be sure all these commands work exactly as shown here in older Windows, but the process is the same, even if you have to change the commands slightly), launch a console window (aka "command prompt", or aka [incorrectly] "dos prompt") and type "assoc .vbs". That should result in a response such as:
C:\Windows\System32>assoc .vbs
.vbs=VBSFile
Using that, you then type "ftype VBSFile", which should result in a response of:
C:\Windows\System32>ftype VBSFile
vbsfile="%SystemRoot%\System32\WScript.exe" "%1" %*
-OR-
C:\Windows\System32>ftype VBSFile
vbsfile="%SystemRoot%\System32\CScript.exe" "%1" %*
If these two are already defined as above, your Windows' is already set up to know how to launch a * .vbs file. (BTW, WScript and CScript are the same program, using different names. WScript launches the script as if it were a GUI program, and CScript launches it as if it were a command line program. See other sites and/or documentation for these details and caveats.)
If either of the commands did not respond as above (or similar responses, if the file type reported by assoc and/or the command executed as reported by ftype have different names or locations), you can enter them yourself:
C:\Windows\System32>assoc .vbs=VBSFile
-and/or-
C:\Windows\System32>ftype vbsfile="%SystemRoot%\System32\WScript.exe" "%1" %*
You can also type "help assoc" or "help ftype" for additional information on these commands, which are often handy when you want to automatically run certain programs by simply typing a filename with a specific extension. (Be careful though, as some file extensions are specially set up by Windows or programs you may have installed so they operate correctly. Always check the currently assigned values reported by assoc/ftype and save them in a text file somewhere in case you have to restore them.)
Second part, avoiding typing the file extension when typing the command from the console window.. Understanding how Windows (and the CMD.EXE program) finds commands you type is useful for this (and the next) part. When you type a command, let's use "querty" as an example command, the system will first try to find the command in it's internal list of commands (via settings in the Windows' registry for the system itself, or programmed in in the case of CMD.EXE). Since there is no such command, it will then try to find the command in the current %PATH% environment variable. In older versions of DOS/Windows, CMD.EXE (and/or COMMAND.COM) would automatically add the file extensions ".bat", ".exe", ".com" and possibly ".cmd" to the command name you typed, unless you explicitly typed an extension (such as "querty.bat" to avoid running "querty.exe" by mistake). In more modern Windows, it will try the extensions listed in the %PATHEXT% environment variable. So all you have to do is add .vbs to %PATHEXT%. For example, here's my %PATHEXT%:
C:\Windows\System32>set pathext
PATHEXT=.PLX;.PLW;.PL;.BAT;.CMD;.VBS;.COM;.EXE;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY
Notice that the extensions MUST include the ".", are separated by ";", and that .VBS is listed AFTER .CMD, but BEFORE .COM. This means that if the command processor (CMD.EXE) finds more than one match, it'll use the first one listed. That is, if I have query.cmd, querty.vbs and querty.com, it'll use querty.cmd.
Now, if you want to do this all the time without having to keep setting %PATHEXT%, you'll have to modify the system environment. Typing it in a console window only changes it for that console window session. I'll leave this process as an exercise for the reader. :-P
Third part, getting the script to run without always typing the full path. This part, in relation to the second part, has been around since the days of DOS. Simply make sure the file is in one of the directories (folders, for you Windows' folk!) listed in the %PATH% environment variable. My suggestion is to make your own directory to store various files and programs you create or use often from the console window/command prompt (that is, don't worry about doing this for programs you run from the start menu or any other method.. only the console window. Don't mess with programs that are installed by Windows or an automated installer unless you know what you're doing).
Personally, I always create a "C:\sys\bat" directory for batch files, a "C:\sys\bin" directory for * .exe and * .com files (for example, if you download something like "md5sum", a MD5 checksum utility), a "C:\sys\wsh" directory for VBScripts (and JScripts, named "wsh" because both are executed using the "Windows Scripting Host", or "wsh" program), and so on. I then add these to my system %PATH% variable (Control Panel -> Advanced System Settings -> Advanced tab -> Environment Variables button), so Windows can always find them when I type them.
Combining all three parts will result in configuring your Windows system so that anywhere you can type in a command-line command, you can launch your VBScript by just typing it's base file name. You can do the same for just about any file type/extension; As you probably saw in my %PATHEXT% output, my system is set up to run Perl scripts (.PLX;.PLW;.PL) and Python (.PY) scripts as well. (I also put "C:\sys\bat;C:\sys\scripts;C:\sys\wsh;C:\sys\bin" at the front of my %PATH%, and put various batch files, script files, et cetera, in these directories, so Windows can always find them. This is also handy if you want to "override" some commands: Putting the * .bat files first in the path makes the system find them before the * .exe files, for example, and then the * .bat file can launch the actual program by giving the full path to the actual *. exe file. Check out the various sites on "batch file programming" for details and other examples of the power of the command line.. It isn't dead yet!)
One final note: DO check out some of the other sites for various warnings and caveats. This question posed a script named "converter.vbs", which is dangerously close to the command "convert.exe", which is a Windows program to convert your hard drive from a FAT file system to a NTFS file system.. Something that can clobber your hard drive if you make a typing mistake!
On the other hand, using the above techniques you can insulate yourself from such mistakes, too. Using CONVERT.EXE as an example.. Rename it to something like "REAL_CONVERT.EXE", then create a file like "C:\sys\bat\convert.bat" which contains:
#ECHO OFF
ECHO !DANGER! !DANGER! !DANGER! !DANGER, WILL ROBINSON!
ECHO This command will convert your hard drive to NTFS! DO YOU REALLY WANT TO DO THIS?!
ECHO PRESS CONTROL-C TO ABORT, otherwise..
REM "PAUSE" will pause the batch file with the message "Press any key to continue...",
REM and also allow the user to press CONTROL-C which will prompt the user to abort or
REM continue running the batch file.
PAUSE
ECHO Okay, if you're really determined to do this, type this command:
ECHO. %SystemRoot%\SYSTEM32\REAL_CONVERT.EXE
ECHO to run the real CONVERT.EXE program. Have a nice day!
You can also use CHOICE.EXE in modern Windows to make the user type "y" or "n" if they really want to continue, and so on.. Again, the power of batch (and scripting) files!
Here's some links to some good resources on how to use all this power:
http://ss64.com/
http://www.computerhope.com/batch.htm
http://commandwindows.com/batch.htm
http://www.robvanderwoude.com/batchfiles.php
Most of these sites are geared towards batch files, but most of the information in them applies to running any kind of batch (* .bat) file, command (* .cmd) file, and scripting (* .vbs, * .js, * .pl, * .py, and so on) files.
When entering the script's full file spec or its filename on the command line, the shell will use information accessibly by
assoc | grep -i vbs
.vbs=VBSFile
ftype | grep -i vbs
VBSFile=%SystemRoot%\System32\CScript.exe "%1" %*
to decide which program to run for the script. In my case it's cscript.exe, in yours it will be wscript.exe - that explains why your WScript.Echos result in MsgBoxes.
As
cscript /?
Usage: CScript scriptname.extension [option...] [arguments...]
Options:
//B Batch mode: Suppresses script errors and prompts from displaying
//D Enable Active Debugging
//E:engine Use engine for executing script
//H:CScript Changes the default script host to CScript.exe
//H:WScript Changes the default script host to WScript.exe (default)
//I Interactive mode (default, opposite of //B)
//Job:xxxx Execute a WSF job
//Logo Display logo (default)
//Nologo Prevent logo display: No banner will be shown at execution time
//S Save current command line options for this user
//T:nn Time out in seconds: Maximum time a script is permitted to run
//X Execute script in debugger
//U Use Unicode for redirected I/O from the console
shows, you can use //E and //S to permanently switch your default host to cscript.exe.
If you are so lazy that you don't even want to type the extension, make sure that the PATHEXT environment variable
set | grep -i vbs
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.py;.pyw;.tcl;.PSC1
contains .VBS and there is no Converter.cmd (that converts your harddisk into a washing machine) in your path.
Update wrt comment:
If you 'don't want to specify the full path of my vbscript everytime' you may:
put your CONVERTER.VBS in a folder that is included in the PATH environment variable; the shell will then search all pathes - if necessary taking the PATHEXT and the ftype/assoc info into account - for a matching 'executable'.
put a CONVERTER.BAT/.CMD into a path directory that contains a line like cscript p:\ath\to\CONVERTER.VBS
In both cases I would type out the extension to avoid (nasty) surprises.
I am wondering why you cannot put this in a batch file. Example:
cd D:\VBS\
WSCript Converter.vbs
Put the above code in a text file and save the text file with .bat extension. Now you have to simply run this .bat file.
Why don't you just stash the vbscript in a batch/vbscript file hybrid. Name the batch hybrid Converter.bat and you can execute it directly as Converter from the cmd line. Sure you can default ALL scripts to run from Cscript or Wscript, but if you want to execute your vbs as a windows script rather than a console script, this could cause some confusion later on. So just set your code to a batch file and run it directly.
Check the answer -> Here
And here is an example:
Converter.bat
::' VBS/Batch Hybrid
::' --- Batch portion ---------
rem^ &#echo off
rem^ &call :'sub
rem^ &exit /b
:'sub
rem^ &echo begin batch
rem^ &cscript //nologo //e:vbscript "%~f0"
rem^ &echo end batch
rem^ &exit /b
'----- VBS portion -----
Dim tester
tester = "Convert data here"
Msgbox tester
You may follow the following steps:
Open your CMD(Command Prompt)
Type 'D:' and hit Enter. Example: C:\Users\[Your User Name]>D:
Type 'CD VBS' and hit Enter. Example: D:>CD VBS
Type 'Converter.vbs' or 'start Converter.vbs' and hit Enter. Example: D:\VBS>Converter.vbs Or D:\VBS>start Converter.vbs

Porting shell functions to cmd.exe: Is it possible to automatically source scripts on startup?

I'm porting a Linux tool-set that makes frequent use of shell functions to provide certain functionality. These functions are automatically sourced when you start a new shell and include things like changing the working directory, which is nigh impossible with stand-alone programs because child processes can't change their parent's environment.
For example, there is a function cdbm which changes the working directory to one that was previously bookmarked. Now I want to do the same on Windows, but I'm stuck with cmd.exe. As far as I understand the scripts could be ported to jscript, vbscript or plain batch, which shouldn't be a problem. But how do I make sure they automatically get sourced on startup and live in the shell's environment?
According to help cmd:
If /D was NOT specified on the command line, then when CMD.EXE starts, it
looks for the following REG_SZ/REG_EXPAND_SZ registry variables, and if
either or both are present, they are executed first.
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun
and/or
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
As a test, in regedit I created a new key in the HLM branch shown above called "AutoRun" with the string value "echo Hi". When I started a new instance of cmd I got:
Microsoft Windows [Version 6.0.6000]
Copyright (c) 2006 Microsoft Corporation. All rights reserved.
Hi
C:\Users\Username>
You could put in the name of a script to run instead (I would put in a fully specified path to the script or one with a environment variable in it like "%HOMEPATH%\scripts\scriptname" (including the quotes in case there are spaces in the name).
Edit:
The registry key has some side effects. One example is help. If I have the echo command above, for example, in the AutoRun when I type help vol I get a "Hi" right above the help text. Doing vol /?, though doesn't do that.
You can set either of the following registry keys to a batch file or other executable to run that program when CMD is started:
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
A batch file should be able to change the current directory of the executing CMD process with the CD command, as it doesn't run as a subprocess. You can disable the autorun behaviour by supplying /D as a switch to CMD.
See CMD /? for more details.
Since cmd doesn't allow you to define functions in global scope, I'm a little at a loss to understand what exactly you're trying to achieve by auto-sourcing a script at startup. I tend to include a batch file directory in my path where you can put batch files I regularly need.
Look at cygwin.

Resources