Setting a variable from an executable - windows

I am running an executable in a batch file with two parameters;
cmd /k ""executable" "param1" "param2""
This returns a string that I want to launch. I can't figure out how to set this return in a variable and subsequently launch it in IE.
Any ideas?

If the returned string contains a single line you may use FOR /F to set the value of an environment variable. For example:
s1.cmd
echo this is a one line string
s2.cmd
#SETLOCAL
#ECHO OFF
for /f "tokens=*" %%a in ('cmd /c s1.cmd') do set MY_VAR=%%a
echo got: %MY_VAR%
ENDLOCAL
Result
C:\> s2.cmd
got: this is a one line string
C:\>

You can use the following syntax to capture the output of your executable into a variable:
FOR /F "tokens=*" %%i in ('%~dp0YOUR_APP.exe') do SET TOOLOUTPUT=%%i
Source
then you can pass the value on to IE like so:
START "YOUR_WINDOW_NAME" /MAX /D"C:\Program Files\Internet Explorer\" iexplore %TOOLOUTPUT%
I take it that the application code that determines the url is too complicated to be reproduced in a batch file directly, or the source to the executable has been lost. If not I personally would prefer to have the logic visible in the batch file itself.

start %1 %2

Edit: Romulo A. Ceccon posted a much better solution which doesn't involve any file system access and dirty tricks. Left this here for reference (it works with command.com as well if you need 9x compatibility), but please prefer Romulo's solution.
Go through an environment variable you set by using an intermediate helper script you dynamically generate from a template. You will need write permissions somewhere, otherwise it cannot be done (the Windows command shell language is very, very limited.)
Let's call your helper script template helper.tpl with the following contents:
set INTERMEDVAR=
Make sure that helper.tpl has only a single line (no trailing CRLF!) and make sure you don't have any spaces after the equals sign there.
Now, in your main script, capture the output from your command into a temporary file (let's call it my_output_file.tmp):
cmd /k ""executable" "param1" "param2"" > my_output_file.tmp
Then copy the contents of the helper template and the output together into your helper script, let's call it my_helper_script.cmd:
copy /b helper.tpl + my_output_file.tmp my_helper_script.cmd
Then evaluate the helper script in the current context:
call my_helper_script.cmd
Now the INTERMEDVAR variable is set to the first line of the output from "executable" (if it outputs more than one line, you're on your own...) You can now invoke IE:
start iexplore.exe "%INTERMEDVAR%"
And don't forget to clean up the created files:
del /q /f my_output_file.tmp my_helper_script.cmd
This will obviously not work when invoked multiple times in parallel - you'll have to parametrize the temporary file and helper script names using the current cmd.exe's PID (for example) so that they won't overwrite each other's output, but the principle is the same.
However, if you can get a real shell, use that. cmd.exe is extremely cumbersome.

Related

Parse an environment variable in a Windows BAT script

I'm trying to create a simple application launcher for the software Nuke that puts the path together by evaluating an environment variable. The value of the variable is used in two ways. First it's used as-is. The second time I need to split the variable and use the first half.
The env variable set for the system:
NUKE_VERSION = 10.0v5
The path to the application:
C:\Program Files\Nuke10.0v5\Nuke10.0.exe
The code below works fine on the cmd prompt:
FOR /F "delims=v tokens=1" %i IN ("%NUKE_VERSION%") DO set NUKE_MAJOR=%i
"C:\Program Files\Nuke%NUKE_VERSION%\Nuke%NUKE_MAJOR%.exe"
But when I run a .bat with the code, it returns this error:
NUKE_VERSIONi was unexpected at this time.
Any insights into what is going on? I could just do this in python, but something this simple I shouldn't have to, right? Many thanks in advance.
In a CMD Window a FOR-LOOP uses a single % sign as you have listed in your question.
In a Batch file a FOR-LOOP uses a double %% sign.
FOR /F "delims=v tokens=1" %%i IN ("%NUKE_VERSION%") DO set NUKE_MAJOR=%%i

windows oneliner to set a command output in an environment variable

As stated here Is it possible to set an environment variable to the output of a command in cmd.exe I always used that
mycommand.exe>%TEMP%\out.txt
set /P FOO=<%TEMP%\out.txt
But that's ugly because it creates a file.
The for method is better but complicated
I wanted something simple a la unix, like:
mycommand.exe|set /P FOO=
No error, but FOO is not set after I run that.
Why is this not working?
Best way I can think of doing this would be to create your own little batch file that silently uses the FOR construct. For instance, you could create a batch named BatchSet.bat, stored somewhere on your path. The batch would contain the following code:
#Echo off
for /f "delims=" %%i in ('%2') do set %1=%%i
Set %1
If you run this with the following command:
BatchSet MyVar whoami
You'll get something like:
MyVar=servername\John
Obviously, the command you run should limit its output to a single line to be stored properly in the environment variable.
For instance, if you run it like this:
BatchSet MyVar Vol
Then you'll only get the first line of the Vol command's output
MyVar= Volume on drive C is labeled MyDisk
But all in all, it's a fairly elegant way of doing what you were looking for.
Note that the last line in the batch is simply there to provide visual output. It can be removed altogether.

How to call internal functions in Windows batch simultaneously?

I have a windows batch that reads my config files (also batch files) from within a directory. Now I want to call an internal function to process each of this config file. Since it is a for-loop, the files are processed one after another. But I want to execute each function for each file at the same time.
So far, I only found solutions for running commands simultaneously, i.e. the "start" command. But no solution for internal functions so far.
Background: Each config file contains lots of variables with different values that the function can automatically use, without passing them on as arguments.
Each config file contains parameters in order to execute sqlcmd with those and to process and define the output file as well. Since the variables are just too many, I don't want to handover them as arguments and therefore don't want to outsource the function into a seperate .bat file.
For reference, the code excerpt:
FOR %%I IN ("%path_job_sheets%\*.bat") DO (CALL "%%I" & CALL :get_period "%%I")
:get_period
CALL LOTS OF VARIABLES
CALL :get_job
:get_job
DO MORE PARAMETER CALLING
The ":get_period" needs to be executed but the batch should move on calling the next .bat-file.
Has anyone a solution, please?
You could use start.
Change your file a bit, so it starts the current batch file itself (thats %~f0)
#echo off
if "%~1"=="thread_job" goto :thread_job
...
FOR %%I IN ("%path_job_sheets%\*.bat") DO (
CALL "%%I"
CALL :get_period "%%I"
)
exit /b
...
:get_period
set "fileName=%~1"
start "Title %filename%" cmd /c "%~f0" thread_job
exit /b
:thread_job
CALL LOTS OF VARIABLES
CALL :get_job
If you have many jobs then it could be a good idea to use start /b to run all jobs in the same window.

Use shebang/hashbang in Windows Command Prompt

I'm currently using the serve script to serve up directories with Node.js on Windows 7. It works well in the MSYS shell or using sh, as I've put node.exe and the serve script in my ~/bin (which is on my PATH), and typing just "serve" works because of it's Shebang (#!) directive which tells the shell to run it with node.
However, Windows Command Prompt doesn't seem to support normal files without a *.bat or *.exe extension, nor the shebang directive. Are there any registry keys or other hacks that I can get to force this behavior out of the built-in cmd.exe?
I know I could just write up a simple batch file to run it with node, but I was wondering if it could be done in a built-in fasion so I don't have to write a script for every script like this?
Update: Actually, I was thinking, is it possible to write a default handler for all 'files not found' etc. that I could automatically try executing within sh -c?
Thanks.
Yes, this is possible using the PATHEXT environment variable. Which is e.g. also used to register .vbs or .wsh scripts to be run "directly".
First you need to extend the PATHEXT variable to contain the extension of that serve script (in the following I assume that extension is .foo as I don't know Node.js)
The default values are something like this:
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
You need to change it (through the Control Panel) to look like this:
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.FOO
Using the control panel (Control Panel -> System -> Advanced System Settings -> Environment Variables is necessary to persist the value of the PATHEXT variable.
Then you need to register the correct "interpreter" with that extension using the commands FTYPE and ASSOC:
ASSOC .foo=FooScript
FTYPE FooScript=foorunner.exe %1 %*
(The above example is shamelessly taken from the help provided by ftype /?.)
ASSOC and FTYPE will write directly into the registry, so you will need an administrative account to run them.
Command prompt does not support shebang , however there are a lot hybrid techniques for different languages that you allow to combine batch and other languages syntax in one file.As your question concerns node.js here's a batch-node.js hybrid (save it with .bat or .cmd extension):
0</* :{
#echo off
node %~f0 %*
exit /b %errorlevel%
:} */0;
console.log(" ---Self called node.js script--- ");
console.log('Press any key to exit');
process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.on('data', process.exit.bind(process, 0));
It is possible to be done with many other languages like Ruby,Perl,Python,PHP and etc.
Here is a simple way to force windows to support shebang however it has a caveat regarding the file naming. Copy the following text in to a batch file and follow general idea in REM comments.
#echo off
REM This batch file adds a cheesy shebang support for windows
REM Caveat is that you must use a specific extension for your script files and associate that extension in Windows with this batch program.
REM Suggested extension is .wss (Windows Shebang Script)
REM One method to still easily determine script type visually is to use double extensions. e.g. script.pl.wss
setlocal enableextensions disabledelayedexpansion
if [%1] == [] goto usage
for /f "usebackq delims=" %%a IN (%1) do (
set shebang=%%a
goto decode_shebang
)
:decode_shebang
set parser=%shebang:~2%
if NOT "#!%parser%" == "%shebang%" goto not_shebang
:execute_script
"%parser%" %*
set exit_stat=%errorlevel%
echo script return status: %exit_stat%
goto finale
:not_shebang
echo ERROR script first line %shebang% is not a valid shebang
echo maybe %1 is not a shebanged script
goto finale
:usage
echo usage: %0 'script with #! shebang' [scripts args]+
echo This batch file will inspect the shebang and extract the
echo script parser/interpreter which it will call to run the script
:finale
pause
exit /B %exit_stat%
No, there's no way to "force" the command prompt to do this.
Windows simply wasn't designed like Unix/Linux.
Is there a shell extension that does something similar?
Not that I've heard of, but that should be asked on Super User, not here.
There's no way to execute random file, unless it is an actual executable binary file. Windows CreateProcess() function just not designed for it. The only files it can execute are those with MZ magic or with extensions from %PATHEXT% list.
However, CMD itself has a limited support for custom interpreters through EXTPROC clause. The limitation is that interpreter should also support and omit this clause in its execution.
#npocmaka Thanks for the hint! After some trial and error I found the equivalent for a batch/php hybrid is as follows:
<?/** :
#echo off
C:\tools\php81\php.exe -d short_open_tag=On %~f0 %*
exit /b
*/ ?>
<?php
header('Location: example.com/');
print("<body><h1>Hello PHP!<h1></body>");
?>

how to use dos commands to do following

At the following location
\ncsusnasent02.na.jnj.com\its_diq_na_win_dev\PowerCenter\infa_shared\WCPIT_BIO_EDW\SrcFiles\DDDMD\DDD.CLI026.WK0933.DDDMR45.001.head
I have one file
DDD.CLI026.WK0933.DDDMR45.001.head
if i open this file
i get data as following(in a single line)
HEADER0101IMS HEALTHDMD Weekly D DD.CLI026.WK0933.DDDMR45 Centocor DMDDRM45 W2009080210120090831125325ssnyder#us.imshealth.com
TRAIL0101 000000000581 0000000000CKSUM000002236804730
we need to copy 581(it will not be same always it gets updated everyday) from this file
and put it in a variable
you can try the below. It will set the field into the environment variable id:
for /f "tokens=10" %%a IN (%1) do (
SET id=%%a
)
echo %id%
You can pass the full path and file name into the bat as the first argument.
edit:
This simple bat will take the input from the file you specify on the commandline (param %1), it will use the default separators of <space> and <tab> to break the line in your file - defined in the IN set - into a set of tokens. The "tokens=10" param tells the processor to pass the 10th token, which turns out to be your number in question, into the DO block. It is passed in as a param %%a. Within the DO block, I simply assign that value to an environment variable id. After the for command is complete, I echo the value out to the console.
Take a look at the FOR command, specifically the part about the /F parameter.
I'm not certain enough about the structure of that line to even try to write the full command, but you should be able to write it yourself given that information.
Hmm to me it looks more like the guy needs a dos substr... i.e.
#Echo Off
If not %1.==[]. (Cmd /V:On /C Call %0 [] %1 & GoTo :EOF)
Shift
Set MyVariable=HELLOWORLD
Set ASubStr=!MyVariable:~%1!
Echo [!ASubStr!]
So for example save this as test.bat and then call "test.bat 5" and it will echo WORLD
Google DOS Substring and work out how to parse your text variable the way you want it.

Resources