话题1360311的标题是:检测某个程序占用的内存(急) (200分)<br>分类:Windows API(Delphi)gztoms(2002-10-05 12:08) <br>各位大虾:<br> 有谁知道用什么API函数能检测出某一程序占用的内存,<br>相当于在“任务管理器”里的“进程”叶中所看到的一样。<br> 多谢了!!!<br> <br>kcahcn(2002-10-10 07:49) <br>任务管理器调用 NtQuerySystemInformation 。还可以用NtQueryInformationProcess.<br>两者都是本机API(Native API) . <br>也可以用GetProcessMemoryInfo 包含在PsAPI.<br>GetPMem(PID
WORD);<br>var<br> pmc: PPROCESS_MEMORY_COUNTERS;<br> cb: Integer;<br> phandle:Thandle;<br>begin<br>phandle:=OpenProcess(PROCESS_ALL_ACCESS,false,PID);<br>cb := sizeof(_PROCESS_MEMORY_COUNTERS);<br> GetMem(pmc, cb);<br> pmc^.cb := cb;<br> if GetProcessMemoryInfo(phandle, pmc, cb) then<br> ShowMessage(IntToStr(pmc^.WorkingSetSize))<br> else<br> ShowMessage('错误');<br>end;<br> <br>gztoms(2002-10-05 17:46) <br>请问kcahcn:<br> 参数PID是要传递什么?<br> <br>duducat(2002-10-05 19:00) <br>pid 进程ID<br> <br>kcahcn(2002-10-06 01:11) <br>Thanks duducat .PID -> 进程ID<br><br>下面是个用NtQueryInformationProcess的例子 : [ NT ,2K,XP ]<br>// 参考: Windows NT/2000 本机API (Gary Nebbett)<br>// Tested using Delphi 6.0, 7.0 On WinXP <br>type<br> PVM_Counters=^TVM_Counters;<br> TVM_Counters=record<br> PeakVirtualSize:ULONG;<br> VirtualSize:ULONG;<br> PagedFaultCount:ULONG;<br> PeakWorkingSetSize:ULONG;<br> WorkingSetSize:ULONG;<br> QuotaPeakPagedPoolUsage:ULONG;<br> QuotaPagedPoolUsage:ULONG;<br> QuotaPeakNonPagedPoolUsage:ULONG;<br> QuotaNonPagedPoolUsage:ULONG;<br> PagefileUsage:ULONG;<br> PeakPagefileUsage:ULONG;<br> end;<br>const ProcessVMCounters =3;<br>...<br>function NtQueryInformationProcess<br> (<br> ProcessHandle: Thandle;<br> PrcInfoClass
WORD ;<br> PrcInfo
ointer ;<br> PrcInfoLength:ULONG;<br> returnlength: TPDword<br>  
:<br> DWORD; stdcall ;external 'ntdll.dll' name 'NtQueryInformationProcess';<br>// 可以用动态调用(隐式装入)<br>....<br>// Our Function here:<br>function GetPrcVMCounters(PID
WORD):TStringList;<br>var<br>status
WORD;<br>retlen
WORD;<br>VM_Info:TVM_Counters;<br>hProcess:THandle;<br>begin<br>result:=TStringList.Create;<br>hProcess :=OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,PID);<br>status:=NtQueryInformationProcess<br> (<br> hProcess,<br> ProcessVMCounters,<br> @VM_Info,<br> sizeof(TVM_Counters),<br> @retlen<br>  
;<br>if(status<>0) then<br>begin<br> ShowMessage('NtQueryInformationProcess 失败');<br> exit;<br>end;<br>with result do<br>begin<br>Add('进程虚拟地址空间的最大数值 : '+IntToStr(VM_Info.PeakVirtualSize)+' Byte');<br>Add('进程的虚拟地址空间的大小 : '+IntToStr(VM_Info.VirtualSize)+' Byte');<br>Add('进程分页错误数目 : '+IntToStr(VM_Info.PagedFaultCount)+' Byte');<br>Add('进程的工作集列表的最大值 : '+IntToStr(VM_Info.PeakWorkingSetSize)+' Byte');<br>Add('进程的工作集列表的大小 : '+IntToStr(VM_Info.WorkingSetSize)+' Byte'); // <--- 就是这个 [
]<br>Add('填充到进程的分页池的峰值的最大值 : '+IntToStr(VM_Info.QuotaPeakPagedPoolUsage)+' Byte');<br>Add('填充到进程的分页池的峰值大小 : '+IntToStr(VM_Info.QuotaPagedPoolUsage)+' Byte');<br>Add('填充到进程的非分页池的峰值的最大值 : '+IntToStr(VM_Info.QuotaNonPagedPoolUsage)+' Byte');<br>Add('填充到进程的分页池的峰值大小 : '+IntToStr(VM_Info.QuotaNonPagedPoolUsage)+' Byte');<br>Add('进程多使用的页文件页的最大值 : '+IntToStr(VM_Info.PeakPagefileUsage)+' Byte');<br>end;<br>end;<br>// ----<br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br> Memo1.Lines:=GetPrcVMCounters(256);<br>end;<br><br>-------------------------<br>CIONO1<br> <br>duducat(2002-10-08 08:27) <br>to kcahcn <br>TPDword=PWORD;<br><br>为什么以上方法对PID=0的Idle Process进程占有的物理内存显示不正确??:))<br>2000下面应该为16K,XP下面是24K,以上方法中GetProcessMemoryInfo显示的是变化的,<br>数值根本不对,NtQueryInformationProcess则显示的为0!<br> <br>duducat(2002-10-08 08:32) <br>另外进程CPU占用率也是一个有点技术含量的问题,不知道各位大侠解决没有?<br> <br>duducat(2002-10-08 08:40) <br>最后9X下面物理内存的使用也是个头痛的问题,嘻嘻……<br>好像据我所知就TaskInfo2002解决的比较圆满(收费),<br>prcview(显示不正确)和processwalker则根本没有解决……(免费)<br>我想这是收费与免费的小小区别吧!<br>……<br>题外话,国产的进程管理器俺真是搞不懂,什么技术含量的问题都没有涉及<br>和解决,就要注册和收注册费了,真是丢中国人的脸……<br>严重了!!!!!!见谅!<br> <br>yyk518(2002-10-08 08:47) <br>做这些东西还有意义吗?技术含量再高,高得过M$吗?[
]<br> <br>duducat(2002-10-08 09:17) <br>to yyk518 <br>那你永远做MS的最“忠实”用户好了:))好乖亚……<br>学计算机干吗??对你有意义嘛?<br>因为你和你的子孙学几百年都不会超过MS的技术高峰的<br><br> <br>yyk518(2002-10-09 08:54) <br>呵呵,这么大火气干嘛呢?<br>你不也在做MS的忠实用户吗?!你要做的什么破软件不也是要在WINDOWS下运行,舔MS的<br>屁股吗?有种开发一套DUDUCAT OS出来看看啊!瞎牛B!![
]<br> <br>duducat(2002-10-09 12:12) <br>白痴……只知道MS……<br> <br>duducat(2002-10-09 12:43) <br>干吗让我开发os??笑死人了……<br>我又不是搞电脑的,也不需要靠它来赚钱谋生……<br>终于知道中国的IT业技术水平为什么这么低,原来是有一些猪头加奴隶充实在当中……<br>另外,我是人不是牛,人为什么要和牛作比较了,弱智……<br>做人不知道廉耻,就猪狗不如了……<br>什么都不知道,还这么神气……佩服佩服呀<br>哈哈哈哈哈哈哈!!!<br>天下真是无其不有……哈哈哈哈哈哈<br><br>to kcahcn<br>要讨论技术问题的,以后再跟你联系吧!<br> <br>yyk518(2002-10-09 16:19) <br>哦?你不是牛?可我怎么看你都比牛还牛啊!也许,是牛的后代也说不定,哈哈哈<br>你既然不是搞电脑的,又在这里瞎起什么哄!<br>知道MS没什么不好吧?!还“中国的IT”呢,谈到IT,不知道MS行吗?蠢猪!!!<br>呀,别生气啊!竟把猪比作了你(猪听见了可要生气了)<br>>>什么都不知道,还这么神气 <br>究竟是谁神气了?初出茅庐就不知天高地厚,连MS都不放在眼里了!如果中国人真的能<br>做出超越MS的软件,我当然非常高兴!但问题是,我们与MS的差距还很大,所以我们必需<br>好好向人家学习,多做些有益的事!不要两眼向天的走路,那样,你迟早会摔死的!<br> <br>duducat(2002-10-09 17:01) <br>做人不知道廉耻,就猪狗不如了……<br>什么都不知道,还这么神气……佩服佩服呀<br>哈哈哈哈哈哈哈!!!<br>天下真是无其不有……哈哈哈哈哈哈<br><br> <br>duducat(2002-10-09 18:11) <br>教教你吧……人不可有傲气,但不能无傲骨……能者为师<br>不过你属牛的,跟你说了也不懂,反正是对牛弹琴……<br>一副奴才像!不过MS好喜欢你的啦,觉得你好哟好可爱哟,呆会买糖给你吃!<br>(旁白:然后高呼打倒unix,Linux,Java……他们牛个屁呀,能玩服务器,能跨平台嘛?……<br> 嘻嘻,都不如我的MS牛牛牛牛牛(省略5万字)……没有想到太高兴,碰了石头,最后“扑哧”<br> 摔了个狗啃屎……5555555道:“MS,MS,……救救我!!他们说你坏话了,<br> 我要你打他们的小屁股……”然后奋力举起MS掉在粪坑黑乎乎糖,<br> 叫道:“MS的糖是世界最香的糖啦……”, 咬了起来。没想到却是个屁,<br> 还得意的叫道,“MS的屁也是最世界最最香的”……)<br>当然领导也很喜欢你这种牛了,帮着擦擦皮鞋,拍拍马屁,<br>赏你个吃“世界上最香的屁”吃吃……哈哈哈哈哈<br>干吗学电脑了,这又不会那也不会编,又要冒充IT人士,这到没有什么!(人各有所长)<br>可恶的是还专门打击比那些比你懂得多的人,心理寻思(他会那么多有啥用?<br>能比XX强嘛?能牛过XX吗?再厉害也不过是个中国人罢了……嘻嘻,<br>到最后还不如我嘴皮子1/100功效了……)<br>…………<br>俺心地善良,以后谁做了大领导一定推荐你这头牛去去拎拎皮鞋哟,呵呵!<br>编程就免了(即没有创意,又不肯向别人学习……)<br>哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈<br>…………<br>to 其他各位,对不起了,浪费你们的时间了……<br>非技术问题,到此为止!<br> <br>kcahcn(2002-10-10 08:06) <br>对于 system process “系统进程“要先设置SeDebugPrivilege才能用OpenProcess。<br>飞到这儿: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q131065<br>用这个方法 对 System Idle Process好像也没有用!!!<br>TaskManager,Pview 调用的是NtQuerySystemInformation所以没出现这个问题。<br>我用了那个函数(服务)果然没问题。可以得到System Idle Process所占的内存 (20kb WinXP)。<br>更多资料关于NtQuerySystemInformation请参考"Windows Nt/2000 本机API"。<br>关于CPU的占用率可以用GetProcessTimes 。(用Native API 也可以)<br>http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=3816527f.149304919%40nntp.cts.com<br><br>看 : http://groups.google.com/groups?q=GetProcessTimes+CPU&ie=UTF-8&oe=UTF-8&hl=en&btnG=Google+Search<br>-----<br>CIONO1<br> <br>yyk518(2002-10-10 08:32) <br>TO duducat:<br>呵呵,没想到我随意说说,竟把这头笨牛给惹疯了,前言不搭后语,牛B哄哄地拉了一大堆<br>牛屎,哈哈哈,我看你不但瞎牛还很蠢,是即有牛的基因又有猪的血统,莫不是猪牛杂交<br>货?[
][
][
]<br> <br>duducat(2002-10-10 12:37) <br>垃圾就是垃圾,呵呵,从里到外都是的……<br>……<br>to kcahcn <br>thanx!我说这些问题去年其实已经解决了……只是想讨论一下还有没有别的更好方法!<br>小日本的Processwalker(免费)<br>http://www001.upp.so-net.ne.jp/yamashita/<br>中还实现了其他很多有用的功能,如:进程拥有的特权之类。这些没有实现得了<br>所以找你的……<br>交个朋友吧,有空来我这里玩……,呵呵<br>代我向你妹妹问好……:)<br> <br>duducat(2002-10-10 21:21) <br>to gztoms<br>把分加给kcahcnkcahcn,他比我大方……<br><br>to kcahcn 再见了……希望以后还有机会跟你联系!我已经把它翻译成Delphi……<br>我用的不是这个函数!不过我现在有点喜欢NTQuerySystemInformation了!虽然它<br>存在不稳定因素:P<br><br>#include <windows.h><br>#include <stdio.h><br>#include <stdlib.h><br><br>#ifndef STATUS_INFO_LENGTH_MISMATCH<br>#define STATUS_INFO_LENGTH_MISMATCH ((DWORD )0xC0000004L)<br>#endif<br><br>typedef struct<br>{<br> FILETIME ftCreationTime;<br> DWORD dwUnknown1;<br> DWORD dwStartAddress;<br> DWORD dwOwningPID;<br> DWORD dwThreadID;<br> DWORD dwCurrentPriority;<br> DWORD dwBasePriority;<br> DWORD dwContextSwitches;<br> DWORD dwThreadState;<br> DWORD dwWaitReason;<br> DWORD dwUnknown2[5];<br>} THREADINFO, *PTHREADINFO;<br><br>#pragma warning( disable:4200 ) // Zero sized array<br>typedef struct<br>{<br> DWORD dwRelativeOffset; //相对偏移量<br> DWORD dwThreadCount; //线程数目<br> DWORD dwUnknown1[6];<br> FILETIME pfCreateTime; <br> DWORD dwUnknown2[5];<br> WCHAR* pszProcessName; //不带路径的名称<br> DWORD dwBasePriority; //优先级 <br> DWORD dwProcessID; //进程ID<br> DWORD dwParentProcessID; //父进程ID<br> DWORD dwHandleCount; //句柄数目<br> DWORD dwUnknown3;<br> DWORD dwUnknown4;<br> DWORD dwVirtualBytesPeak;<br> DWORD dwTotalVirtualBytes;<br> DWORD dwPageFaults;<br> DWORD dwWorkingSetPeak; <br> DWORD dwTotalWorkingSet; //占用物理内存大小 <br> DWORD dwPeakPagedPoolUsagePages;<br> DWORD dwTotalPagedPoolUsagePages;<br> DWORD dwPeakNonPagedPoolUsagePages;<br> DWORD dwTotalNonPagedPoolUsagePages;<br> DWORD dwPageFileBytesPeak;<br> DWORD dwPrivateBytes;<br> DWORD dwPageFileBytes;<br> DWORD dwUnknown7[4];<br> THREADINFO ti[0];<br>} _PROCESSINFO, *PPROCESSINFO;<br>#pragma warning( default:4200 )<br><br>DWORD (__stdcall *NtQuerySystemInformation )(ULONG,PVOID,ULONG,ULONG);<br><br>void ShowPI(void)<br>{<br> PBYTE pbyInfo = NULL;<br> PPROCESSINFO pProcessInfo;<br> DWORD dwSize = 0x4000;<br> WCHAR *pname;<br><br> if (!NtQuerySystemInformation)<br> NtQuerySystemInformation=(DWORD (__stdcall*)(ULONG,PVOID,ULONG,ULONG))<br><br>GetProcAddress(GetModuleHandle("ntdll.dll"
,"NtQuerySystemInformation"
;<br><br> pbyInfo=(PBYTE) malloc(dwSize);<br><br> if (pbyInfo)<br> {<br> for(;
<br> {<br> memset(pbyInfo,0,dwSize);<br><br><br>if(NtQuerySystemInformation(5,pbyInfo,dwSize,0)!=STATUS_INFO_LENGTH_MISMATCH<br>)<br> break;<br><br> dwSize += 0x1000;<br><br> pbyInfo=(PBYTE) realloc(pbyInfo,dwSize);<br> }<br><br> pProcessInfo = ( PPROCESSINFO ) pbyInfo;<br><br> for(;
<br> {<br> pname=pProcessInfo->pszProcessName;<br><br> if (!pname)<br> pname=(L"Idle"
;<br><br> printf("%-40ls %-12lu %12luK/n",<br> pname,<br> pProcessInfo->dwProcessID,<br> pProcessInfo->dwTotalWorkingSet/1024ul<br> );<br><br> if ( pProcessInfo->dwRelativeOffset == 0 )<br> break;<br><br><br>pProcessInfo=(PPROCESSINFO)((PBYTE)pProcessInfo+pProcessInfo->dwRelativeOffset);<br> }<br><br> free( pbyInfo );<br> } <br>}<br><br>int main(void)<br>{<br> ShowPI();<br> getchar();<br> return 0;<br>}<br><br> <br>duducat(2002-10-10 21:28) <br>to gztoms <br>9X的自己研究吧……实在不知道,明年再联系!<br>to kcahcn <br>人生无常,唯朋友最值得珍惜……<br> <br>kcahcn(2002-10-10 22:17) <br>to duducat : Thanks alot;<br>我会把我写的代码(经过改进后)发到你的邮箱。(还要一段时间)<br>NativeAPI有很多东西可以研究。很多人在研究。多多看看Nebbett写的那本书。<br>有什么冬冬告诉我。[
]<br>to gztoms :我不是为了积分而回答。我不需要积分。Knowledge is free .<br><br>CIONO1<br> <br>gztoms(2002-10-11 15:43) <br>谢谢kcahcn,duducat<br> <br><br>duducat-50,kcahcn-150,的回答最终被接受。