I am trying to invoke WTSEnumerateProcesses()
but am having some trouble converting type ProcessInfo
to WTS_PROCESS_INFO
.
This is the code I have so far:
ProcessInfo
class ProcessInfo
{
public int basePriority;
public int handleCount;
public int mainModuleId;
public long pageFileBytes;
public long pageFileBytesPeak;
public long poolNonpagedBytes;
public long poolPagedBytes;
public long privateBytes;
public int processId;
public string processName;
public int sessionId;
public ArrayList threadInfoList;
public long virtualBytes;
public long virtualBytesPeak;
public long workingSet;
public long workingSetPeak;
public ProcessInfo()
{
}
}
WTS_PROCESS_INFO
public struct WTS_PROCESS_INFO
{
public int SessionID;
public int ProcessID;
// This is spointer to a string...
public IntPtr ProcessName;
public IntPtr userSid;
}
WTSEnumerateProcesses()
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern bool WTSEnumerateProcesses(
IntPtr serverHandle, // Handle to a terminal server.
Int32 reserved, // must be 0
Int32 version, // must be 1
ref IntPtr ppProcessInfo, // pointer to array of WTS_PROCESS_INFO
ref Int32 pCount // pointer to number of processes
);
public static WTS_PROCESS_INFO[] WTSEnumerateProcesses()
{
IntPtr pProcessInfo = IntPtr.Zero;
int processCount = 0;
var hServer = OpenServer("XA7-06");
if (!WTSEnumerateProcesses(hServer, 0, 1, ref pProcessInfo, ref processCount))
return null;
IntPtr pMemory = pProcessInfo;
WTS_PROCESS_INFO[] processInfos = new WTS_PROCESS_INFO[processCount];
for (int i = 0; i < processCount; i++)
{
processInfos[i] = (ProcessInfo)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));
pProcessInfo = (IntPtr)((int)pProcessInfo + Marshal.SizeOf(processInfos[i]));
}
WTSFreeMemory(pMemory);
return processInfos;
}
My issue is near the end of the WTSEnumerateProcesses()
method on this line:
processInfos[i] = (ProcessInfo)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));
Where I think I may have missed out a step in defining the relationship between WTS_PROCESS_INFO
and ProcessInfo
, but I am not sure how to do this. Is anyone able to point me in the right direction?
This is the error I am seeing:
// Cannot implicitly convert type 'ProcessInfo' to 'WTS_PROCESS_INFO'
Your ProcessInfo
type is unrelated to WTS_PROCESS_INFO
. So this line:
processInfos[i] = (ProcessInfo)Marshal.PtrToStructure(pProcessInfo,
typeof(WTS_PROCESS_INFO));
actually contains two errors. The compiler picks up one. Specifically that processInfos[i]
is of type WTS_PROCESS_INFO
and is not assignment compatible with ProcessInfo
. The other mistake is a little more subtle. Your cast of the value returned by Marshal.PtrToStructure()
to the type ProcessInfo
is wrong. The value returned by Marshal.PtrToStructure()
is a boxed WTS_PROCESS_INFO
. So that line of code should be:
processInfos[i] = (WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo,
typeof(WTS_PROCESS_INFO));
Your pointer arithmetic can fail in a 64 bit process. If you are using a recent version of .net you can perform arithmetic directly on IntPtr:
pProcessInfo += Marshal.SizeOf(processInfos[i]);
Or if you target older .net versions you should perform the arithmetic in a 64 bit context by casting to ulong
rather than int
.
As for your ProcessInfo
type, I think that's just a mis-think on your part. There appears to be no use for that type here.
If I were you I would force the use of the Unicode version of WTSEnumerateProcessesW
, for instance like this:
[DllImport("wtsapi32.dll", EntryPoint = "WTSEnumerateProcessesW", SetLastError = true)]
static extern bool WTSEnumerateProcesses(
....
);
To read the process name as a string, pass the pointer returned in the WTS_PROCESS_INFO
struct to Marshal.PtrToStringUni
.