I need to write some code to invoke tesseract OCR in C#. I installed it and use the follow code. But it doesn't work:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.WorkingDirectory = tempDir.FullName;
// doesn't work
startInfo.Arguments = string.Format("/C tesseract {0} {1}", imgName, textName);
// this works
//startInfo.Arguments = string.Format("/C copy {0} {1}", imgName, textName);
Process p = new Process();
p.StartInfo = startInfo;
p.Start();
p.WaitForExit();
p.Close();
No exception or error is thrown. I just can't get the output file in the directory. I try a built-in command like the copy which commented and it works. I tried to get the stdout of the process but it always throw a "Process exit" exception.
After that I try to call tesseract in a command window. I cd into the temp dir, run tesseract img.png output and here the interest thing happens:
When start the command window via Start->Run->cmd, it works fine.
When start the command window in Visual Studio solution explorer, right click-> Open Command Prompt (It's a feature of VS Productivity Power Tools), it shows "tesseract is not recognized as an internal or external command".
I check the PATH in environment variable, it is correct. The only difference I can see is that the VS prompt shows "Setting environment for using Microsoft Visual Studio 2010 x86 tools." on the top. Doesn't it search the PATH variable to find command? Aren't they the same thing? Is it somehow related to my C# code's failure?
My OS is Windows Server 2008 64-bit.
I used it differently, as follows:
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "tesseract.exe";
p.StartInfo.Arguments = string.Format("\"{0}\" \"{1}\" -l {2} -psm {3} {4}", imageFile, outputFileName, language, PageSegMode, Hocr ? "hocr" : string.Empty);
p.Start();
p.WaitForExit();
if (p.ExitCode == 0)
{
// read output text file
}
p.Close();
Related
I'm trying to run a curl command from a C# program. My code is below. When I run the code below, I get an exception that the file is not found. I want to be able to do this but I do not want to use a batch file as a parameter for the filename. That is because the arguments for my curl command are variable based upon other conditions in the C# code. My variable strCmdText has the arguments for the curl command (the source and destination files). There are other examples of this on Stackoverflow, but they all use a batch file which I'm trying to avoid.
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "C:\\Windows\\System32\\curl.exe";
p.StartInfo.Arguments = strCmdText;
p.StartInfo.UseShellExecute = false;
p.Start();
p.WaitForExit();
I changed my code to the following:
System.Diagnostics.ProcessStartInfo p = new
System.Diagnostics.ProcessStartInfo();
p.UseShellExecute = true;
p.WorkingDirectory = "C:\\Windows\\System32\\";
p.FileName = "curl.exe";
p.ErrorDialog = true;
p.CreateNoWindow = true;
System.Diagnostics.Process.Start(p);
From a DOS prompt, curl does exist in this directory. But I still get the curl not found message.
Something has to be strange with the path here. When I put a break point in though, and view the Environment class, System32 is in the path.
Curl is available at the location: C:\Windows\System32\curl.exe
That only leaves the source file to be the culprit of a "File not found" issue.
As you're launching curl through a process, ensure that your paths are escaped properly in your startup arguments.
Alternatively, you could launch curl through cmd (through a process), you can try with the following, changing the command-line arguments from --help to suit your desired action.
string script = $"\"C:\\Windows\\System32\\curl.exe\" --help";
Process process = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = "cmd",
Arguments = script
}
};
process.Start();
Please note that this is in principle, essentially using a batch file as it's just throwing some commands into a cmd.
I had the exact same problem. Just delete curl.exe from System32 and place it on another folder (dont't forget the dependences, dlls, etc.).
Then in the line
p.StartInfo.FileName = "C:\\Windows\\System32\\curl.exe";
Overwrite "C:\\Windows\\System32\\curl.exe" to "C:\\NEW PATH\\curl.exe".
Note: You MUST delete it from System32. If you just copy to the new location it will still don't work.
Some application code using Process.Start() and PsExec.exe to start a video on a serverpc is running OK when run from a Console application, but not when run from a button press in a WPF application. This sent me nuts today.
So:
I am running a small WPF app on a PC which, once a button is pressed, will send a command to a server PC to run a video file. I am using PsExec.exe to run the process on the server interactively (did not manage with WMI)
This is the code I'm using:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.FileName = #"C:\Windows\System32\PsExec.exe";
p.StartInfo.Arguments = #"\\192.168.1.3 -u Administrator -p hagarmikejessav -i cmd.exe /c START E:\Media\FerroniConcettaAapp\Videos\Photoslideshow.mp4";
p.StartInfo.CreateNoWindow = true;
p.Start();
No, this exact same code can open video file Photoslideshow.mp4 on the server PC (192.168.1.3) when run from a normal console App. However when I try to run it after pressing a button in a WPF app, p.Start() gives me a "The system cannot find the file specified" error. Here is the WPF code snippet (it's the same as above):
private void Video1_btn_Click(object sender, RoutedEventArgs e)
{
try
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.FileName = #"C:\Windows\System32\PsExec.exe";
p.StartInfo.Arguments = #"\\192.168.1.3 -u Administrator -p hagarmikejessav -i cmd.exe /c START E:\Media\FerroniConcettaAapp\Videos\Photoslideshow.mp4 //fullscreen";
p.StartInfo.CreateNoWindow = true;
p.Start();
}
}
When I tried to use p.Start on a file that is local to my PC, that opened as expected. It's just the server that is not 'seeing' the FileName. As I said originally, the same code only fails on p.Start when accessing it after a button click.
What am I doing wrong? Please someone tell me that this is the result of hours in front of the PC and that it's only a stupid mistake which I cannot see!.
EDIT:
After more playing around,I realised that the error "The system cannot find the file specified" related to this line:
p.StartInfo.FileName = #"C:\Windows\System32\PsExec.exe";
enter image description here
Upon changing this line to:
p.StartInfo.FileName =#"C:\Windows\System32\Notepad.exe";
and removing the next line, Notepad opens up on my local PC. However, when I change the 2 lines back to something like:
p.StartInfo.FileName = #"Notepad.exe";
p.StartInfo.Arguments = #"\192.168.1.3 -u Administrator -p pass-i cmd.exe /c START C:\realtek.txt";...
notepad opens on my local PC but an error "Network path not found". (which is a similar error to when I run the 'non-button- code.)
Thus I know the problem is something to do with either the WPF/Button application. But I dont know what the problem is!
thanks a lot,
Mario
I managed to figure it out.
For some reason, the system was not finding PSExec from this path (even though it existed in that folder).
p.StartInfo.FileName = #"C:\Windows\System32\PsExec.exe";
Upon copying the File to another directory and using the full path, it finally worked.
I'm trying to start a local instance of notepad with a text file to try out c# cmd line arguments for eventual use in a remote connection script. I'm using System.Diagnostics.Process, but the StartInfo.Arguments doesn't actually run completely and open the notepad instance.
var p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = #"cd\ start notepad C:\test\testcmdline.txt";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.Start();
The window opens at root, which tells me the cd\ is working, but the "start notepad" does not seem to be running.
Am I missing something about the structure of StartInfo.Arguments?
EDIT: I'm trying to figure out how to run a python script on a remote server, and using this as a test for running things in cmd in c#. While it's fine to run this in notepad, I'm not sure if the principle would carry over to the eventual implementation of running a python script remotely so I'm attempting to learn how to run items through cmd in C# in general.
I ended up using the more simple 2 arg Process.Start.
string cmdText;
cmdText = #"/C C:\test\testcmdline.txt";
Process.Start("cmd.exe", cmdText);
Try adding /c in the beginning of the Arguments.
Or the above task can be done as below
var process = new ProcessStartInfo
{
FileName = "cmd.exe",
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = #"/c start notepad C:\test\testcmdline.txt"
};
Process.Start(process );
I am developing a Visual Studio plugin. It will automatically generate and run a command line. If I run the command in the shell, it could generate some logs during running.
However, I want to hide the shell window and display the logs in the Visual Studio Output Window. Is there a way to implement this?
Here's my code to run the command:
var process = new System.Diagnostics.Process();
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c"+command;
process.Start();
according to this similar question
Change application type to Windows before debugging. Without Console window, Console.WriteLine works like Trace.WriteLine. Don't forget to reset application back to Console type after debugging.
This might help:
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.startInfo.RedirectStandardOutput = true;
process.startInfo.RedirectStandardError = true;
StreamReader stringBackFromProcess = process.StandardOutput;
Debug.Write(stringBackFromProcess.ReadToEnd());
// or
Console.Write(stringBackFromProcess.ReadToEnd());
I'm working on making a tech-toolkit program, and included in this 'toolkit' will be a button which runs a defrag on the local disk. Currently the batch file I've made for this is simple, it just runs a basic fragmentation analysis:
defrag C: /A
The C# code behind the button that triggers this is:
System.Diagnostics.ProcessStartInfo procInfo =
new System.Diagnostics.ProcessStartInfo();
procInfo.Verb = "runas";
procInfo.FileName = "(My Disk):\\PreDefrag.bat";
System.Diagnostics.Process.Start(procInfo);
This code does exactly what I want, it calls UAC then launches my batch file with Administative Privledges. Though once the batch file is ran, the output I recieve to the command console is:
C:\Windows\system32>defrag C: /A
'defrag' is not recognized as an internal or external command,
operable program or batch file.
What causes this Error and how do I fix it?
Check to make sure your defrag.exe file actually exists in C:\Windows\System32.
Try fully qualifying the 'defrag' command as:
C:\WINDOWS\system32\defrag.exe C: /A
Open up a cmd prompt and run this command: defrag.exe /? and post in the question what you get.
First of all: set yout project Platform Target property to Any CPU and untick the Prefer 32-bit option (99,9% this is the issue). Then... why starting a batch that invokes the command when you can just do this?
ProcessStartInfo info = new ProcessStartInfo();
info.Arguments = "/C defrag C: /A";
info.FileName = "cmd.exe";
info.UseShellExecute = false;
info.Verb = "runas";
info.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(info);
Works like a charm on my machine. For multiple commands:
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "cmd.exe";
info.RedirectStandardInput = true;
info.UseShellExecute = false;
Process cmd = Process.Start(info);
using (StreamWriter sw = p.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
sw.WriteLine(command1);
sw.WriteLine(command2);
// ...