How to pass argv[0] with Process.Start in C# - c#

I'm writing a wrapper program in C# with Mono under Ubuntu. The key of a successful wrapper is to be as transparent as possible. One of the requirement is to pass argv through exactly.
When use Process.Start to start the wrapped program, how can we pass argv[0] to the wrapped program? It seems that we can't pass argv[0] at all, it is just
set to the wrapped program's executable full path.
Some program's behavior may depends on argv[0]. This is true for AOSP's prebuilt clang tool set. For example, under
prebuilts/clang/host/linux-x86/clang-4691093/bin$
there is lld, this program obvious check argv[0] to decide which symbol link you invoke (ld.lld/ld-link/ld64.lld). If you don't invoke lld through predefined symbol links, lld will report error.
With C/C++, it is easy to set argv[0] to the symbol link's name to successfully invoke lld. But can we do this in C#?

Related

Detect when exe launched via Google Chrome Native Message Passing

I'm trying to retrofit an existing NPAPI plugin to use Google's native message passing technology. Since it's an existing exe, we already have some console behavior programmed in so that users can call our program from the terminal. Is there any way for us to detect, in a C# application, that the exe has been launched by Google Chrome for message passing? If we could do that, we could launch the message passing loop if we're called from Chrome but resume normal behavior if called from Powershell/cmd.
I've tried inspecting the command line arguments passed to the program when launched by Chrome, but there are none. Having a configurable option there would solve this for us, but as far as I can tell it's not possible. I haven't yet had a chance to inspect the current working directory in case it could also be used as an identifier.
Actually, yes, I believe it is possible.
When, for example, a C# console application is started as a native message client host, it is passed two arguments:
--parent-window=<number>
and
chrome-extension://<extension identifier>/
I think the second argument is probably the ideal one for determining that not only was it Chrome that launched the process, but that the specific extension you authored and intended to call it launched it!
Please make note in the above, the "<" and ">" are not literally part of the argument, and just used to denote the beginning and end of that part of the message, much like double quotes.
Alternatively, just have your extension invoke a script (.bat, .sh, etc.) that passes special arguments to your native host. This way you could pass specific arguments of your own.
The API doesn't support passing command line arguments, but your host process should be able to inspect its own parent process to determine if it was launched by Chrome or something else.
An alternative to checking the arguments as suggested by #aikeru would be to check for the existence of certain environment variables that were passed from Chrome to the native messaging host. My host has the following variables that seem to be specific to Chrome (found with Sysinternals Process Monitor):
CHROME_ALLOCATOR=TCMALLOC
CHROME_BREAKPAD_PIPE_NAME=\\.\pipe\GoogleCrashServices\S-1-5-18
CHROME_MAIN_TIME=13037817851797830
CHROME_METRO_DLL=0
CHROME_PRE_READ_EXPERIMENT=100-pct-default
CHROME_RESTART=Google Chrome|Whoa! Google Chrome has crashed. Relaunch now?|LEFT_TO_RIGHT
CHROME_VERSION=33.0.1750.117

using CreateProcessAsUser to launch a url

Recently I bumped into an issue where I need to open a webpage from an elevated application. I need the browser to be opened non elevated so I looked around and found this solution
This would definitely solve my issue except that CreateProcessAsUser does not accept URIs as a filename, the execution will fail with the error message being "The filename, directory name, or volume label syntax is incorrect"
Can someone tell me if there is a way to launch a website through CreateProcessAsUser or if there is a similar API that does the job.. Please note that my actual application is always elevated and thus I cannot uses the usual Process.Start(), CreateProcess() or ShellExecute()
There are two distinct families of functions that you will need to use to get this task done:
CreateProcess and related functions. These can be used to start a new process. You must supply a filename of an executable image.
ShellExecute and friends. These will apply verbs to files using the shell's rules for associating file classes to executables.
In order to open a URI you need to use one of the ShellExecute family. And in order to execute as a standard user from your elevated process, you need to use one of the CreateProcess family.
You cannot meet both your requirements with a single function. Your solution therefore is to use one of the CreateProcessXXX functions to create a process that runs as standard user. That process in turn will call ShellExecuteXXX. You will pass the URI as command line arguments to CreateProcessXXX.
You will therefore need to either create a distinct executable as your standard user launcher. Or re-use your existing executable but make it switch into launcher mode depending on the arguments that you pass it.

Converting a C# (Windows application) into commandline application?

I am looking to convert a C# (Windows platform application) into a commandline version.
The scenario is: I have implemented a C# (Windows application) in VS 2010. The output of this application is to generate a txt (log) file (in simple explanation).
Now the case is, there is one other application which need to use my this C# application, by calling my C# application from the command line at the run time.
My question is, how is it possible to convert an already existing C# application into commandline application, so that this C# application can be called from the calling (other) program? There is one input parameter which need to be passed on the commandline to my C# application. And then this C# application will process the data according to input parameter and then generate the output log(txt) file.
Added explanation
I am really impressed by the solutions here. Just a bit more expertise is required from readers. I want one application only to work as both commandline application as well Windows-application (forget to mention it before, sorry!), depending on the number of input parameter pass to the application. From this point of view, I have two options to implement it,
1) Make separate functions for both applications (commandline and windows-forms). Call them according to the input parameter pass. In each function implement the complete functionality of each application without disturbing (or going into the code of other application). Also I will be able to re-use 2 main functions, already built in windows-form application into my commandline application after some editing.
Disadvantage: This will make the code size nearly 50% more than case 2.
2) The second idea is same as describe by one of the expert here, to use the same application/functions for commandline as that of already built windows-form application. The only way to distinguish is to look at the input parameter pass, and decide accordingly whether to show the GUI interface or just use the commandline input (and do processing).
Disadvantage: This case will make the code bit messy and difficult to maintain/implement due to extra adding of check for number of input parameter decisions.
Which strategy should I follow for implementation?
Sure - just:
Create a new VS2010 command-line project
You'll now have a "main ()" (or, in MS-Land, "_tmain()") function instead of a root class.
Cut and paste the relevant code into "main()" (or into a function called by main (), or into a class created from main() - your choice).
Do a search-and-destroy mission to find anyplace where you're doing GUI input, and substitute command line parameters instead.
Parse your command line.
Voila! Done!
You don't have to convert it. Your application can stay as a Windows application. You simply need to handle command line arguments.
To get the command line arguments from ANYWHERE in the application, just use Environment.GetCommandLineArgs();
You want to get value from command line is not a good reason to convert winform app to console app. You may use,
string[] args = Environment.GetCommandLineArgs();
However you can change application type by opening project properties (right click on project name) and change the Output type.
Just don't show the GUI if you get paramater passed in, as when called from the other program.

Run an executable present in Windows Path using C#

I'm trying to run some commands, like rails test, using a C# command line. I tried using How To: Execute command line in C#, get STD OUT results but I'll need full path to the rails executable for that to work. Is there any alternative that will find work just like the windows command line does?
If you can P/Invoke, you could locate the executable with PathFindOnPath. A quick google doesn't show a C# equivalent.
without P/Invoke, Environment.GetEnvironmentVariable("Path").Split(";") should give you a list of paths to probe.
However, this is not the entire resolution used by ShellExecute or even the console.
I believe if you have UseShellExecute set to true in the ProcessStartInfo used to start the process, it'll use the path. Haven't checked it yet - will do so when I get a chance.

Launching a .pl file using Process.Start

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.

Categories