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, ...
Related
I need the process ID for a program that is already running on the computer. How would I go about doing this? (The process isn't started from Process.Start())
Use GetProcessesByName or just GetProcesses with a bit of LINQ, depending on how you intend to identify the program.
using System;
using System.Diagnostics;
using System.ComponentModel;
void Example()
{
// Get all processes running on the local computer.
var localProcesses = Process.GetProcesses();
//Get all processes with a name that contain "Foo" in the title
var fooProcess = localProcesses.Where(p => p.MainWindowTitle.Contains("Foo"));
// Get all instances of Notepad running on the local computer.
var notepad = Process.GetProcessesByName("notepad").Single();
}
Once you have the Process object, you can get its ID with the Id property.
var id = process.Id;
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());
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];
}
It's not possible to setlocale of a process running as root, how can I use gettext to obtain localized strings (the locale is not auto detected, nor can I force it to a particular value using setlocale) in such a process. Is there any workaround?
Edit -> Adding the code, I used for testing the issue. I force changed the environment variables - LC_ALL, LANGUAGE, LANG to fr_FR.UTF8. I set the locale to fr_FR.UTF8 explicitly too. All the putenv calls returned 0 and the setlocale call returned "C".
int err = putenv("LC_ALL=fr_FR.UTF8");
err = putenv("LANG=fr_FR.UTF8");
err = putenv("LANGUAGE=fr_FR.UTF8");
char *loc = setlocale(LC_ALL, "fr_FR.UTF8");
bindtextdomain("default", "locale");
textdomain("default");
char *text = gettext("hello");
The same code snippet works if I try it in a user process. The exe of both the processes are in same directory, which contains directory locale\fr\LC_MESSAGES\default.mo
Can we change the locale of a process which is running as system process and not user?
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.