简体   繁体   English

从 C# 控制台应用程序静默读/写到 a.cmd 脚本

[英]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.我正在尝试从 C# 控制台应用程序静默读写 a.cmd 文件。 The.cmd file looks like this: .cmd 文件如下所示:

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:这是我在 C# 控制台应用程序中尝试的内容,但我无法阅读上述两个问题并写信给他们:

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.我无法阅读 process_OutputDataReceived() 中的问题,也没有关于插入值的线索。 Just wanted to know if I am reading/writing to the.cmd file from C# application correctly?只是想知道我是否正确地从 C# 应用程序读取/写入 .cmd 文件? 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.处理批处理文件的 Windows 命令处理器cmd.exe不是为与其他进程通信而设计的。 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.它被设计用于一个接一个地执行命令和可执行文件,并支持简单的IF条件和GOTO来控制命令/程序执行的顺序和FOR在循环中重复执行某些操作。 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.但也可以从另一个可执行文件(例如在 C# 中编码的程序或从命令提示符 window 或由另一个批处理文件调用的程序)中运行带有一个或两个 arguments 的批处理文件。

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.第一个参数分配给环境变量IsCustom ,该变量在没有任何参数或以""作为第一个参数的情况下执行的批处理文件上未明确定义。 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.稍后用于引用环境变量IsCustom的字符串值的IF条件仅检查字符串值是Y还是y以执行自定义操作。 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.第二个参数分配给环境变量Input ,在没有任何参数或以""作为第二个参数的情况下执行的批处理文件上也明确未定义。 If the second argument is case-insensitive equal /N , then the batch file interprets this as explicit request to use no product name.如果第二个参数不区分大小写,等于/N ,则批处理文件将此解释为不使用产品名称的显式请求。

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.是/否提示是使用命令CHOICE完成的,如果调用批处理文件时不带任何参数或使用""作为第一个参数,则强烈建议将其用于此类选择提示。

The second prompt is done using set /P if the batch file is called without a second argument or with just "" as second argument.如果在没有第二个参数的情况下调用批处理文件或仅使用""作为第二个参数,则使用set /P完成第二个提示。 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.目录DeployScript很可能是包含批处理文件的目录的子目录,因此命令CD与选项/D一起使用,以便在需要时更改当前驱动器并明确地将子目录DeployScript当前目录,而与哪个目录无关开始执行批处理文件时的当前目录。

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 . nant应使用文件扩展名引用,如果完整路径由于相对于批处理文件路径而众所周知,或者已修复,则应使用完整路径引用,这样就可以在批处理文件中使用完全限定的文件名,因为它已完成外部命令CHOICE

The command ENDLOCAL results in making the initial current directory again the current directory SETLOCAL pushes the current directory path on stack.命令ENDLOCAL导致初始当前目录再次成为当前目录SETLOCAL将当前目录路径推入堆栈。 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). ENDLOCAL从堆栈中弹出该路径并使该目录再次成为当前目录(如果同时未删除,这在此处是不可能的)。 For that reason the execution of cd.. is not needed at all.因此,根本不需要执行cd..

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 .现在 C# 编码的应用程序可以运行cmd.exe选项/D/C以及带有两个 arguments YN和产品名称或/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 . 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. 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当然还有批处理文件可能额外运行的任何其他可执行文件。 A C# coded application has direct access to all Windows library functions used by cmd.exe on processing a batch file. C# 编码的应用程序可以直接访问cmd.exe在处理批处理文件时使用的所有 Windows 库函数。 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.要了解批处理文件中使用的命令及其工作原理,请打开命令提示符window,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • call /? ... explains batch file argument referencing ...解释批处理文件参数引用
  • choice /?
  • cmd /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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