Here's how you use the new method:
//// // 'WindowsIdentity' Extension Method Demo: // Enumerate all running processes with their associated Windows Identity ////foreach (var p in Process.GetProcesses())
{ string processName; try {processName = p.WindowsIdentity().Name;
}
catch (Exception ex)
{ processName = ex.Message; // Probably "Access is denied"}
Console.WriteLine(p.ProcessName + " (" + processName + ")");
}
Here's the corresponding class:
//-----------------------------------------------------------------------// <copyright file="ProcessExtensions.cs" company="DockOfTheBay">// http://www.dotbay.be// </copyright>// <summary>Defines the ProcessExtensions class.</summary>//-----------------------------------------------------------------------namespace DockOfTheBay{ using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Principal;/// <summary>
/// Extension Methods for the System.Diagnostics.Process Class.
/// </summary>
public static class ProcessExtensions
{/// <summary>
/// Required to query an access token.
/// </summary>
private static uint TOKEN_QUERY = 0x0008;
/// <summary>
/// Returns the WindowsIdentity associated to a Process
/// </summary>
/// <param name="process">The Windows Process.</param>
/// <returns>The WindowsIdentity of the Process.</returns>
/// <remarks>Be prepared for 'Access Denied' Exceptions</remarks>
public static WindowsIdentity WindowsIdentity(this Process process)
{IntPtr ph = IntPtr.Zero;
WindowsIdentity wi = null;
try { OpenProcessToken(process.Handle, TOKEN_QUERY, out ph);wi = new WindowsIdentity(ph);
}
catch (Exception)
{ throw;}
finally {if (ph != IntPtr.Zero)
{CloseHandle(ph);
}
}
return wi;}
[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);
}
}

Great post, and what I was looking for, BUT, it needed the following to get it working for me:
ReplyDeleteI'm sure you can work out the tidyup and const definition code:-)
OpenProcessToken(process.Handle, TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY, out ph);
wi = new WindowsIdentity(DuplicateToken(ph, SecurityImpersonation, ref dupeTokenHandle)?dupeTokenHandle:ph);
Just to clarify, I was using your class like this:
ReplyDeleteusing (Process ownerProcess = Process.GetProcessById((int) info.ProcessId))
{
using (WindowsImpersonationContext impersonationContext = ownerProcess.WindowsIdentity().Impersonate())
{
// Do Access / ACL stuff
}
}