0

I'm currently revising a small application that I wrote as a demonstration for a security course I'm taking. The prof loved it and has requested some modifications that I'm unable to figure out. I would like to add the ability to pass in as a parameter to the batch file a few variables from my code (i.e. the number of cmd.exe instances to run and in the code below, the message variable).

Using an answer found at Launching multiple shell prompts from a single batch file among other helpful SO threads, here's an example of the code I've put together:

The batch file:

@echo off

if not "%1" == "" goto :%1

SET message="The random number is: "

SET /a rand=%RANDOM%

start "Job 1" "%~dpfx0" job1
start "Job 2" "%~dpfx0" job2
start "Job 3" "%~dpfx0" job3
goto :eof

:job1
call :showMessage %message% %rand%

:job2
call :showMessage %message% %rand%

:job3
call :showMessage %message% %rand%

:showMessage 
echo %~1 %~2

This works great to spawn 3 instances of cmd.exe. I'm stumped, though, as to how I can dynamically choose the number of jobs to run and how to pass in a variable to the batch file with the above configuration. I figure I need a FOR loop, but I'm uncertain how to do it either with the above setup or a new way entirely.

I'm 110% sure the line from the batch file "if not "%1" == "" goto :%1" is absolutely necessary as without it, the system will continuously open cmd.exe processes (experimentation resulted in several hard resets). It interferes with passing in parameters to the batch file, but I am not able to find a way around using it.

For reference:

The batch file is executed in Java via the following code:

public class CmdProcess{
    Runtime rt;

    public cmdProcess() {
        rt = Runtime.getRuntime();
    }

    public void startSpawning() {
        try {
            rt.exec("cmd.exe /C example.bat");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

I call this class from the gui code with the following listener:

private void setupListeners() {
    class spawnButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent ae) {
            // Fire off 3 cmd.exe processes that show a message
            CmdProcess proc = new CmdProcess ();
            proc.startSpawning();
            // Increment the local counter and display on the client
            processCounter += 3;
            processCounterTextField.setText(Integer.toString(processCounter));
            }
        }

tl;dr: I need to know if it's possible with DOS magic in a batch file executed with Java to pass in the parameters necessary to run any number of cmd.exe instances that will each perform the same command.

EDIT TO INCLUDE SOLUTION: Based on input from @JosefZ, here is a solution that works the way I need it to:

@echo off
if not %1 == "" (
    set /A noiter=%1
    ) Else (
    set /A noiter=1
    )

SET message="The random number is: "

SET /a rand=%RANDOM%

if %noiter% == 0 (
    call :showMessage %message% %rand%
    ) Else (
    For /L %%G IN (1, 1, %noiter%) do (
        start "Job %%G" "%~dpfx0" job%%G
        set /a rand=%RANDOM%
        :job%%G
        call :showMessage %message% %rand%
        )
    )
)

:showMessage
echo %~1 %~2

If I wanted to pass in additional parameters, I would handle them in the first if block...

@echo off
if not %1 == "" (
    rem passed in parameters
    set /A noiter=%1
    set /A message=%2
    set /A rand=%3
    ) Else (
    rem default parameters
    set /A noiter=1
    set message="The random number is: "
    set /a rand=%RANDOM%
    )

1 Answer 1

1

You know we can call a script with a parameter. Let's check this parameter as follows: if it's a numeric value, consider this is instances count of cmd.exe to be launched and remember it to a numeric environment variable: set /A "noiter=%1"; otherwise it's simply a flag to end. Here's the code:

if not "%1" == "" (
  set /A "noiter=%1"
) Else (
  set /A "noiter=1"
)

Sample an effect of set /A "noiter=text" yoursef. Now we can test value of the noiter variable:

if "%noiter%" == "0" (
  call :showMessage %message% %rand%
) Else (
  rem loop here
)

Finally, substitute next code snippet in place of above's rem loop here:

  rem loop from 1 stepping 1 to "noiter"
  For /L %%G IN (1, 1, %noiter%) do (
    rem for testing purposes only: echo our command line first  
    echo start "Job %%G" "%~dpnx0" job%%G
    rem for testing purposes only: simulate real call
    set /a "rand=%RANDOM%"
    call :showMessage %message% %rand%
  )

This is a raw blueprint only; there are still some issues: e.g. %random% tends to stay constant :-)

So, learn more on set command, setlocal, enabledelayedexpansion etc. etc.

Sign up to request clarification or add additional context in comments.

3 Comments

It looks like there's a missing function for each job, i.e. :job%%G. I'm going to experiment and see if I can figure it out.
All the Job1, Job2 and Job3 in your code seem to be identical: call :showMessage %message% %rand%. Should be different? Then you should appoint maximal count of cmds, create that number of labels and instead of call :showMessage %message% %rand% substitute call :%1 or even (uncommendable) goto :%1
I've edited my original post with a solution that works for what I need based on the input you've provided. TYVM for your knowledge and assistance, @JosefZ!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.