private static void GetProcessInfos(TerminalServer terminalServer)
        {
            try
            {
                IntPtr pProcessInfo            = IntPtr.Zero;
                int    processCount            = 0;
                IntPtr useProcessesExStructure = new IntPtr(1);

                if (WTSEnumerateProcessesExW(terminalServer.ServerPointer, ref useProcessesExStructure, WTS_ANY_SESSION, ref pProcessInfo, ref processCount))
                {
                    const int NO_ERROR = 0;
                    const int ERROR_INSUFFICIENT_BUFFER = 122;

                    WTS_PROCESS_INFO_EX[] processInfos = new WTS_PROCESS_INFO_EX[processCount];

                    for (int i = 0; i < processCount; i++)
                    {
                        processInfos[i] = (WTS_PROCESS_INFO_EX)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO_EX));

                        SessionProcess p = new SessionProcess
                        {
                            SessionID          = processInfos[i].SessionID,
                            ProcessID          = processInfos[i].ProcessID,
                            ProcessName        = processInfos[i].ProcessName,
                            NumberOfThreads    = processInfos[i].NumberOfThreads,
                            HandleCount        = processInfos[i].HandleCount,
                            PagefileUsage      = (processInfos[i].PagefileUsage / 1024.0 / 1024.0).ToString("##0.## MB"),
                            PeakPagefileUsage  = (processInfos[i].PeakPagefileUsage / 1024.0 / 1024.0).ToString("##0.## MB"),
                            WorkingSetSize     = (processInfos[i].WorkingSetSize / 1024.0 / 1024.0).ToString("##0.## MB"),
                            PeakWorkingSetSize = (processInfos[i].PeakWorkingSetSize / 1024.0 / 1024.0).ToString("##0.## MB"),
                            KernelTime         = processInfos[i].KernelTime,
                            UserTime           = processInfos[i].UserTime
                        };

                        if (processInfos[i].UserSid != IntPtr.Zero)
                        {
                            byte[] Sid = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                            Marshal.Copy(processInfos[i].UserSid, Sid, 0, 14);
                            StringBuilder name = new StringBuilder();

                            uint          cchName = (uint)name.Capacity;
                            SID_NAME_USE  sidUse;
                            StringBuilder referencedDomainName = new StringBuilder();

                            uint cchReferencedDomainName = (uint)referencedDomainName.Capacity;

                            if (LookupAccountSid(terminalServer.ServerName, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
                            {
                                int err = Marshal.GetLastWin32Error();

                                if (err == ERROR_INSUFFICIENT_BUFFER)
                                {
                                    name.EnsureCapacity((int)cchName);
                                    referencedDomainName.EnsureCapacity((int)cchReferencedDomainName);

                                    err = NO_ERROR;

                                    if (!LookupAccountSid(null, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
                                    {
                                        err = Marshal.GetLastWin32Error();
                                    }
                                }

                                p.Sid  = sidUse.ToString();
                                p.User = name.ToString();
                            }
                        }

                        terminalServer.Sessions.FirstOrDefault(s => s.SessionId == p.SessionID).Processes.Add(p);
                        pProcessInfo = (IntPtr)((int)pProcessInfo + Marshal.SizeOf(processInfos[i]));
                    }
                }

                if (pProcessInfo != IntPtr.Zero)
                {
                    WTSFreeMemory(pProcessInfo);
                }
            }
            catch (Exception ex)
            {
                Log.Info("Error enumerating remote processes for RDP sessions.", ex);
                terminalServer.Errors.Add(ex.Message + "\r\n" + Marshal.GetLastWin32Error());
            }
        }
        private static void GetProcessInfos(TerminalServer terminalServer)
        {
            try
            {
               	IntPtr pProcessInfo = IntPtr.Zero;
                int processCount = 0;
                IntPtr useProcessesExStructure = new IntPtr(1);

                if (WTSEnumerateProcessesEx(terminalServer.ServerPointer, ref useProcessesExStructure, WTS_ANY_SESSION, ref pProcessInfo, ref processCount))
                {
                    const int NO_ERROR = 0;
                    const int ERROR_INSUFFICIENT_BUFFER = 122;

                    WTS_PROCESS_INFO_EX[] processInfos = new WTS_PROCESS_INFO_EX[processCount];

                    for (int i = 0; i < processCount; i++)
                    {
                        processInfos[i] = (WTS_PROCESS_INFO_EX) Marshal.PtrToStructure(pProcessInfo, typeof (WTS_PROCESS_INFO_EX));

                        SessionProcess p = new SessionProcess
                        {
                           SessionID = processInfos[i].SessionID,
                           ProcessID = processInfos[i].ProcessID,
                           ProcessName = Marshal.PtrToStringAnsi(processInfos[i].ProcessName),
                           NumberOfThreads = processInfos[i].NumberOfThreads,
                           HandleCount = processInfos[i].HandleCount,
                           PagefileUsage = processInfos[i].PagefileUsage,
                           PeakPagefileUsage = processInfos[i].PeakPagefileUsage,
                           WorkingSetSize = processInfos[i].WorkingSetSize,
                           PeakWorkingSetSize = processInfos[i].PeakWorkingSetSize,
                           KernelTime = processInfos[i].KernelTime,
                           UserTime = processInfos[i].UserTime
                        };

                        if (processInfos[i].UserSid != IntPtr.Zero)
                        {
                            byte[] Sid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
                            Marshal.Copy(processInfos[i].UserSid, Sid, 0, 14);
                            StringBuilder name = new StringBuilder();

                            uint cchName = (uint) name.Capacity;
                            SID_NAME_USE sidUse;
                            StringBuilder referencedDomainName = new StringBuilder();

                            uint cchReferencedDomainName = (uint) referencedDomainName.Capacity;

                            if (LookupAccountSid(terminalServer.ServerName, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
                            {
                                int err = Marshal.GetLastWin32Error();

                                if (err == ERROR_INSUFFICIENT_BUFFER)
                                {
                                    name.EnsureCapacity((int) cchName);
                                    referencedDomainName.EnsureCapacity((int) cchReferencedDomainName);

                                    err = NO_ERROR;

                                    if (!LookupAccountSid(null, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
                                        err = Marshal.GetLastWin32Error();
                                }

                                p.Sid = sidUse.ToString();
                                p.User = name.ToString();
                            }
                        }

                        terminalServer.Sessions.FirstOrDefault(s => s.SessionId == p.SessionID).Processes.Add(p);
                        pProcessInfo = (IntPtr) ((int) pProcessInfo + Marshal.SizeOf(processInfos[i]));
                    }
                }

                if (pProcessInfo != IntPtr.Zero)
                    WTSFreeMemory(pProcessInfo);
            }
            catch (Exception ex)
            {
                Log.Info("Error enumerating remote processes for RDP sessions.", ex);
                terminalServer.Errors.Add(ex.Message + "\r\n" + Marshal.GetLastWin32Error());
            }
        }