Add single doskey command - Windows Registry - batch-file

I'm working on a batch file, and I need to add this entry:
doskey wfreerdp="C:\Program Files\wfreerdp\wfreerdp.exe" $*
to this regkey:
HKCU\Software\Microsoft\Command Processor
I played with the options of reg add, but I simply cannot get it to work.
I know it should be something like:
reg add "HKCU\Software\Microsoft\Command Processor" /v doskey wfreerdp = "C:\Program Files\wfreerdp\wfreerdp.exe" $*
but I don't which one and how to use the /t, /S, /d & /f flags.
If I manually add the entry:
doskey wfreerdp = "C:\Program Files\wfreerdp\wfreerdp.exe" $*
it works perfectly.
Alternativelly I tried creating the C:\bat\macros.doskey file, containing the doskey command:
doskey wfreerdp = "C:\Program Files\wfreerdp\wfreerdp.exe" $*
and the following in the batch file:
reg add "HKCU\Software\Microsoft\Command Processor" /v Autorun /d "doskey /macrofile=\"c:\bat\macros.doskey\"" /f
No success.
Any tips?

If you are trying to add the doskey command to your Command Prompt's AutoRun so that it will run every time you open cmd.exe, then you would need to run the following:
reg add "HKCU\Software\Microsoft\Command Processor" /v "AutoRun" /d "doskey wfreerdp = \"C:\Program Files\wfreerdp\wfreerdp.exe\" $*"
Let's break this down:
From the documentation at 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
You already know you're placing the key into HKEY_CURRENT_USER\Software\Microsoft\Command Processor.
The /v switch specifies the value name to add/modify, which in this case is the AutoRun key.
The /d switch specifies what that key should contain, which in this case is the doskey command.
Since your command contains quotation marks ("), you would need to escape them so they are not processed by the command line (\").

Related

Open file in program from batch file windows

I have a batch file to open a bunch of programs on demand (not start-up)
E.g.
cd "C:\Program Files (x86)\Microsoft Office\root\Office16"
start lync.exe
I want to open files inside another program automatically specifically AutoHotKey scripts but with the option to open general files e.g. something like
d:
cd "D:\.PortableApps\AutoHotkey_1.1.28.02\"
start notifier.ahk AutoHotkeyU64.exe
I have tried
START "" /D "D:\.PortableApps\AutoHotkey_1.1.28.02\notifier.ahk" "D:\.PortableApps\AutoHotkey_1.1.28.02\AutoHotkeyU64.exe"
I would recommend, first and foremost, that you open a Command Prompt window and enter start /? to read its usage information.
For your first example, you should just Start your executable linc.exe directly, you do not need to change your working directory to do so:
#Start "" "C:\Program Files (x86)\Microsoft Office\root\Office16\lync"
In the above example you'll note that as the first doublequoted string is expected to be a title, I have used an empty one to prevent your command being read as one. Also if you cannot be sure that .EXE is a value entry under %PATHEXT%, you'd include that .exe extension, i.e. #Start "" "C:\Program Files (x86)\Microsoft Office\root\Office16\lync.exe".
As a final note, as lync.exe is a Microsoft Office product, I'd fully expect that its path is entered in the registry under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\lync.exe. In that case, you should not need to enter its path at all and the following would be all that is needed:
#lync
For the second example, the first thing you should note from the output of start /? is that you should be starting the executable with its script as an argument, not starting the script with its executing file as the argument.
If your AHk command does not require that your current directory is its own, the following should suffice:
#Start D:\.PortableApps\AutoHotkey_1.1.28.02\AutoHotkeyU64 D:\.PortableApps\AutoHotkey_1.1.28.02\notifier.ahk
If there were spaces or other poison characters in any of those names or paths, then the safer doublequoted option, complete with executable extension, would be better:
#Start "" "D:\.PortableApps\AutoHotkey_1.1.28.02\AutoHotkeyU64.exe" "D:\.PortableApps\AutoHotkey_1.1.28.02\notifier.ahk"
If you need to change directory, for the AHk command to work properly, then you have two options along the lines of your provided tests:
#PushD D:\.PortableApps\AutoHotkey_1.1.28.02
#Start AutoHotkeyU64 notifier.ahk
#PopD
If you cannot be sure that .EXE is a value entry under %PATHEXT%, you'd include that .exe extension, i.e. #Start AutoHotkeyU64.exe notifier.ahk. Also if there were spaces in the first line directory path, then you would doublequote it, if that path was not on an NTFS file system.
To use the Start option directly, similar to the first example:
#Start /D D:\.PortableApps\AutoHotkey_1.1.28.02 D:\.PortableApps\AutoHotkey_1.1.28.02\AutoHotkeyU64 notifier.ahk
If there were spaces or other poison characters in any of those names or paths, then the safer doublequoted option, complete with executable extension, would be better:
#Start "" /D "D:\.PortableApps\AutoHotkey_1.1.28.02" "D:\.PortableApps\AutoHotkey_1.1.28.02\AutoHotkeyU64.exe" "notifier.ahk"
In all of the examples above I have prepended the commands with #. If your script has already turned echoing off, then you can omit all of those prepending characters.
When you run cd /? from cmd you will find this section in the help topic:
Use the /D switch to change current drive in addition to changing current
directory for a drive.
You are therefore required to use the /d switch when changing directories which are on a different drive letters.
#echo off
cd /d "D:\.PortableApps\AutoHotkey_1.1.28.02\"
start notifier.ahk AutoHotkeyU64.exe
Alternatively by using pushd
#echo off
pushd "D:\.PortableApps\AutoHotkey_1.1.28.02\"
start notifier.ahk AutoHotkeyU64.exe
popd
Or simply start (without the incorrectly implemented /D as in your example).
start "" "D:\.PortableApps\AutoHotkey_1.1.28.02\notifier.ahk" "D:\.PortableApps\AutoHotkey_1.1.28.02\AutoHotkeyU64.exe"
Alternatively you can use pushd
or start /b without creating a new window:
start /b "" "D:\.PortableApps\AutoHotkey_1.1.28.02\notifier.ahk" "D:\.PortableApps\AutoHotkey_1.1.28.02\AutoHotkeyU64.exe"
Just as a reminder, all of the relevant help for the above mentioned commands can be found by running the following from cmd.exe
cd /?
pushd /?
popd /?
start /?

Find Specific *.exe files in directories and run the app with parameters

I'm trying to find recursively all "MyApp.exe" apps in "C:\Builds" folder and run the apps with "createdatabase closeimmediately" arguments/parameters.
What I search so far:ForFiles Microsoft docs
Here is the forfiles pattern:
forfiles [/p <Path>] [/m <SearchMask>] [/s] [/c "<Command>"] [/d [{+|-}][{|}]]
Here is what I have:
forfiles /p c:\Builds /s /m MyApp.exe /c "cmd /c start #path" "createdatabase closeimmediately"
If I run above script, it is showing error:
ERROR: Invalid argument/option - 'createdatabase closeimmediately'.Type "FORFILES /?" for usage.
If I run without parameteres, it finds apps correctly and runs, but I need to run with parameters:
forfiles /p c:\Builds /s /m MyApp.exe /c "cmd /c start #path"
How can I run apps with parameters in ForFiles?
I know this was mentioned in the comments, but the comments are becoming too long for me to post a decent comment still, so here is an answer. This should do exactly what you want, it will recursively search for the file and execute if exists.
#echo off
for /r "c:\Builds" %%i in (myapp.exe) do if exist "%%i" "%%i" createdatabase closeimmediately
a slightly different way, find all executables, and launch if the name matches myapp.exe:
for /r "c:\Builds" %%i in (*.exe) do if /I "%%~nxi" == "myapp.exe" "%%I" createdatabase closeimmediately
There are multiple methods possible to search for MyApp.exe in C:\Build and all subfolders and execute the found executable with the two parameters createdatabase and closeimmediately.
The first solution uses command FOR to search for any file matching the wildcard pattern MyApp*.exe in C:\Build and any non-hidden subfolder.
For usage in a batch file:
for /R "C:\Build" %%I in ("MyApp*.exe") do if /I "%%~nxI" == "MyApp.exe" "%%I" createdatabase closeimmediately
For usage in command prompt window:
for /R "C:\Build" %I in ("MyApp*.exe") do #if /I "%~nxI" == "MyApp.exe" "%I" createdatabase closeimmediately
It is necessary that the string inside the round brackets contains at least one * or ? to define a wildcard pattern. Otherwise FOR would not search for files with name MyApp.exe on using just "MyApp.exe" in C:\Build and all its subfolders. It would simply append the string "MyApp.exe" (with the double quotes) to folder path of every folder found in C:\Build folder structure and would assign folder path + "MyApp.exe" to loop variable I and execute the command line referencing the loop variable.
The IF condition is used to make sure that only MyApp.exe is executed and not for example MyAppOther.exe found by chance also by FOR with wildcard pattern MyApp*.exe. The string comparison is done case-insensitive because of /I.
It would be also possible to use a different wildcard pattern like MyApp.exe*. This could reduce the number of false positives. But for security the IF condition should be nevertheless used.
The second solution is using just MyApp.exe and check if a file with that name really exists in the given folder path before executing it.
For usage in a batch file:
for /R "C:\Build" %%I in (MyApp.exe) do if exist "%%I" "%%I" createdatabase closeimmediately
For usage in command prompt window:
for /R "C:\Build" %I in (MyApp.exe) do #if exist "%I" "%I" createdatabase closeimmediately
MyApp.exe is specified in round brackets without being enclosed in " as otherwise the string assigned to loop variable I would be for example C:\Build\"MyApp.exe" and not C:\Build\MyApp.exe. By automatic error correction the string value C:\Build\"MyApp.exe" might also work depending on which string is really used instead of MyApp.exe. But this is not really a safe method and does not work if the string MyApp.exe contains a space, comma, semicolon, or other characters like &()[]{}^=;!'+,`~.
The third solution is using the command DIR for searching for MyApp.exe without a wildcard pattern to find only files with exactly that name and let FOR execute the found executables with that name.
For usage in a batch file:
for /F "delims=" %%I in ('dir "C:\Build\MyApp.exe" /A-D-H /B /S 2^>nul') do "%%I" createdatabase closeimmediately
For usage in command prompt window:
for /F "delims=" %I in ('dir "C:\Build\MyApp.exe" /A-D-H /B /S 2^>nul') do #"%I" createdatabase closeimmediately
In comparison to FOR the command DIR really searches for files with name MyApp.exe even on argument string not containing a wildcard character like * or ?.
FOR executes the DIR command line in a separate command process started with cmd.exe /C in background and captures everything written to handle STDOUT of this command process.
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
2>nul is used to suppress the error message output by DIR to handle STDERR by redirecting it to device NUL if no file MyApp.exe could be found in C:\Build or its subdirectories.
DIR outputs because of /B and /S just the full qualified file name, i.e. file path + file name + file extension, of every found MyApp.exe line by line.
FOR processes the captured output line by line with skipping empty lines and lines starting with a semicolon. Such lines are surely not output by DIR with the used options.
FOR would also split up each line into substrings (tokens) on spaces/tabs and would assign only first substring to loop variable I. This string splitting behavior is not wanted here as a folder name could contain one or more spaces. For that reason FOR option delims= is used to define an empty list of delimiters which disables the line splitting behavior.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
for /?
if /?

Batch file command to select newest folder except if specific name

We have a batch file to create a variable from the folder name of the newest folder created in a specific location. As newer versions of this software is released the version number (folder name also) i.e. 10.0, 10.1, 10.2, 10.3 folder is created in this directory. Until now this has worked without hitch, however in the last update they decided to add a folder called Install in this same directory.
Is it possible to change the following script to ignore the Install folder and select the newest created folder name instead:
SET TABVER="C:\Program Files\Tableau\Tableau Server\"
FOR /F "delims=" %%i IN ('dir %TABVER% /b /ad-h /t:c /od') DO SET VERSION=%%i
SET TABCMD="C:\Program Files\Tableau\Tableau Server\%VERSION%\bin\tabcmd.exe"
This batch code could be used:
set "TABVER=C:\Program Files\Tableau\Tableau Server\"
for /F "delims=" %%I in ('dir "%TABVER%" /B /AD-H /T:C /O-D 2^>nul') do if /I not "%%I" == "Install" set "VERSION=%%I" & goto FoundVersion
echo Error: There is no version subfolder in probably not already existing folder:
echo/
echo %TABVER%
echo/
pause
goto :EOF
:FoundVersion
set TABCMD="%TABVER%%VERSION%\bin\tabcmd.exe"
rem Other commands using TABCMD
The DIR option /od is modified to /O-D to get the list of subdirectories in reverse order output by command DIR with newest directory first and oldest directory last.
The additional IF command compares case-insensitive the current directory name with the string Install. Only if the directory name is not Install the directory name is assigned to environment variable VERSION and the loop is exited without processing all other directory names with a jump to label FoundVersion.
I added an error output in case of C:\Program Files\Tableau\Tableau Server does not exist at all, contains no subdirectories or contains just Install and with halting batch file execution until user presses any key and then exiting the batch file processing.
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
See also How to set environment variables with spaces? In general it is better to use the command line set "variable=value" and reference the environment variable with "%variable%" instead of using set variable="value" and reference the environment variable with just %variable%. Look on %TABVER% references why it makes sense not having assigned a folder path with the double quotes to an environment variable.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
Read also single line with multiple commands using Windows batch file and Where does GOTO :EOF return to?

Run all SQL files in multiple directories

I combined a couple of solutions I found online to try and make this happen.
https://stackoverflow.com/a/6504317/2471473
https://sqlandme.com/2013/03/25/sql-server-executing-multiple-script-files-using-sqlcmd/
I'm trying to run a single .cmd script (Script1.cmd) with folder locations of .sql files. That single script runs another script (Script2.cmd) to use sqlcmd to execute all the .sql files in that folder location. It mostly works, but it leaves a command window open that I have to exit from for each folder location.
Script1.cmd
start Script2.cmd "C:\Location1"
start Script2.cmd "C:\Location2"
Script2.cmd
#Echo Off
FOR /f %%i IN ('DIR %1\*.Sql /B') do call :RunScript %1 %%i
GOTO :END
:RunScript
Echo Executing Script: %2
cd %1
SQLCMD -S Server123 -d Database456 -E -i %2
Echo Completed Script: %2
:END
Official command line reference for Windows XP or for Windows Server 2003, Windows Vista (and above) seems to be too brief. Read this (extended) start command documentation:
Syntax: START "title" [/D path] [options] "command" [parameters]
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.
If command is an internal cmd command or a batch file then the command
processor is run with the /K switch to cmd.exe. This means that the
window will remain after the command has been run.
Next Script1.cmd should work and close started command windows:
start "" cmd /C Script2.cmd "C:\Location1"
start "" cmd /C Script2.cmd "C:\Location2"

How to specify /D in FOR command?

The Windows command line interpreter features a FOR command, which is able to parse the output of a given command and execute the loop for each line of the output, e.g.:
FOR /F %%i IN ('DIR .') DO echo %i # Outputs each file name
The command (DIR .) is executed in a child command line via cmd /C <command> <command-arguments>, however, the /D parameter is not specified ... this leads to weird behavior if the user has a AutoRun command with output (e.g. echo, or cls).
Is there a way to force FOR to execute the command via cmd /C /D <command> <command-arguments>?
You have run across one of the many design flaws of cmd.exe, and this one has bothered me for quite some time. I'm pretty sure there is no way to suppress AutoRun when FOR /F executes a command.
What makes this especially irritating is that pipes also use CMD /C (one for each side of the pipe), but the designers of the pipe were smart enough to incorporate both the /D and /S options. It is really a shame the designers of FOR /F couldn't have done the same.
I believe your only recourse One option is to be defensive within your AutoRun command definition. I suggest putting all the AutoRun commands within a batch script that has something like the following at the top:
#echo off
if defined AutoRunComplete exit /b
set AutoRunComplete=1
REM Put your AutoRun commands below...
But if you cannot control the AutoRun commands, then I think you are out of luck. Aacini's idea of using a temporary file to get around the problem is an effective and simple solution.
A very simple solution for your problem is use a file in the for /F command instead of a command. This way, we just emulate the internal operation of for /F over a command, but executing each step explicitly: 1. Execute the command and store its output in a temporary text file. 2. Process all lines in the temporary file. 3. Delete the file.
DIR . > TempFile.txt
FOR /F %%i IN (TempFile.txt) DO echo %%i
DEL TempFile.txt
When you have many FOR /F blocks for parsing program output, then it could be useful to add a cmd.exe wrapper.
This wrapper can be installed with
set "comspec=C:\somewhere\cmdWrapper.exe"
FOR /F %%i IN ('DIR .') DO echo %%i
The wrapper itself has to start the original cmd.exe with /D /C.
But the behaviour of the comspec variable itself is a bit strange.

Resources