Getting the name of what program ran an console app [duplicate] - c#

This question already has answers here:
How to get parent process in .NET in managed way
(7 answers)
Closed 5 years ago.
I need to get the name of the program that launched a console application i am making in Visual studio. Any ideas on how i can do this?
I am doing this so i can see for how long robots in out company is running and when they are running.

You can get the parent process of some other process like this:
public static Process GetParentProcess(Process process)
{
string query = "SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = " + process.Id;
using (ManagementObjectSearcher mos = new ManagementObjectSearcher(query))
{
foreach (ManagementObject mo in mos.Get())
{
if (mo["ParentProcessId"] != null)
{
try
{
var id = Convert.ToInt32(mo["ParentProcessId"]);
return Process.GetProcessById(id);
}
catch
{
}
}
}
}
return null;
}
Inside your console app you would use it like
var parent = GetParentProcess(Process.GetCurrentProcess());
From this you can get all information about parent process.

If you can modify the call of the console application, you can give the program name as an argument.

Related

How to get apps(processes) per user on a terminal server? [duplicate]

I'm trying to get a list of processes currently owned by the current user (Environment.UserName). Unfortunately, the Process class doesn't have any way of getting the UserName of the user owning a process.
How do you get the UserName of the user which is the owner of a process using the Process class so I can compare it to Environment.UserName?
If your solution requires a pinvoke, please provide a code example.
Thanks, your answers put me on the proper path. For those who needs a code sample:
public class App
{
public static void Main(string[] Args)
{
Management.ManagementObjectSearcher Processes = new Management.ManagementObjectSearcher("SELECT * FROM Win32_Process");
foreach (Management.ManagementObject Process in Processes.Get()) {
if (Process["ExecutablePath"] != null) {
string ExecutablePath = Process["ExecutablePath"].ToString();
string[] OwnerInfo = new string[2];
Process.InvokeMethod("GetOwner", (object[]) OwnerInfo);
Console.WriteLine(string.Format("{0}: {1}", IO.Path.GetFileName(ExecutablePath), OwnerInfo[0]));
}
}
Console.ReadLine();
}
}
The CodeProject article How To Get Process Owner ID and Current User SID by Warlib describes how to do this using both WMI and using the Win32 API via PInvoke.
The WMI code is much simpler but is slower to execute. Your question doesn't indicate which would be more appropriate for your scenario.
You will have a hard time getting the username without being an administrator on the computer.
None of the methods with WMI, through the OpenProcess or using the WTSEnumerateProcesses will give you the username unless you are an administrator. Trying to enable SeDebugPrivilege etc does not work either. I have still to see a code that works without being the admin.
If anyone know how to get this WITHOUT being an admin on the machine it is being run, please write how to do it, as I have not found out how to enable that level of access to a service user.
You might look at using System.Management (WMI). With that you can query the Win32_Process tree.
here is the MS link labelled "GetOwner Method of the Win32_Process Class"
Props to Andrew Moore for his answer, I'm merely formatting it because it didn't compile in C# 3.5.
private string GetUserName(string procName)
{
string query = "SELECT * FROM Win32_Process WHERE Name = \'" + procName + "\'";
var procs = new System.Management.ManagementObjectSearcher(query);
foreach (System.Management.ManagementObject p in procs.Get())
{
var path = p["ExecutablePath"];
if (path != null)
{
string executablePath = path.ToString();
string[] ownerInfo = new string[2];
p.InvokeMethod("GetOwner", (object[])ownerInfo);
return ownerInfo[0];
}
}
return null;
}
You'll need to add a reference to System.Management.dll for this to work.
Here's what I ended up using. It works in .NET 3.5:
using System.Linq;
using System.Management;
class Program
{
/// <summary>
/// Adapted from https://www.codeproject.com/Articles/14828/How-To-Get-Process-Owner-ID-and-Current-User-SID
/// </summary>
public static void GetProcessOwnerByProcessId(int processId, out string user, out string domain)
{
user = "???";
domain = "???";
var sq = new ObjectQuery("Select * from Win32_Process Where ProcessID = '" + processId + "'");
var searcher = new ManagementObjectSearcher(sq);
if (searcher.Get().Count != 1)
{
return;
}
var process = searcher.Get().Cast<ManagementObject>().First();
var ownerInfo = new string[2];
process.InvokeMethod("GetOwner", ownerInfo);
if (user != null)
{
user = ownerInfo[0];
}
if (domain != null)
{
domain = ownerInfo[1];
}
}
public static void Main()
{
var processId = System.Diagnostics.Process.GetCurrentProcess().Id;
string user;
string domain;
GetProcessOwnerByProcessId(processId, out user, out domain);
System.Console.WriteLine(domain + "\\" + user);
}
}

Check if process is running for current user in C#

I have a program in which I check if the program is already launched or not.
I use:
if (System.Diagnostics.Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location)).Count() > 1) return;
The check works but the problem is that this doesn't work on a terminal server.
The reason is, is because I check if the process exist in the existing processes.
Example:
If user A is connected to a terminal server and runs program X, user B won't be able to launch the program (because the program X usage of user A will show up in the list)
My question is, how in C#, can I check if the program is already running under the context of the user?
I have discovered the following WMI-code that works in PowerShell, but the problem is that this doesn't work in C#
$owners = #{ }
gwmi win32_process |% {$owners[$_.handle] = $_.getowner().user}
$ps = get - process | select processname,Id,#{ l = "Owner"; e ={$owners[$_.id.tostring()]} }
foreach ($p in $ps) {
if ($p.Owner - eq $env: USERNAME) {
$p
}
}
Would there be a method by editing my existing method to allow this?
I tried to do:
Process[] runningProcesses = Process.GetProcesses();
var currentSessionID = Process.GetCurrentProcess().SessionId;
Process[] sameAsThisSession =
runningProcesses.Where(p => p.SessionId == currentSessionID).ToArray();
if (sameAsThisSession.Contains(System.Diagnostics.Process.GetCurrentProcess()))
{
MessageBox.Show("Program already running!");
}
But this doesn't work. (It does show the processes of the user only though).

Is it possible to check if a Mutex is created by using wildcards?

For example my application creates mutex's like so:
MyApplication\\{UserName}
and then my updater program (that updates this application) needs to check whether this has been created or not but it doesn't know the username.
I have the code:
string mutexString = "MyApplication\\User1"
bool isNew;
var mutex = new Mutex(true, mutexString , out isNew);
if(isNew)
{
//Run my program
}
This works fine if I know the username but I would like to know if it is possible for this to work with wildcards?
So from the comments I get the sense that this is impossible so a better solution might be to check the running processes which I achieved like so:
foreach (var process in Process.GetProcesses())
{
if (process.MainWindowTitle.IndexOf("MyApp",StringComparison.InvariantCultureIgnoreCase) >= 0)
{
isNew = false;
}
}

Running program as admin on startup [duplicate]

This question already has answers here:
How do I force my .NET application to run as administrator?
(12 answers)
Closed 8 years ago.
I am creating an application that monitors another application, if the application get close the former will restart that, and I have to create a folder in c:\ drive , if i simply run the application nothing happens but when i run that as admin it works as required.
What can I do to make this application automatically start as admin without any prompt, as i want to run this application on start up, just like some antivirus programs which do not ever need admin rights.
public bool IsProcessOpen()
{
string name = "aProgram";
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Contains(name))
{
return true;
}
}
return false;
}
private void timer1_Tick_1(object sender, EventArgs e)
{
try
{
bool track = false;
track =IsProcessOpen();
if (!track)
{
Process firstProc = new Process();
firstProc.StartInfo.FileName =Application.StartupPath + "\\" + fileName;
firstProc.EnableRaisingEvents = true;
firstProc.Start();
}
}
catch (Exception)
{
}
}
I dont want that the user gets UAC prompt.
in windows there is something called task scheduler, there one can create the task and give the path to any specific program, choose admin rights and when to start etc. attached screenshots for your reference

Querying if a Windows Service is disabled (without using the Registry)?

Is there a .NET (C#) method or API call that I can use to query if a Windows Service is disabled? The relevant MSDN article is here.
I want to avoid querying the registry directly. Below is some of the code that I am using right now (and it works). However I am looking for something more elegant and less invasive.
const String basepathStr = #"System\CurrentControlSet\services\";
String subKeyStr = basepathStr + servicenameStr;
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(subKeyStr))
{
return (int) key.GetValue("Start");
}
I did find a simliar question but I was hoping for a better answer since the answers are presumably outdated (3 years have passed).
This the most relevant section of the code I decided to use...thanks for the help all!
StartupState state = StartupState.Unknown;
try
{
PermissionSet fullTrust = new PermissionSet(System.Security.Permissions.PermissionState.Unrestricted);
fullTrust.Demand();
string wmiQuery = #"SELECT * FROM Win32_Service WHERE Name='" + servicenameStr + #"'";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiQuery);
ManagementObjectCollection results = searcher.Get();
foreach (ManagementObject service in results)
{
if (service["StartMode"].ToString() == "Disabled")
state = StartupState.Disabled;
else
state = StartupState.Enabled;
}
return state;
}
catch (SecurityException se)
{
return StartupState.Refused;
}
catch (Exception e)
{
return StartupState.Error;
}
Use the ServiceController class to get information about services.
EDIT
Seems one of the things you can't do with the ServiceController is get the startup type. Googling showed the following blog post that has code that uses P/Invoke to get the service startup type: http://peterkellyonline.blogspot.de/2011/04/configuring-windows-service.html
Add a ref to System.Management and the following code will get you the StartMode
string wmiQuery = "SELECT * FROM Win32_Service WHERE Name='YourServiceName'";
var searcher = new ManagementObjectSearcher(wmiQuery);
var results = searcher.Get();
foreach (ManagementObject service in results)
{
Console.WriteLine(service["StartMode"]);
}
ServiceController class doesn't provide this information. You should use WMI. See here for detailed solution
WMI can be another way for querying the status of the windows services
You can use:
using System.ServiceProcess;
And then link the service you want to view the satus by:
// Link by service name
ServiceController TheServiceName = new ServiceController();
TheServiceName.ServiceName = "Spooler";
// Link by display name
ServiceController TheDisplayName = new ServiceController();
TheDisplayName.ServiceName = "Print Spooler";
To check for example the isRunning Status :
if (TheServiceName.Status == ServiceControllerStatus.Running)
MessageBox.Show("The service is running.");

Categories

Resources