batch file execution in c# - c#

I am running a Java batch file from C#. If I run it by double clicking it executes successfully, but if I run it from C# code it gives exception in thread
"exception in "main" thread
java.lang.noclassdeffoundError"..
what can be the reason and how can it be solved? I am using the code:
var si = new ProcessStartInfo();
si.CreateNoWindow = true;
si.FileName = "batch-file path";
si.UseShellExecute = true;
Process.Start(si);

You are most likely missing some of the parameters that would be included in your systems environment variables.

Try setting working directory like this
process.StartInfo.WorkingDirectory = "C:\";
Also, try few other options as mentioned here,
http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/20992653-dabf-4b31-85f7-e7bfbfb4557c

Try adding the following code as the first line to your batch file.
#cd /d %~dp0

Do not use batch_process_path + "\" + instead use Path.Combine() to make sure the path is correctly fitted with slashes.
Also read this "When UseShellExecute is true, the WorkingDirectory property specifies the location of the executable"
So set it to false.

Related

Execute a batch file from c# and store result into a variable

I am writing a program that is running a batch file, and will need the output further in the program. this is my C# code:
public void ExecuteBatFile()
{
Process proc = null;
try
{
string targetDir = string.Format("C:\\Users"); //this is where mybatch.bat lies
proc = new Process();
proc.StartInfo.WorkingDirectory = targetDir;
proc.StartInfo.FileName = "batch.bat";
proc.StartInfo.Arguments = string.Format("10"); //this is argument
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; //this is for hiding the cmd window...so execution will happen in back ground.
proc.Start();
string output = proc.StandardOutput.ReadToEnd();
Console.WriteLine(output);
proc.WaitForExit();
}
catch (Exception ex)
{
Console.WriteLine("Exception Occurred :{0},{1}", ex.Message, ex.StackTrace.ToString());
}
}
}
Once I run I get this error though:
Exception thrown: 'System.InvalidOperationException' in System.dll
Exception Occurred :StandardOut has not been redirected or the process
hasn't started yet., at
System.Diagnostics.Process.get_StandardOutput() at
CefSharp.MinimalExample.Wpf.CallBatchFile.ExecuteBatFile() in
C:\Users\CefSharp.MinimalExamplemaster\CefSharp.MinimalExample.Wpf\CallBatchFile.cs:line
27
The batch file runs successfully, but then I'm not able to store the result into a variable. I can't get it to work in anyway. Has anyone got any suggestion?
This is my moch batch:
#echo off
cd C:\users\934874
echo.>silvio.txt
title This is your first batch script!
echo Welcome to batch scripting!
if "%errorlevel%"=="0" cls &Echo Success.
if "%errorlevel%"=="1" cls &Echo Fail
pause
The output that I'm expecting is either Success / Fail at console, and store that as a string into a variable.
Thanks in advance for your help
Need to redirect the output
proc.StartInfo.RedirectStandardOutput = true;
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.110).aspx
Quoting from
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.useshellexecute(v=vs.110).aspx
When UseShellExecute is false, the WorkingDirectory property is not used to find the executable. Instead, it is used only by the process that is started and has meaning only within the context of the new process. When UseShellExecute is false, the FileName property can be either a fully qualified path to the executable, or a simple executable name that the system will attempt to find within folders specified by the PATH environment variable.
One of the simplest way is to make your batch file write its output to a text file. Then your main program can read the text file after the batch has finished.
If you really want to read from the standard output stream, please take a look at this other SO post:
Capturing console output from a .NET application (C#)

How to pass parameters to an exe?

I am using psexec on my server to run an exe file on another server. How do I pass parameters to the other exe ?
The exe that I am running on my server is psexec which in turn must run the exe named vmtoolsd.exe located on another system. How do I pass parameters to vmtoolsd.exe ? Also, where do I pass it ? Would I pass it as part of the info.Arguments ? I've tried that but it isn't working.
ProcessStartInfo info = new ProcessStartInfo(#"C:\Tools");
info.FileName = #"C:\Tools\psexec.exe";
info.Arguments = #"\\" + serverIP + #"C:\Program Files\VMware\VMwareTools\vmtoolsd.exe";
Process.Start(info);
Also, as part of info.Arguments would I have to preface the path of vmtoolsd.exe with the IP address, followed by the drive path ?
Hope the below code may help.
Code from first .exe:
Process p= new Process();
p.StartInfo.FileName = "demo.exe";
p.StartInfo.Arguments = "param1 param2";
p.Start();
p.WaitForExit();
or
Process.Start("demo.exe", "param1 param2");
Code in demo.exe:
static void Main (string [] args)
{
Console.WriteLine(args[0]);
Console.WriteLine(args[1]);
}
Right click on .exe file-->goto shortcut-->in target tab write the arguement in extreme right...
in my case it worked
You can see it in the following post (answer by #AndyMcCluggage):
How do I start a process from C#?
using System.Diagnostics;
...
Process process = new Process();
// Configure the process using the StartInfo properties.
process.StartInfo.FileName = "process.exe";
process.StartInfo.Arguments = "-n";
process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
process.Start();
process.WaitForExit();// Waits here for the process to exit.
It provides far more control as you can see in the MSDN, but basically the arguments control is quite easy as you can see, is just to modify a property with a string.
Update: Since with the snippet code above you would be starting PsExec, based on:
PsExec
The format you have to use is:
psexec #run_file [options] command [arguments]
Where: arguments Arguments to pass (file paths must be absolute paths on the target system).
Since the process you're starting is psexec, in the process.StartInfo.Arguments you would have to put all the parameters it would need, in a sigle chain: #run_file [options] command [arguments].
Step1.Create Shortcut and then Right click on Shortcut-->click properties page then target tab write the comment line argument in extreme right... this way worked for me

Process.Start starts a shell then quickly exits

I am writing a C# application that uses WinForms.
I want to launch my own shell as an Admin then use Stream Writer to run some commands.
I am not doing any thing malicious. It's to fix the connection issues with another internal application (for work). The other team isn't willing to fix their program so they provided us with a command line fix. However I have to run this on many PC's so I am learning C# and trying to build something that I would use.
As soon as myProcess.Start executes, a black box appears then quickly disappears before going to the next line.
public void ProcessStartAsAdmin(string command)
{
string cname = Environment.UserDomainName + "\\" + Environment.UserName;
Process myProcess = new Process();
myProcess.StartInfo.FileName = #"C:\Windows\System32\CMD.exe";
myProcess.StartInfo.Verb = #"runas";
//myProcess.StartInfo.Arguments = command;
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.Start();
StreamWriter myStreamWriter = myProcess.StandardInput;
String inputText;
string resetConnection = "C:\\APP\\application.exe /reset /server:example.com /uid:" + cname + " /pwd:" + textBoxPassword.Text.Trim();
myStreamWriter.WriteLine(resetConnection);
myStreamWriter.Close();
myProcess.WaitForExit();
myProcess.Close();
}
If I am doing anything wrong, please let me know. If I can use a better technique, I'm open for suggestions.
Thanks.
I don't know whether this is the only issue, but there's no space between these two arguments:
/uid:" + cname + "/pwd:"
it should be:
/uid:" + cname + " /pwd:"
string resetConnection = "C:\\APP\application.exe
\a is illegal. You should write \\ (it seems you know it, and missed).
Edit:
The screen that your see is empty, because of you chose to redirect output.
What is probably happening is that the line has some error (or it's running time is very small), and you not see that.
Cancel temporary the output redirection, and the process closing, and see what happened.
Let's take a look at how you initialize the start info:
myProcess.StartInfo.Verb = #"runas";
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.StartInfo.RedirectStandardOutput = true;
You are redirecting the standard input, output and error streams. The documentation for this says:
You must set UseShellExecute to false if you want to set RedirectStandardOutput to true. Otherwise, reading from the StandardOutput stream throws an exception.
And likewise for the other two standard streams. So, redirection implies that you must set UseShellExecute to false.
On the other hand, you wish the new process to be elevated. Which means that you want to use the runas verb.
The documentation does not say so, but the Verb property only has impact when UseShellExecute is set to true. So, requesting elevation implies that you must set UseShellExecute to true. There is no other way to request elevation for a new process. You have to pass through the ShellExecuteEx (or its relatives) with the runas verb and that forces you to set UseShellExecute to true.
So there are two conflicting requirements here. You've got no option at all over elevation I presume. You must elevate for this task. Which means you'll have to give up on redirection. I suppose the only other option would be for you to run the calling process elevated. That would mean that any child processes would also be elevated and there would be no need for runas and so you could set UseShellExecute to false.
However, I see no reason for redirection. You are only doing that, I think, so that you can send commands to the cmd process. Instead you can pass the commands as arguments, or place them in an external .bat or .cmd file. So if I were you I would stop redirecting, and set UseShellExecute to true, and take it from there.

.CMD execution in C# inexplicably failing

I'm attempting to execute a .cmd process from a C# program. When I run the process in command line, i.e.
C:\Directory\Process.cmd -x 1000 -y 1000 C:\Input\input.txt
I get an appropriate result (in this case, that means that the process writes a file to:
C:\Output\output.txt
However, When I try to run this process from a simple C# program, the output file is not created. Here are a couple of my attempts:
Attempt 1)
try
{
string processName = #"C:\Directory\Process.cmd";
string argString = #" -x 1000 -y 1000 C:\Input\input.txt"; //The extra space in front of the '-x' is here on purpose
Process prs = new Process();
prs.StartInfo.UseShellExecute = false;
prs.StartInfo.RedirectStandardOutput = false;
prs.StartInfo.FileName = processName;
prs.StartInfo.Arguments = argString;
prs.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
prs.Start()
}
catch (Exception e)
{
Console.Writeline(e.Message);
}
Attempt 2)
try
{
System.Diagnostics.Process.Start(#"C:\\Directory\\Process.cmd", " -x 1000 -y 1000 C:\\Input\\input.txt";
}
catch (Exception e)
{
Console.Writeline(e.message);
}
Now, in both cases, no exceptions are thrown, and Process.cmd is accessed (it prints status updates in a shell), but the process does not create any output files. Is there something wrong with the way I am attempting to call Process.cmd, that it works properly when run directly form the command line but does not work properly when I attempt to call it from my C# program?
Thy this one?
System.Diagnostics.Process.Start("cmd.exe", #"/c C:\Directory\Process.cmd -x 1000 -y 1000 C:\Input\input.txt");
AFAIK, '#' prepends verbatim strings, wich do not requires backslash masking )
The file may be getting created, but not where you think. Use
prs.StartInfo.WorkingDirectory = "yourpath"
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.workingdirectory.aspx
The WorkingDirectory property must be set if UserName and Password are
provided. If the property is not set, the default working directory is
%SYSTEMROOT%\system32.
If the directory is already part of the system path variable, you do
not have to repeat the directory's location in this property.
The WorkingDirectory property behaves differently when UseShellExecute
is true than when UseShellExecute is false. When UseShellExecute is
true, the WorkingDirectory property specifies the location of the
executable. If WorkingDirectory is an empty string, the current
directory is understood to contain the executable.
When UseShellExecute is false, the WorkingDirectory property is not
used to find the executable. Instead, it is used by the process that
is started and only has meaning within the context of the new process.
I deleted this after realizing that a path is passed in as an argument and was probably using hardcoded path logic for the file it writes to, but since a comment has referenced this, I'll undelete in case it is still of assistance.
So I was finally able to get my hands on the source code, and realized that the problem was in the java code... it was interpreting the project directory as the output directory. Thank you for all of the help though, you guys gave some very useful information!

C# Open File With Associated Application passing arguments

I am trying to launch the default application registered for an extension specifying an additional argument:
ProcessStartInfo p = new ProcessStartInfo();
p.Arguments = "myargument";
p.FileName = "file.ext";
Process.Start(p);
The application starts correctly opening the specified file.
The problem is that it is getting just one parameter (the name of the file), totally ignoring the additional "Arguments".
Is it possible to do what I want?
Am I doing something wrong?
Thanks in advance for any help,
Paolo
I believe this is expected. Behind the scenes, Windows is finding the default application in the registry and creating a new process and passing your file name to it. I get the same behavior if I go to a command prompt and type "filename.ext argument", that my arguments are not passed to the application.
What you probably need to do is find the default application yourself by looking in the registry. Then you can start that process with arguments, instead of trying to start by filetype association. There is an answer here on how to find the default application in the registry:
Finding the default application for opening a particular file type on Windows
what exactly is your "argument", does it have spaces, backslash, etc?
Process process = new Process();
process.StartInfo.FileName = #"C:\process.exe";
process.StartInfo.Arguments = #"-r -d something else";
process.StartInfo.CreateNoWindow = false;
process.StartInfo.UseShellExecute = false;
process.Start();
Is there any reason why you cant start the app, then use the extension and arguments in your arguments?
I think an easier method is using the cmd command
void LaunchAssociatedProgram(string filename) {
Process.Start( #"cmd.exe", "/C start "+ filename );
}
EDIT:
I don't know if it works with arguments, but it is what I was looking for to launch an associated program...

Categories

Resources