tiempo - stopwatch c#
¿Cómo determino el propietario de un proceso en C#? (7)
Estoy buscando un proceso con el nombre de "MyApp.exe" y quiero asegurarme de obtener el proceso que pertenece a un usuario en particular.
Uso el siguiente código para obtener una lista de los procesos:
Process[] processes = Process.GetProcessesByName("MyApp");
Esto me da una lista de procesos, pero no parece haber una forma en la clase Process para determinar a quién pertenece ese proceso. ¿Alguna idea sobre cómo puedo hacer esto?
Agregue una referencia a su proyecto:
System.Management
A continuación, agregue el siguiente método a su proyecto:
public string GetProcessOwner(int processId)
{
string MethodResult = null;
try
{
StringBuilder sb = new StringBuilder();
sb.Append(" SELECT ");
sb.Append(" * ");
sb.Append(" FROM ");
sb.Append(" WIN32_PROCESS");
sb.Append(" WHERE ");
sb.Append(" ProcessId = " + processId);
string Query = sb.ToString();
ManagementObjectCollection Processes = new ManagementObjectSearcher(Query).Get();
foreach (ManagementObject Process in Processes)
{
string[] Args = new string[] { "", "" };
int ReturnCode = Convert.ToInt32(Process.InvokeMethod("GetOwner", Args));
switch(ReturnCode)
{
case 0:
MethodResult = Args[1] + "//" + Args[0];
break;
default:
MethodResult = "None";
break;
}
}
}
catch //(Exception ex)
{
//ex.HandleException();
}
return MethodResult;
}
Luego agrega este método:
public DataTable GetProcessTable()
{
DataTable MethodResult = null;
try
{
List<Process> Processes = Process.GetProcesses().ToList<Process>();
DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns["Name"].ReadOnly = true;
dt.Columns.Add("Id", typeof(string));
dt.Columns["Id"].ReadOnly = true;
dt.Columns.Add("Owner", typeof(string));
dt.Columns["Owner"].ReadOnly = true;
foreach (Process p in Processes)
{
DataRow r = dt.NewRow();
bool Match = false;
r["Id"] = p.Id.ToString();
r["Name"] = p.ProcessName;
r["Owner"] = GetProcessOwner(p.Id);
dt.Rows.Add(r);
}
MethodResult = dt;
}
catch //(Exception ex)
{
//ex.HandleException();
}
return MethodResult;
}
Llamar a GetProcessTable () le proporciona una DataTable de todos los procesos en ejecución junto con su Id y Name, que es útil porque puede usarse como un parámetro Datasource de DataGridView.
Avíseme si necesita agregar más campos a la tabla.
Aquí está la versión de VB para los altavoces que no C #:
Function GetProcessOwner(ProcessName As String) As String
Dim query = "Select * from Win32_Process Where Name = """ + ProcessName + """"
Dim searcher = New ManagementObjectSearcher(query)
Dim processList = searcher.Get()
For Each obj As ManagementObject In processList
Dim argList As String() = {String.Empty, String.Empty}
Dim returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList))
If returnVal = 0 Then
'' return DOMAIN/user
Dim owner = argList(1) + "//" + argList(0)
Return owner
End If
Next
Return "NO OWNER"
End Function
Function GetProcessOwner(processId As Integer) As String
Dim query = "Select * From Win32_Process Where ProcessID = " & processId
Dim searcher = New ManagementObjectSearcher(query)
Dim processList = searcher.Get()
For Each obj As ManagementObject In processList
Dim argList As String() = {String.Empty, String.Empty}
Dim returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList))
If returnVal = 0 Then
'' return DOMAIN/user
Return argList(1) + "//" + argList(0)
End If
Next
Return "NO OWNER"
End Function
Como WMI no siempre es una forma rápida de recuperar información, aquí está la forma nativa de P / Invoke de hacerlo:
El valor de retorno es null
cuando no tiene éxito. Para obtener los nombres de los procesos que se ejecutan bajo el usuario del SISTEMA, debe ejecutar este código como administrador.
private static string GetProcessUser(Process process)
{
IntPtr processHandle = IntPtr.Zero;
try
{
OpenProcessToken(process.Handle, 8, out processHandle);
WindowsIdentity wi = new WindowsIdentity(processHandle);
string user = wi.Name;
return user.Contains(@"/") ? user.Substring(user.IndexOf(@"/") + 1) : user;
}
catch
{
return null;
}
finally
{
if (processHandle != IntPtr.Zero)
{
CloseHandle(processHandle);
}
}
}
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
Esta es la forma más fácil que he encontrado para hacerlo:
Process[] processes = Process.GetProcessesByName("MyApp");
foreach (Process process in processes)
{
string username = process.StartInfo.Environment["USERNAME"];
// do some stuff
}
Lamentablemente, no existe una forma .Net nativa de obtener el propietario del proceso.
Echa un vistazo a estos para encontrar una solución potencial:
Puede usar WMI para que el usuario sea dueño de un determinado proceso. Para usar WMI, necesita agregar una referencia a System.Management.dll
a su proyecto.
Por id de proceso:
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";
}
Por nombre del proceso (encuentra el primer proceso solamente, ajuste en consecuencia):
public string GetProcessOwner(string processName)
{
string query = "Select * from Win32_Process Where Name = /"" + processName + "/"";
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
string owner = argList[1] + "//" + argList[0];
return owner;
}
}
return "NO OWNER";
}
System.Security.Principal.WindowsIdentity.GetCurrent().Name