Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > полный путь к процессам в WIN NT


Автор: Sunvas 23.3.2006, 08:30
Вот есть код, который вполне нормально работает в Win 32, но в Nt я вижу не полный путь откуда был запущен процесс, а лишь имя исполняемого файла.
Код

procedure TForm1.Button1Click(Sender: TObject);
var
  hSnapShot: THandle;
  lppe: TProcessEntry32;
  Count: Integer;

  procedure _FillList;
  begin
    listbox1.Items.Add(lppe.szExeFile);
    Inc(Count);
  end;

begin
  hSnapShot:= CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if hSnapShot <> INVALID_HANDLE_VALUE then
  begin
    Listbox1.Items.Clear;
    lppe.dwSize:= SizeOf(lppe);
    Count:= 0;
    if Process32First(hSnapShot, lppe) then _FillList;
    while Process32Next(hSnapShot, lppe) do _FillList;
    CloseHandle(hSnapShot);
  end;
end;

Как же сделать, чтобы можно было увидеть и в Nt полный путь к файлу?

Вот то, что я уже знаю и это мне не помогает, соответственно такое предлагать не нужно:
-Искать имя файла по модулям процесса.
-Лезть в реестр за списком процессов.

Автор: Matematik 23.3.2006, 08:45
Код

Function CreateWinNTProcessList:AnsiString;
var
  PIDArray   : array [0..1023] of DWORD;
  cb         : DWORD;
  I          : Integer;
  ProcCount  : Integer;
  hMod       : HMODULE;
  hProcess   : THandle;
  ModuleName : array [0..1024] of Char;
begin
  result := '';
  EnumProcesses(@PIDArray, SizeOf(PIDArray), cb);
  ProcCount := cb div SizeOf(DWORD);
  for I := 0 to ProcCount - 1 do
  begin
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,False,PIDArray[I]);
    if (hProcess <> 0) then
      begin
       if PIDArray[I]=4 then
       begin
         result := result + inttostr(PIDArray[I]) + ' System' + AOL
       end
                     else
       begin
          EnumProcessModules(hProcess, @hMod, SizeOf(hMod), cb);
          GetModuleFilenameEx(hProcess, hMod, ModuleName, SizeOf(ModuleName));
          result := result + inttostr(PIDArray[I]) + ' ' + ModuleName + AOL;
       end
      end;
    CloseHandle(hProcess)
  end
end;

Автор: Sunvas 24.3.2006, 08:19
Молодец, ценю!

Автор: Sunvas 2.4.2006, 01:23
Matematik, а чтобы все процессы были видны и в ограниченой учетной записи никак нельзя сделать?

Автор: Тутанхамец 12.5.2006, 07:58
Matematik, понимаю, что тема старая, но может ты от нее забыл отписаться... smile 

У меня такая проблема. Пытаюсь получить список процессов с помощью EnumProcesses, а Делфи говорит, что EnumProcesses - это необъявленный идентификатор. В модулях в папке Делфи я ее тоже не нашел. Работаю в WinXP Pro и Delphi5.

Не подскажешь, как быть?

Добавлено @ 08:02 
А, всё! smile  Нашел, что эта функция из psapi. Подключил, работает. Непонятно, почему было не включить ее описание в Windows SDK help... 

Автор: Sunvas 12.5.2006, 19:02
Цитата(Тутанхамец @  12.5.2006,  07:58 Найти цитируемый пост)
А, всё!   Нашел, что эта функция из psapi. Подключил, работает. Непонятно, почему было не включить ее описание в Windows SDK help... 

Поделись кодом! 

Автор: Тутанхамец 12.5.2006, 19:16
Если интересно - пожалуйста.  smile Тут по одной кнопке вызывается код Математика, по другой - моя функция. Но свой путь в WinAPI я только начинаю, так что это очень и очень далекий от совершенства код.  smile 

По щелчку на процесс в списке выводится информация о его модулях в другом списке. 

Код

unit uprocesses;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, psapi;

type

  TProcess=record
    ID:dword;
    Desc:DWORD;
    name:string;
    ModCount:integer;
    Mods:array of DWORD;
    ModsName:array of string;

  end;

  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    Memo1: TMemo;
    Button2: TButton;
    ListBox2: TListBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
  private
    procedure GetProcesses;
    procedure GetPIDs;
    procedure GetModules(i:integer);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  pr:array of Tprocess;
  PrCount:DWORD;
implementation

{$R *.DFM}

procedure TForm1.GetModules(i:integer);//èíäåêñ â ìàññèâå pr
var
    hProcess:DWORD;
    j:integer;
    needed:DWORD;
begin
    pr[i].desc := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,False, pr[i].id);

    if pr[i].desc=0 then exit;

    pr[i].modcount:=15;
    repeat
    needed:=0;
    pr[i].modcount:=pr[i].modcount*2;
    SetLength(pr[i].mods,pr[i].modcount);
    EnumProcessModules(pr[i].desc, @(pr[i].mods[0]), pr[i].modcount*sizeof(DWORD), needed);
    until needed<pr[i].modcount*sizeof(DWORD);

    pr[i].modcount:=needed div 4;
    SetLength(pr[i].mods,pr[i].modcount);
    SetLength(pr[i].modsname,pr[i].modcount);

    if pr[i].modcount>0 then begin
        for j:=0 to pr[i].modcount-1 do begin
        SetLength(pr[i].modsname[j],MAX_PATH-1);
        needed:=0;
        needed:=GetModuleBaseName(pr[i].desc, pr[i].mods[j], pchar(pr[i].modsname[j]), length(pr[i].modsname[j]));
        SetLength(pr[i].modsname[j],needed);
        end;
    end;

    CloseHandle(pr[i].desc);
end;

procedure TForm1.GetPIDs;
var
    needed,i:DWORD;
    prids:array of DWORD;
begin
    prcount:=15;
    repeat
    needed:=0;
    prcount:=prcount*2;
    SetLength(prids,prcount);
    EnumProcesses(@prids[0],prcount*sizeof(DWORD),needed);
    until needed<prcount*sizeof(DWORD);
    prcount:=needed div sizeof(DWORD);
    SetLength(pr,prcount);
    for i:=0 to prcount-1 do pr[i].id:=prids[i];

end;

Function CreateWinNTProcessList:AnsiString;
var
  PIDArray   : array [0..1023] of DWORD;
  cb         : DWORD;
  I          : Integer;
  ProcCount  : Integer;
  hMod       : HMODULE;
  hProcess   : THandle;
  ModuleName : array [0..1024] of Char;
begin
  result := '';
  EnumProcesses(@PIDArray, SizeOf(PIDArray), cb);
  ProcCount := cb div SizeOf(DWORD);
  for I := 0 to ProcCount - 1 do
  begin
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,False,PIDArray[I]);
    if (hProcess <> 0) then
      begin
       if PIDArray[I]=4 then
       begin
         result := result + inttostr(PIDArray[I]) + ' System'+chr(13)+chr(10);
       end
                     else
       begin
          EnumProcessModules(hProcess, @hMod, SizeOf(hMod), cb);
          GetModuleFilenameEx(hProcess, hMod, ModuleName, SizeOf(ModuleName));
          result := result + inttostr(PIDArray[I]) + ' ' + ModuleName+chr(13)+chr(10);
       end
      end;
    CloseHandle(hProcess)
  end
end;


procedure TForm1.GetProcesses;
var
Needed:DWORD;
PrIDs:array of DWORD;
h,i,j,n:integer;
b:boolean;
begin
listbox1.items.clear;

getpids;

for i:=0 to prcount-1 do begin
    getmodules(i);
    if pr[i].ModCount >0 then listbox1.items.Add(inttostr(pr[i].id)+' '+pr[i].modsname[0]) else listbox1.items.Add(inttostr(pr[i].id)+' cant open, it is system process');
end;


end;

procedure TForm1.Button1Click(Sender: TObject);

begin
memo1.text:=CreateWinNTProcessList;
//GetProcesses;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
getprocesses;
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var i:integer;
begin
listbox2.items.clear;
for i:=0 to pr[listbox1.ItemIndex].modcount-1 do
    listbox2.items.add(pr[listbox1.ItemIndex].modsname[i]);

end;

end.


Много пока непонятно. Например вот у меня вопрос - я не могу открыть (OpenProcess) некоторые процессы - csrss.exe, svchost и др. Как бы их все-таки открывать? Spy++ это делает. Или хотя бы как понять, что это за процесс? svchost'ов к примеру может быть несколько и по id их отличать не получается.   

Автор: Nickel 13.5.2006, 09:00
Цитата(Тутанхамец @ 12.5.2006,  19:16)
Много пока непонятно. Например вот у меня вопрос - я не могу открыть (OpenProcess) некоторые процессы - csrss.exe, svchost и др. Как бы их все-таки открывать? Spy++ это делает. Или хотя бы как понять, что это за процесс? svchost'ов к примеру может быть несколько и по id их отличать не получается.

Т.к. это системные процессы, нужно взять привелегии отладчика:
Код

function EnablePrivilege(Process: dword; lpPrivilegeName: PChar):Boolean;
var
  hToken: dword;
  NameValue: Int64;
  tkp: TOKEN_PRIVILEGES;
  ReturnLength: dword;
begin
  Result:=false;
  OpenProcessToken(Process, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);
  if not LookupPrivilegeValue(nil, lpPrivilegeName, NameValue) then
    begin
     CloseHandle(hToken);
     exit;
    end;
  tkp.PrivilegeCount := 1;
  tkp.Privileges[0].Luid := NameValue;
  tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
  AdjustTokenPrivileges(hToken, false, tkp, SizeOf(TOKEN_PRIVILEGES),
    tkp, ReturnLength);
  if GetLastError() <> ERROR_SUCCESS then
     begin
      CloseHandle(hToken);
      exit;
     end;
  Result:=true;
  CloseHandle(hToken);
end;

...

EnablePrivilege(INVALID_HANDLE_VALUE ,'SeDebugPrivilege');


svchost'ов действительно несколько, но id у них разный. 

Автор: Тутанхамец 13.5.2006, 09:41
Спасибо, Nickel smile  Открываются все процессы, кроме system и idle. А я почему-то думал, что чтобы их открыть нужно регистрироваться как системный сервис. А какие преимущества дает регистрация в качестве системного сервиса? 

И еще если не трудно в двух словах, что это за штука "токен процесса"? 

Автор: Тутанхамец 13.5.2006, 10:05
Так, с токеном процесса более-менее ясно. 

Но вот еще вопрос: 

Код

  PTokenPrivileges = ^TTokenPrivileges;
  _TOKEN_PRIVILEGES = record
    PrivilegeCount: DWORD;
    Privileges: array[0..0] of TLUIDAndAttributes;
  end;



Зачем нужен нединамический массив из одного элемента? Какой смысл тогда в PrivilegeCount?

И что делать, если я хочу дать процессу больше одной привелегии?  

Автор: Nickel 13.5.2006, 11:42
Цитата(Тутанхамец @ 13.5.2006,  09:41)
И еще если не трудно в двух словах, что это за штука "токен процесса"?

Цитата
access token 
An access token contains the security information for a logon session. The system creates an access token when a user logs on, and every process executed on behalf of the user has a copy of the token. The token identifies the user, the user's groups, and the user's privileges. The system uses the token to control access to securable objects and to control the ability of the user to perform various system-related operations on the local computer. There are two kinds of access token, primary and impersonation. 

Цитата(Тутанхамец @ 13.5.2006,  09:41)
Спасибо, Nickel   Открываются все процессы, кроме system и idle. А я почему-то думал, что чтобы их открыть нужно регистрироваться как системный сервис. А какие преимущества дает регистрация в качестве системного сервиса? 

Странно у меня system вроде открывается, а idle  я бы даже сказал что это не процесс, он и не должен открываться. Сервисы я не очень люблю. Помоему всё что даёт сервис можно сделать и без него. Если нужны супер-пупер привелегии - пиши драйвер, если нет - обычное приложение.
Цитата(Тутанхамец @ 13.5.2006,  10:05)
Зачем нужен нединамический массив из одного элемента? Какой смысл тогда в PrivilegeCount?

И что делать, если я хочу дать процессу больше одной привелегии?
 
Честно говоря, я не знаю, почему сделано именно так. PrivilegeCount - это сколько элементов  нашего массива должна прочитать функция. В подобных случаях я поступаю так (и какая нам разница динамический или статический массив =))):
Код

function EnablePrivileges(Process: Cardinal; lpPrivilegeName:array of PChar):Boolean;
var
  hToken, ReturnLength, Size, Count: Cardinal;
  NameValue: Int64;
  tkp: PTokenPrivileges;
  i :integer;
begin
  Result:=false;
  OpenProcessToken(Process, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);
  Count:=High(lpPrivilegeName)+1;
  Size:=SizeOf(Cardinal)+Count*SizeOf(tkp.Privileges);
  GetMem(tkp, Size);
  tkp.PrivilegeCount := Count;
  for i:=0 to Count-1 do
    begin
      if LookupPrivilegeValue(nil, lpPrivilegeName[i], NameValue) then
         begin
           tkp.Privileges[i].Luid := NameValue;
           tkp.Privileges[i].Attributes := SE_PRIVILEGE_ENABLED;
         end
      else exit;
    end;
  AdjustTokenPrivileges(hToken, false, tkp^, Size, tkp^, ReturnLength);
  if GetLastError() <> ERROR_SUCCESS then
     begin
        CloseHandle(hToken);
        exit;
     end;
  Result:=true;
  CloseHandle(hToken);
end;

...

EnablePrivileges(INVALID_HANDLE_VALUE ,['SeDebugPrivilege','SeBackupPrivilege']);

 

Автор: Тутанхамец 13.5.2006, 11:56
Ага. Кажется, кое-чего понял smile Еще раз спасибо.
 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)