List administrator processes in C# - c#

I am trying to print all running processes in C#, similarly to how tasklist or ps does. I tried it with the following code:
foreach(Process process in Process.GetProcesses()) {
if(!process.HasExited) {
Console.WriteLine(process.ProcessName);
}
}
But with it, I run into some issues on Windows (did not try it on Linux):
When I execute the above code with user-privileges, it only prints processes started by this user. If I run it as administrator, all processes are printed.
When I open a cmd window with user privileges and list the processes (i.e. execute tasklist), all processes are printed, even those started by the system / by an administrator account.
Is there a way to get all processes, even those started by a higher privileged user, without requiring the program to be run as administrator?
One solution came to my mind:
System.Diagnostics.Process.Start("CMD.exe", "tasklist > C:\file.txt");
String[] processes = File.ReadAllLines(#"C:\file.txt");
But this is really hacky and does not work on linux.

You can't. You can't let the same process run parts in elevated and in user mode. That's just the way they built it, mainly for security reasons. You can't just bypass it.
Enough about what you can't. What can you do? You could start a second (different) program that runs in elevated mode, or you could restart your current application when there is a section you need elevated privileges. You need Process.Start for this and you will have to set the ProcessStartInfo.Verb to "runas":
ProcessStartInfo startInfo = new ProcessStartInfo(exePath);
startInfo.Verb = "runas";
Process.Start(startInfo);

After some testing I found out, that administrator processes will show in the Process.GetProcesses() list but the boolean HasExited of admin privileged processes is always true (even if it hasn't closed)
So I just looped through the list without checking for process.HasExited
foreach(Process process in Process.GetProcesses()) {
if(!process.HasExited) { //running process with user privileges
//do some stuff here
}
else { //closed process or administrator process
//do some stuff here
}
}
And for the case that the process has actually stopped, I wrap it inside a try-catch block.
As this solution does not seem optimal to me, I am leaving this question open.

Related

Killing process as admin via another process

I'm trying to kill some processes by their names (specific names that I already know) In C#. I find them and kill them with Process.Kill(), but sometimes on some processes i get 'access denied'. I assume it is because I'm not running them as an admin.
I created a batch that does the same, and if I run it as an admin it kills them all, otherwise not.
I can run the batch as an admin via the c# code, i.e:
var psi = new ProcessStartInfo();
psi.Verb = "runas"; //This suppose to run the command as administrator
//Then run a process with this psi
My question is, is this really a way to solve the access problem? Is there a better way? If I run my C# code as an admin, does Process.Kill() suppose to have the same result as doing it with the batch file?
What you are talking about are Elevated rights.
You need the programm that finds the programms and sends out the kills to always run Elevated. The most reliable way to do that, is to add this requirement to the Programm Manifest. It is something the UAC will read to help you.
The second most reliable way is to check if you got the rights. And if not, have the programm try to (re)start itself elevated. I did write some sample code for this a while back:
using System;
using System.Diagnostics;
using System.IO;
namespace RunAsAdmin
{
class Program
{
static void Main(string[] args)
{
/*Note: Running a batch file (.bat) or similar script file as admin
Requires starting the interpreter as admin and handing it the file as Parameter
See documentation of Interpreting Programm for details */
//Just getting the Absolute Path for Notepad
string windir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
string FullPath = Path.Combine(windir, #"system32\notepad.exe");
//The real work part
//This is the programm to run
ProcessStartInfo startInfo = new ProcessStartInfo(FullPath);
//This tells it should run Elevated
startInfo.Verb = "runas";
//And that gives the order
//From here on it should be 100% identical to the Run Dialog (Windows+R), except for the part with the Elevation
System.Diagnostics.Process.Start(startInfo);
}
}
}
Note that regardless how you try to elevate, Eleveation can fail in very rare OS settings.

Process.Start(); as another user works but explorer.exe iexplore.exe throws exception

I'm having problems with a program and its buttons (I know, I'm awesome lol) the buttons can be "programmed" to run programs. They also can be set to run as admin (different credentials).
If I set up simply notepad or cmd or explorer it runs like charm. But if I start iexplore it has got no admin rights.
I had problems before with running explorer.exe the solution was that I had to run it by typing the full path C:\windows\explorer.exe to be able to run it but that I solved it by setting up the VB2015 compiler (?) to Platform target: x64.
My other problem is that if I try to run dsa.msc or generally anything ends with msc it throws the following exception, even if I set up the full path to the syswow64 (or the system32) folder like c:\windows\syswow64\dsa.msc
"The specified executable is not a valid application for this OS platform."
Running the C:\Windows\System32\mmc.exe "services.msc" (or syswow64, with or without the /computer= switch) throws
"The requested operation requires elevation." which I have since I'm able to run services.msc (and all other msc-s from command line with the same user rights)
Thank you.
A beginner.
Basically you don't need to run the host app as administrator! There is a variable (inside your Process instance) called StartInfo (which is an instance of the ProcessStartInfo Class), where Verbs could be used as followed:
Process p = new Process()
{
StartInfo = new ProcessStartInfo("E:\\Users\\Temp\\app.exe")
{
Verb = "runas"
}
};
p.Start();
This will prompt the user to run the app.exe as administrator.
Edit
Running a Process as a defined user:
Process p = new Process()
{
StartInfo = new ProcessStartInfo("E:\\Users\\Temp\\app.exe")
{
Verb = "runas",
Arguments = "/user:Vira"
}
};
For more information about those RUNAS Arguments, click me! :)

Find out if another application is running as admin

I'm trying to determine if another application is running as an administrator. There are 100's of SO questions about finding if your application is or not, but not for another application.
If I do var processes = Process.GetProcesses(); and loop through them, they don't appear to have any "Elevated" or "IsAdministrator" properties on them. I also found a function on here to get the Owner but they all come back as "My-Laptop\Me" so that's not working for me the way I hoped it would.
Is there a way to find this? I'm on Win 8.1 and would prefer something that works for 7 as well, but if it only works for 8.1+ that's totally fine.
Thanks!
EDIT:
My application has to run as an administrator.
You can use the technique from this answer, just replace Process.GetCurrentProcess().Handle with the Process.Handle of the other process.
If you look at the code (there's quite a bit of code there) it get the process "user token" (the permissions the process is running under) and checks if this token has the administrator role or not,
Assuming your process is not running as administrator, trying to get information about a process that is elevated via UAC (such as its MainWindowTitle) will throw an AccessDenied exception, where a non-elevated process will permit you access to that information. This assumes you also verify the owner of the process to check that it's you.
try
{
var foo = process.MainWindowTitle;
return false; //Process is not elevated
}
catch (Win32Exception ex)
{
return true; //Process is elevated if ex error code is AccessDenied
}

how can I check and kill another instance of my application?

I face to a problem that my customer is already running the application appA. Then they go to desktop (not kill the appA), and upgrade the application with the version up by run appA.ps1 with PowerShell. After that, click on appA after installed -> get an exception. I guess the root cause is that have another instance is running.
My question is how can I check my application is already running? Can I kill it?
Additional, my application is windows 8 store, c#.
If you wand to keep your current instance running and kill all other instances of your application, you can do this:
using namespace System.Diagnostics;
...
// get current process
Process current = Process.GetCurrentProcess();
// get all the processes with currnent process name
Process[] processes = Process.GetProcessesByName(current.ProcessName);
foreach (Process process in processes)
{
//Ignore the current process
if (process.Id != current.Id)
{
process.Kill();
}
}
From Social MSDN:
All the Metro-style applications work in the highly sandboxed environment and there is no way to directly start an external application.
You cannot access windows app processes. Unfortunately, you aren't able to check for running windows apps.
I didn't find another way so far.
No Metro-style application
At first, you need the processes:
var processes = Process.GetProcessesByName("your application name")
To check whether your program is already running:
var isRunning = processes.Length > 1;
Then you loop through them and close the processes:
foreach (var process in processes)
{
process.CloseMainWindow();
// OR more aggressive:
process.Kill();
}

Running as admin sometimes

I have a program that needs to run as a normal user most of the time, but once in a while I need to stop and start a service. How do I go about making a program that runs as a normal user most of the time but elevates into administrator mode for some function?
You can't elevate a process once its running but you could either :-
Restart the process as elevated
private void elevateCurrentProcess()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = true;
startInfo.WorkingDirectory = Environment.CurrentDirectory;
startInfo.FileName = Application.ExecutablePath;
startInfo.Verb = "runas";
try
{
Process p = Process.Start(startInfo);
}
catch
{
// User didn't allow UAC
return;
}
Application.Exit();
}
This method means that your process continues to run elevated and no more UAC promopts - both a good and a bad thing, depends upon your audience.
Put the code that requires elevation into a seperate exe
Set the manifest as requireAdministrator and start it as a separate process. See this sample code
This method means a UAC prompt every time you run the operation.
Best method depends upon your audience (admin types or not) and frequency of the elevated operation.
As far as I know, you need to start a seperate process that runs as the administrator. You can't elevate a process once it's already been started.
See this question.
You need to use what is referred to as Impersonation..
[http://support.microsoft.com/kb/306158][1]
The above shows how it would be accomplished for an ASP.Net app, but the code is probably near identical for your needs.

Categories