×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Jobs

How to get the command-line of all running processes?
2

How to get the command-line of all running processes?

How to get the command-line of all running processes?

(OP)
I want to see the full path of every running process on my system.  Task Manager shows, eg.

delph32.exe
firefox.exe
svchost.exe
svchost.exe

but I want to see where those processes were executed from, eg.

c:\program files\borland\delphi6\bin\delphi32.exe
c:\program files\mozilla firefox\firefox.exe
C:\WINDOWS\System32\svchost.exe -k netsvcs
C:\WINDOWS\system32\svchost.exe -k LocalService

I've gotten started with this code snippet that shows the first bare list:

CODE

uses TLHelp32;
var
  MyHandle: THandle;
  Struct: TProcessEntry32;
begin
  Memo1.Clear;
  try
    MyHandle:=CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
    Struct.dwSize:=Sizeof(TProcessEntry32);
    if Process32First(MyHandle, Struct) then
      Memo1.Lines.Add(Struct.szExeFile);
    while Process32Next(MyHandle, Struct) do
      Memo1.Lines.Add(Struct.szExeFile);
  except
    ShowMessage('Error showing process list');
  end;
 

But Google isn't helping me out getting any further.  Help please?

RE: How to get the command-line of all running processes?

Yep.  That seems to be the way to go, along with some selective filtering.

CODE

{$APPTYPE CONSOLE}
program procbrowse; uses Windows, TLHelp32;

// be careful with this.  In Windows 7, it shows up in kernel32.dll, so you might want to code to check for this and load dynamically
  function GetModuleFileNameEx(inProcess: THandle; inModule: THandle;
        Filename: PChar; size: DWord): DWord; stdcall;
        external 'psapi.dll' name 'GetModuleFileNameExA';

  function GetMFEx(inmod: THandle): string;
    var
      hProcess: THandle;
      ModuleName: array [0..300] of Char;
    begin
      hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
                  False, inmod);
      if (hProcess <> 0) then
        begin
          GetModuleFilenameEx(hProcess, 0, ModuleName, SizeOf(ModuleName));
          CloseHandle(hProcess);
          Result := ModuleName;
        end;
    end;

  var
    MyHandle: THandle;
    Struct: TProcessEntry32;
    pathstr: string;
  begin
    try
      MyHandle:=CreateToolHelp32SnapShot(TH32CS_SNAPProcess, 0);
      Struct.dwSize:=Sizeof(TProcessEntry32);
      if Process32First(MyHandle, Struct) then
        begin
          pathstr := GetMFEx(Struct.Th32ProcessID);
          writeln(pathstr);
        end;
      while Process32Next(MyHandle, Struct) do
        begin
          pathstr := GetMFEx(Struct.Th32ProcessID);
          writeln(pathstr);
        end;
    except
      writeln('Error showing process list');
    end;
    readln;
  end.
 

Measurement is not management.

RE: How to get the command-line of all running processes?

Module32First / Module32Next functions will also do the trick. Remember that GetModuleFileNameEx is only available from windows 2000 and up. Module32x functions are available from win95 (psapi)

/Daddy

-----------------------------------------------------
 What You See Is What You Get
Never underestimate tha powah of tha google!

RE: How to get the command-line of all running processes?

I got to thinking and realized you might want the command-line parms too, so I got to looking around a bit and ported a C program I found online (can't refind it to give proper credit).  See the note at the top of the source, as it's VERY IMPORTANT to remember.  Again, what is returned will be incomplete so you'll have to pair this up with the other function if you use both.

Anyhow, it uses NTDLL.DLL, so somehow I believe you won't find too much support if you run with using it:

CODE

{$APPTYPE CONSOLE}
program getcommline; uses windows;

// ported C program to Delphi.  Returns exact command-line used in calling program, including command-line parms.
  type
    TUnicodeString = record
      Length: ShortInt;
      MaxLength: ShortInt;
      Buffer: PWideChar;
    end;
    TProcessBasicInformation = record
      ExitStatus: DWord;
      PEBBaseAddress: Pointer;
      AffinityMask: DWord;
      BasePriority: DWord;
      UniqueProcessID: Word;
      ParentProcessID: DWord;
    end;

  function GetPEBAddress(inhandle: THandle): pointer;
    type
      NTQIP = procedure(ProcessHandle: THandle;
                        ProcessInformationClass: DWord;
                        ProcessInformation: Pointer;
                        ProcessInformationLength: DWord;
                        ReturnLength: Pointer); stdcall;
    var
      pbi: TProcessBasicInformation;
      MyHandle: THandle;
      myFunc: NTQIP;
    begin
      MyHandle := LoadLibrary('NTDLL.DLL');
      if MyHandle <> 0 then
        begin
          myfunc := GetProcAddress(myHandle, 'NtQueryInformationProcess');
          if @myfunc <> nil then
            MyFunc(inhandle, 0, @pbi, sizeof(pbi), nil);
        end;
      FreeLibrary(Myhandle);
      Result := pbi.PEBBaseAddress;
    end;

 function getcommandline(inproc: THandle): string;
    var
      myproc: THandle;
      rtlUserProcAddress: Pointer;
      PMBAddress: Pointer;
      command_line: TUnicodeString;
      command_line_contents: WideString;
      outr: DWord;
    begin
      myproc := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
                        false, inproc);
      PMBAddress := GetPEBAddress(myproc);
      ReadProcessMemory(myproc, Pointer(Longint(PMBAddress) + $10),
            @rtlUserProcAddress, sizeof(Pointer), outr);
      ReadProcessMemory(myproc, Pointer(Longint(rtlUserProcAddress) + $40),
            @command_line, sizeof(command_line), outr);

      SetLength(Command_Line_Contents, command_line.length);
      ReadProcessMemory(myproc, command_Line.Buffer, @command_Line_contents[1],
               command_line.length, outr);
      CloseHandle(myproc);

      Result := WideCharLenToString(PWideChar(command_Line_Contents),
                           command_line.length div 2);
    end;

 begin
   writeln('This process invoked with: ');
   writeln(GetCommandLine(GetCurrentProcessID));
   readln;
 end.

Quote (whosrdaddy):


Module32First / Module32Next functions will also do the trick. Remember that GetModuleFileNameEx is only available from windows 2000 and up. Module32x functions are available from win95 (psapi)

1) Actually all that is needed is Module32First.  Any subsequent calls enumerates all the DLLs associated with the main process.  It seemed a bit...troublesome, so I went the other path.
2) All the documentation I found (like http://support.microsoft.com/kb/228469) seems to indicate that GetModuleFileName returns a full path on 95/98/ME systems.  So not so much an issue, assuming that is indeed the case.  But might be worth testing there if you do plan to implement there.

Anyway, Griffyn hope all this helps you out.

Measurement is not management.

RE: How to get the command-line of all running processes?

thumbsup

/Daddy

-----------------------------------------------------
 What You See Is What You Get
Never underestimate tha powah of tha google!

RE: How to get the command-line of all running processes?

(OP)
Thanks guys.  The combination Process32x, plus the GetCommandLine function works great. And in WinNT too.

 

RE: How to get the command-line of all running processes?

Glenn9999,

Thanks so much for translating that code to Delphi.  It's just what I was looking for.  One problem, though.  It wasn't returning the command lines for all the processes, just some of them.  I found the problem.

  type
    TUnicodeString = record
      Length: ShortInt;
      MaxLength: ShortInt;
      Buffer: PWideChar;
    end;

should be:

  type
    TUnicodeString = record
      Length: UShort;
      MaxLength: UShort;
      Buffer: PWideChar;
    end;

ShortInt is signed whlie UShort is not and can hold numbers twice the size of ShortInt.  The processes it was not working for were the ones with longer command lines.

Cheers.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close