请教一个关于进程的问题

baiyunfei 2005-03-08 10:27:20
我想取得系统中各个进程的I/O读取数,要怎么做啊?我知道有个API ,GetProcessIoCounters
,可我不知道怎么用(主要是怎么取参数,传递的问题)。大家帮帮我吧!
...全文
294 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
胖河马 2005-03-14
  • 打赏
  • 举报
回复
定译成动态数组,GetProcessIoCounters会改变l、temp(数组指向的地址)、jj、k
定译成静态数组,GetProcessIoCounters会改变l、temp(改变内容不祥)
应该与打开自己的进程无关,因为即使那么做也会出错!
胖河马 2005-03-11
  • 打赏
  • 举报
回复
再次设置my.dwSize是因为他的值被改变了,这是编译成p-code时的情况
编译成本机代码后my.dwSize、jj和l也改变了,而且如果用另一个变量备份他们的值,那么这个备份变量也会被修改。这是生成符号调试文件后用vs2003跟踪到的结果,但原因我不清楚
homezj 2005-03-11
  • 打赏
  • 举报
回复
修改了值?这一点,我不这样认为。当然,我没有测试这段代码,只能谈点想法:
1、我不知道你GetProcessIoCounters是怎么声明的,我想句柄肯定是Byval传递的,所以它不会改变jj原值。
2、遍历所有进程失败的最大可能是某次调用出错,造成Process32Next不能继续

你这个代码,存在问题还是很多的
可能错误先例举一二,后面发现再说:
--------------------------------
Loop Until (Process32Next(l, my) < 1)这句肯定有问题
应改为
Loop Until (Process32Next(l, my) = 0)
不知道,你是什么习惯,前面,我就说过句柄是Long型,可正可负,为什么还犯这种错误?
这在遇到返回句柄为负值时,就会让你的遍历突然停止!是这个过程的核心错误!
----------------------------------

后面my.dwSize = Len(my)这句去掉,并把它替换掉前面那句my.dwSize = 1060,
PROCESSENTRY32结构中的szExeFile长度声明,是可根据需要改变的,一般使用MAX_PATH=260就可以,估计你声明时使用了1024,这样应该也没问题,但你认定它就是1060,就不好了,加上后面再来个多余的my.dwSize = Len(my),我想可能会引出问题,其实只需一开始赋值一次就行了。

使用API,声明的灵活性很大,并不是一成不变,光看代码不看声明,有时是发现不了问题。还可能引来莫名奇妙的错误。结构的声明,关系到传递的长度,弄错了,有时并不会立即看出来,但却可能随时造成程序崩溃。
homezj 2005-03-11
  • 打赏
  • 举报
回复
怎么尽出怪事呀!Redim编译后也会报错!
不过,这倒是让我突然想到了一个,昨天看贴时,就想到的问题,只是后来忘说了:

你这样遍历肯定会用OpenProcess访问自已所在的程序进程,这样对自己GetProcessIoCounters的调用会不会产生什么暂时锁定或改变?在IDE环境,外交由VB负责,看不出来,编译后可就全是自己的事了。Redim出错会不会是这个原因?

CreateToolhelp32Snapshot建立的是静态快照,不会产生任何影响!但OpenProcess后再GetProcessIoCounters,天知道会出什么事。

以前写过进程程序,都是在启动时用GetCurrentProcessId先将自己的ProcessId获取并保存,建立快照时,把自己跳过,当时虽没遇过OpenProcess自己出错的事,只是感觉这样做会有问题。

我试过OpenProcess自己,再TerminateProcess,是可行的。GetProcessIoCounters会带来什么,就不得而知了
baiyunfei 2005-03-11
  • 打赏
  • 举报
回复
这里是直接定义了数组的上界。我开始是打算用redim的,可是编译成exe后,运行会报内存不能为written的错误,帮我看下有何解决办法。毕竟进程数量是未知的
baiyunfei 2005-03-11
  • 打赏
  • 举报
回复
不错,用数组存放是个好办法,不会出现改值的问题,这是我修改后的代码:
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long

Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal ApphProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function GetProcessIoCounters Lib "kernel32" (ByVal hProcess As Long, lpIoCounters As IO_COUNTERS) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function OpenProcessToken Lib "Advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long

Private Type PROCESSENTRY32
dwSize As Long
cntUsage As Long
th32ProcessID As Long
th32DefaultHeapID As Long
th32ModuleID As Long
cntThreads As Long
th32ParentProcessID As Long
pcPriClassBase As Long
dwFlags As Long
szExeFile As String * 1024
End Type

Private Type IO_COUNTERS
ReadOperationCount As Long
WriteOperationCount As Long
OtherOperationCount As Long
ReadTransferCount As Long
WriteTransferCount As Long
OtherTransferCount As Long
End Type

Private Type LUID
UsedPart As Long
IgnoredForNowHigh32BitPart As Long
End Type

Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
TheLuid As LUID
Attributes As Long
End Type

Const TH32CS_SNAPHEAPLIST = &H1
Const TH32CS_SNAPPROCESS = &H2
Const TH32CS_SNAPTHREAD = &H4
Const TH32CS_SNAPMODULE = &H8
Const TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST Or TH32CS_SNAPPROCESS Or TH32CS_SNAPTHREAD Or TH32CS_SNAPMODULE)
Const TH32CS_INHERIT = &H80000000
'///OpenProcess的常量
Const STANDARD_RIGHTS_REQUIRED = &HF0000
Const SYNCHRONIZE = &H100000
Const PROCESS_TERMINATE = &H1& ' Used to kill a process
Const PROCESS_CREATE_THREAD = &H2&
Const PROCESS_VM_OPERATION = &H8&
Const PROCESS_VM_READ = &H10&
Const PROCESS_VM_WRITE = &H206
Const PROCESS_DUP_HANDLE = &H40&
Const PROCESS_CREATE_PROCESS = &H80&
Const PROCESS_SET_QUOTA = &H100&
Const PROCESS_SET_INFORMATION = &H200& ' Used to set information on a process (like priority)
Const PROCESS_QUERY_INFORMATION = &H400&
Const PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)

Const TOKEN_QUERY = &H8
Const TOKEN_ADJUST_PRIVILEGES = &H20
Const SE_PRIVILEGE_ENABLED = &H2

'得到进程填充listview
Private Sub AdjustToken()
Dim lngTokenHandle As Long
Dim tmpLuid As LUID
Dim tkp As TOKEN_PRIVILEGES
Dim tkpTemp As TOKEN_PRIVILEGES
OpenProcessToken GetCurrentProcess(), (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), lngTokenHandle
LookupPrivilegeValue "", "SeDebugPrivilege", tmpLuid
tkp.PrivilegeCount = 1
tkp.TheLuid = tmpLuid
tkp.Attributes = SE_PRIVILEGE_ENABLED
AdjustTokenPrivileges lngTokenHandle, False, tkp, Len(tkpTemp), tkpTemp, 0
End Sub

Private Sub Command1_Click()
Dim my As PROCESSENTRY32
Dim ioc As IO_COUNTERS
Dim jj As Long
Dim l As Long
Dim l1 As Long
Dim mlistitem As ListItem
ListView1.ListItems.Clear
' List1.Clear
l = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If l Then
my.dwSize = Len(my)
Dim temp(50) As Long
Dim i As Integer
i = 0
If (Process32First(l, my)) Then '遍历第一个进程
Do
temp(i) = my.th32ProcessID
i = i + 1
Loop Until (Process32Next(l, my) = 0) '遍历所有进程知道返回值为False
End If
Dim k As Integer
For k = 0 To i - 1
Set mlistitem = ListView1.ListItems.Add(, , temp(k))
jj = OpenProcess(PROCESS_ALL_ACCESS, 0, temp(k)) '返回进程句柄
GetProcessIoCounters jj, ioc
mlistitem.SubItems(3) = ioc.ReadOperationCount '进程的 I/O 读取
mlistitem.SubItems(4) = ioc.OtherOperationCount '进程的 I/O 写入
CloseHandle (jj)
Next
l1 = CloseHandle(l)
End If
End Sub
Private Sub Form_Load()
Call AdjustToken
ListView1.ListItems.Clear
ListView1.FullRowSelect = True
ListView1.View = lvwReport
End Sub
homezj 2005-03-11
  • 打赏
  • 举报
回复
我还想了另一个方案,是不是可以,先将进程遍历后,将ProcessID存入数组,在另一个循环中用OpenProcess再打开,总感觉现在这种方式看了很不习惯。
homezj 2005-03-11
  • 打赏
  • 举报
回复
IO_COUNTERS的结构定义呢?
核心问题还是GetProcessIoCounters调用上,我就是没用过这个函数

因为Process32First与Process32Next我编译过多个这类程序,重没见API会修改dwSize值的现象,这也完全违背API的正常规则,更不可思议的是会修改Byval传值的VB内部变量。这样的修改要是发生,那不天下大乱了!

唯一能让我解释这种情况的,可能就是内存越界读写了,所以我想:会不会IO_COUNTERS这个结构定义上有出入,造成API读写了不属于这个结构范围的内存,从而导致一些值被修改。
baiyunfei 2005-03-11
  • 打赏
  • 举报
回复
homezj 提到的一些错误,我已经改正,只是后面那句 my.dwSize= Len(my) 不能去掉,正如bdhh(Silent)所说的那样。去了就只能列举到几个进程。
我的函数声明如下,可以看下有没问题:
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal ApphProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function GetProcessIoCounters Lib "kernel32" (ByVal hProcess As Long, lpIoCounters As IO_COUNTERS) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function OpenProcessToken Lib "Advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
homezj 2005-03-10
  • 打赏
  • 举报
回复
1、管理员身份登录运行程序

2、AdjustToken只需在Form_load事件中调用一次

3、AdjustToken过程有问题:
tkp.PrivilegeCount = 1
tkp.TheLuid = tmpLuid
tkp.Attributes = SE_PRIVILEGE_ENABLED
三句要放到LookupPrivilegeValue后面
baiyunfei 2005-03-10
  • 打赏
  • 举报
回复
感谢大家!我把分数加到100
我按照 bdhh(Silent) 的方法做了,可是没效果,数值都是0呢。麻烦再看看,是什么原因
'函数声明
.....
Private Sub AdjustToken()
Dim lngTokenHandle As Long
Dim tmpLuid As LUID
Dim tkp As TOKEN_PRIVILEGES
Dim tkpTemp As TOKEN_PRIVILEGES
tkp.PrivilegeCount = 1
tkp.TheLuid = tmpLuid
tkp.Attributes = SE_PRIVILEGE_ENABLED
OpenProcessToken GetCurrentProcess(), (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), lngTokenHandle
LookupPrivilegeValue "", "SeDebugPrivilege", tmpLuid
AdjustTokenPrivileges lngTokenHandle, False, tkp, Len(tkpTemp), tkpTemp, 0
End Sub
Private Sub Command1_Click()
Dim my As PROCESSENTRY32
Dim ioc As IO_COUNTERS
Dim jj As Long
Dim l As Long
Dim l1 As Long
Dim mlistitem As ListItem
ListView1.ListItems.Clear
' List1.Clear
l = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If l Then
my.dwSize = 1060
If (Process32First(l, my)) Then '遍历第一个进程
Do
Call AdjustToken
Set mlistitem = ListView1.ListItems.Add(, , my.th32ProcessID)
mlistitem.SubItems(1) = my.th32ParentProcessID
mlistitem.SubItems(2) = my.szExeFile
jj = OpenProcess(PROCESS_ALL_ACCESS, 0, my.th32ProcessID) '返回进程句柄
GetProcessIoCounters jj, ioc
mlistitem.SubItems(3) = ioc.ReadOperationCount '进程的 I/O 读取
mlistitem.SubItems(4) = ioc.OtherOperationCount '进程的 I/O 写入
CloseHandle (jj)
my.dwSize = Len(my)
Loop Until (Process32Next(l, my) < 1) '遍历所有进程知道返回值为False
End If
l1 = CloseHandle(l)
End If
End Sub

大家帮忙测试下
baiyunfei 2005-03-10
  • 打赏
  • 举报
回复
见鬼了。原来要这样,受教啦!
胖河马 2005-03-10
  • 打赏
  • 举报
回复
GetProcessIoCounters不光修改l,而且修改jj

我试着存储一个备份,等调用后恢复,结果备份也被改了!!!!
jj1=jj
GetProcessIoCounters jj, ioc
jj=jj1

后来把jj1的声明改成static,然后编译成本机代码,测试通过

最后的解决办法就是将l和jj的声明改成static,但造成这种情况的原因不明
胖河马 2005-03-10
  • 打赏
  • 举报
回复
我前面回复过。编译后,调用GetProcessIoCounters会修改l的值,原因不明,而且有可能导致程序出错。编译成p-code才可以正常运行
baiyunfei 2005-03-10
  • 打赏
  • 举报
回复
我晕!这个程序DEBUG的时候都正确了,可当我生成 EXE 后再运行,又出问题了,只能列出前2个进程!麻烦再帮帮我,看是什么原因。
baiyunfei 2005-03-10
  • 打赏
  • 举报
回复
哈!homezj(小吉) 说的没错,终于弄好了。感谢各位的热心帮助!
请homezj(小吉)和 bdhh(Silent) 到
http://community.csdn.net/Expert/topic/3840/3840106.xml?temp=.2578089
再接点分,辛苦了!
胖河马 2005-03-10
  • 打赏
  • 举报
回复
呵呵,那个确实应该放在LookupPrivilegeValue后面
baiyunfei 2005-03-09
  • 打赏
  • 举报
回复
终于有人回复了!大家帮我看下这段程序为什么取不到所有的程序的I/O 读取,写入数。取出来怎么都是0啊,而且也不能遍历所有进程!!

Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long

Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal ApphProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function GetProcessIoCounters Lib "kernel32" (ByVal hProcess As Long, lpIoCounters As IO_COUNTERS) As Long
Private Type PROCESSENTRY32

dwSize As Long

cntUsage As Long

th32ProcessID As Long

th32DefaultHeapID As Long

th32ModuleID As Long

cntThreads As Long

th32ParentProcessID As Long

pcPriClassBase As Long

dwFlags As Long

szExeFile As String * 1024

End Type

Private Type IO_COUNTERS
ReadOperationCount As Long
WriteOperationCount As Long
OtherOperationCount As Long
ReadTransferCount As Long
WriteTransferCount As Long
OtherTransferCount As Long

End Type


Const TH32CS_SNAPHEAPLIST = &H1

Const TH32CS_SNAPPROCESS = &H2

Const TH32CS_SNAPTHREAD = &H4

Const TH32CS_SNAPMODULE = &H8

Const TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST Or TH32CS_SNAPPROCESS Or TH32CS_SNAPTHREAD Or TH32CS_SNAPMODULE)

Const TH32CS_INHERIT = &H80000000
'///OpenProcess的常量
Const STANDARD_RIGHTS_REQUIRED = &HF0000
Const SYNCHRONIZE = &H100000
Const PROCESS_TERMINATE = &H1& ' Used to kill a process
Const PROCESS_CREATE_THREAD = &H2&
Const PROCESS_VM_OPERATION = &H8&
Const PROCESS_VM_READ = &H10&
Const PROCESS_VM_WRITE = &H206
Const PROCESS_DUP_HANDLE = &H40&
Const PROCESS_CREATE_PROCESS = &H80&
Const PROCESS_SET_QUOTA = &H100&
Const PROCESS_SET_INFORMATION = &H200& ' Used to set information on a process (like priority)
Const PROCESS_QUERY_INFORMATION = &H400&
Const PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)

'得到进程填充listview

Private Sub Command1_Click()

Dim my As PROCESSENTRY32
Dim ioc As IO_COUNTERS
Dim jj As Long

Dim l As Long

Dim l1 As Long

Dim mlistitem As ListItem

ListView1.ListItems.Clear


' List1.Clear

l = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)

If l Then

my.dwSize = 1060

If (Process32First(l, my)) Then '遍历第一个进程

Do

Set mlistitem = ListView1.ListItems.Add(, , my.th32ProcessID)

mlistitem.SubItems(1) = my.th32ParentProcessID
mlistitem.SubItems(2) = my.szExeFile
jj = OpenProcess(PROCESS_ALL_ACCESS, 0, my.th32ProcessID) '返回进程句柄
GetProcessIoCounters jj, ioc
mlistitem.SubItems(3) = ioc.ReadOperationCount '进程的 I/O 读取
mlistitem.SubItems(4) = ioc.WriteOperationCount '进程的 I/O 写入
CloseHandle (jj)

Loop Until (Process32Next(l, my) < 1) '遍历所有进程知道返回值为False

End If

l1 = CloseHandle(l)

End If

End Sub
胖河马 2005-03-09
  • 打赏
  • 举报
回复
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocessiocounters.asp
baiyunfei 2005-03-09
  • 打赏
  • 举报
回复
我自己也顶!!
加载更多回复(14)

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧