CheckProcess application close - c#

how can I make my application not open if AnyDesk and TeamViewer are open? Example: If AnyDesk and TeamViewer are running, my application will not open, but if AnyDesk and TeamViewer are closed, it will open normally.
Process[] runningProcs = Process.GetProcesses("Anydesk.exe");
foreach(Process process in runningProcs)
{
Application.Exit();
}
I don't know if this is right, but that's what I was trying

The idea you have is right but you don't have to get all processes twice and you don't have to use a foreach to exit. If you use a foreach on processes with only the name "Anydesk.exe," you'll exit when even only one of the apps is running and not both. You can use LINQ's convenient features to do this:
public static void Main()
{
var processNames = Process
.GetProcesses()
.Select(p => p.ProcessName);
if (processNames.Any(name => name is "name1" or "name2"))
{
Console.WriteLine("Found forbidden process");
Environment.Exit(exitCode: 1);
}
Console.WriteLine("No forbidden processes found");
}
The downside to this code is that only one of the applications needs to be running in order for the app to exit. Instead, you can use .Contains to ensure both are in the enumerable like this:
public static void Main()
{
var processNames = Process
.GetProcesses()
.Select(p => p.ProcessName)
.ToArray(); // Avoid multiple enumeration
if (processNames.Contains("name1") && processNames.Contains("name2"))
{
Console.WriteLine("Found forbidden process");
Environment.Exit(exitCode: 1);
}
Console.WriteLine("No forbidden processes found");
}
If the convenience of LINQ is too slow for your likings, you can use regular for loops and do the same things

Related

Is it possible to prevent to startup of applications?

TLDR; Just like Voodooshield or other application whitelisters do.
I want to prevent apps from spawning or if not possible kill them as soon as they spawn. So my question is: would it be possible to subscribe and interfere the spawn process with C# or (more likely) with the win32 API?
You can get all running processes using the Process class in System.Diagnostics.
class Program
{
static void Main(string[] args)
{
while (true)
{
foreach (var item in Process.GetProcesses())
{
/*Kills all chrome.exe processes*/
/*Replace chrome with the process you want to kill*/
if (item.ProcessName == "chrome")
{
//Kills the process
item.Kill();
}
}
}
}
}

Code is still looping after break

I have 3 instances of the same app running. If I have my program mark one to be killed, it works fine, and 2 remain running. When I mark another to be killed, then it kills the remaining 2, instead of just one more. If I put a messagebox before the "break;", it works correctly, only killing one more and leaving one running. But without the messagebox, when I try to kill the second instance, it always kills both that one and the third instance. Any idea why a messagebox there would make it work correctly? I'm assuming some type of timing issue, but I can't figure out why, since there's a "break;".
foreach (WatcherScraperModel scraper in this.Scrapers.Except(scheduled.Where(x => x.Active)))
{
totalinstances = 0;
foreach (Process process in Process.GetProcesses())
{
try
{
if (process.MainModule.FileName == scraper.FileName)
{
// get instances already running
totalinstances++;
}
}
catch
{
// certain core processes cannot be accessed, don't worry about it
}
}
foreach (Process process in Process.GetProcesses())
{
try
{
// only kill an instance if there's too many running
if (process.MainModule.FileName == scraper.FileName && totalinstances > scheduled.Count(x => x.Active && x.FileName == scraper.FileName))
{
logger.DebugFormat("Killed {0} because it was not scheduled to be running", scraper.FileName);
process.Kill();
scraper.RestartRemaining = 0;
break;
}
}
catch
{
// certain core processes cannot be accessed, don't worry about it
}
}
}
Check out the documentation for Process.Kill
The Kill method executes asynchronously. After calling the Kill method, call the WaitForExit method to wait for the process to exit, or check the HasExited property to determine if the process has exited.
If you add a process.WaitForExit(); after process.Kill(); then the next time you call Process.GetProcesses() that process should not longer be there allowing your count to be correct. This also explains why adding a message box fixes the problem as that will give the process time to stop before you continue with the outer foreach loop.

how to get PID of my app at runtime using C#

My app checks at startup if any other instance of the same is running already, if yes then it will close all other instances. For this I tried using Process.GetProcessByName("AppName") function and store all the process with AppName in processes[] array. Now i want to find the PID of current instance so that i can close all other instances of my app (which obviously have same name but different PIDs). But i am unable to find that even after lot of googling. Also how can i find the PID of an instance of my app which i have created with Process.Start("AppName.exe") function called from inside AppName.exe
OK, given problems with my other solution, see the following
In order to hook in between processes, you need some form of IPC. To use the simplicty of shared handles between EventWaitHandles, you could make each program listen for a cancellation flag.
public static EventWaitHAndle CancellationEvent =
new EventWaitHandle(
false,
EventResetMode.AutoReset,
"MyAppCancel");
private object lockObject = new object();
And later...
Task.Run(() =>
{
while(true)
{
CancellationEvent.WaitOne();
lock(lockObject)
if(!thisIsCalling) // static bool to prevent this program from ending itself
Environment.Exit(0);
}
}
And then call the cancellation like so
lock(lockObject)
{
thisIsCalling = true;
CancellationEvent.Set();
thisIsCalling = false;
}
Why don't you just check equality with your current process?
var processes = Process.GetProcessByName("AppName");
foreach (var p in processes)
{
if (p != Process.GetCurrentProcess())
p.CloseMainWindow();
}
If you're interested in closing other instances of your app, why not do the opposite and prevent multiple instances from opening in the first place? Using EventWaitHandle can do this thusly:
bool created;
var eve = new System.Threading.EventWaitHandle(
false,
EventResetMode.AutoReset,
"MyAppHandle",
out created);
if(!created)
{
eve.Set();
Environment.Exit(-1); // Always use an exit error code if you're expecting to call from the console!
}
The handle parameter, "MyAppHandle" in this case, will be shared across the entire system, thus meaning not only will the out created paramete be false on secondary instaces, but you can use eve.Set() to cause the handle to fire acorss application. Set up a listening thread and this can allow a message loop to display a message when you attempt to open second instance.
Task.Run(() =>
{
while(true)
{
eve.WaitOne();
// Display an error here
}
}

Starting and stopping a process in C# .NET

I am trying towrite a simple program that has two methods, one that starts a process and one that takes down the same process.
as in:
public Process StartProc(string procname)
{
Process proc = new Process();
proc.StartInfo.FileName = procname;
proc.Start();
return proc;
}
public void StopProc(Process proc)
{
proc.Close();
}
Is it possible to do this like that?
Yes, the method you are after is called Kill, not Close:
public void StopProc(Process proc)
{
proc.Kill();
}
This will forcibly close the process - when possible it is preferable to signal the application to close such as by requesting that the application close the main window:
public void StopProc(Process proc)
{
proc.CloseMainWindow();
}
This allows the application to perform clean-up logic (such as saving files), however may allow the process to continue running if it chooses to ignore the request and will do nothing if the process does not have a main window (for example with a console application).
For more information see the documentation on the Process.CloseMainWindow method.
I think you are looking for Process.Kill().
You don't really need a StopProc() method, you can just write proc.Kill() directly.
However, it is not generally recommended that you terminate processes in such a brutal way. Doing so can leave shared objects in an undefined state. If you can find a way to co-operatively close the process that is to be preferred.
By starting the process, you can get the unique Id of that process and then you can kill it like this:
public static int Start(string processName)
{
var process =
Process.Start(processName);
return
process.Id;
}
public static void Stop(int processId)
{
var process =
Process.GetProcessById(processId);
process.Kill();
}

A better way of finding out if any running process was launched from a given file?

I have to check whether another process is running, based only on the name of the EXE file.
Currently I get the process list and then query the MainModule.FileName property, however some processes throw Win32Exception "Unable to enumerate the process modules" when you access the MainModule property.
Currently I am filtering to a 'safe list' by catching these access exceptions thus:
List<Process> processes = new List<Process>(Process.GetProcesses());
// Slow, but failsafe. As we are dealing with core system
// data which we cannot filter easily, we have to use the absense of
// exceptions as a logic flow control.
List<Process> safeProcesses = new List<Process>();
foreach (Process p in processes)
{
try
{
ProcessModule pm = p.MainModule;
// Some system processes (like System and Idle)
// will throw an exception when accessing the main module.
// So if we got this far, we can add to the safe list
safeProcesses.Add(p);
}
catch { } // Exception for logic flow only.
}
Needless to say I really don't like having to use exceptions like this.
Is there a better way to get the process list for which I can access the MainModule property, or even a better method of checking if any process was spawned from a given file?
I think that there are only System and Idle processes that will throw the exception so you can filter them out before and you're ready to go.
I will use like
List<Process> processes = Process.GetProcesses().ToList();
List<Process> safeProcesses = processes .Select(X =>
{
try { ProcessModule pp = X.MainModule; return X; }
catch { return null; }
}).Where(X=>X!=null).ToList();

Categories

Resources