从 C# 控制台应用程序静默 Read/Write 到 .cmd 脚本
Silently Read/Write to a .cmd script from a C# console application
我正在尝试从 C# 控制台应用程序静默读取和写入 .cmd 文件。 .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
这是我要插入值的地方:
set /p IsCustom="Do you want to create a custom deploy package ? (Y/N)"
set /p Input="Enter product name (press enter for none):"
这是我在 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");
}
我无法阅读 process_OutputDataReceived() 中的问题,也不知道如何插入值。只是想知道我是否正确 reading/writing 从 C# 应用程序到 .cmd 文件?我在这里遗漏了什么或者有其他方法吗?
处理批处理文件的 Windows 命令处理器 cmd.exe
不是为与其他进程通信而设计的。它设计用于依次执行命令和可执行文件,支持简单的 IF 条件和 GOTO 来控制 command/program 执行的顺序FOR 用于在循环中重复执行某些操作。就是这样。
我建议将批处理文件修改为这段代码:
@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
现在可以在没有任何参数的情况下执行批处理文件,在这种情况下,系统会提示用户两次以安全可靠的方式评估输入。
但也可以 运行 批处理文件带有来自另一个可执行文件的一个或两个参数,例如用 C# 编码的程序或来自命令提示符 window 或由另一个批处理文件调用.
第一个参数被分配给环境变量 IsCustom
,它在没有任何参数或 ""
作为第一个参数执行的批处理文件中明确未定义。稍后使用的 IF 条件引用环境变量 IsCustom
的字符串值只是检查字符串值是 Y
还是 y
来执行自定义操作。作为第一个参数传递给批处理文件的任何其他参数字符串都会导致 运行 执行标准操作。
第二个参数被分配给环境变量Input
,它在没有任何参数或使用""
作为第二个参数执行的批处理文件中也明确未定义。如果第二个参数 case-insensitive 等于 /N
,则批处理文件将此解释为不使用产品名称的明确请求。
Yes/No 提示是使用命令 CHOICE 完成的,如果不带任何参数或使用 [=13= 调用批处理文件,强烈建议将其用于此类选择提示] 作为第一个参数。
如果调用批处理文件时没有第二个参数或仅使用 ""
作为第二个参数,则使用 set /P
完成第二个提示。如果用户输入了一个字符串,则双引号会从输入字符串中删除,以便其余行安全可靠地处理输入字符串。
目录 DeployScript
很可能是包含批处理文件的目录的子目录,因此命令 CD 与选项 /D
一起使用如果需要,还可以更改当前驱动器,并明确地使子目录 DeployScript
当前目录独立于哪个目录是开始执行批处理文件时的当前目录。
nant
应该用文件扩展名引用,如果可能的话用完整路径引用,如果完整路径是众所周知的,因为它是相对于批处理文件路径的,或者是固定的,可以使用完全限定的文件名在批处理文件中,因为它是为外部命令完成的 CHOICE.
命令ENDLOCAL 导致初始当前目录再次成为当前目录。 SETLOCAL 将当前目录路径压入堆栈。 ENDLOCAL 从堆栈中弹出该路径并使该目录再次成为当前目录(如果在此期间没有删除,这在此处是不可能的)。因此根本不需要执行 cd ..
。
现在 C# 编码的应用程序可以 运行 cmd.exe
使用选项 /D
和 /C
以及批处理文件名及其完整路径和两个参数 Y
或 N
和产品名称或 /N
。不再需要与 cmd.exe
通信处理批处理文件或通过标准输入流将参数传递给 cmd.exe
.[=51 的内部命令 SET =]
注:
我不太明白为什么C#Process class is used being a C# wrapper class for the Windows kernel function CreateProcess called with using the STARTUPINFO结构要运行cmd.exe
来处理一个批处理文件。也可以直接通过 C# 编码程序使用 Process
class 到 运行 nant
,当然也可以使用批处理文件 [=133] 的任何其他可执行文件=]s 另外。 C# 编码的应用程序可以直接访问 cmd.exe
在处理批处理文件时使用的所有 Windows 库函数。因此,根据提供的有关任务的信息,我认为根本没有必要为任务使用批处理文件。
为了了解批处理文件中使用的命令及其工作原理,请打开一个 command prompt window,在那里执行以下命令,并仔细阅读每个命令显示的所有帮助页面.
call /?
...解释批处理文件参数引用
choice /?
cmd /?
echo /?
endlocal /?
goto /?
if /?
set /?
setlocal /?
我正在尝试从 C# 控制台应用程序静默读取和写入 .cmd 文件。 .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
这是我要插入值的地方:
set /p IsCustom="Do you want to create a custom deploy package ? (Y/N)"
set /p Input="Enter product name (press enter for none):"
这是我在 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");
}
我无法阅读 process_OutputDataReceived() 中的问题,也不知道如何插入值。只是想知道我是否正确 reading/writing 从 C# 应用程序到 .cmd 文件?我在这里遗漏了什么或者有其他方法吗?
处理批处理文件的 Windows 命令处理器 cmd.exe
不是为与其他进程通信而设计的。它设计用于依次执行命令和可执行文件,支持简单的 IF 条件和 GOTO 来控制 command/program 执行的顺序FOR 用于在循环中重复执行某些操作。就是这样。
我建议将批处理文件修改为这段代码:
@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
现在可以在没有任何参数的情况下执行批处理文件,在这种情况下,系统会提示用户两次以安全可靠的方式评估输入。
但也可以 运行 批处理文件带有来自另一个可执行文件的一个或两个参数,例如用 C# 编码的程序或来自命令提示符 window 或由另一个批处理文件调用.
第一个参数被分配给环境变量 IsCustom
,它在没有任何参数或 ""
作为第一个参数执行的批处理文件中明确未定义。稍后使用的 IF 条件引用环境变量 IsCustom
的字符串值只是检查字符串值是 Y
还是 y
来执行自定义操作。作为第一个参数传递给批处理文件的任何其他参数字符串都会导致 运行 执行标准操作。
第二个参数被分配给环境变量Input
,它在没有任何参数或使用""
作为第二个参数执行的批处理文件中也明确未定义。如果第二个参数 case-insensitive 等于 /N
,则批处理文件将此解释为不使用产品名称的明确请求。
Yes/No 提示是使用命令 CHOICE 完成的,如果不带任何参数或使用 [=13= 调用批处理文件,强烈建议将其用于此类选择提示] 作为第一个参数。
如果调用批处理文件时没有第二个参数或仅使用 ""
作为第二个参数,则使用 set /P
完成第二个提示。如果用户输入了一个字符串,则双引号会从输入字符串中删除,以便其余行安全可靠地处理输入字符串。
目录 DeployScript
很可能是包含批处理文件的目录的子目录,因此命令 CD 与选项 /D
一起使用如果需要,还可以更改当前驱动器,并明确地使子目录 DeployScript
当前目录独立于哪个目录是开始执行批处理文件时的当前目录。
nant
应该用文件扩展名引用,如果可能的话用完整路径引用,如果完整路径是众所周知的,因为它是相对于批处理文件路径的,或者是固定的,可以使用完全限定的文件名在批处理文件中,因为它是为外部命令完成的 CHOICE.
命令ENDLOCAL 导致初始当前目录再次成为当前目录。 SETLOCAL 将当前目录路径压入堆栈。 ENDLOCAL 从堆栈中弹出该路径并使该目录再次成为当前目录(如果在此期间没有删除,这在此处是不可能的)。因此根本不需要执行 cd ..
。
现在 C# 编码的应用程序可以 运行 cmd.exe
使用选项 /D
和 /C
以及批处理文件名及其完整路径和两个参数 Y
或 N
和产品名称或 /N
。不再需要与 cmd.exe
通信处理批处理文件或通过标准输入流将参数传递给 cmd.exe
.[=51 的内部命令 SET =]
注:
我不太明白为什么C#Process class is used being a C# wrapper class for the Windows kernel function CreateProcess called with using the STARTUPINFO结构要运行cmd.exe
来处理一个批处理文件。也可以直接通过 C# 编码程序使用 Process
class 到 运行 nant
,当然也可以使用批处理文件 [=133] 的任何其他可执行文件=]s 另外。 C# 编码的应用程序可以直接访问 cmd.exe
在处理批处理文件时使用的所有 Windows 库函数。因此,根据提供的有关任务的信息,我认为根本没有必要为任务使用批处理文件。
为了了解批处理文件中使用的命令及其工作原理,请打开一个 command prompt window,在那里执行以下命令,并仔细阅读每个命令显示的所有帮助页面.
call /?
...解释批处理文件参数引用choice /?
cmd /?
echo /?
endlocal /?
goto /?
if /?
set /?
setlocal /?