我必须从某个进程的PID中检索进程创建时间。我相信(不确定)Windows会将进程启动时间保存在进程内存中的某个位置(用户模式)。是否可以直接从内存中读取它?
我知道windbg有一个选项(.time)也是如此,但我想知道是否可以使用windbg或任何其他调试器手动获取它?
感谢Adv。
答案 0 :(得分:4)
此信息存储在内核模式对象中:
0:077> dt nt!_EPROCESS
ntdll!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x06c ProcessLock : _EX_PUSH_LOCK
+0x070 CreateTime : _LARGE_INTEGER
+0x078 ExitTime : _LARGE_INTEGER
...
因此,在运行时获取此信息的唯一方法是通过对GetProcessTimes()的API调用,如Raymond Chen或.NET中的Process.StartTime所述(可能在内部使用API调用)。
要在调试器中手动获取信息,您需要一个指向_EPROCESS结构的指针,然后使用dt nt!_EPROCESS <address>
。您可以使用!process 0 7 myapp.exe
从内核转储中获取地址。
答案 1 :(得分:4)
您需要使用GetProcessTimes。这将处理该过程,您可以使用OpenProcess从指示的PID中检索该过程。像下面这样的东西应该产生类似于.time的结果。
void Process(_TCHAR* szPid)
{
_TCHAR* pEnd;
DWORD pid = ::_tcstoul(szPid, &pEnd, 10);
HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
if (handle == NULL)
{
// Error handling omitted.
}
else
{
FILETIME createTime, exitTime, kernelTime, userTime;
if (!GetProcessTimes(handle, &createTime, &exitTime, &kernelTime, &userTime))
{
// Error handling omitted.
}
else
{
OutputToConsole(L"Process Uptime", &createTime);
OutputToConsole(L" Kernel time", &kernelTime);
OutputToConsole(L" User time", &userTime);
}
::CloseHandle(handle);
}
}
void OutputToConsole(TCHAR* descr, const FILETIME* lpFileTime)
{
SYSTEMTIME stDiff = FileTimeDiff(lpFileTime);
_tprintf(TEXT("%s: %hu days %hu:%02hu:%02hu.%03hu\n"), descr, stDiff.wDay, stDiff.wHour, stDiff.wMinute, stDiff.wSecond, stDiff.wMilliseconds);
}
SYSTEMTIME FileTimeDiff(const FILETIME* ftDT)
{
SYSTEMTIME stNow;
::GetSystemTime(&stNow);
FILETIME ftNow;
::SystemTimeToFileTime(&stNow, &ftNow);
ULARGE_INTEGER uliNow, uliCurrent, uliDiff;
uliNow.LowPart = ftNow.dwLowDateTime;
uliNow.HighPart = ftNow.dwHighDateTime;
uliCurrent.LowPart = ftDT->dwLowDateTime;
uliCurrent.HighPart = ftDT->dwHighDateTime;
uliDiff.QuadPart = uliNow.QuadPart - uliCurrent.QuadPart;
FILETIME ftDiff;
ftDiff.dwLowDateTime = uliDiff.LowPart;
ftDiff.dwHighDateTime = uliDiff.HighPart;
SYSTEMTIME stDiff;
::FileTimeToSystemTime(&ftDiff, &stDiff);
return stDiff;
}
我的一个流程的结果如下:
Process Uptime: 8 days 7:18:42.303
Kernel time: 16 days 7:06:31.995
User time: 16 days 7:11:16.462
答案 2 :(得分:1)
在命令提示符下使用wmic,CreationDate将列出所有正在运行的进程的创建时间
time:\>wmic process get processid , name , creationdate | grep opera
20140616162551 opera.exe 1108
time:\>tlist 1108 | grep Stack
1108 opera.exe windows - Process Creation Time from Process Memory (Win3
2) - Stack Overflow - Opera
time:\>
如果不喜欢grep,请在windows
中使用findstr.exe一个收件箱实用程序time:\>wmic process get processid,creationdate,name | findstr /C:opera
20140616162551 opera.exe 1108
如果你想从windbg获取它,请创建一个脚本文件并从命令提示符运行本地kd会话,如下所示(/ os vista中的/ debug switch reqd +)
C:\>type printtimes.txt
aS ${/v:ctime} @@( ( ( nt!_EPROCESS * ) @#Process )->CreateTime.QuadPart ) ;
aS ${/v:pid} @@( ( ( nt!_EPROCESS * ) @#Process )->UniqueProcessId ) ;
aS ${/v:imname} @@( ( ( nt!_EPROCESS * ) @#Process )->ImageFileName ) ;
.block { !for_each_process ".printf \"%20ma\t%8d\t\",${imname},${pid};!filetime
${ctime}" }
q
C:\>kd -kl -c "$$>a< c:\\printtimes.txt" | findstr /c:opera
opera.exe 1108 6/16/2014 16:25:51.500 (unknown)
和GetProcessTimes就像这样实现
#include <windows.h>
#include <stdio.h>
void printtimes(FILETIME *ft);
int main(int argc, char * argv[])
{
if (argc != 2) { printf ("usage proctime.exe Pid\n"); return 0;}
HANDLE hProc = NULL;
FILETIME ft[4];
memset(&ft,0,sizeof(ft));
if ( ( hProc = OpenProcess(
PROCESS_QUERY_INFORMATION,
FALSE, strtoul( argv[1], NULL, 10 ) ) ) != NULL )
{
__asm
{
push 0 // retn value ignored
push 20h // sizeof input buffer
lea eax,ft
push eax // inputbuffer
push 4 // processinfoclass
push hProc // Handle to Process
lea ecx,retback
push ecx // setup stack and index for sysenter
mov eax, 09ah // index of NtQueryInformationProcess
mov edx,07ffe0300h // sysenter in winxp sp3
call [edx] // kuser KiFastSystemCall pointer
retn 14h
}
retback:
printtimes(&ft[0]);
CloseHandle(hProc);
}
else
{
printf("Could not open process quitting\n ");
}
return 0;
}
void printtimes(FILETIME *ft)
{
SYSTEMTIME stime,ltime;
memset (&stime,0,sizeof(stime));
memset (<ime,0,sizeof(stime));
FileTimeToSystemTime(ft,&stime);
SystemTimeToTzSpecificLocalTime(NULL,&stime,<ime);
printf(
"%02d-%02d-%04d %02d:%02d:%02d\n",
ltime.wDay,ltime.wMonth,ltime.wYear,
ltime.wHour,ltime.wMinute,ltime.wSecond);
}
结果
time:\>proctimenew.exe
usage proctime.exe Pid
time:\>proctimenew.exe 1108
16-06-2014 16:25:51
time:\>