2

Im trying to get a list of process ID and File names however its giving me a lot of issues...

Heres the console output:

success=True
bytesCopied=344
Name '<unknown>' PID '0'
Name '<unknown>' PID '4'
Name '<unknown>' PID '308'
Name '<unknown>' PID '440'
Name '<unknown>' PID '488'
Name '<unknown>' PID '512'
Name '<unknown>' PID '548'
Name '<unknown>' PID '572'
Name '<unknown>' PID '580'
Name '<unknown>' PID '644'
Name '<unknown>' PID '732'
Name '<unknown>' PID '792'
Name '<unknown>' PID '816'
Name '<unknown>' PID '860'
Name '<unknown>' PID '940'
Name '<unknown>' PID '992'
Name '<unknown>' PID '264'
Name '<unknown>' PID '1160'
Name '<unknown>' PID '1220'
Name '<unknown>' PID '1292'
Name '<unknown>' PID '1424'
Name '<unknown>' PID '1452'
Name '<unknown>' PID '1556'
Name '<unknown>' PID '1596'
Name '<unknown>' PID '2044'
Name '<unknown>' PID '1504'
Name '<unknown>' PID '1132'
Name '<unknown>' PID '1912'
Name '<unknown>' PID '1972'
Name '<unknown>' PID '2084'
Name '<unknown>' PID '2124'
Name '<unknown>' PID '2560'
Name '<unknown>' PID '2796'
Name '<unknown>' PID '2808'
Name '<unknown>' PID '3000'
Name '<unknown>' PID '2116'
Name 'DTAgent.exe' PID '2228'
Name 'ISUSPM.exe' PID '2644'
Name 'DTShellHlp.exe' PID '2652'
Name 'Dropbox.exe' PID '2664'
Name 'acrotray.exe' PID '3124'
Name 'RIMBBLaunchAgent.exe' PID '3180'
Name 'vmware-tray.exe' PID '3188'
Name '<unknown>' PID '3520'
Name '<unknown>' PID '3592'
Name '<unknown>' PID '3780'
Name '<unknown>' PID '3964'
Name 'TrueCrypt.exe' PID '3392'
Name '<unknown>' PID '3800'
Name '<unknown>' PID '4680'
Name '<unknown>' PID '680'
Name 'FileZilla server.exe' PID '2240'
Name 'mysqld.exe' PID '4160'
Name 'uTorrent.exe' PID '7796'
Name 'svchost.exe' PID '44412'
Name '<unknown>' PID '10624'
Name '<unknown>' PID '35644'
Name 'httpd.exe' PID '44260'
Name 'httpd.exe' PID '40556'
Name '<unknown>' PID '11488'
Name 'RIMDeviceManager.exe' PID '42832'
Name 'BbDevMgr.exe' PID '45108'
Name '<unknown>' PID '31208'
Name '<unknown>' PID '34812'
Name 'trillian.exe' PID '61420'
Name 'Microsoft Visual C++ 6.0.exe' PID '52212'
Name '<unknown>' PID '33752'
Name '<unknown>' PID '47564'
Name '<unknown>' PID '39952'
Name 'mysqld-opt.exe' PID '61884'
Name 'winamp.exe' PID '42008'
Name 'opera.exe' PID '4560'
Name 'PowerGREP.exe' PID '12860'
Name 'PowerGREP.exe' PID '13280'
Name 'GOLD Parser Builder.exe' PID '32368'
Name 'Server.exe' PID '16396'
Name '<unknown>' PID '50976'
Name 'xampp-control.exe' PID '56084'
Name 'notepad++.exe' PID '27932'
Name 'WinAMP2.exe' PID '23336'
Name '<unknown>' PID '8044'
Name 'devenv.exe' PID '61172'
Name '<unknown>' PID '14780'
Name '<unknown>' PID '52180'
Name 'Sputnik.vshost.exe' PID '3672'
Name '<unknown>' PID '39480'

Here the console output i WANT it to make.... (This is using my C++ code)

Name '[System Process]' PID '0'
Name 'System' PID '4'
Name 'smss.exe' PID '308'
Name 'csrss.exe' PID '440'
Name 'wininit.exe' PID '488'
Name 'csrss.exe' PID '512'
Name 'services.exe' PID '548'
Name 'lsass.exe' PID '572'
Name 'lsm.exe' PID '580'
Name 'winlogon.exe' PID '644'
Name 'svchost.exe' PID '732'
Name 'nvvsvc.exe' PID '792'
Name 'nvSCPAPISvr.exe' PID '816'
Name 'svchost.exe' PID '860'
Name 'svchost.exe' PID '940'
Name 'svchost.exe' PID '992'
Name 'svchost.exe' PID '264'
Name 'svchost.exe' PID '1160'
Name 'qmserv.exe' PID '1220'
Name 'svchost.exe' PID '1292'
Name 'spoolsv.exe' PID '1424'
Name 'svchost.exe' PID '1452'
Name 'mDNSResponder.exe' PID '1556'
Name 'svchost.exe' PID '1596'
Name 'svchost.exe' PID '2044'
Name 'vmware-usbarbitrator64.exe' PID '1504'
Name 'vmnat.exe' PID '1132'
Name 'vmware-authd.exe' PID '1912'
Name 'vmnetdhcp.exe' PID '1972'
Name 'vmware-hostd.exe' PID '2084'
Name 'WmiPrvSE.exe' PID '2124'
Name 'svchost.exe' PID '2560'
Name 'nvxdsync.exe' PID '2796'
Name 'nvvsvc.exe' PID '2808'
Name 'taskhost.exe' PID '3000'
Name 'dwm.exe' PID '2116'
Name 'DTAgent.exe' PID '2228'
Name 'ISUSPM.exe' PID '2644'
Name 'DTShellHlp.exe' PID '2652'
Name 'Dropbox.exe' PID '2664'
Name 'acrotray.exe' PID '3124'
Name 'RIMBBLaunchAgent.exe' PID '3180'
Name 'vmware-tray.exe' PID '3188'
Name 'nvtray.exe' PID '3520'
Name 'SearchIndexer.exe' PID '3592'
Name 'FNPLicensingService.exe' PID '3780'
Name 'wmpnetwk.exe' PID '3964'
Name 'TrueCrypt.exe' PID '3392'
Name 'svchost.exe' PID '3800'
Name 'daemonu.exe' PID '4680'
Name 'svchost.exe' PID '680'
Name 'FileZilla Server.exe' PID '2240'
Name 'mysqld.exe' PID '4160'
Name 'uTorrent.exe' PID '7796'
Name 'svchost.exe' PID '44412'
Name 'iexplore.exe' PID '10624'
Name 'iexplore.exe' PID '35644'
Name 'httpd.exe' PID '44260'
Name 'httpd.exe' PID '40556'
Name 'svchost.exe' PID '11488'
Name 'RIMDeviceManager.exe' PID '42832'
Name 'BbDevMgr.exe' PID '45108'
Name 'TeamViewer_Service.exe' PID '31208'
Name 'taskhost.exe' PID '34812'
Name 'trillian.exe' PID '61420'
Name 'Microsoft Visual C++ 6.0.exe' PID '52212'
Name 'explorer.exe' PID '33752'
Name 'VisualSVNServer.exe' PID '47564'
Name 'VisualSVNServer.exe' PID '39952'
Name 'mysqld-opt.exe' PID '61884'
Name 'winamp.exe' PID '42008'
Name 'opera.exe' PID '4560'
Name 'PowerGREP.exe' PID '12860'
Name 'PowerGREP.exe' PID '13280'
Name 'GOLD Parser Builder.exe' PID '32368'
Name 'Server.exe' PID '16396'
Name 'conhost.exe' PID '50976'
Name 'xampp-control.exe' PID '56084'
Name 'notepad++.exe' PID '27932'
Name 'WinAMP2.exe' PID '23336'
Name 'CryptoObfuscator.exe' PID '8044'
Name 'devenv.exe' PID '61172'
Name 'hh.exe' PID '14780'
Name 'Sputnik.vshost.exe' PID '62828'
Name 'conhost.exe' PID '37164'

As you can see a lot of PIDS are actually missing the file name and i cant figure out why for the most part i also copied working code from C++ that didnt work either i also tired the code on pinvoke and that didnt do it either.

Heres the c# code

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace testie
{
    public class EnumerateProcesses
    {
        #region APIS
        [DllImport("psapi")]
        private static extern bool EnumProcesses([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] IntPtr[] processIds,UInt32 arraySizeBytes,[MarshalAs(UnmanagedType.U4)] out UInt32 bytesCopied);

        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, IntPtr dwProcessId);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseHandle(IntPtr hObject);

        [DllImport("psapi.dll")]
        static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] int nSize);

        [DllImport("psapi.dll", SetLastError = true)]
        public static extern bool EnumProcessModules(IntPtr hProcess,
        [Out] IntPtr lphModule,
        uint cb,
        [MarshalAs(UnmanagedType.U4)] out uint lpcbNeeded);

        [DllImport("psapi.dll")]
        static extern uint GetModuleBaseName(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] int nSize);
        #endregion
        #region ENUMS

        [Flags]
        enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VMOperation = 0x00000008,
            VMRead = 0x00000010,
            VMWrite = 0x00000020,
            DupHandle = 0x00000040,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            Synchronize = 0x00100000
        }
        #endregion

        static string PrintProcessName(IntPtr processID)
        {
            string sName = "";
            bool bFound = false;
            IntPtr hProcess = OpenProcess(ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VMRead, false, processID);
            if (hProcess != IntPtr.Zero)
            {
                StringBuilder szProcessName = new StringBuilder(260);
                IntPtr hMod = IntPtr.Zero;
                uint cbNeeded = 0;
                EnumProcessModules(hProcess, hMod, (uint)Marshal.SizeOf(typeof(IntPtr)), out cbNeeded);
                if (GetModuleBaseName(hProcess, hMod, szProcessName, szProcessName.Capacity) > 0)
                {
                    sName = szProcessName.ToString();
                    bFound = true;
                }

                // Close the process handle
                CloseHandle(hProcess);
            }
            if (!bFound)
            {
                sName = "<unknown>";
            }
            return sName;
        }
        public static void Testy()
        {
            UInt32 arraySize = 9000;
            UInt32 arrayBytesSize = arraySize * sizeof(UInt32);
            IntPtr[] processIds = new IntPtr[arraySize];
            UInt32 bytesCopied;

            bool success = EnumProcesses(processIds, arrayBytesSize, out bytesCopied);

            Console.WriteLine("success={0}", success);
            Console.WriteLine("bytesCopied={0}", bytesCopied);

            if (!success)
            {
                Console.WriteLine("Boo!");
                return;
            }
            if (0 == bytesCopied)
            {
                Console.WriteLine("Nobody home!");
                return;
            }

            UInt32 numIdsCopied = bytesCopied >> 2; ;

            if (0 != (bytesCopied & 3))
            {
                UInt32 partialDwordBytes = bytesCopied & 3;

                Console.WriteLine("EnumProcesses copied {0} and {1}/4th DWORDS...  Please ask it for the other {2}/4th DWORD",
                    numIdsCopied, partialDwordBytes, 4 - partialDwordBytes);
                return;
            }

            for (UInt32 index = 0; index < numIdsCopied; index++)
            {
                string sName = PrintProcessName(processIds[index]);
                IntPtr PID = processIds[index];
                Console.WriteLine("Name '" + sName + "' PID '" + PID + "'");
            }
        }
    }
}

As you can see by calling Testy function it will list all processes on system but it will fail to get all their names... Does anybody have a solution to this? Thanks :)

And for the record i did ALSO try getting the modules as an array that too produces the exact same result.

user1057061
  • 61
  • 1
  • 4
  • oh all the processes with are returning a hProcess of 0 on OpenProcess... Maybe that helps to narrow it down? -- Also for the record im aware of Process.List in c# however i cant get it to give .exe etc on the file names and without the FULL filename its useless to me..... – user1057061 Dec 07 '11 at 17:28
  • 1
    I'll guess run your code while elevated to administrator you may see the process but don't have the right to open them or ask them their name. – Julien Roncaglia Dec 07 '11 at 17:33
  • Nice idea VirtualBlackFox however i already tried that... No effect also the C++ program does not require admin rights to work and my code is almost a 1:1 copy of the C++ one so im really not sure what to do with it lol there must be a way to make it work ;/ – user1057061 Dec 07 '11 at 17:39

5 Answers5

2

Well thanks for trying guys however i decided to go with "CreateToolhelp32Snapshot" it seems to work with my app in 32 and 64 bit mode and its accurate in both and doesnt require admin rights to use and its fast and it gives file name and pid.

So i guess it will do.

user1057061
  • 61
  • 1
  • 4
1

You could try this using the System.Diagnostics namespace

    foreach (Process theProcess in Process.GetProcesses())
    {
        StringBuilder sb = new StringBuilder();
        try
        {
            sb.AppendLine(theProcess.Modules[0].FileName);
        }
        catch { }
        Console.WriteLine("Process: {0}  ID:  {1}", sb, theProcess.Id);
    }

This will not show the System or Idle Process executable names as they do not load modules.

http://msdn.microsoft.com/en-us/library/system.diagnostics.process.modules.aspx

Bueller
  • 2,336
  • 17
  • 11
  • 2
    that works but the try catch is VERY VERY slow takes around 10 seconds to complete the function any ideas to fix that? – user1057061 Dec 08 '11 at 01:06
0

It may also be ... that after toy have called EnumProcesses and built your list into an array, that by the time you call PrintProcesses the REAL (i.e. original) list of processes on the machine has changed and that your array index (into what you THINK is still 'the' list) has changed (based on your array index). Quantum mechanics springs to mind - by the time you've observed it, its changed. Just a thought -

0

Using System.Diagnostics, I tried this:

foreach(Process theprocess in Process.GetProcesses())
{
            Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}

And got this result:

Process: AgentMon ID: 2948
Process: OUTLOOK ID: 3144
Process: ctfmon ID: 3136
...

Now, I am an admin on a Win XP machine... YMMV, as it were.

I know you had stated to use PSAPI, but is there some reason you have to use that and not just regular managed C#?

pennyrave
  • 750
  • 2
  • 18
  • 32
  • Yea "foreach(Process theprocess in Process.GetProcesses())" does not tell you the .exe or .bat .dat whateva name the file is and it does not give u the directory of it, I require the full path name with the PID. I already stated above this method didnt work for me since it doesnt produce the file name and directory. – user1057061 Dec 07 '11 at 18:20
0
  1. You should really try try this using the System.Diagnostics namespace if you want the full path it's possible :

    process.MainModule.FileName
    
  2. For it to work on other users processes you need to be Admin (A true admin so either no UAC or UAC elevated) as you will need the right to enable SeDebugPrivilege. From C# :

    try { Process.EnterDebugMode(); } catch(Win32Exception) { /* Not admin */ }
    

    See the documentation on MSDN. But it seem that at least on C#4.0 it's now done automatically as long as you have the right to do it.

  3. EnumProcessModules won't give you 64 bits process from a 32 bit one or 32-bit ones from a 64-bit process. For it you either need to create 2 processes one in each architecture on from a 64-bit process call EnumProcessModulesEx. (See How to enum modules in a 64bit process from a 32bit WOW process on SO)
    System.Diagnostics already does that for you
  4. Anyway GetModuleBaseName won't give you the full path of the program its GetModuleFileName (nitpicking)

There is another way using QueryFullProcessImageName (Available since Vista) that may work without the right to OpenProcess and so without being an administrator.

Community
  • 1
  • 1
Julien Roncaglia
  • 17,397
  • 4
  • 57
  • 75
  • Thats good but how do i get the modulename without admin rights? – user1057061 Dec 08 '11 at 00:56
  • You can't for other users processes that's a security feature, managing to bypass it would mean that you defeat the windows security system and would be fixed in the next microsoft patch anyway... – Julien Roncaglia Dec 08 '11 at 00:58
  • See for example the Task Manager on Win7 where only the current user processes are listed and to display all other there is a button protected by UAC (That doesn't generate a prompt on the default medium security but generate one in high security setting) – Julien Roncaglia Dec 08 '11 at 01:00
  • Well if its not possible to get all processes how do i get the ones im capable of seeing? For example at the moment i have to use a try/catch or else it will crash on getting module name (not enough privilages) but the try catch is slowing the code down MASSIVELY is there a way to check if im capable of getting the module name? – user1057061 Dec 08 '11 at 01:02
  • One thing to the point no.3: `System.Diagnostics` doesn't do that. If you have 64 bit process it will give you process module, ntdll and 3 wow64 modules. It's so wrong even Powershell won't list modules for 32 bit processes with Get-Process. – Dominik Szymański Sep 27 '20 at 19:36