Bjorn Abelli said:
"Willy Denoyette [MVP]" ...
I'd be very grateful for that.
The OS is Windows XP (both Home and Pro).
// Bjorn A
Bjorn,
Following two console samples:
- [1] uses the WIN32 API OpenProcessToken, but has problems to retrieve the
process identity for some processes (due to a lack of privileges).
[1]
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security.Principal;
using System.Diagnostics;
using System.Security;
// Problem: proc.Handle property returns Access denied for 'idle' process
and,
// Cannot OpenProcessToken() for NT AUTHORITY\NETWORK SERVICE and NT
AUTHORITY\LOCAL SYSTEM
// Better use - WTSEnumerateProcesses on XP and higher
//
using HANDLE = System.IntPtr;
class IdentUser {
[DllImport("advapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern int OpenProcessToken(
HANDLE ProcessHandle, // handle to process
int DesiredAccess, // desired access to process
ref IntPtr TokenHandle // handle to open access token
);
[DllImport("kernel32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool CloseHandle(HANDLE handle);
public const int TOKEN_QUERY = 0X00000008;
public static void Main() {
Process[] _process = Process.GetProcesses();
foreach(Process proc in _process)
{
try {
Console.WriteLine("Process Name :{0} \tProcess ID : {1} ",
proc.ProcessName, proc.Id);
DumpPrincipalName(proc.Handle);
Console.WriteLine("--------------------------------------------------");
}
catch(Exception ex)
{Console.WriteLine("Exception: {0}", ex.Message);}
}
}
static void DumpPrincipalName(HANDLE processHandle)
{
int access = TOKEN_QUERY;
HANDLE tokenHandle = IntPtr.Zero;
if ( 0 != OpenProcessToken( processHandle, access, ref tokenHandle ) )
{
WindowsIdentity wi = new WindowsIdentity(tokenHandle);
Console.WriteLine(wi.Name);
CloseHandle(tokenHandle); // Close process token
}
else
Console.WriteLine("Error OpenProcessToken:
{0}",Marshal.GetLastWin32Error());
}
}
- [2] uses the WTS API's which has not the same prblems as [1], but requires
XP or higher.
[2]
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
// Using Wtsapi32 (available on Windows.NET and XP)
// Get Process information using Terminal server API's
// Requirements: TCB privilege???
using HANDLE = System.IntPtr;
class ProcIdent {
[DllImport("wtsapi32", CharSet=CharSet.Auto, SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool WTSEnumerateProcesses (
HANDLE ProcessHandle, // handle to process (from WTSOpenServer)
int Reserved, // dmust be 0
uint Version, // must be 1
ref IntPtr ppProcessInfo, // pointer to pointer to Processinfo
ref uint pCount // no. of processes
);
[DllImport("wtsapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern IntPtr WTSOpenServer (
string ServerName // Server name (NETBIOS)
);
[DllImport("wtsapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern void WTSCloseServer (
HANDLE hServer // Handle obtained by WTSOpenServer
);
[DllImport("wtsapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern void WTSFreeMemory (
IntPtr pMemory );
[StructLayout(LayoutKind.Sequential)]
struct WTSProcessInfo {
internal uint SessionId;
internal uint ProcessId;
[MarshalAs(UnmanagedType.LPTStr)] internal string pProcessName;
internal IntPtr pUserSid;
}
[DllImport("advapi32", CharSet=CharSet.Auto)]
static extern bool ConvertSidToStringSid(
IntPtr pSID,
[In,Out,MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);
[DllImport("advapi32", CharSet=CharSet.Auto, SetLastError=true)]
static extern bool LookupAccountSid
(
string lpSystemName, // name of local or remote computer
IntPtr pSid, // security identifier
StringBuilder Account, // account name buffer
ref int cbName, // size of account name buffer
StringBuilder DomainName, // domain name
ref int cbDomainName, // size of domain name buffer
ref int peUse // SID type
);
const int ERROR_NO_MORE_ITEMS = 259;
public static void Main() {
HANDLE hServer = IntPtr.Zero;
IntPtr pInfo = IntPtr.Zero;
IntPtr pInfoSave = IntPtr.Zero;
WTSProcessInfo WTSpi; // Reference to ProcessInfo struct
uint count = 0;
int iPtr = 0;
try {
hServer = WTSOpenServer(System.Environment.MachineName);
if(hServer == IntPtr.Zero)
Console.WriteLine(Marshal.GetLastWin32Error());
if (WTSEnumerateProcesses(hServer, 0, 1, ref pInfo, ref count))
{
pInfoSave = pInfo;
Console.WriteLine("Number of processes :{0}", count);
for(int n = 0; n < count; n++) {
WTSpi = (WTSProcessInfo) Marshal.PtrToStructure(pInfo,
typeof(WTSProcessInfo) );
iPtr = (int)(pInfo) + Marshal.SizeOf(WTSpi);
pInfo = (IntPtr)(iPtr);
if(WTSpi.ProcessId != 0)
Console.WriteLine(WTSpi.pProcessName + "\t" + WTSpi.ProcessId + "\t" +
DumpAccountFromSid(WTSpi.pUserSid));
else
Console.WriteLine("Idle pseudo proc");
}
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
// Free memory used by WTSEnumerateProcesses
WTSFreeMemory(pInfoSave);
// Close server handle
WTSCloseServer(hServer);
}
}
static string DumpAccountFromSid(IntPtr SID)
{
int cchAccount = 0;
int cchDomain = 0;
int snu = 0 ;
StringBuilder sb = new StringBuilder();
// Caller allocated buffer
StringBuilder Account= null;
StringBuilder Domain = null;
// Lookup account name on local system
// First call to get required buffer sizes
bool ret = LookupAccountSid(null, SID, Account, ref cchAccount, Domain,
ref cchDomain, ref snu);
if ( ret == true )
if ( Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS )
return "Error";
Account = new StringBuilder( cchAccount );
Domain = new StringBuilder( cchDomain );
ret = LookupAccountSid(null, SID, Account, ref cchAccount, Domain, ref
cchDomain, ref snu);
if (ret)
{
sb.Append(Domain);
sb.Append(@"\");
sb.Append(Account);
}
else
sb.Append("Win32 Error: " + Marshal.GetLastWin32Error());
return sb.ToString();
}
}
Hope this helps.
Willy.