简体   繁体   中英

Silently Read/Write to a .cmd script from a C# console application

I am trying to silently read and write to a.cmd file from a C# console application. The.cmd file looks like this:

ECHO OFF
set Input=""
set /p IsCustom="Do you want to create a custom deploy package ? (Y/N)"
set /p Input="Enter product name (press enter for none):"
ECHO ON
cd .\DeployScript

IF /I "%IsCustom%" == "Y" (
    nant -buildfile:Deploy.build -D:environment=Disk Deploy.LocalRelease -D:productname=%Input%
    cd ..
    GOTO END
)

nant -buildfile:Deploy.build -D:environment=Disk Deploy.NewLocalRelease -D:productname=%Input%
cd ..

:END

This is where I want to insert the values:

set /p IsCustom="Do you want to create a custom deploy package ? (Y/N)"
set /p Input="Enter product name (press enter for none):"

Here is what I tried in C# console application, but I am not able to read the above two questions and write to them:

private static void ExecuteCmdFile()
{
    Process process = new Process();
    process.EnableRaisingEvents = true;
    process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_OutputDataReceived);
    process.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_ErrorDataReceived);
    process.Exited += new System.EventHandler(process_Exited);

    process.StartInfo.FileName = Path + @"\createPackage.cmd";
    process.StartInfo.UseShellExecute = false;           
    process.StartInfo.RedirectStandardOutput = true;

    process.Start();          
    process.BeginOutputReadLine();
    process.WaitForExit();
}

static void process_Exited(object sender, EventArgs e)
{
    Console.WriteLine(string.Format("process exited with code {0}\n", ""));
}

static void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    //Console.WriteLine(e.Data + "\n");
}

I am unable to read the questions at process_OutputDataReceived() and have no clues on inserting values. Just wanted to know if I am reading/writing to the.cmd file from C# application correctly? Am I missing something here or is there any other approach?

The Windows Command Processor cmd.exe processing a batch file is not designed for communication with other processes. It is designed for executing commands and executables one after the other and supports simple IF conditions and GOTO to control the sequence of command/program executions and FOR for doing something repeated in a loop. That´s it.

I suggest to modify the batch file to this code:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "IsCustom=%~1"
if defined IsCustom goto CheckInput
%SystemRoot%\System32\choice.exe /C NY /N /M "Do you want to create a custom deploy package (Y/N)?"
if errorlevel 2 (set "IsCustom=Y") else set "IsCustom=N"

:CheckInput
set "Input=%~2"
if not defined Input goto InputPrompt
if /I "%Input%" == "/N" set "Input="
goto ProcessData

:InputPrompt
set /P "Input=Enter product name (press enter for none): "
if not defined Input goto ProcessData
set "Input=%Input:"=%"

:ProcessData
cd /D "%~dp0DeployScript"
if /I "%IsCustom%" == "Y" (
    nant -buildfile:Deploy.build -D:environment=Disk Deploy.LocalRelease -D:productname="%Input%"
    goto END
)

nant -buildfile:Deploy.build -D:environment=Disk Deploy.NewLocalRelease -D:productname="%Input%"

:END
endlocal

Now the batch file can be executed without any argument in which case the user is prompted twice with evaluation of the input in a safe and secure manner.

But it is also possible to run the batch file with one or two arguments from another executable like a program coded in C# or from within a command prompt window or called by another batch file.

The first argument is assigned to the environment variable IsCustom which is explicitly undefined on batch file executed without any argument or with "" as first argument. The IF condition used later with referencing the string value of the environment variable IsCustom just checks if the string value is Y or y to do the custom action. Any other argument string passed as first argument to the batch file results in running the standard action.

The second argument is assigned to the environment variable Input which is also explicitly undefined on batch file executed without any argument or with "" as second argument. If the second argument is case-insensitive equal /N , then the batch file interprets this as explicit request to use no product name.

The Yes/No prompt is done using command CHOICE which is highly recommended for such choice prompts if the batch file is called without any argument or with "" as first argument.

The second prompt is done using set /P if the batch file is called without a second argument or with just "" as second argument. Double quotes are removed from input string if the user inputs a string at all for safe and secure processing of the input string by the remaining lines.

The directory DeployScript is most likely a subdirectory of the directory containing the batch file and for that reason the command CD is used with option /D to change if needed also the current drive and make explicitly the subdirectory DeployScript the current directory independent on which directory is the current directory on starting the execution of the batch file.

nant should be referenced with file extension and if possible with full path if the full path is well known because of being relative to batch file path or is fixed making it possible to use the fully qualified file name in the batch file as it is done for external command CHOICE .

The command ENDLOCAL results in making the initial current directory again the current directory SETLOCAL pushes the current directory path on stack. ENDLOCAL pops that path from stack and makes this directory again the current directory (if not deleted in the meantime which is not possible here). For that reason the execution of cd.. is not needed at all.

Now the C# coded application can run cmd.exe with the options /D and /C and the batch file name with its full path with the two arguments Y or N and product name or /N . There is no need anymore to communicate with cmd.exe processing the batch file or passing the arguments via standard input stream to the internal command SET of cmd.exe .

Note:

I do not really understand why the C# Process class is used being a C# wrapper class for the Windows kernel function CreateProcess called with using the STARTUPINFO structure because it would be also possible to use the Process class to run nant directly by the C# coded program and of course also any other executable which the batch file perhaps runs additionally. A C# coded application has direct access to all Windows library functions used by cmd.exe on processing a batch file. So there is really no need in my opinion to use a batch file at all for the task according to the provided information about the task.

For understanding the used commands in the batch file 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.

  • call /? ... explains batch file argument referencing
  • choice /?
  • cmd /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM