I have a question concerning the Visual Studio COM interface. I use the code below to get all processes on a remote machine and attach to MyExe.exe. The problem is that iterating through the processes' names takes very long. There are only ~20 processes, but the iteration takes ~8 seconds (that means the foreach-loop, not the code before that).
// Get processes
EnvDTE80.Debugger2 debugger2 = (EnvDTE80.Debugger2)dte.Debugger;
EnvDTE80.Transport trans = debugger2.Transports.Item("Default");
processes = debugger2.GetProcesses(trans, remoteName);
// Find exe and attach to it
foreach (EnvDTE.Process proc in processes)
{
if (proc.Name.Contains("MyExe.exe"))
{
proc.Attach();
break;
}//end if
}//end foreach
Is that normal? Is there anything I can do to speed things up?
Thanks!
Related
Is there a way to obtain the process name/id of a Steam game started via:
Process.Start("steam://rungameid/#");
As expected the above method returns Steam.exe.
Every game has a key in the registry under HKCU\SOFTWARE\Valve\Steam\Apps
You should be able to check for the Installed value of your game from there, then run the game using steam://rungameid/#, and then wait for the Running or Updating values to change to 1, and again for 0.
This makes it possible to track a game execution, however, you still can't directly have the process id of the game.
This is an old question but I just got done doing the same thing (for a project somewhat similar to what you're working on). You can use ManagementObjects from System.Management to find the ParentId of a process. If you are launching Steam, you will have the process Id of Steam, although the way you're currently launching games, you will need to look up the process Id of Steam.
One thing you will find is each game will generally spawn 2-3 different child processes. The steam overlay, the webclienthelper, and then the game itself (and possibly another for the game's launcher). They should all be children to the Steam process, though, and all should show up in the found processes list.
It would look something like this.
List<Process> procs = Process.GetProcesses();
Process steam = procs.Find(x => x.ProcessName == "Steam");
int steamId = steam.Id;
foreach (var proc in procs)
{
using (ManagementObject mo = new ManagementObject($"win32_process.handle='{proc.Id}'"))
{
if (mo != null)
{
try
{
mo.Get();
int parentPid = Convert.ToInt32(mo["ParentProcessId"]);
if (parentPid == steamId)
{
Console.WriteLine($"{proc.ProcessName} is running as a child to {mo["ParentProcessId"]}");
}
}
catch (Exception ex)
{
// the process ended between polling all of the procs and requesting the management object
}
}
}
}
In general, no.
Steam simply uses a custom URI prefix, which allows you to specify which application will service that request. But it doesn't create a new prefix for each game - instead, it's handled by steam.exe, which decides what application to actually run.
Steam itself of course does track the games it runs, but I assume it simply keeps track of their process IDs, perhaps with some influence from either Steam integration or the Steam overlay injection to track games that use a launcher. I don't think there's any simple way of keeping that information if you're not willing to mess around with other application's privates.
There may be some cases where you have other solutions; e.g. if you don't mind if there may be multiple Steam games running at the same time, you could try finding all processes that have the Steam overlay, but those are rather specific - they might work well for you, but fail for other users.
As the new process will not be started as a child process of steam, it will be impossible to derive its id. What you could try though is to derive the currently running game via the API - and then search through all running processes for their names. The API should expose the game's name via the gameextrainfo property, which should be identical to the process' name (untested, though).
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
}
}
i have this piece of code to detect a Process:
private Boolean IsGameRunning()
{
Process[] game = Process.GetProcesses();
foreach (Process process in game)
{
if (process.ProcessName.Contains("GameWindow"))
{
return true;
}
}
return false;
}
Since the code has to run a lot of times because it is inside a Timer, is there any way to improve the speed of the process?
I do not have any control over the game.
This code is inside a timer always enabled with an interval of 2000-3000 ms:
if (IsGameRunning())
{
Do stuff
}
else
{
Status("Waiting for game to start");
}
Given that the process is launched by another, in this case Steam, we can narrow the list to search to only child processes.
First, need to get the parent process id (PID).
var parentProcess = Process.GetProcesses().FirstOrDefault(x => x.ProcessName == "Steam");
Then using the Windows Management Instrumentation (accessed using the System.Management.dll), you can then search only the child processes.
bool IsGameRunning(int parentProcess, string childExecutableName)
{
var query = string.Format("SELECT * FROM Win32_Process WHERE ParentProcessId = {0} AND Name = '{1}'", parentProcess, childExecutableName);
using (var searcher = new ManagementObjectSearcher(query))
using (var results = searcher.Get())
{
return (results.Count > 0);
}
}
e.g. IsGameRunning(parentProcess.Id, "SuperMeatBoy.exe")
No guarantee that this is faster as I haven't done any comparative testing, however from prior experience using the WMI is more performant than iterating a list of processes.
If you want to go further, a more advanced solution would be to hook up events to tell you process is created and deleted using a ManagementEventWatcher as shown in this blog post http://weblogs.asp.net/whaggard/438006.
WMI gives you a visible performance hit with noticeable recurring CPU spikes when looking at it run in task manager. The way I made my process hunting work was to use a linq statement on Process.GetProcessByName, which I've never seen go above 0% when scanning for processes every .3 seconds. I store the processes I already know about in the memory, and filter them out in the linq statement.
If your EXE has enough permission (or is elevated), you can set EnableRaisingEvents = true, and attach to the Exited event to know exactly when the process dies.
I'm trying to make a console app in c# that will confirm that another application is always running. The other application periodically crashes, and I need to check every few minutes and relaunch it if it has stopped working.
There are many questions on SO that address making sure than no more than one instance of the application is running. I'm trying to confirm that one (no more or less) is running at all times.
Does anybody know how to even begin approaching this?
I would suggest using System.Diagnostics.Process.GetProcessesByName to see if your process is running and then, if not, using System.Diagnostics.Process.Start to start the process.
var processes = Process.GetProcessesByName("yourProcessName");
if(processes.Length == 0)
{
Process.Start(#"C:\Path\To\Your\Process.exe");
}
// Kill the extras
for(int i = 1; i < process.Length; i++)
{
processes[i].Kill();
}
These commands are useful to control processes:
// check for processes
Process[] processes = Process.GetProcessesByName("nameOfExecutable");
foreach (Process proc in processes)
{
// do stuff
}
// start process (need path)
Process.Start("pathToExecutable");
// close gui process gently (if needed)
bool status = proc.CloseMainWindow();
// wait for process to close gently
bool status = proc.WaitForExit(killTimeMS);
// force close (kill) process
proc.Kill();
If you implement a "no more than one" rule (which is well-documented, as you point out) and then implement the periodic crash-checker, that should be sufficient to ensure that one and only one copy is running.
In fact, the periodic process doesn't even have to check for a crash. It can just fire up an instance, which will immediately exit if another instance is already running, thanks to whatever "no more than one" mechanism you implement. This has the added benefit of avoiding a possible race-condition between detecting a dead process and starting a new one.
You have a few options. The first is checking for a running process using the Process class. I got this from a Microsoft site, but it looks like it works:
public bool IsProcessRunning(string name)
{
//here we're going to get a list of all running processes on
//the computer
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.StartsWith(name))
{
//process found so it's running so return true
return true;
}
}
//process not found, return false
return false;
}
You could also use interprocess communications. This is something we do in house. We have a watcher application that sends a message to a service being monitored. If the service doesn't return an ACK in a timeout period, we attempt to restart it.
I suggest you to check if your application is in the list of running processes:
System.Diagnostics.Process.GetProcesses();
I have a simple .exe that needs to be running continuously.
Unfortunately, sometimes it crashes unexpectedly, and there's nothing that can be done for this.
I'm thinking of like a C# program that scans the running application tree on a timer and if the process stops running it re-launches it... ? Not sure how to do that though....
Any other ideas?
It's fairly easy to do that, but the "crashes unexpectedly, and there's nothing that can be done for this" sounds highly suspect to me. Perhaps you mean the program in question is from a third party, and you need to work around problems they can't/won't fix?
In any case, there's quite a bit of sample code to do exactly what you're talking about.
The first solution would be to fix your EXE, so it does not crash. If you can not fix it now, you probably need to add exception handling, so you can catch the exception, and not close the EXE.
Second solution is to write simple guard programm that will start your simple .exe and will monitor specific process handle. It will restart your program when it closes.
easiest way is to have you program see if an instance of itself is running and exit if it is. Set up a scheduled task to run it every couple of minutes.
class Program
{
static void Main(string[] args)
{
if (IsRunning())
{
return;
}
else
{
for (int x = 0; x < 10; x++)
{
//Do Stuff
System.Threading.Thread.Sleep(1000);
}
}
}
private static bool IsRunning()
{
Process[] P = Process.GetProcessesByName( Process.GetCurrentProcess().ProcessName ) ;
return P.Count() > 1;
}
}
One trick occasionally employed by malware in days past was to have two processes that each monitor the currently running processes and restart the other process if it is terminated.
The System.Diagnostics namespace has classes which can help, particularly "Process".
For example
static Process[] Process.GetProcesses()
returns a list of all the currently running processes.
If your other process is not in this list, you just restart it with, for example
Process.Start()
Your program needs to initially start your target process itself (with Process.Start), then simply wait for it to terminate (with WaitForExit on object that is returned by Process.Start()). After that whole procedure is repeated.
This way you'd be sure that you are watching the process you are interested in, and you don't need to poll process list at all.
Process.Start() and WaitForExit() usage example.