Je suis à la recherche d'un processus portant le nom "MyApp.exe" et je souhaite m'assurer d'obtenir le processus appartenant à un utilisateur particulier.
J'utilise le code suivant pour obtenir une liste des processus:
Process[] processes = Process.GetProcessesByName("MyApp");
Cela me donne une liste de processus, mais il ne semble pas y avoir de moyen dans la classe Process de déterminer à qui appartient ce processus. Des idées sur comment je peux faire ça?
Vous pouvez utiliser WMI pour que l'utilisateur possède un certain processus. Pour utiliser WMI, vous devez ajouter une référence au System.Management.dll
à votre projet.
Par identifiant de processus:
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";
}
Par nom de processus (recherche uniquement le premier processus, ajustez en conséquence):
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";
}
Comme WMI n’est pas toujours un moyen rapide de récupérer des informations, voici le moyen natif de le faire/invoquer:
La valeur de retour est null
en cas d'échec. Pour obtenir les noms des processus en cours d'exécution sous l'utilisateur SYSTEM, vous devez exécuter ce code en tant qu'administrateur.
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);
Voici la version VB des haut-parleurs autres que 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
Malheureusement, il n’existe aucun moyen .Net natif d’obtenir le propriétaire du processus.
Jetez un coup d'oeil à ceux-ci pour une solution potentielle:
Ajoutez une référence à votre projet:
System.Management
Ajoutez ensuite la méthode suivante à votre projet:
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;
}
Puis ajoutez cette méthode:
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;
}
L'appel de GetProcessTable () vous donne un DataTable de tous les processus en cours d'exécution avec leur ID et leur nom, ce qui est pratique car il peut être utilisé comme paramètre Datasource de DataGridView.
Faites-moi savoir si vous avez besoin d'ajouter d'autres champs à la table.
System.Security.Principal.WindowsIdentity.GetCurrent().Name