用多个TIMER分别定时取多个不同进程信息...
每个TIMER代码基本相同...但是却不能完全取打开进程..总会有一个或多个TIMER得不到信息...我把其中一个TIMER的代码贴出来...请大家帮我看看..问题出在哪
private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
// 获取APPSERVER1进程信息 HMODULE hMods[1024];
// 模块结构体大小
DWORD cbNeeded;
HANDLE hProcess_One_Process;
HANDLE hProcess_All_Process; // 进程建立,退出,系统调用,用户调用时间
ULONGLONG createTime, exitTime, kernelTime, userTime;
BOOL bEmpt;
BOOL bGet_Fail;
DWORD dPid; // 进程内存结构
PROCESS_MEMORY_COUNTERS sTr_pMemory; // 进程结构
PROCESSENTRY32 sTr_Of_Process; // 系统内存结构
MEMORYSTATUSEX sTr_SysMemory;
sTr_SysMemory.dwLength = sizeof (sTr_SysMemory); String^ sFolder;
String^ sExeNameTemp;
String^ sExeName;
String^ sPath = label19->Text;
String^ sSlash = "\\";
String^ sFolderPath = "Program Files";       //进程所以文件夹及文件名
String^ sExeName2__ = "sqlservr.exe"; sTr_Of_Process.dwSize = sizeof(sTr_Of_Process); // 得到所有进程句柄
hProcess_All_Process = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
// 获取第一个进程结构
if (Process32First(hProcess_All_Process, &sTr_Of_Process)){
while ( Process32Next(hProcess_All_Process, &sTr_Of_Process))
{ // 获取进程PID
dPid = sTr_Of_Process.th32ProcessID;
// 打开进程
hProcess_One_Process = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, dPid); // 进程路径
if (EnumProcessModules(hProcess_One_Process, hMods, sizeof(hMods), &cbNeeded))
{
WCHAR szModName[MAX_PATH]; // 句柄数
label17->Text = ((UInt32)sTr_Of_Process.cntUsage).ToString();
GetModuleFileNameEx( hProcess_One_Process, hMods[0], szModName, sizeof(szModName) ); // 路径
label19->Text = gcnew String(szModName);
}
else
{
label19->Text = "Unknow!";
}
// 取进程所在文件夹
sFolder = "";
sExeNameTemp = "";
sExeName = "";
sPath = label19->Text; // 斜杠字符数量
int iCountOfSlash = 0;
int i = 0;
for ( i; i < sPath->Length; i++){
if (String::Compare(sPath->Substring(i,1), sSlash) & (iCountOfSlash == 1) )
{
sFolder = sFolder + sPath->Substring(i,1);
}
else
{
if ( String::Compare(sPath->Substring(i,1), sSlash) == 0 )
iCountOfSlash++;
if ( iCountOfSlash >= 2 )
break;
}
}
// 程序名
int k = sPath->Length - 1;
int iCountOfSlash2 = 0;
for ( k; k > 0; k--){
if ( String::Compare(sPath->Substring(k,1), sSlash) )
{
sExeNameTemp = sExeNameTemp + sPath->Substring(k,1);
}
else
{
iCountOfSlash2 ++;
if ( iCountOfSlash >= 1 )
break;
}
}
k = sExeNameTemp->Length - 1;
for ( k; k >= 0; k--){
sExeName = sExeName + sExeNameTemp->Substring(k,1);
sExeName = sExeName->ToLower();
}
// 取APPSERVER1句柄,PID
if ( (String::Compare(sFolder, sFolderPath, true) == 0) & (String::Compare(sExeName, sExeName2__ ,true) ==0) ){ // 内存占用
bGet_Fail = GetProcessMemoryInfo(hProcess_One_Process, &sTr_pMemory, sizeof(sTr_pMemory));
label12->Text = ( (UInt32)sTr_pMemory.WorkingSetSize / 1024 ).ToString() + " K"; // 获取进程内存使用峰值
label13->Text = ( (UInt32)sTr_pMemory.PeakWorkingSetSize / 1024 ).ToString() + " K"; // 路径中文件夹名
label7->Text = sFolder;
// PID 
label6->Text = ((UInt32)dPid).ToString(); // 进程名
label4->Text = gcnew String(sTr_Of_Process.szExeFile); // 线程数
label16->Text = ((UInt32)sTr_Of_Process.cntThreads).ToString(); // 句柄数
//label17->Text = ((UInt32)sTr_Of_Process.dwFlags).ToString();
// 获取进程CPU时间
::GetProcessTimes(hProcess_One_Process, (LPFILETIME)&createTime, (LPFILETIME)&exitTime, (LPFILETIME)&kernelTime, (LPFILETIME)&userTime);
UInt32 totalSeconds = UInt32(((kernelTime + userTime) / 10000000));
UInt32 seconds = totalSeconds % 60;
UInt32 minutes = totalSeconds / 60 % 60;
UInt32 hours = totalSeconds / 60 / 60 % 24;
UInt32 days = totalSeconds / 60 / 60 / 24;
String^ CpuTime = L"";
if (days != 0)
CpuTime += days.ToString() + "天";
if (hours != 0)
CpuTime += hours.ToString() + "小时";
if (minutes != 0)
CpuTime += minutes.ToString() + "分";
if (seconds != 0)
CpuTime += seconds.ToString() + "秒";
label15->Text = CpuTime;
// 关闭进程句柄
CloseHandle( hProcess_One_Process );
break;
} //关闭进程
CloseHandle( hProcess_One_Process );
Process32Next(hProcess_All_Process, &sTr_Of_Process); }

CloseHandle( hProcess_All_Process );
//GlobalMemoryStatusEx(&sTr_SysMemory);
//label32->Text = ((UInt32)sTr_SysMemory.ullTotalPhys/1024).ToString() ;
}

解决方案 »

  1.   

    该代码能获取指定进程名.进程ID.程序名.程序所在完整路.进程线程数.CPU时间.内存占用等..还有一个问题:现在还差句柄数.不知怎样可以得到.望大虾们指点....
      

  2.   

    我的系统是2000,不能用GetProcessHandleCount.第一个问题是怎么回事呢?我取不全想要的进程..只能取一两出来...而且运行起来很不稳定.任务管理器里面可以看到进程..但我就是取不全.
      

  3.   

    如果是2000那只能调用ZwQueryInformationProcess了,你在网上搜索一下这个函数,其它信息也可以通过这个函数来获取。
    第1个问题,不知道你为何用多个Timer,是多线程吗?如果是多线程可能会有冲突,可以加同步对象试试。另外Process32First之后要用do...while循环,否则会丢失第1个;还有OpenProcess需要SeDebugPrivilege权限。
      

  4.   

    cnzdgs ,我可以加你QQ或者用邮箱把整个程序传给你吗?用多个Timer,是每一个TIMER负责定时取一个指定进程的信息.每个TIMER代码差不多.惟一不同的只是取出来的信息放入不同的标签框,以及进程的名称..没有用多线程.Process32First得到第一个进程.PID是0.这个我不需要.只想跟踪几个.比如WORD,QQ之类的
    String^   sFolderPath   =   "Program   Files";               //进程所以文件夹及文件名 
    String^   sExeName2__   =   "sqlservr.exe"; 
    这里定义的是进程所根目录的第一个文件名.和程序名.我刚学用VC.这个程序能写到这种程序..多谢你们的帮助!
      

  5.   

    //   得到所有进程句柄 
    hProcess_All_Process   =   CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,   0); 这一句有没有问题..我调试的时候在任务管理器里面可以看到进程.比如QQ.但是用EnumProcessModules却得到
      

  6.   

    我不上QQ,我的邮箱:[email protected]
    我建议你还是自己来找问题,从而提升自己的能力,当你遇到困难时大家可以给你一些提示和建议。
    对于目前的问题,你应该在各个函数调用后(主要是OpenProcess),判断是否成功,如果失败则取出错误码,设断点查看或者把错误码显示出来,然后再根据错误码判断可能的原因。
      

  7.   

    打开进程时怎样给予SeDebugPrivilege权限呢?
      

  8.   

    BOOL EnableDebugPrivilege()
    {
    HANDLE token;
    TOKEN_PRIVILEGES tp;
    LUID luid; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) return FALSE;
    if (!LookupPrivilegeValue(NULL, _T("SeDebugPrivilege"), &luid)) return FALSE;
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    tp.Privileges[0].Luid = luid;
    return AdjustTokenPrivileges(token, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
    }程序初始化的时候执行一次即可。
      

  9.   

    HANDLE token;
    TOKEN_PRIVILEGES tp;
    LUID luid;
    LPCWSTR LTEMP1 = L"ntdll";   
    BOOL a,b,c;
    a = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token);
    b = LookupPrivilegeValue(NULL, LTEMP1, &luid);
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    tp.Privileges[0].Luid = luid;
    c = AdjustTokenPrivileges(token, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);报错.fatal error LNK1120: 3 个无法解析的外部命令
    在网上查了一下.
    我把这段代码放在private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) 
      

  10.   

    我的账号是ADMINISTRATOR权限的.而且我想取的进程是有时候能打得..有时不能打开...你运行程序之后发现这个问题.
    比如我取的是WORD.EXCEL.POWERPOINT.等进程信息...界面只显示一个或两个进程信息.但是我关闭一个,比如WORD之后.另外的进程信息就会显示出来.
      

  11.   

    Link报错需要导入Advapi32.lib来解决。
      

  12.   

    在我的电脑上,Office的程序都不在Program Files下面,运行你的程序时上面全都是Unkown和0,只有下面的CPU和内存有数据。不过我已经看出了问题,就是多线程的问题。因为每个Timer每次都会创建一个线程,各个线程都执行CreateToolhelp32Snapshot,相互影响,使每个线程都不能查到所有进程。建议你改成只有一个Timer。另外提一下,String中有个Split函数,可以拆分字符串,不用逐个找\。再多说一句,你的代码实在是太长了,应该缩减到20%左右,不过你刚开始学VC,以后逐渐就知道该怎么做了。
      

  13.   

    改成一个TIMER我还暂时没想到该怎么做...感觉没有用多个TIMER直观.请问没有其他办法了吗?只能用一个TIMER吗?
      

  14.   

    用多个Timer则需要线程同步,用一个Timer是最简单的,而且也没必要用多个Timer。你可以把取进程信息的几个Timer合成一个,在这个Timer事件中把原本各个Timer中的程序都执行一遍。我举个例子说明一下一个定时器如何完成多个定时功能。假设你打算每2秒执行一次函数A,每3秒执行一次函数B。你可以设置一个定时器,定时时间为1秒,再在类中定义两个计数器a和b(数值变量即可),初始值a=2、b=3。在Timer时间中,把这两个计数器分别减1,如果a=0,则调函数A,并将a重新赋值为2;如果b=0,则调函数B,并将b重新赋值为3。
      

  15.   

    谢谢提醒...已经将多个TIMER改成一个TIMER了...
    1.得到进程快照
    2.取出进程所在文件夹和文件名后.用了4个IF来判断当前打开的进程是否是想取的进程;
    但是问题依然没有解决.
    要关闭一个进程.另一个进程才会显示出来更改以后的程序已经发到你邮箱里了..麻烦再帮我看看吧.如果OFFICE不在Program Files下.更改
    String^ sFolderPath1 = "Program Files"; 
    这个变量值就可以了....
      

  16.   

    while ( Process32Next(hProcess_All_Process, &sTr_Of_Process))
    { //关闭进程
    CloseHandle( hProcess_One_Process );
    //Process32Next(hProcess_All_Process, &sTr_Of_Process);}// While 循环结束cnzdgs 你好..我找到问题根源了..很简单...我的代码出现了严重的逻辑错误.WHILE的时候就是运行了Process32Next.而在循环结束的时候我再次运行Process32Next,造成不能打开所有进程...太高兴了...马上结贴 ..再次感谢你..以后还有很多问题要请教你.呵呵...担搁你这么多时间 ...真不好意思啊...