
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.3] |
![]() |
|
![]() |
|
|
Господа вопрос такой. Есть процесс.
Как узнать процесс родителя. Тоесть узнать имя процесса запустившего мою программу. Хотел написать плагин для Internet explorer'а, где если бы программа запускалась с параметром -d то сразу программа определяла что программу запустил Internet explorer,ан нет оказываеться нет. Там в ветви Software\Microsoft\Internet Explorer\Extensions, добавляються программы на исполнение, без дополнительных параметров, то есть не гибкий однако Internet explorer. Вопрос: Может есть у кого наработки на узнавание родителя процесса. Спросите вы, что мне лень. Да нет с TlHelp32 работал, просто чьйто наработки могут быть полезны для меня, и для других, кто дальше столкнеться с данной проблемой... Добавлено Я люблю, когда появляються задачи по программированию.. Но тут немного в невиддении насчет родителя.. |
Сообщ.
#2
,
|
|
|
Да в плагины гораздо логичнее передавать какой-то интерфейс (не обязательно в прямом смысле слова) основного приложения, а не хаками это определять.
Цитата SOLON7 @ то есть не гибкий однако Internet explorer Да что вы говорите, с каких это пор динамические библиотеки (DLL) стали запускаться с параметрами коммандной строки? Добавлено Где в LoadLibrary вы увидели параметры коммандной строки? |
Сообщ.
#3
,
|
|
|
Ничего не поняла насчет "плагин для Internet explorer'а" и "не гибкости Internet explorer"
![]() Посему, попробую ответить на "Тоесть узнать имя процесса запустившего мою программу." Раз любишь задачки, то вот для затравки набросала ф-ию поиска ID родителя: (не тестировала) ![]() ![]() function GetMyParentID(var ParentID: DWord): DWord; var ProcEntry: TProcessEntry32; hSnapshot: THandle; CurrID: DWord; _OK: Boolean; begin hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if hSnapshot <> INVALID_HANDLE_VALUE then try ProcEntry.dwSize := SizeOf(ProcEntry); _OK := Process32First(hSnapshot, ProcEntry); if _OK then begin CurrID := GetCurrentProcessId; SetLastError(ERROR_SUCCESS); while _OK do if ProcEntry.th32ProcessID = CurrID then begin ParentID := ProcEntry.th32ParentProcessID; Break; end else _OK := Process32Next(hSnapshot, ProcEntry); end; Result := GetLastError; finally CloseHandle(hSnapshot); end else Result := GetLastError; end; Ну а чуть-чуть ее видоизменить для нахождения имени родителя по его ID оставляю в качестве домашего задания ![]() P.S. Только проку от данной методики, как от козла молока. Процесса родителя уже может и не быть в помине, пока мы тут соизволяем его искать ![]() И полученный нами ID, можно выбрасывать на помойку. Гораздо лучше использовать NtQuerySystemInformation с параметром SystemProcessesAndThreadsInformation - можно обойтись одним "снимком". Правда и с CreateToolhelp32Snapshot можно, но придется запоминать ProcEntry`ы. P.S.S. >Да нет с TlHelp32 работал >Я люблю, когда появляються задачи по программированию.. >Но тут немного в невиддении насчет родителя.. Ой как "не вяжутся" эти три фразы ![]() (особенно учитывая, что в Help`е есть пример ![]() Забыла еще одну неприятную вещь: Может получиться так, что к моменту нашего поиска, родитель уже умрет, и будет создан другой процесс с такм же ID, как и у родителя. А вот чтобы не попасть впросак с этим, придется использовать NtQuerySystemInformation и сравнивать времена создания найденого нами родителя и наше. |
Сообщ.
#4
,
|
|
|
Цитата Riply @ Забыла еще одну неприятную вещь: Может получиться так, что к моменту нашего поиска, родитель уже умрет, и будет создан другой процесс с такм же ID, как и у родителя. Да вы что, а разве PID не растет с каждым новым запуском нового процесса, как-то не вяжется, чтобы PID был одинаков у процессов, это было по крайне мере глупо со стороны MICROSOFT делать такое. Процесса может быть уже убит, но чтобы pid были одинаковы не вериться... Добавлено Я нашел пожалуй самый легкий метод определения, как узнавать запущенна ли прога из интернет експлорер. При запуске из ИНтернет Експолера не передаеться параметр "Рабочий каталог". То есть можно проверить если рабочий каталог неравен Extractfilepath(paramstr(0)) то значит его запустил ИНтернет Експолера. Да твик не гибкий, но простой и не требующих мозломства. RIPLY, а вы что преподователь, изложили все в такой форме, красиво. Мне кажеться вы преподователь, или по крайне мере имеете его задатки... ВСЕМ СПАСИБО ПЛАН РАБОТЫ НАМЕЧЕН, БУДЕМ РАБОТАТАТЬ. |
Сообщ.
#5
,
|
|
|
Цитата SOLON7 @ Да вы что, а разве PID не растет с каждым новым запуском нового процесса Нет. В общем случае это не так. Цитата SOLON7 @ как-то не вяжется, чтобы PID был одинаков у процессов У двух процессов, существовавших одновременно в некий момент времени, одинаковых ID быть не может. Но эта ситуация вполне реальна, для процессов, разнесенных во времени. Кстати, вероятность этого не так уж мала, как кажется. Цитата SOLON7 @ Я нашел пожалуй самый легкий метод определения, как узнавать запущенна ли прога из интернет експлорер. При запуске из ИНтернет Експолера не передаеться параметр "Рабочий каталог". То есть можно проверить если рабочий каталог неравен Extractfilepath(paramstr(0)) то значит его запустил ИНтернет Експолера Этот способ определения череват ошибками, imho. Ибо из факта "если рабочий каталог неравен Extractfilepath(paramstr(0))" отнюдь не следует, что нас запустил IE. ![]() |
Сообщ.
#6
,
|
|
|
Цитата Да вы что, а разве PID не растет с каждым новым запуском нового процесса, как-то не вяжется, чтобы PID был одинаков у процессов Riply абсолютно права. Я к сожелению не смог найти прямого ответа в MSDN, там весьма уклончиво отвечают на этот вопрос - "The identifier is valid from the time the process is created until the process has been terminated." Эту фразу, в принципе, можно понять по разному. Зато недвусмысленно это описано у Рихтера, так что сошлемся на его авторитет: Подчеркну ещс один чрезвычайно важный момент система способна повторно использовать идентификаторы процессов и потоков. Например, при создании про цесса система формирует объект "процесс", присваивая ему идентификатор со зна чением, допустим, 122 Создавая новый объект "процесс", система уже не присвоит ему данный идентификатор. Но после выгрузки из памяти первого объекта следу ющему создаваемому объекту "процесс" может быть присвоен тот же идентификатор — 122. Эту особенность нужно учитывать при написании кода, избегая ссылок на невер ный объект "процесс" (или "поток"). Действительно, затребовать и сохранить иден тификатор процесса несложно, но задумайтесь, что получится, ссли в следующий момент этот процесс будет завершен, а новый получит тот же идентификатор: сохра ненный ранее идентификатор уже связан совсем с другим процессом. |
![]() |
Сообщ.
#7
,
|
|
Узнать родителя любого процесса можно и без перебора процессов в снимке. Например вот так:
![]() ![]() type PROCESS_BASIC_INFORMATION = packed record ExitStatus: DWORD; PebBaseAddress: Pointer; AffinityMask: DWORD; BasePriority: DWORD; uUniqueProcessId: Ulong; uInheritedFromUniqueProcessId: Ulong; end; function NtQueryInformationProcess( ProcessHandle : THandle; ProcessInformationClass : Byte; ProcessInformation : Pointer; ProcessInformationLength : ULONG; ReturnLength : PULONG ): DWORD; stdcall; external 'ntdll.dll'; function GetOwnedProcessID(const dwProcessHandle: DWORD): DWORD; const ProcessBasicInformation = 0; var Info: PROCESS_BASIC_INFORMATION; begin Result := 0; if NtQueryInformationProcess(dwProcessHandle, ProcessBasicInformation, @Info, SizeOf(Info), nil) = NO_ERROR then Result := Info.uInheritedFromUniqueProcessId; end; Вот так будет выглядеть получение родителя от текущего процесса: ![]() ![]() procedure TForm1.Button1Click(Sender: TObject); var dwProcessHandle: DWORD; begin DuplicateHandle(GetCurrentProcess, GetCurrentProcess, GetCurrentProcess, @dwProcessHandle, 0, False, DUPLICATE_SAME_ACCESS); Caption := IntToStr(GetOwnedProcessID(dwProcessHandle)); end; |
Сообщ.
#8
,
|
|
|
Rouse_
DuplicateHandle не обязательно. NtQueryInformationProcess прекрасно съедает и псевдохэндл. |
![]() |
Сообщ.
#9
,
|
|
Rose, согласен...
|
Сообщ.
#10
,
|
|
|
Цитата Rouse_ @ Узнать родителя любого процесса можно и без перебора процессов в снимке. Например вот так: А мы не привыкли искать легкие пути ![]() А если серьезно, то мне это просто не пришло в голову. Спасибо. |
Сообщ.
#11
,
|
|
|
НУ родителя мы то узнаем, а как узнать является ли процесс Internet Explorer....
|
![]() |
Сообщ.
#12
,
|
|
GetModuleFileNameEx очевидно
![]() |
Сообщ.
#13
,
|
|
|
А какой же быстрый способ узнать по ПИДУ имя процесса.
Какую функцию по обьему кода посоветуете???? Чтоб поменьше кода было.... |
![]() |
Сообщ.
#14
,
|
|
Тэкссс... тебе уже много насоветовали. Давай сначала посмотрим, понял ли ты все это. Выкладывай аттачем код, с которым сейчас эксперементируешь...
|
Сообщ.
#15
,
|
|
|
Вобщем если я правильно понял автору нужно что-то врое этого:
![]() ![]() const ProcessBasicInformation = 0; CSIDL_PROGRAM_FILES = $0026; IExplorePath: string = '\Internet Explorer\IEXPLORE.EXE'; type PROCESS_BASIC_INFORMATION = packed record ExitStatus: DWORD; PebBaseAddress: Pointer; AffinityMask: DWORD; BasePriority: DWORD; uUniqueProcessId: Ulong; uInheritedFromUniqueProcessId: Ulong; end; function NtQueryInformationProcess( ProcessHandle : THandle; ProcessInformationClass : Byte; ProcessInformation : Pointer; ProcessInformationLength : ULONG; ReturnLength : PULONG ): DWORD; stdcall; external 'ntdll.dll'; function GetModuleFileNameExA( hProcess: DWORD; hModule: DWORD; lpFilename: PAnsiChar; nSize: DWORD ): DWORD; stdcall; external 'PSAPI.dll'; function OwnerProcessIs_IExplore: Boolean; var lInfo: PROCESS_BASIC_INFORMATION; lParentProcHandle: THandle; lpFileName, lPFPath: PAnsiChar; dwProcessHandle: DWORD; begin Result := False; ZeroMemory(@lInfo, SizeOf(PROCESS_BASIC_INFORMATION)); DuplicateHandle(GetCurrentProcess, GetCurrentProcess, GetCurrentProcess, @dwProcessHandle, 0, False, DUPLICATE_SAME_ACCESS); if NtQueryInformationProcess(dwProcessHandle, ProcessBasicInformation, @lInfo, SizeOf(PROCESS_BASIC_INFORMATION), nil) = NO_ERROR then begin lParentProcHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, lInfo.uInheritedFromUniqueProcessId); if lParentProcHandle > 0 then begin lpFileName := GetMemory(MAX_PATH); ZeroMemory(lpFileName, MAX_PATH); lPFPath := GetMemory(MAX_PATH); ZeroMemory(lPFPath, MAX_PATH); if SHGetSpecialFolderPath(0, lPFPath, CSIDL_PROGRAM_FILES, False) and (GetModuleFileNameExA(lParentProcHandle, 0, lpFileName, MAX_PATH) > 0) then Result := lPFPath + IExplorePath = lpFileName; FreeMemory(lpFileName); FreeMemory(lPFPath); end; CloseHandle(lParentProcHandle); end; CloseHandle(dwProcessHandle); end; Добавлено Цитата DuplicateHandle не обязательно. NtQueryInformationProcess прекрасно съедает и псевдохэндл. Кстати пока отлаживал, псевдохендл не всегда отрабатывал(закономерности не понял), и NtQueryInformationProcess выкидывало с "неверный декриптор". Пришлось DublicateHandle все-таки оставить. |
Сообщ.
#16
,
|
|
|
Цитата Кстати пока отлаживал, псевдохендл не всегда отрабатывал(закономерности не понял), и NtQueryInformationProcess выкидывало с "неверный декриптор". Пришлось DublicateHandle все-таки оставить. Честно говоря, не сталкивался с проблемами из-за псевдохэндла, но раз так, то буду иметь в виду. PS: Закройте его тогда уж, хотя бы, dwProcessHandle в смысле... |
Сообщ.
#17
,
|
|
|
Цитата PS: Закройте его тогда уж, хотя бы, dwProcessHandle в смысле... Сорь ![]() |
Сообщ.
#18
,
|
|
|
Цитата Rennigth @ Вобщем если я правильно понял автору нужно что-то врое этого: Ну раз уж выкладывается решение для copy/paste`ого использования, то не плохо было бы включить в него и проверку настоящего родителя мы нашли или так "погулять вышедшего" ![]() |
Сообщ.
#19
,
|
|
|
Цитата Ну раз уж выкладывается решение для copy/paste`ого использования, то не плохо было бы включить в него и проверку настоящего родителя мы нашли или так "погулять вышедшего" Riply, поясни плиз. Не понял что ты имеешь ввиду под "настоящим родителем". Добавлено Это: Цитата P.S. Только проку от данной методики, как от козла молока. Процесса родителя уже может и не быть в помине, пока мы тут соизволяем его искать И полученный нами ID, можно выбрасывать на помойку. Гораздо лучше использовать NtQuerySystemInformation с параметром SystemProcessesAndThreadsInformation - можно обойтись одним "снимком". Правда и с CreateToolhelp32Snapshot можно, но придется запоминать ProcEntry`ы. P.S.S. >Да нет с TlHelp32 работал >Я люблю, когда появляються задачи по программированию.. >Но тут немного в невиддении насчет родителя.. Ой как "не вяжутся" эти три фразы (особенно учитывая, что в Help`е есть пример Забыла еще одну неприятную вещь: Может получиться так, что к моменту нашего поиска, родитель уже умрет, и будет создан другой процесс с такм же ID, как и у родителя. А вот чтобы не попасть впросак с этим, придется использовать NtQuerySystemInformation и сравнивать времена создания найденого нами родителя и наше. имеешь ввиду? Или более жесткая проверка на то что это именно IE? |
Сообщ.
#20
,
|
|
|
Цитата Rennigth @ Riply, поясни плиз. Не понял что ты имеешь ввиду под "настоящим родителем". Я хотела сказать, что у нас нет уверенности в том, что ID, с которым мы работаем, действительно ID нашего родителя, а не какого-то левого процесса. (случай с использованием старого значения ID, для нового процесса). Соответственно, как положительный ответ OwnerProcessIs_IExplore, так и отрицательный верны с некой долей вероятности. Проверять можно так: сравнить время нашего создания, с временем создания "родителя". И если родитель был создан позже нас, то кричать о подлоге ![]() |
Сообщ.
#21
,
|
|
|
Цитата Я хотела сказать, что у нас нет уверенности в том, что ID, с которым мы работаем, действительно ID нашего родителя, а не какого-то левого процесса. (случай с использованием старого значения ID, для нового процесса). Соответственно, как положительный ответ OwnerProcessIs_IExplore, так и отрицательный верны с некой долей вероятности. Проверять можно так: сравнить время нашего создания, с временем создания "родителя". И если родитель был создан позже нас, то кричать о подлоге Желание дамы - закон! ![]() ![]() ![]() uses ShlObj //Лень в ручную экспортировать //... const SYSTEM_PROCESSES_AND_THREADS_INFORMATION = 5; NT_STATUS_SUCCESS = DWord($00000000); NT_STATUS_ACCESS_DENIED = DWord($C0000022); NT_STATUS_INFO_LENGTH_MISMATCH = DWord($C0000004); CSIDL_PROGRAM_FILES = $0026; IExplorePath: string = '\Internet Explorer\IEXPLORE.EXE'; type PSYSTEM_THREAD_INFORMATION = ^_SYSTEM_THREAD_INFORMATION; _SYSTEM_THREAD_INFORMATION = packed record KernelTime: LARGE_INTEGER; UserTime: LARGE_INTEGER; CreateTime: LARGE_INTEGER; WaitTime: ULONG; StartAddress: Pointer; UniqueProcess: DWORD; UniqueThread: DWORD; Priority: Integer; BasePriority: Integer; ContextSwitchCount: ULONG; State: Longint; WaitReason: Longint; end; PSYSTEM_PROCESS_INFORMATION = ^_SYSTEM_PROCESS_INFORMATION; _SYSTEM_PROCESS_INFORMATION = packed record NextOffset: ULONG; ThreadCount: ULONG; Reserved1: array [0..5] of ULONG; CreateTime: FILETIME; UserTime: FILETIME; KernelTime: FILETIME; ModuleNameLength: WORD; ModuleNameMaxLength: WORD; ModuleName: PWideChar; BasePriority: ULONG; ProcessID: ULONG; InheritedFromUniqueProcessID: ULONG; HandleCount: ULONG; Reserved2 : array[0..1] of ULONG; PeakVirtualSize : ULONG; VirtualSize : ULONG; PageFaultCount : ULONG; PeakWorkingSetSize : ULONG; WorkingSetSize : ULONG; QuotaPeakPagedPoolUsage : ULONG; QuotaPagedPoolUsage : ULONG; QuotaPeakNonPagedPoolUsage : ULONG; QuotaNonPagedPoolUsage : ULONG; PageFileUsage : ULONG; PeakPageFileUsage : ULONG; PrivatePageCount : ULONG; ReadOperationCount : LARGE_INTEGER; WriteOperationCount : LARGE_INTEGER; OtherOperationCount : LARGE_INTEGER; ReadTransferCount : LARGE_INTEGER; WriteTransferCount : LARGE_INTEGER; OtherTransferCount : LARGE_INTEGER; ThreadInfo: array [0..0] of _SYSTEM_THREAD_INFORMATION; end; function ZwQuerySystemInformation(ASystemInformationClass: Cardinal; ASystemInformation: Pointer; ASystemInformationLength: Cardinal; AReturnLength: PCardinal): Cardinal; stdcall; external 'ntdll.dll'; function GetModuleFileNameExA(hProcess: THandle; hModule: HModule; lpFilename: PAnsiChar; nSize: DWORD): DWORD; stdcall; external 'PSAPI.dll'; function OwnerProcessIs_IExplore: Boolean; var pSI, pSITemp: PSYSTEM_PROCESS_INFORMATION; hParentProcess: THandle; dwParentProcessID, dwSelfProcessID: DWORD; lpFileName, lpPFPath: PAnsiChar; dwOffSet, dwSize: DWORD; ftSelfProcTime: FILETIME; begin Result := False; dwSelfProcessID := GetCurrentProcessId; dwSize := 0; dwParentProcessID := 0; if ZwQuerySystemInformation(SYSTEM_PROCESSES_AND_THREADS_INFORMATION, nil, 0, @dwSize) <> NT_STATUS_INFO_LENGTH_MISMATCH then Exit; pSI := VirtualAlloc(nil, dwSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE); if Assigned(pSI) then try if ZwQuerySystemInformation(SYSTEM_PROCESSES_AND_THREADS_INFORMATION, pSI, dwSize, @dwSize) = NT_STATUS_SUCCESS then begin pSITemp := pSI; repeat if pSITemp^.ProcessID = dwSelfProcessID then begin dwParentProcessID := pSITemp^.InheritedFromUniqueProcessID; ftSelfProcTime := pSITemp^.CreateTime; Break; end; dwOffSet := pSITemp^.NextOffset; pSITemp := Pointer(DWORD(pSITemp) + dwOffSet); until dwOffSet = 0; if dwParentProcessID > 0 then begin pSITemp := pSI; repeat if pSITemp^.ProcessID = dwParentProcessID then begin if CompareFileTime(ftSelfProcTime, pSITemp^.CreateTime) > 0 then begin hParentProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, dwParentProcessID); try if hParentProcess > 0 then begin lpFileName := GetMemory(MAX_PATH); try ZeroMemory(lpFileName, MAX_PATH); lpPFPath := GetMemory(MAX_PATH); try ZeroMemory(lpPFPath, MAX_PATH); if SHGetSpecialFolderPath(0, lpPFPath, CSIDL_PROGRAM_FILES, False) and (GetModuleFileNameExA(hParentProcess, 0, lpFileName, MAX_PATH) > 0) then Result := lpPFPath + IExplorePath = lpFileName; finally FreeMemory(lpPFPath); end; finally FreeMemory(lpFileName); end; end; finally CloseHandle(hParentProcess); end; end; Break; end; dwOffSet := pSITemp^.NextOffset; pSITemp := Pointer(DWORD(pSITemp) + dwOffSet); until dwOffSet = 0; end; end; finally VirtualFree(pSI, 0, MEM_RELEASE); end; end; Добавлено Кстати вопросик, чем отличаеютя в структуре SYSTEM_PROCESS_INFORMATION времена CreateTime, UserTime, KernelTime? |
![]() |
Сообщ.
#22
,
|
|
Что значит чем отличаются. UserTime + KernelTime = общее время работы процесса.
|
Сообщ.
#23
,
|
|
|
Цитата Кстати вопросик, чем отличаеютя в структуре SYSTEM_PROCESS_INFORMATION времена CreateTime, UserTime, KernelTime? Соответственно время создания процесса, время, которое его потоки выполнялись в пользовательском режиме и режиме ядра. Здесь описано: http://msdn2.microsoft.com/en-us/library/ms683223.aspx |
Сообщ.
#24
,
|
|
|
Цитата Что значит чем отличаются. UserTime + KernelTime = общее время работы процесса. Логично... ![]() ![]() Добавлено Цитата Соответственно время создания процесса, время, которое его потоки выполнялись в пользовательском режиме и режиме ядра. Здесь описано: http://msdn2.microsoft.com/en-us/library/ms683223.aspx О спс, почитаем... |
Сообщ.
#25
,
|
|
|
Rouse_
Кстати, ExitTime - CreationTime не равно UserTime + KernelTime. Когда все потоки процесса простаивают, UserTime и KernelTime не меняется. В этом случае UserTime + KernelTime будет меньше. И наоборот, если у процесса несколько потоков и все они работают безперебойно, UserTime + KernelTime может быть больше чем ExitTime - CreationTime, так как вроде бы UserTime и KernelTime суммируются по всем потокам процесса. |
![]() |
Сообщ.
#26
,
|
|
Rose, ну это то понятно
![]() ![]() Цитата Rose @ так как вроде бы UserTime и KernelTime суммируются по всем потокам процесса. Конечно, но т.к. система псевдомногопоточная, т.е. в единый квант времени выполняется только что-то одно, то ExitTime - CreationTime никогда не будет меньше чем UserTime + KernelTime ![]() |
Сообщ.
#27
,
|
|
|
Цитата Конечно, но т.к. система псевдомногопоточная, т.е. в единый квант времени выполняется только что-то одно, то ExitTime - CreationTime никогда не будет меньше чем UserTime + KernelTime Логично, но это верно только для однопроцессорной системы. На многопроцессорной UserTime + KernelTime уже может и превышать ![]() Кстати, мне тоже интересно, как система следит за тем, в каком режиме (user или kernel) выолняется поток? |
![]() |
Сообщ.
#28
,
|
|
Цитата Rose @ На многопроцессорной UserTime + KernelTime уже может и превышать Истину глаголишь ![]() Цитата Rose @ Кстати, мне тоже интересно, как система следит за тем, в каком режиме (user или kernel) выолняется поток? Вычисляется в KeUpdateRunTime() Грубо говоря выглядит примерно так: ![]() ![]() push ebx ; we will destroy ebx inc dword ptr [eax]+PcPrcbData+PbInterruptCount mov ebx, [eax]+PcPrcbData+PbCurrentThread ; (ebx)->current thread mov ecx, ThApcState+AsProcess[ebx] ; (ecx)->current thread's process test dword ptr [ebp]+TsEFlags,EFLAGS_V86_MASK jne Kutp20 ; if ne, user mode test byte ptr [ebp]+TsSegCs, MODE_MASK ; test if prev mode was kernel jne Kutp20 ; if ne, user mode ; ; Update the total time spent in kernel mode ; mov edx, 0 ; set kernel mode inc dword ptr [eax].PcPrcbData.PbKernelTime cmp byte ptr [esp+8], DISPATCH_LEVEL jc short Kutp4 ; OldIrql<2, then kernel ja short Kutp3 ; OldIrql>2, then interrupt |
Сообщ.
#29
,
|
|
|
Ага, осталось только выяснить где и когда вызывается KeUpdateRunTime? Надо полагать, по прерыванию от таймера?
|
![]() |
Сообщ.
#30
,
|
|
Она вызывается из KeUpdateSystemTime который дергается каждый раз при срабатывании прерывания системного таймера (тамже увеличивается и знаение возвращаемое GetTiCkCount и много чего еще)
![]() |
Сообщ.
#31
,
|
|
|
Ясно, спасибо. Правда насколько я знаю, системный таймер на NT тикает каждые 10 мс (тогда же планировщик потоков получает управление), так что соблюсти документированную дискретность 100 нс никак не получится. Или это я с прямым углом перепутал?
|
![]() |
Сообщ.
#32
,
|
|
В действительности срабатывает он намного чаще 10 мс. Иначе пропала бы возможность работы с мультимедийными таймерами
![]() |
Сообщ.
#33
,
|
|
|
Цитата Rennigth @ Вроде без особых косяков... Да. На первый взгляд, не видно ![]() P.S. Цитата Rennigth @ Желание дамы - закон! Вот бы везде было так, как на форумах по программированию ![]() |
Сообщ.
#34
,
|
|
|
Уважаемые!!! ПОМОГИТЕ!!!!
![]() Ни кто не пособит- как туже самую задачу воспроизвести на Visual Basic 6.0 ??? т.е. меня интересует, КАК узнать имя процесса запустившего мою программу, но через VB? СПАСИБО огромное любому, кто хоть что то посоветует ![]() |
![]() |
Сообщ.
#35
,
|
|
Точно так-же, берешь приведенный код и переписываешь его на VB.
|
Сообщ.
#36
,
|
|
|
Rouse
Александр В том то и проблема, у меня не выходит (если честно, то я не спец в программировании, тока VB изучаю, а тут совсем др. язык).. Помогите, плиз, если можете) Спасибо. |
Сообщ.
#37
,
|
|
|
Цитата akkorn @ В том то и проблема, у меня не выходит (если честно, то я не спец в программировании, тока VB изучаю, а тут совсем др. язык).. Помогите, плиз, если можете) Спасибо. Ты думаешь Розыч спец в VB? ЛУчше задать вопрос в соответствующем разделе форума. |
Сообщ.
#38
,
|
|
|
Демо
Александр А КТО ЕСТЬ ТАКОЙ огромный спец, кто мог бы это провернуть??? Пасиб)) |
Сообщ.
#39
,
|
|
|
Пожалуй, апну тему.
Использую приведенный выше код. GetModuleFileNameExA на некоторых компьютерах возвращает ошибку, Getlasterror = 299, запрос Readprocessmemory или writeprocessmemory выполнен только частично. Оно же "Only part of a ReadProcessMemory or WriteProcessMemory request was completed." или ERROR_PARTIAL_COPY. Пробовал увеличить буффер - дело не в этом. GetModuleFileNameExW дает ровно тот же результат - либо обе работают, либо обе нет. Работает на WindowsXP x86, Windows2003 x86, Windows 2003 x64. Не работает: словил только на Win2003x64, запущенном под Oracle VirtualBox, но есть и другие эпизоды. Сделал мощный дебаг, в Memo выводится все и на каждом шаге. Функции GetModuleFileNameEx передается нормальный хендл. Приложение 32битное, в диспетчере задач отмечено как *32. Возможно, как-то связано. Запуск в режиме совместимости с любой другой ОС во первых, не решает задачу, во вторых - выдается тот же результат. Запустившее приложение еще в памяти, не тот случай когда бы оно успело закрыться. Как фиксить? --- еще порылся и выяснил, что ошибка возникает только при запуске приложения из проводника (Explorer.exe) либо через CMD.exe на некоторых 64-битных системах. Запуск другой программой определяется. Решается использованием GetProcessImageFileNameA, которая дает путь в виде \Device1\PArtition2\windows\explorer.exe или типа того, но сойдет. Надеюсь, GetProcessImageFileNameA есть на всех системах и не будет "точка входа не найдена"... Рекомендуемую QueryFullProcessImageName в системных библиотеках не нашел, в модулях Delphi тем более. |
Сообщ.
#40
,
|
|
|
Цитата Виталь @ QueryFullProcessImageName Minimum supported client Windows Vista [desktop apps only] Minimum supported server Windows Server 2008 [desktop apps only] Header WinBase.h (include Windows.h) Library Kernel32.lib DLL Kernel32.dll |