How to start process /instance with a custom identifier - c#

I have to start several instances of the application and I have to identify it later somehow.
Is it possible to start instance with some custom TAG so later I can find the instance I need?
Process p = new Process();
// p.TAG = "Guid"; ??????
p.StartInfo.FileName = "path";
p.Start();
UPDATE 1
I start several processes in the LOAD event of WPF app. And sometimes cannot get process Id of the current app. So I am looking for approach to differentiate an instance in some custom way if it is possible...
So the model looks like
ParentApp.exe
----> Sun.exe
----> Moon.exe
ParentApp.exe
----> Sun.exe
----> Moon.exe
And I use LOAD event of ParentApp.exe to pass to Sun.exe and Moon.exe correct Process ID so later they can able create correct MSMQ and exchange data with ParentApp.exe and also ParentApp.exe could close those apps.
UPDATE 2
May we keep some custom data during application executing here
p.Domain = "mydomain?????";
p.EnvironmentVariables.Add("MY_NEW_VARIABLE", "SOME_TEXT????");
http://blog.gapotchenko.com/eazfuscator.net/reading-environment-variables

You could store the Process.Id
Process p = Process.Start("notepad.exe");
MessageBox.Show(p.Id.ToString());

Related

Assign A Process Id C#

I am sending messages to a listener windows service. Within the message is a process id. I want to use the process id to attach it to my windows service in order to access a folder on the server.
I cannot see how to set a process id only get one
int nProcessID = Process.GetCurrentProcess().Id;
You can not assign an ID to a process, it is only set by the operating system. You can however search for one by name:
int yourProcess = Process.GetProcessesByName( "YourListener.exe" )[0].Id;
Enhancing a bit the answer of #BillyDvd, I suggest you getting the name of your process instead of hardcoding it, this way, you can change it in your project structure safely:
var name = Process.GetCurrentProcess().ProcessName; // always fix, like "myapp.rms"
var myProcess = Process.GetProcessesByName(name)[0].Id; // variable, given new by Windows OS on every start of your app: 44580, 36960, 38184, ...

How can I capture process names using the TraceEvent library?

I'm using the TraceEvent library to capture ETW traces, but I'm not able to determine the name of the process that caused an event.
Here is what I have so far:
var session = new TraceEventSession(sessionName, null);
session.EnableProvider(MyEventSource.Log.Guid, TraceEventLevel.Informational,
options: TraceEventOptions.Stacks);
Task.Delay(1000).ContinueWith(t => session.Stop()); // for testing, deal with it (⌐■_■)
var src = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session);
TraceLog.CreateFromSource(src, etlxFile, null);
var log = TraceLog.OpenOrConvert(etlxFile);
var process = log.Events.First().ProcessName;
// breakpoint
When the breakpoint at the end is hit, process is "". ProcessID is a proper PID, but that's the only useful information I could find from the processes in the log.
I expected process names to be captured by the log. Am I doing something wrong, or is this API just not available on my OS (Windows 7)?
I truly believe that process name is not being captured by the ETW log. Etw system event contains only process ID field. Although TraceEvent library declares this one as a part of TraceEvent, this one actually is being populated based on executable image filename and process ID, which is implemented differently for all 4 TraceEventSource implementations.
Another observation is that I was never able to have this one populated (my OS is Windows 8.1).
The simple repro is to use SimpleEventSourceMonitor sample from Microsoft TraceEvent Library Samples package.
If you suspect that this is an issue, then it is better ask its owners Vance Morrison and Cosmin Radu.
This can be done by enabling the kernel provider, and then maintaining a lookup of process id to process name. Here's a rough example - no error checking, but you get the idea.
// create a lookup collection for future use
var pidToProcessName = new Dictionary<int, string>();
var session = new TraceEventSession(...);
// enable the kernel provider - note! this most come first
session.EnableKernelProvider(KernelTraceEventParser.Keywords.Process);
...
session.Source.Kernel.ProcessStart += ProcessStart;
session.Source.Dynamic.All += TraceEvent;
...
session.Source.Procces();
void ProcessStart(ProcessTraceData obj)
{
if(obj.OpCode == TraceEventOpcode.Start)
{
pidToProcessName[obj.ProcessID] = obj.ProcessName;
}
}
void TraceEvent(TraceEvent obj)
{
// pull the process name from our lookup
var processNameOfEvent = pidToProcessName[obj.ProcessID];
}

c# detect an open web browser

I am writing a program that searches certain web pages before closing. I would like my program to open a NEW WINDOW using the DEFAULT BROWSER. I can have my program focus the newest window instance, and then it will close that instance once it is done.
I have been staring at WebBrowser.Navigate and System.Diagnostics.Process.Start(target) all day but I cant find the sweet spot with either of them.
WebBrowser.Navigate always opens IE, I have been looking in the API and can't find a way to change the program used. Does anyone else see something that I dont? Is there a way to change the application used?
System.Diagnostics.Process.Start(target) opens in a new tab, not a new window like navigate does. However none of the overloaded functions from the API have a way of saying "create a new instance or window".
this is my issue, they both have pieces that I want, but I cant figure out how to get the pieces I need for either one.
I would be extremely grateful for you help. I have been looking for hours now and I can seem to come to a solution.
code sample for Jester:
Process defaultbrowser = new Process();
defaultbrowser.StartInfo.CreateNoWindow = true;
defaultbrowser = Process.Start(target);
int waitTime = Convert.ToInt32(numericUpDown2.Value);
System.Threading.Thread.Sleep(waitTime*1000);
defaultbrowser.CloseMainWindow();
defaultbrowser.Close();
furthermore my Close() function is causing a runtime error that says;
System.NullReferenceException: Object reference not set to an instance
of an object.
which seems silly because too me the above code makes me think that my defaultbrowser is an instance of a process, which is then supposed to be able to call the non-static function "close()".
ok If I got your problem right you are looking for a way to open a web page in the "default" browser.
That can be done by simply make a new process like:
Process.Start("http://google.com");
If you would like to control witch browser gets used you can do it by passing the web address to the browser's exe file as a parameter:
System.Diagnostics.Process.Start("PATH to exe", "Command Line Arguments");
To start the process in the new window pass a ProcessInfo object to the Process.Start
And set the CreateNoWindow
more info on that
Hey To check if it's loaded wherever, do:
if(browser.ReadyState == WebBrowserReadyState.Complete) {
// It's Open!
}
You should use System.Diagnostics.Process like that:
Process Chrome = new Process(); //Create the process
Chrome.StartInfo.FileName = #"C:\Program Files\Google\Chrome\Application\chrome.exe"; // Needs to be full path
Chrome.StartInfo.Arguments = ""; // If you have any arguments
Chrome.Start();

How to pass named parameter list to an opening windows form application

I have a windows form application
Lets call it B
Now i have another application. Lets call it A
A will start B as a new process
Now i want to pass named parameter list to B and use them in B
How can i do that ?
What i mean is example parameter list
{job:"computer engineer",age:"32",experience:"3 years"}
Also these parameter list should be optional. Sometimes i may pass 5 parameters sometimes 0
And how will i read these parameters at start up on B application
So what is the way of doing this ? thank you
c#
Assuming you're calling your "B" process with Process.Start, the following should work:
System.Diagnostics.Process.Start(string fileName, string arguments)
And your "B" processes main thread should accept an array to house possible arguments that you can then iterate over.
static void Main(string[] args)
{
//your code to decipher arguments here
}
There are two ways I can think of doing this.
First is to use command line arguments. If you were to call you process (from the command line) as:
your.exe -job "computer engineer" -age 32 -experience "3 years"
You would then duplicate this in your code by settings the arguments in your process's start options. You would then have to set up your process to look for all of these flags, remembering that they can all be optional, and so on.
The second option (and this is a bit more flexible) is to make a file that holds the values you are passing over, and read it from your launched process. You could make this XML, or straight values.
Edit: here is an example of the first option
Process p = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "your exe path";
startInfo.Arguments = "your argument list";
p.StartInfo = startInfo;
p.Start();
I don't want to tell you how to format your argument string; that should be up to you to decide. However, I will recommend a library to use that might make the parsing on the receiving end a bit easier.

Add new environment variable to a process launched by ProcessStartInfo.LoadUserProfile

I'm logged on my pc with the user 'podosta'
This is working fine
ProcessStartInfo p = new ProcessStartInfo("c:\myapp.exe");
p.UserName = "myuser";
p.Domain = "mydomain";
p.Password = SecureString;
p.UseShellExecute = false;
p.LoadUserProfile = true;
Process.Start(p);
Environment variables of the process are the environment variable of the user 'myuser'
ex: %USERPROFILE% points to the profile of 'myuser'
This is not working
ProcessStartInfo p = new ProcessStartInfo("c:\myapp.exe");
p.UserName = "myuser";
p.Domain = "mydomain";
p.Password = SecureString;
p.UseShellExecute = false;
p.LoadUserProfile = true;
p.EnvironmentVariables.Add("MY_NEW_VARIABLE", "SOME_TEXT");
Process.Start(p);
Environment variables of the process are the environment variable of me 'podosta'
ex: %USERPROFILE% points to my profile 'podosta'
By the way, %MY_NEW_VARIABLE% is created
Why this behavior ?
I need to start an application with a RunAs, having the environment of the runned user and add some additional environment variable to the process.
Thanks
The behaviour you're seeing is basically document on MSDN for the CreateProcessWithLogon Win32 function which works in the background when starting a process for a different user (using System.Diagnostics.Process):
A pointer to an environment block for the new process. If this
parameter is NULL, the new process uses an environment created from
the profile of the user specified by lpUsername.
So as soon as you specify a single one environment variable for the new process, you need to specify them all.
The problem now is the ProcessStartInfo.EnvironmentVariables property. As soon as you access it the first time (for a given instance of ProcessStartInfo), it will be automatically populated with the complete environment for the current user (ref).
Take this line, which runs in the context of user "podosta":
p.EnvironmentVariables.Add("MY_NEW_VARIABLE", "SOME_TEXT");
It does two things:
fill the p.EnvironmentVariables with the environment of "podosta" (including "USERPROFILE=...podosta").
Add the new variable "MY_NEW_VARIABLE=SOME_TEXT" to that.
This combined set is then passed to the process launched as "myuser" and thus it gets the "wrong" (better: unexpected) value for "USERPROFILE".
If you want to make sure that you pass a NULL environment block to the underlying Win32 function, to get the behavior described in the quote above, you cannot ever "touch" the EnvironmentVariables property - not even iterate and dump it for logging purposes.
It is also not sufficient to do EnvironmentVariables.Clear(). That will not set the internal field to null and the CreateProcessWithLogon function is just passed an empty environment block, but not a null one.
If you fail to do so, you get all sorts of funny behaviours, for example the then-executing process will have a value for USERPROFILE that is that of the user that started the process, etc.
You might get around that stuff by calling CreateEnvironmentBlock via p/invoke, add your environment variables as needed, then calling CreateProcessAsUser (also via p/invoke), passing that modified environment. That is all not an easy undertaking, especially when you want all the features of the Process-class like output redirection, etc.
It is kind of unfortunate that the ProcessStartInfo.EnvironmentVariables property works as it does.

Categories

Resources