merging the content of a directory using cmd shell - c#

I want to merge all the files in a directory into one. However I tried several versions but none of them seem to work. I am getting an error saying that the file was not found. Here is what I was trying:
String outputFile = this.outputTxt.Text;
String inputFolder = this.inputTxt.Text;
String files = "";
String command;
foreach (String f in Directory.GetFiles(inputFolder))
{
files += f+"+";
}
files = files.Substring(0, files.Length - 1);
command = files + " " + outputFile;
Process.Start("copy",command);
sample of what I want to obtain:
copy a.txt+b.txt+c.txt+d.txt output.txt
And the error I get is:
An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in System.dll
Additional information: The system cannot find the file specified

Try starting cmd rather than "start" with process.
Process.Start("cmd", "copy " + command);
'copy' is a command in the command prompt, aliased to... something, and not an actual file itself that windows knows how to run (outside of the command prompt).
There are properties of the Process class that you can use to suppress the window that the shell pops up if you don't want it on the screen while the program is running.

Should you not be using command instead of files for your second parameter to Process.Start?
Process.Start("copy", command);
UPDATE:
Ok, so it was a typo. How about your inputFolder text? Is it using double back-slashes for the directories (escaping the back-slashes)? As in all \ characters should be \\.

You need to call cmd.exe with the copy command and your arguments (as was mentioned by #Servy). Here is a cleaned up version of your code to do what you need:
String outputFile = this.outputTxt.Text;
String inputFolder = this.inputTxt.Text;
StringBuilder files = new StringBuilder();
foreach (String f in Directory.EnumerateFiles(inputFolder))
{
files.Append(f).Append("+");
}
files = files.Remove(file.Length-1, 1); // Remove trailing plus
files.Append(" ").Append(outputFile);
using (var proc = Process.Start("cmd.exe", "/C copy " + files.ToString()))
{
proc.WaitForExit();
}
You need to dispose of the Process (thus the using statement) and since you are concatenating a lot of strings (potentially a lot of strings anyway), you should use a StringBuilder.

Related

How to mimic Stdin input when running an exe from C# using create process?

I have an audio converter .exe that i want to wrap in a C# program, for UI and inputs etc.
To use the AudioConverter.exe, it is ran from the console with the suffix " < inputFile > ouputFile".
So the full line reads something like
C:\\User\Audioconverter.exe < song.wav > song.ogg
So far i have been able to start the converter succesfully outside of C#, I have managed to have the converter run via create process in C# in a hang state (without input and output files).
My code in C# thus far is pretty similar to the answers given on this site:
using System;
using System.Diagnostics;
namespace ConverterWrapper2
{
class Program
{
static void Main()
{
LaunchCommandLineApp();
}
static void LaunchCommandLineApp()
{
// For the example
const string ex1 = "C:\\Users\\AudioConverter.exe";
const string ex2 = "C:\\Users\\res\\song.wav";
const string ex3 = "C:\\Users\\out\\song.ogg";
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "AudioConverter2.exe";
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.Arguments = ex1 + " < " + ex2 + " > " + ex3; \\Process is ran successfully without the addition of input and output files, but hangs waiting for files.
try
{
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// Log error.
}
}
}
}
So far the converter exe hasnt been able to start up correctly, this leads me to ask the question are inputs for stdin different from arguments?
Regardless i need to mimic this style of input and would appreciate any information. I had assumed that i could just pass the input and output files as arguments but i havent had much luck.
startInfo.Arguments = ex1 + " < " + ex2 + " > " + ex3; \\Process is ran successfully without the addition of input and output files, but hangs waiting for files.
That won't work.
A.exe < B > C is not process A.exe called with arguments < B > C. It's rather a shell instruction to:
start A.exe without arguments,
read file B and redirect its contents to the new process' stdin and
write the new process' stdout to file C.
You have two options to do that in C#:
You can use the help of the shell, i.e., you can start cmd.exe with arguments /c C:\User\Audioconverter.exe < song.wav > song.ogg or
you can re-implement what the shell is doing in C#. A code example for that can be found in this related question:
redirecting output to the text file c#

Why don't my Quote Marks work inside the CMD

Im currently trying to run openVPN from a CMD that is programatically created.
Below is the code that I have created:
private void btnRunVpn_Click(object sender, EventArgs e)
{
string openVpnDir = #"""C:\Program Files\OpenVPN\bin\openvpn.exe""";
string myDir = #"""C:\Users\Jeremy\Desktop\OpenSource Rat\easyRDPClient\TutClient\bin\Debug\NewServerClient.ovpn""";
string configCommand = " --config ";
string command = openVpnDir + configCommand + myDir;
System.Diagnostics.Process.Start("CMD.exe", "/K " + command);
MessageBox.Show(command);
}
The message box displays the correct Command:
"C:\Program Files\OpenVPN\bin\openvpn.exe" --config "C:\Users\Jeremy\Desktop\OpenSource Rat\easyRDPClient\TutClient\bin\Debug\NewServerClient.ovpn"
However the command prompt is returning:
'C:\Program' is not recognized as an internal or external command, operable program or batch file.
The command is deffinatly correct because the message box that displays the command is correct, also when i copy what is in the message box into the command prompt it works perfectly.
wondering if it is anything to do with the two strings created that both have #"""message""" to display the message correctly. Wondering if that is the issue.
I can't seem escape the double quotes properly because it is a directory. So Im forced to use the #"""test""" to display a command like this "test"
Wondering if anyone understands this a little more than I do.
Would be great help.
Thankyou in advance!
I believe this will do what you are hoping to accomplish. It should leave the command line open, and correct the issue where the quotes are removed.
In the sample below, I added quotes around the command variable in the Start command.
private void btnRunVpn_Click(object sender, EventArgs e)
{
string openVpnDir = #"""C:\Program Files\OpenVPN\bin\openvpn.exe""";
string myDir = #"""C:\Users\Jeremy\Desktop\OpenSource Rat\easyRDPClient\TutClient\bin\Debug\NewServerClient.ovpn""";
string configCommand = " --config ";
string command = openVpnDir + configCommand + myDir;
System.Diagnostics.Process.Start("CMD.exe", "/K " + "\"" + command + "\"");
MessageBox.Show(command);
}
What I believe is happening is the CMD /K is expecting 1 argument. Since you are passing multiple, it is only looking at the first one (and removes the quotes when it does). This leaves it with:
C:\Program Files\OpenVPN\bin\openvpn.exe
It then cannot locate the application because of the space in the path.
By wrapping the entire command in quotes, it forces CMD to treat it as a single argument. It then removes the outer quotes and processes the desired command.
I tried it with Notepad in VB.NET, so hopefully I adjusted it correctly for your scenario.

'No such file or directory' if process is run programmatically (from C#)

I have an application that dumps a lot of files to a directory. I want to copy these files to a Hadoop cluster using the hadoop command. I use the following code to run the command.
System.Diagnostics.ProcessStartInfo export = new System.Diagnostics.ProcessStartInfo();
export.RedirectStandardOutput = false;
export.RedirectStandardError = false;
export.UseShellExecute = false;
export.WorkingDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
export.FileName = "hadoop";
export.Arguments = "fs -copyFromLocal " + Path.Combine(dumpDirectory, "*.txt") + " " + hadoopPath));
Console.WriteLine("Copying data: hadoop " + export.Arguments);
System.Diagnostics.Process proc = System.Diagnostics.Process.Start(export);
proc.WaitForExit();
if (proc.ExitCode == 0)
{
IEnumerable<string> files = Directory.EnumerateFiles(dumpDirectory);
foreach (string file in files)
File.Delete(file);
}
else
Console.WriteLine("Error copying to Hadoop: " + proc.ExitCode);
The program writes the following message:
Copying data: hadoop fs -copyFromLocal local/directory/*.txt /user/remote/directory/
copyFromLocal: `local/directory/*.txt': No such file or directory
Error copying to Hadoop: 1
Interestingly, when I run the command manually, the files copy without error.
Also, if the program runs the command without using *.txt and instead calls the command for each file individually, the command succeeds.
Can anyone shed some light on this?
I partially resolved the problem by creating a bash script containing the given command. I ran the bash script programmatically and it worked.
However, I still do not know why the original did not work.

Starting an executable and passing arguments

I have definitely done something like this before, but something is not working right and I'm not 100% sure what it is.
I have an executable executable.exe that takes a file, does some magic and outputs a second file somewhere else. So when I run this executable via CMD, all I need to do is pass "path1" and "path2". I put the paths in quotations because they may have spaces.
Anyway, so what I'm doing in my c# application is something like:
public void methodToRunExecutable()
{
var exePath = "\""+ "C:\\SomePathToAnExecutable" + "\"";
var firstFilePath = "C:\\PathToFirstFile\\NameOfFile.txt"
var secondFilePath= "C:\\PathToSecondFile\\NameOfFile.txt"
Process.Start(exePath, "\""firstFilePath + "\" \"" + secondFilePath+"\"")
}
However, I notice when I'm debugging is that the "\"" is actually showing up as \", like the backslash isn't escaping the quotation mark.
To be clear, when I run the CMD exe all I have to do is:
"C:\\PathToFirstFile\\NameOfFile.txt" "C:\\PathToSecondFile\\NameOfFile.txt"
and it works great. Any Ideas on what I'm doing wrong? Is it because the " is not being escaped?
Escaping is ugly and error prone. Use # and you won't need to escape:
var firstFilePath = #"C:\PathToFirstFile\NameOfFile.txt"
It might also be easier to use Process this way:
using (Process process = new Process())
{
process.StartInfo.FileName = exePath;
process.StartInfo.Arguments = ""; // args here
process.Start();
}

Starting a Jar file using System.Diagnostics.Process

I have a jar file which I want to run from within C#.
Here's what I have so far:
clientProcess.StartInfo.FileName = #"java -jar C:\Users\Owner\Desktop\myJarFile.jar";
clientProcess.StartInfo.Arguments = "[Something]";
clientProcess.Start();
clientProcess.WaitForExit();
int exitCode = clientProcess.ExitCode;
Unfortunatly I get "System could not find specified file", which makes sense since its not a file its a command.
I've seen code online which tells you to use:
System.Diagnostics.Process.Start("java -jar myprog.jar");
However I need the return codes AND I need to wait for it to exit.
Thanks.
Finally solved it. The filename has to be java and the arguments has to contain the location of the jar file (and anything arguments you want to pass that)
System.Diagnostics.Process clientProcess = new Process();
clientProcess.StartInfo.FileName = "java";
clientProcess.StartInfo.Arguments = #"-jar "+ jarPath +" " + argumentsFortheJarFile;
clientProcess.Start();
clientProcess.WaitForExit();
int code = clientProcess.ExitCode;
You need to set environment variable Path of java.exe executable or specify the full path of java.exe.
ProcessStartInfo ps = new ProcessStartInfo(#"c:\Program Files\java\jdk1.7.0\bin\java.exe",#"-jar C:\Users\Owner\Desktop\myJarFile.jar");
Process.Start(ps);

Categories

Resources