Get DLL names from running process, possible? - c#

I'm seeking for a way to get DLL names from a running process, sorry if I'm poorly expressing myself though.
I need to "connect" to this process via it's name or PID and retrieve the DLL names that it's using if that's possible.
Regards.

Yes it is possible. You can use the Process class. It has a Modules property that lists all the loaded modules.
For example, to list all processes and all modules to the console:
Process[] processes = Process.GetProcesses();
foreach(Process process in processes) {
Console.WriteLine("PID: " + process.Id);
Console.WriteLine("Name: " + process.ProcessName);
Console.WriteLine("Modules: ");
foreach(ProcessModule module in process.Modules) {
Console.WriteLine(module.FileName);
}
}
You can of course check Process.Id for the PID you would like etc.
For more information check out the documentation for this class:-
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx
Note: This code might get upset for certain system processes which you will not have access permission to.

Related

Process MainModule - can I avoid Win32 exception?

I am enumerating processes to find if excel.exe is running (for example).
I get a lot of Win32Exception from system services and such.
Process[] pps = Process.GetProcesses();
foreach (var process in pps)
{
string module = null;
try
{
module = process.MainModule?.FileName;
}
catch (Win32Exception)
{
continue;
}
which make enumeration to run 500ms instead of 10ms.
Is there a way to figure if a process has main module without triggering the exception? Or any other way to find process exe path?
This exception occurs when you're trying to do something which your OS doesn't allow. You can check the NativeErrorCode property to see more details about the exception.
You can find a solution here to deal with that issue.
As mentioned by #steeeve in comment, you can use GetProcessByName, if performance is the only criteria for you.

Is there any way to get list of all applications opens, and jump to that window [duplicate]

I would like to find a way to loop through all the active processes and do diagnostics checks on them (mem usage, cpu time etc) kinda similar to the task manager.
The problem is broken down into two parts:
Finding all the processes
Finding diagnostics attributes about them
I am not sure even in what namespace to go looking about it. Any help / tips / links is grateful.
Finding all of the processes
You can do this through the Process class
using System.Diagnostics;
...
var allProcesses = Process.GetProcesses();
Running Diagnostics
Can you give us some more information here? It's not clear what you want to do.
The Process class provides a bit of information though that might help you out. It is possible to query this class for
All threads
Main Window Handle
All loaded modules
Various diagnostic information about Memory (Paged, Virtual, Working Set, etc ...)
Basic Process Information (id, name, disk location)
EDIT
OP mentioned they want to get memory and CPU information. These properties are readily available on the Process class (returned by GetProcesses()). Below is the MSDN page that lists all of the supported properties. There are various memory and CPU ones available that will suite your needs.
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx
Code:
Add this line to your using list:
using System.Diagnostics;
Now you can get a list of the processes with the Process.GetProcesses() method, as seen in this example:
Process[] processlist = Process.GetProcesses();
foreach (Process theprocess in processlist)
{
Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}
Finding all processes is rather easy actually:
using System.Diagnostics;
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
// Get whatever attribute for process.
}
JaredPar already pointed out the Process class, so I'll just add, that you should be aware, that the class takes a snapshot of the process' information when the instance is created. It is not a live view. To update it you have to call Refresh() on the instance.
Also keep in mind, that the process may close while you are inspecting it, so be prepared to catch exceptions and handle them accordingly.
And finally if you call Process.GetProcesses() you will also get the pseudo processes "idle" and "system". IIRC they have specific process IDs so you can easily filter them out.
This is how I prefer to access the processes:
static void Main(string[] args)
{
Process.GetProcesses().ToList().ForEach(p =>
{
Console.WriteLine(
p.ProcessName + " p.Threads.Count=" + p.Threads.Count + " Id=" + p.Id);
});
Console.ReadKey();
}
Well you can do this in powershell
1.Finding all the processes
get-Process
2.Finding diagnostics attributes about them
get-Process | where-object { $_.Handles -gt 200 }
The above code will return all processes with over 200 handles, you can specify your diagnostic attributes in this manner easily.
For more information on how to handle processes using powershell see this
using System.Diagnostics;
class Program
{
static void Main()
{
Process[] processlist = Process.GetProcesses();`
}
}
here process arrray contains all the number of process present into it.
What operating system are you using? I take it from your C# tag that it's windows?
If so, check out WMI, particularly the Win32_Process class. Here's the MSDN reference: http://msdn.microsoft.com/en-us/library/aa394372(VS.85).aspx
As well as a couple of usage scenarios here (such as getting a list of processes): http://msdn.microsoft.com/en-us/library/aa394599(VS.85).aspx

Is there a way to find a process on top of the process id and name in c#

I have multiple processes started and I want to keep track of each of them so that I can start the process again if it ended without my knowledge.
Currently, I store the process id in my database and I use the process id and name to check if the process is still running.
Process process=Process.GetProcessById(id);
if(process.ProcessName==processName){
//kill the process
}
However, I was reading online that when a process dies, its id will be free for other processes to use. There could be a chance that there will be a new process with my old process id and name which might lead me to assume my old process is still running.
Is there any additional fields I can add to make my process unique? such as the process site? I am unable to get more information on what the process site is used for.
You could store the Process.StartTime property in addition to its ID. That should protect you in the case that the PID has been re-used since the new process would have a different start time to the one stored.
var process = Process.GetProcessById(id);
if (process.ProcessName == processName && process.StartTime == startTime)
{
//kill the process
}
I suspect the following does not apply since you're persisting process information, but if your application is continually monitoring these processes then you might consider using the Process.Exited event to receive notifications when a process exits rather than checking every so often, e.g.
process.EnableRaisingEvents = true;
process.Exited += (sender, args) => { /* Do something */ };
Run this piece of code and look at the available properites of
runningProcesses
...
private static void KillProcess(string processName)
{
Process[] runningProcesses = Process.GetProcesses();
foreach (Process process in runningProcesses)
{
if (process.ProcessName == processName)
{
process.Kill();
}
}
}
You could create your process with a unique BasePriority
or something similar.
Documentation

When killing a process in C#, how can I be sure I'm killing the right one?

Overall Goal
I'm attempting to kill all of the processes by a certain name (notepad.exe below) that I currently own. Generally speaking, it's along the lines of:
Get all of the applications with a certain name that I'm the owner of
In this case, "I" will usually be a service account
Kill all of them.
Questions
How likely is it that from the time I grab a PID to the time I kill it, another application could have spawned that uses that PID? If I grab a PID of ID 123, how likely is it that it could have closed and a different application now owns PID 123?
What is the best way I can reasonably pull this off while limiting the potential that I kill off the wrong PID?
What I have so Far
The below code is based on another SO answer and uses WMI to get all the processes by a certain name and list the users.
What's next: The next step is to kill the processes that are owned by me; however, how can I tell that the PIDs I have here will be the same PIDs I'm trying to kill?
static void Main(string[] args)
{
const string PROCESS_NAME = "notepad.exe";
var queryString = string.Format("Name = '{0}'", PROCESS_NAME);
var propertiesToSelect = new[] { "Handle", "ProcessId" };
var processQuery = new SelectQuery("Win32_Process", queryString, propertiesToSelect);
using (var searcher = new ManagementObjectSearcher(processQuery))
{
using (var processes = searcher.Get())
foreach (var aProcess in processes)
{
var process = (ManagementObject)aProcess;
var outParameters = new object[2];
var result = (uint)process.InvokeMethod("GetOwner", outParameters);
if (result == 0)
{
var user = (string)outParameters[0];
var domain = (string)outParameters[1];
var processId = (uint)process["ProcessId"];
Console.WriteLine("PID: {0} | User: {1}\\{2}", processId, domain, user);
// TODO: Use process data...
}
else
{
// TODO: Handle GetOwner() failure...
}
}
}
Console.ReadLine();
}
Yes, there is a risk of killing the wrong process. The reuse of PIDs probably is a history accident that has caused a lot of grief over the years.
Do it like this:
Find the PIDs you want to kill.
Obtain handles to those processes to stabilize the PIDs. Note, that this might obtain handles to wrong processes.
Re-find the PIDs you want to kill.
Kill those processes that you have stabilized and that are in the second find result set.
By inserting this lock-and-validate step you can be sure.
How likely is it that from the time I grab a PID to the time I kill it, another application could have spawned that uses that PID?
Another application wouldn't be assigned the same PID if it was spawned whilst the other one was alive. So this condition wouldn't happen as Windows' PIDs are unique decimal numbers to that specific process.
If I grab a PID of ID 123, how likely is it that it could have closed and a different application now owns PID 123?
This is technically feasible that the process could be closed between the time you gain your handle on the process and when you want to kill it. However, that would depend entirely on the lifespan of the process handling within your code. I guess there will always be edge cases where the application could be closed just as you're about to hook onto it, but if you're talking milliseconds/a couple of seconds I imagine it would be few and far between. As for Windows assigning the same PID immediately afterwards, I don't know for sure but they seem pretty random and now allocated again immediately after use, but they eventually would do.
What is the best way I can reasonably pull this off while limiting the potential that I kill off the wrong PID?
There is the Management Event Watcher class which appears to allow you to monitor the starting and stopping of processes. Maybe this could be used to capture events whenever they are closed for your given process name, so this way you know that it no longer exists?
Another answer discussing Management Event Watcher
MSDN ManagementEventWatcher class with example usage
Consider opposite approach - adjust permissions on service account so it can't kill processes of other users.
I believe such permissions are very close to default for non-admin accounts (or just default) - so unless you run service as box admin/system you may be fine with no-code solution.
A process id is guaranteed to stay the same as long as the process continues to run. Once the process exits... there is no guarantee.
When a new process starts, Windows will pick a random process ID and assign it to the new process. Its unlikely, but possible that the id chosen was associated with a process that recently exited.
Have you looked at System.Diagnostics.Process?
They have a GetProcessesByName method that will return a list of Process objects.
Process [] localByName = Process.GetProcessesByName("notepad");
Then you can simply iterate through the Processes and kill them. Since the Process object has a handle to the process... an attempt to kill it will generate a useful exception, which you can catch.
foreach (Process p in localByName)
{
try
{
p.Kill();
}
catch (Exception e)
{
// process either couldn't be terminated or was no longer running
}
}

Process Monitoring

I'm quite familiar with the System.Diagnostics.Process class. But, I'm wondering about how I can monitor a specific process (i.e. Check to see if it's running every XX mins/secs). I need to be able to checking whether a process is running and if it is, continue with initialising the rest of the program.
Thanks,
-Zack
Checking if it's still running is easy: Process.HasExited.
Rather than polling this periodically, however, you could set EnableRaisingEvents to true, and attach a handler to the Exited event.
EDIT: To answer the question in the comment about "fetching" the process - that depends on what you already know. If you know its process ID, you could use Process.GetProcessById. If you only know its name, you would have to use Process.GetProcessesByName and work out what to do if you get multiple results. If you don't know the exact name, you could use Process.GetProcesses and look for whatever you do know about it. Those options are effectively in order of preference :)
If you didn't start the process yourself, you get find the Process object associated with a process by looking through the list returned by Process.GetProcessesByName(...) or Process.GetProcesses(...)
Once you have the process, you can listen read its properties (including HasExited) and (as Jon mentions in his response) if you set EnableRaisingEvents you can listen to its events (including Exited).
Something like this, maybe?
Process[] processlist = Process.GetProcesses();
bool found = false;
foreach (Process theprocess in processlist)
{
if(theprocess.ProcessName == "YourProcessName")
{
found = true;
break;
}
}
if (!found)
{
return;
}

Categories

Resources