How to get username of process running in task manager? - c#

I want to know the user that created each process.
How do I get the usernames of all the processes running in task manager using c#?

Look into Win32_Process Class, and GetOwner Method
Sample Code
Sample code
public string GetProcessOwner(int processId)
{
string query = "Select * From Win32_Process Where ProcessID = " + processId;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
foreach (ManagementObject obj in processList)
{
string[] argList = new string[] { string.Empty, string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
{
// return DOMAIN\user
return argList[1] + "\\" + argList[0];
}
}
return "NO OWNER";
}

Related

I want w3wp.exe process to access a specific folder

i am working on a project that requires a folder to be accessed by only w3wp.exe process.
no other user can access this folder on the machine
i am working on a console project my implementation so far is
public static void SetFolderPermission(string folderPath){
bool exists = Directory.Exists(folderPath);
if (!exists)
{
DirectoryInfo di = System.IO.Directory.CreateDirectory(folderPath);
Console.WriteLine("The Folder is created Sucessfully");
}
else
{
Console.WriteLine("The Folder already exists");
}
var directoryInfo = new DirectoryInfo(folderPath);
var directorySecurity = directoryInfo.GetAccessControl();
var currentUserIdentity = GetIISProcessID("w3wp");
//WindowsIdentity.GetCurrent();
var fileSystemRule = new FileSystemAccessRule(currentUserIdentity,
FileSystemRights.FullControl,
InheritanceFlags.ObjectInherit |
InheritanceFlags.ContainerInherit,
PropagationFlags.None,
AccessControlType.Allow);
directorySecurity.AddAccessRule(fileSystemRule);
directoryInfo.SetAccessControl(directorySecurity);
}
and getting the process is
public static int GetIISProcessID(string appPoolName)
{
//return 0;
string commandLine = String.Empty;
Process[] pCollection = Process.GetProcessesByName(appPoolName);
//Process.GetProcessById(7684, "w3wp.exe");
//Process.GetProcessesByName("w3wp.exe");
foreach (Process pInstance in pCollection)
{
ObjectQuery sq = new ObjectQuery
("Select CommandLine from Win32_Process Where ProcessID = '" + pInstance.Id + "'");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(sq))
{
ManagementObjectCollection objectCollection = searcher.Get();
foreach (ManagementObject oReturn in objectCollection)
{
commandLine = oReturn["CommandLine"].ToString(); break;
}
Console.WriteLine(commandLine);
}
}
return 0;
}
can someone help me figuring out this how can i make a process access a folder.

Get process owner name is slow

I found the following method to get a process's owner:
public string GetProcessOwner(int processId)
{
string query = "Select * From Win32_Process Where ProcessID = " + processId;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
foreach (ManagementObject obj in processList)
{
string[] argList = new string[] { string.Empty, string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
{
return argList[1] + "\\" + argList[0];
}
}
return "";
}
This works fine, however it is very slow. I use it in conjunction with Process.GetProcesses() and it takes circa 20 seconds in total to get every process owner. Is there any way to speed this up?

Unable to remotely terminate a process using WMI and C#

I am trying to write a method that will terminate a service on a remote system, by process ID, if it fails to stop using the StopService method. I have tried two different ways of invoking the "Terminate" method on a ManagementObject, and I get two different errors. It's also important to me that I be able to get the return code from the Terminate method.
If I declare a ManagementPath directly to the process I want to terminate, I get the error "System.Management.ManagementException: Invalid object path" at line:
ManagementBaseObject processParams = processObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null);
If I get a ManagementObjectCollection and loop through it looking for the Process ID I want to terminate, I get the error "Invalid parameter" at line:
ManagementBaseObject termParams = currentObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null);
So, in both cases, I get an error when I try to invoke the Terminate method, but the error differs depending on how I arrive at the object (direct path or loop through collection).
I don't think this is related to SeDebugPrivilege, as I believe I'd be getting "access denied" or "insufficient privilege" if it was.
Code if I attempt to directly specify the path to the process:
public int KillServiceWMI(string serviceName, string serverName, string serverUser, string serverDomain, string serverPassword)
{
try
{
ConnectionOptions options = new ConnectionOptions();
options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
options.Username = serverDomain + "\\" + serverUser;
options.Password = serverPassword;
ManagementScope scope = new ManagementScope("\\\\" + serverName + "\\root\\cimv2", options);
Console.WriteLine("Connecting to scope");
scope.Connect();
Console.WriteLine("Getting ManagementPath");
ManagementPath servicePath = new ManagementPath("Win32_Service.Name='" + serviceName + "'");
Console.WriteLine("Getting ManagementObject");
ManagementObject serviceObj = new ManagementObject(scope, servicePath, new ObjectGetOptions());
Console.WriteLine("Name of service is " + serviceObj["DisplayName"].ToString());
Console.WriteLine("Process ID of service is " + serviceObj["ProcessId"].ToString());
ManagementPath processPath = new ManagementPath("Win32_Process.ProcessId='" + serviceObj["ProcessId"] + "'");
ManagementObject processObj = new ManagementObject(scope, processPath, new ObjectGetOptions());
ManagementBaseObject processParams = processObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null);
int returnCode = System.Convert.ToInt32(processParams.Properties["ReturnValue"].Value);
return returnCode;
}
catch (Exception connectEx)
{
Console.WriteLine("Connecting to " + serverName + " caused an exception");
Console.Write(connectEx);
return 99;
}
}
Code if I loop through a collection of processes:
public int KillServiceWMI(string serviceName, string serverName, string serverUser, string serverDomain, string serverPassword)
{
try
{
ConnectionOptions options = new ConnectionOptions();
options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
options.Username = serverDomain + "\\" + serverUser;
options.Password = serverPassword;
ManagementScope scope = new ManagementScope("\\\\" + serverName + "\\root\\cimv2", options);
Console.WriteLine("Connecting to scope");
scope.Connect();
Console.WriteLine("Getting ManagementPath");
ManagementPath servicePath = new ManagementPath("Win32_Service.Name='" + serviceName + "'");
Console.WriteLine("Getting ManagementObject");
ManagementObject serviceObj = new ManagementObject(scope, servicePath, new ObjectGetOptions());
Console.WriteLine("Name of service is " + serviceObj["DisplayName"].ToString());
Console.WriteLine("Process ID of service is " + serviceObj["ProcessId"].ToString());
ObjectQuery serviceQuery = new ObjectQuery("SELECT * from Win32_Process WHERE ProcessID = '" + serviceObj["ProcessId"].ToString() + "'");
ManagementObjectSearcher serviceSearcher = new ManagementObjectSearcher(scope, serviceQuery);
ManagementObjectCollection serviceColl = serviceSearcher.Get();
int returnCode = 0;
foreach (ManagementObject currentObj in serviceColl)
{
if (currentObj["ProcessId"].ToString().Equals(serviceObj["ProcessId"].ToString(), StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Found process " + currentObj["ProcessId"].ToString() + ". Terminating...");
ManagementBaseObject termParams = currentObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null);
returnCode = System.Convert.ToInt32(termParams.Properties["ReturnValue"].Value);
}
}
return returnCode;
}
catch (Exception connectEx)
{
Console.WriteLine("Connecting to " + vaultName + " caused an exception");
Console.Write(connectEx);
return 99;
}
}
I eventually gave up trying to use the Terminate method on Win32_Process, and instead I'm using Create to call TaskKill.exe remotely. Because the return info is now hidden behind taskkill.exe, I then have to get the process list again and look for the target pid to make sure that the process was actually terminated.
ConnectionOptions options = new ConnectionOptions();
options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
options.Username = serverDomain + "\\" + serverUser;
options.Password = serverPassword;
ManagementScope scope = new ManagementScope("\\\\" + serverName + "\\root\\cimv2", options);
Console.WriteLine("Connecting to scope");
scope.Connect();
Console.WriteLine("Getting ManagementPath");
ManagementPath servicePath = new ManagementPath("Win32_Service.Name='" + serviceName + "'");
Console.WriteLine("Getting ManagementObject");
ManagementObject serviceObj = new ManagementObject(scope, servicePath, new ObjectGetOptions());
Console.WriteLine("Name of service is " + serviceObj["DisplayName"].ToString());
Console.WriteLine("Process ID of service is " + serviceObj["ProcessId"].ToString());
// use processid to kill process with taskkill
ObjectGetOptions processObjGetOpt = new ObjectGetOptions();
ManagementPath processPath = new ManagementPath("Win32_Process");
ManagementClass processClass = new ManagementClass(scope, processPath, processObjGetOpt);
ManagementBaseObject processInParams = processClass.GetMethodParameters("Create");
processInParams["CommandLine"] = string.Format("cmd /c \"taskkill /f /pid {0}\"", serviceObj["ProcessId"].ToString());
ManagementBaseObject outParams = processClass.InvokeMethod("Create", processInParams, null);
Console.WriteLine("Return code for taskkill: " + outParams["returnValue"]);
int returnCode = System.Convert.ToInt32(outParams["returnValue"]);

User logged into remote machine

Is there a way to determine what all users are logged into remote machine, using WMI and C#
After little research I was able to figure it out, although not sure if this is the best way
public void GetCompDet(string ComputerName)
{
CurrentSystem = ComputerName;
ConnectionOptions options = new ConnectionOptions();
ManagementScope moScope = new ManagementScope(#"\\" + ComputerName + #"\root\cimv2");
try
{
moScope.Connect();
}
catch
{
return;
}
ObjectQuery query = new ObjectQuery("select * from Win32_Process where name='explorer.exe'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(moScope, query);
ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
ManagementOperationObserver mo = new ManagementOperationObserver();
mo.ObjectReady += new ObjectReadyEventHandler(mo_ObjectReady);
m.InvokeMethod(mo, "GetOwner", null);
}
}
void mo_ObjectReady(object sender, ObjectReadyEventArgs e)
{
ManagementObject m = sender as ManagementObject;
LoggedinUser.Enqueue(CurrentSystem + " - >" + e.NewObject.Properties["user"].Value.ToString());
Console.WriteLine(CurrentSystem + " - >" + e.NewObject.Properties["user"].Value.ToString());
}

query on Win32_NTLogEvent WHERE Logfile = 'Security' works only on remote machine

I've have a problem using the code below to retrieve data from the security log event of my local machine. I tested on various computers: the local machine is a windows xp sp3. The query has no error but it returns 0 record. For remote machines it works perfectly
Anyone can give me a solution?
This is the code:
using System;
using System.Management;
using System.Windows.Forms;
namespace WMISample
{
public class MyWMIQuery
{
public static void Main()
{
try
{
string[] arrComputers = {".","clientN"};
foreach (string strComputer in arrComputers)
{
Console.WriteLine("==========================================");
Console.WriteLine("Computer: " + strComputer);
Console.WriteLine("==========================================");
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(
"\\\\" + strComputer + "\\root\\CIMV2",
"SELECT * FROM Win32_NTLogEvent WHERE Logfile = 'Security'");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("-----------------------------------");
Console.WriteLine("Win32_NTLogEvent instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("RecordNumber: {0}", queryObj["RecordNumber"]);
Console.WriteLine("SourceName: {0}", queryObj["SourceName"]);
Console.WriteLine("TimeGenerated: {0}", queryObj["TimeGenerated"]);
}
}
}
catch(ManagementException err)
{
MessageBox.Show("An error occurred while querying for WMI data: " + err.Message);
}
}
}
}
I understood that using the impersonation level for the wmi query in vbs it works.
Set objWMI = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate,(Security)}!\\" _
& strComputer & "\root\cimv2")
Set colLoggedEvents = objWMI.ExecQuery _
("Select * from Win32_NTLogEvent Where Logfile = 'Security'" )
So I have to translate in c#.
Ok so I close this Question using my code.
the code is:
using System;
using System.Management;
namespace WMISample
{
public class MyWMIQuery
{
public static void Main()
{
try
{
ConnectionOptions oConn = new ConnectionOptions();
oConn.Impersonation = ImpersonationLevel.Impersonate;
oConn.EnablePrivileges = true;
string[] arrComputers = {".","clientN"};
foreach (string strComputer in arrComputers)
{
Console.WriteLine("==========================================");
Console.WriteLine("Computer: " + strComputer);
Console.WriteLine("==========================================");
ManagementObjectSearcher searcher = new ManagementObjectSearcher
(
new ManagementScope("\\\\" + strComputer + "\\root\\CIMV2", oConn),
new ObjectQuery( #"SELECT * FROM Win32_NTLogEvent WHERE Logfile = 'Security'")
);
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("-----------------------------------");
Console.WriteLine("Win32_NTLogEvent instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("RecordNumber: {0}", queryObj["RecordNumber"]);
Console.WriteLine("SourceName: {0}", queryObj["SourceName"]);
Console.WriteLine("TimeGenerated: {0}", queryObj["TimeGenerated"]);
}
}
}
catch(ManagementException err)
{
MessageBox.Show("An error occurred while querying for WMI data: " + err.Message);
}
}
}
}
try using the local computername instead of ".". so, instead of
string[] arrComputers = {".","clientN"};
you would have
string[] arrComputers = { Environment.GetEnvironmentVariable("computername"), "clientN" };

Categories

Resources