Launching a .pl file using Process.Start - c#

I have been using Process.Start to launch executables (.exe) files. Now I need to execute a .pl file with some arguments. can I still use Process.Start or I need a different approach?
EDIT :- I am having to mark this question unanswered as I am getting the following error when I try to call the perl file from the CSharp code:- (When I call the same from the commandline with the same path and parameters, It works fine)
System.ApplicationException: StartProcess Failed
System.ComponentModel.Win32Exception: The specified executable is not a valid application for this OS platform)
Please note that when I try to call an .exe file from my C# code, I dont see the above error.
EDIT:-
Checking the following link now:- How do I call Perl script in C# application?
It seems that the ProcessStartInfo constructor has two parameters - fileName and the arguments. You should set Perl.exe as the fileName and the "argument" would be your perl file (.pl) with other arguments It accepts. Checking now....

You certainly can :) you can also pass it arguments by adding them after the file name in
Process.Start(file.pl args1 args 2);
It will load the file with your default application for .pl files, the other option is to specify the software then pass your file as a parameter providing you have the right software to handle the file it should be fine
Process.Start() can be pointed at any file and it will be opened using the default software or that which you specify, it need not be an executable.

Yes you can, Process.Start() takes a string parameter, what you pass for this parameter does exactly the same thing it would do if you entered the same string in the windows start -> run dialog.

Related

Run an External Program or Batch File From a C# Xamarin Program

I want to have my C# (Xamarin) program run an EXE or batch (BAT) file. The user will be running my program, and will click on one of several buttons, some of which open Web pages and others of which run external programs. These files will be on the same computer as the one running the main program and don't need greater permissions. The overall program will be in Windows, UWP.
I already have code to pull info from the database saying "the button the user clicked references a program and it's (eg) C:\Tools\MyTool.exe". (Real path more like (C:\Users\Me\source\repos\ProductNameV2\ProductName\ProductName.UWP\Assets\EXE\whatever.exe".) I used a "demo.bat" file containing nothing but echo and pause statements, or references to a built-in Windows program like Notepad or Calc that an ordinary command prompt can recognize without an explicit path (ie. that's part of the recognized system Path). Yes, the real path to the dummy file does exist; I checked. I've also explicitly added files demo.bat and dummy.txt to my C# project.
Here's roughly what I've tried so far to actually run a batch file, or an EXE, or just to try opening a text file. Nothing works.
1)
bool check = await Launcher.CanOpenAsync(#"file:///C:\Tools\demo.bat"); // Returns false.
bool check = await Launcher.CanOpenAsync(#"file:///C:\Tools\dummy.txt"); // Returns true.
await Launcher.OpenAsync(#"file:///C:\Tools\demo.bat") // Seems to do nothing; silently fails.
await Launcher.OpenAsync(#"file:///C:\Tools\dummy.txt") // Same.
2)
Process batchProcess = new Process();
batchProcess.StartInfo.FileName = #"file:///C:\Tools\demo.bat"; // Same result with notepad.exe
batchProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
batchProcess.Start();
batchProcess.WaitForExit();
// Result: "Access is denied" error during Start().
3)
var otherProcessInfo = new ProcessStartInfo(#"file:///C:\Tools\demo.bat")
var otherProcess = Process.Start(otherProcessInfo);
otherProcess.WaitForExit();
otherProcess.Close();
// Result: "The system cannot find the file specified" despite it being the same path as in previous examples.
// Also tried literally using the path C:\Tools\demo.bat, without adding that to the C# project.
// One thing that slightly works is to use:
var otherProcessInfo = new ProcessStartInfo("cmd.exe", "/c echo Hello world!");
// This version opens a window and instantly closes it again. With "/c pause" instead, it opens, saying "press any key to continue".
// Chaining multiple commands with newline or semicolon characters doesn't work as a form of batch file.
So: the only tiny success I've had here is to run cmd.exe, to run a one-line command. I suppose that depending on what the batch file must do, there's some possibility of receiving a string, breaking it into lines, then running cmd.exe using method 3 to call them one at a time. Which is ugly at best.
Is there some better way to do this -- to run a batch file or an EXE from within my program?
EDIT: Yes, I did in fact look at documentation before asking. Why did I use URIs? Because of multiple errors telling me that the simple path strings ("C:\this\that") I was using were in an "Invalid URI format". Using Process.Start("notepad.exe") silently fails, doing nothing. Using a method involving System.Diagnostics.Process (found at How to run external program via a C# program? and yes I saw that before) fails with an error of "Access denied" when using my batch file reference, or silently failing (no window opens) using plain old notepad.exe. I avoided setting Process options that say hide the window.
So to rephrase: Is there a way to make my program run some EXE somewhere on the computer, or to run a batch file that has more than one command in it? What is that way?
Using the data you collected, I was able to run a batch file by doing the following:
var strPathToExeOrBat = System.IO.Path.Combine("C:\\Tools", "demo.bat");
var otherProcessInfo = new ProcessStartInfo("cmd.exe", $"/c call \"{strPathToExeOrBat\"");
var otherProcess = Process.Start(otherProcessInfo);
otherProcess.WaitForExit();
otherProcess.Close();
I also think it would be helpful to review the capabilities of the cmd.exe application.
I found this post to be helpful:
https://stackoverflow.com/questions/515309/what-does-cmd-c-mean#:~:text=%2FC%20Carries%20out%20the%20command%20specified%20by%20the%20string%20and,switches%20by%20typing%20cmd%20%2F%3F%20.
In particular the /k option will leave the window open, if you don't want it to close after running a script.
Thank you very much for your question! It really helped me find the answer to this! (at least for my situation of a .NET MAUI windows app, but MAUI is built off of Xamarin.Forms, so you shouldn't have a problem doing the same thing)
EDIT: Updated to use file path from question and string interpolation with System.IO.Path.Combine for slightly greater cross platform capability

Process.Start working directory in the same string as filepath

Is there any way to specify working directory as below?
Process.Start("c:\someDir\someExecutable.exe + working directory path");
or how to make windows environment variable path work with :
Process.Start("c:\someDir\someExecutable.exe");
I know that ProcessStartInfo can be use to specify working directory.
I have my own reason to for wanting to put working directory and file path in same parameter of Process.Start().
The documentation for public static Process Start(string fileName) is found here: https://msdn.microsoft.com/en-us/library/53ezey2s(v=vs.110).aspx
As you can see the description for that parameter is:
The name of a document or application file to run in the process.
The remarks also note:
This overload does not allow command-line arguments for the process. If you need to specify one or more command-line arguments for the process, use the Process.Start(ProcessStartInfo) or Process.Start(String, String) overloads.
So in summary no, you can't do this. Even if your program accepted a working directory as a command line argument this overload will not work.

Process.start results in file not found even though the file exists

I am using following code to open an arbitrary file with an arbitrary application that is installed on the system :
if (File.Exists(_document.DocumentFullPath))
{
Process.Start(_document.DocumentFullPath);
}
else MessageBox.Show(string.Format("Document {0} does not exist!", _document.DocumentFullPath));
When I execute this code I see that the file.Exists returns true, so the file does exist. But then the corresponding application opens, for instance an image viewer or a pdf viewer depending on the file type (jpg or pdf) that I am trying to open, but it shows an error in that application that it cannot find the file. No exceptions are thrown.
This does not happen all the time but only for some files.
If I try to open these files manually by copy pasting the content of DocumentFullPath in the explorer, then the file does open correctly in the applicable application.
Duh I don't understand what is wrong.
Example of a filename that don't work :
C:\Users\stuyckp\Documents\Visual Studio 2010\Projects\WPF\FrakoKlantOpvolgingWPF\FrakoKlantOpvolgingWPF\bin\Debug\ProjectDocumenten\11339_Wigbers\6197_koelkast \big-money.jpg
I am running on windows 10.
Do you have spaces in the file path? File.Exists can handle spaces fine, presumably as can Windows Explorer, but it's possible that Process.Start cannot.
I think this is what you want bud. Use the process start using a ProcessStartInfo object with the file path with spaces passed as a string separately.
Use Process.Start with parameters AND spaces in path

Execute command like Start>Run in C#

I want to create a command executor like Start > Run. The application has a TextBox and when a user enters a command eg : notepad "C:\test.txt" it should open notepad with this file or %PROGRAMFILES% it should open 'Programs Files' directory.
For %PROGRAMFILES% and other Windows variables I can use Environment.ExpandEnvironmentVariable and get their path and pass to Process.Start
and for notepad, I can split the with space and first part goes in FileName and rest of string goes in Arguments of ProcessStartInfo.
But what I want to know is, how does Start > Run work ? is there something like I can execute the whole command without splitting command-line or expanding the variables ? Maybe with pinvoke ?
To the very best of my knowledge, the run dialog is implemented with a call to ShellExecuteEx. You can achieve the same with Process.Start and UseShellExecute. You do need to expand the environment variables, and split the command into filename and arguments. You already describe how to do that in your question, and, again to the best of my knowledge, there is no programmatic interface to the functionality of the Run dialog.
However, what you can do programmatically is show the Run dialog. Create an instance of the Shell object requesting the IShellDispatch interface, and then call the FileRun method.

How to open a file using a specified third party program in C#?

so what I'm trying to do is open a file (well, actually two folders, but I figure I'll start with a single file for now) using a third party comparison tool called UltraCompare. I'm working in a C# website project in Visual Studio 2010 (Express edition). I've seen how to open a file using a different program, here: Open a file with Notepad in C#.
Problem is, this only lets you open it using the default program for that file type. But I want to open it in a specified program. For example, a text file should open in UltraCompare, not notepad. Here's the code which does this:
string textBoxContents1 = TextBox1.Text;
Process.Start(textBoxContents1);
The textbox on the webform accepts a string, in which the user types the file's full path (not the most user-friendly design I know, but I'm not sure how to allow them to browse for a folder using a GUI interface in asp.NET). The file is then passed into the Process.Start() method, which opens it using the default program for that file type.
Is there any way to modify this to make it open using UltraCompare??
You can specify the program you want to open the file in:
Process.Start("yourprogram.exe", textBoxContents1);
Update
To open two files in Ultracompare, you'd probably do something like that:
Process.Start("yourprogram.exe", "file1.txt file2.txt");
Keep in mind that the second parameter of Process.Start method are the arguments passed to the program.
I said this is probably going to work because I assumed to be very likely that Ultracompare expects 2 arguments, but this might not be the case.
Quick question: Are you trying to do this for the client machine? Hope not
And I guess it looks into the PATH variable for finding your exe

Categories