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

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 modifying 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 makes 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 to run cmd.exe to process a batch file. 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 /?

Related

Delete a program that are running in console of C#

I have create a program that delete a folder.
Like this :
if (Directory.Exists((System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "My Dir Name"))))
{
Directory.Delete(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "My Dir Name"), true);
}
this is alright . But a file that name is "Delete.exe" is in directory of "My Dir Name" [Like my code ] ! It gave an error, because "Delete.exe" is running and can't delete .
What can I do to delete, "Delete.exe"?
You're trying to delete the folder in which your running application is in and therefore delete the program itself? Well, you have a few options. It is interesting to note as well that batch files can delete themselves. So, that also leaves you a few more options:
have your C# program copy itself to a temp directory before deleting the folder, and run from there.
use a batch file entirely instead of C# - having it do whatever and then delete itself afterwards.
have your C# program generate and execute a batch file and then quit - leaving the batch file to clean up after the C# program exits.
run a CLI command to delete your program after a specified time:
Process.Start("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del " + Application.ExecutablePath);
you can use MovFileEx to specify to have your program deleted on next start up.
Most of these answers imply that the running EXE is your own appliation. if it is not, though - #5 will still work. you can schedule it to be deleted the next time the computer starts.

Trouble running .cmd file with c#

For some reason, I can't seem to launch and run a .cmd file with c#. An example of a line of the cmd file is:
"C:\Windows\system32\ffmpeg64.exe" -v verbose -y -i "S:\TEMP\A.ts" -c:v copy -c:a copy -ss 00:00:00.000 -t 2 "S:\TEMP\A_SHORT.ts"
I've tried several different ways to launch this file from within C#, such as (where curDirectory is for example "S:\TEMP")
Process p = Process.Start(curDirectory + "\\ffmpeg.cmd");
I've also tried
string path = curDirectory + "\\ffmpeg.cmd";
Process p = Process.Start("cmd.exe", #"/c " + path); //I've also tried /k
But what happens is the cmd prompt will show up and say "C:\Windows\System32\ffmpeg64.exe" is not recognized ..." even though the file is there. What am I doing wrong?
If your system is running the Windows 6.1 kernel or later, System32 is actually comprised of other directories based on the application you're running (depending on whether it is a 32-bit or 64-bit application).
I assume that ffmpeg64.exe is a 64-bit application, and when you execute the .cmd file manually, it should default to a 64-bit command prompt - Also ensure that your application is targeting "x64" or "Any CPU". Alternatively, you could place a 32-bit version of ffmpeg in the WoW64 directory.
Also, I know you've stated in comments that you don't want to read the .cmd file and modify it, but you could compose your ProcessStartInfo with Environment.SystemDirectory instead of the hard-coded path.
As a last option, you could place the ffmpeg exe somewhere static (as you stated in the comments, in c:\ works), or just in your application's working directory.

Run exe file in silent mode using command prompt

I am trying to run xxx.exe file using command prompt with silent mode. i saw this link in Google: http://www.powerware.com/Software/lansafe_help/LSHelp424.htm.
when i run this command : C:>"D:\xxx.exe" -r -f1"D:\Test.iss"
am getting error : "xxx.exe" is not recognized as an internal or external command operable program or batch file.
Can any body give the idea where i am doing mistake.
As others said, make sure your path to your exe file is correct. You can change directory where exe is before execution or write out the full path.
By silent mode if you mean to run exe without any output on screen, then simply redirect the output to a file.
E.g. if your exe is in D:\myprog\myprog.exe, then following command will make your program run in "silent" mode:
c:>"D:\myprog\myprog.exe" > "D:\myprog\output.txt"
Above example will dump output into output.txt file.
you have to run your command in which location EXE file is located. can you check whether its residing in d:?
You may switch over to the D:\ drive before running your command, but it shouldn't matter. Double check it actually exists in that location

Batch file not executing through windows service

I have a scenario in which i have to create a windows service which will check that if the batch file is not running then it should execute that batch file.
Moreover, my batch file is used for automation using Selenium for Application checkout.
When i create that service, somehow the batch file is not executing and is not able to launch the selenium. When i see same in task manager, i can see a cmd instance is running but that cannot run my selenium.
Code of my Project: Timer is set to 1 minute
private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!File.Exists(ConfigurationManager.AppSettings["testFilePath"])) //To check whether batch file is running or not
{
System.Diagnostics.Process proc = new System.Diagnostics.Process(); // Declare New Process
proc.StartInfo.FileName = ConfigurationManager.AppSettings["BatchFilePath"];
proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.WaitForExit();
}
}
Batch File is like This:
copy C:\AutomatedTests\AHD\testingWS.txt C:\AutomatedTests\AHD\AHDExecutionService\testingWS.txt
start cmd /k java -jar "C:\AHS_Automation\Release\UnifiedBillingSystem\Selenium RC\selenium-server-1.0.3\selenium-server.jar"
This code will check periodically that if batch file is not under execution then my service will start its execution otherwise will do nothing.
Not sure with so little context... but the first thing I would check is the path that executes the bat file with respect to the files that the bat file uses; if you're calling the bat file from another program, it normally inherits the environment folder from that program - which is something that most people don't expect. (for a windows service this is windows\system32) The easiest way to check if this is the case is by setting the path explicitly in the first line of the bat file (e.g. cd [path of bat file] )

running a batch file through c# console app. Commands get ignored

i'm trying to execute a .bat file through a c# console application using code from here:
Service hangs up at WaitForExit after calling batch file
Kevin's solution kinda works, but some commands in my .bat file get ignored for some reason, but when i manually execute the .bat file all commands work just fine.
e.g. xcopy command doesn't work while executing .bat from console app, but start command works fine.
Any idea why this happens?
p.s. recently i found that if the program is being launched from command prompt, it works well. How come? Still i need to put it on autorun, so this doesn't solve the problem.
Also, if launched by clicking on exe file, output shows
xcopy folder1 folder2
but if launched from command prompt, output shows
xcopy folder1 folder2
smth/smth.smth copied
....
5 files copied.
And it actually is being copied.
proc.StartInfo.FileName = target;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit
(
(timeout <= 0)
? int.MaxValue : timeout * NO_MILLISECONDS_IN_A_SECOND *
NO_SECONDS_IN_A_MINUTE
);
errorMessage = proc.StandardError.ReadToEnd();
proc.WaitForExit();
outputMessage = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
Batch file commands do not get ignored when you execute the command processor from a service. They however easily fail and can do so unobserved since you cannot see their output. Typical reasons for failure are having the ProcessStartInfo.WorkingDirectory not set correctly so that relative paths no longer work or trouble caused by the service running with a different user account that doesn't have the same rights as the one you use from the desktop.
Diagnose problems by redirecting output to a file, run cmd.exe /c and use the > operator. Append 2>&1 so that the file contains both regular and error output. And by using the %errorlevel% variable and EXIT command judiciously so you can discover that execution failed by using the Process.ExitCode property.

Categories

Resources