[译]WMI Tamer-在登录时使WMI行为
By robot-v1.0
本文链接 https://www.kyfws.com/applications/wmi-tamer-making-wmi-behave-at-login-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 9 分钟阅读 - 4256 个词 阅读量 0[译]WMI Tamer-在登录时使WMI行为
原文地址:https://www.codeproject.com/Articles/21089/WMI-Tamer-Making-WMI-Behave-at-Login
原文作者:Harold Bamford
译文由本站 robot-v1.0 翻译
前言
This is a simple program which demonstrates how to find and change a process' priority, such as wmiprvse.exe
这是一个简单的程序,演示了如何查找和更改进程的优先级,例如wmiprvse.exe
介绍(Introduction)
这是如何找到流程并更改其优先级的简单演示.在这种情况下,(This is a simple demonstration of how to find a process and change its priority. In this case, it is for)wmiprvse.exe(wmiprvse.exe)(Windows Management Instrumentation),其优先级无法通过任务管理器更改.奇怪的是,它的优先级((Windows Management Instrumentation), whose priority cannot be changed via the task manager. Oddly, its priority)能够(can)可以使用SysInternals Process Explorer((be changed using the SysInternals Process Explorer () 流程浏览器(Process Explorer) ),由Mark Russinovich撰写.去搞清楚!() by Mark Russinovich. Go figure!)
我介绍这个小工具有两个目的:(I present this little tool for two purposes:)
- 用非常简单的代码演示如何获取所有进程的列表并调整进程类(例如,进程优先级,而不是线程优先级)(Demonstrate in very simple code how to get a list of all processes and adjust the process class (e.g. process priority, not thread priority))
- 提供针对似乎常见问题的简单解决方案(Provide a simple fix for what seems to be a common problem) 还有其他文章针对流程优先级解决了许多相同的问题,但是拥有另一个可行的示例也无济于事.特别是没有太多其他事情的事情,很难说出需要什么和不需要什么.这里没有聪明或魔术,它只是以简单(但蛮力)的方式完成了工作,可以用作开发自己的代码的示例.它使用C ++,但是大多数可以使用直接C语言.不使用MFC或STL.(There are other articles that address many of the same issues for process priority, but it never hurts to have another working example. Particularly one that doesn’t have so much other stuff going on that it is hard to tell what is needed and what isn’t. There is nothing clever or magic here, it just does the job in a simple (but brute force) manner and can be used as an example for developing your own code. It uses C++, but most of it could be in straight C. No MFC or STL is used.)
唯一的C ++项是一个奇怪的宏,用于以类型安全的方式在编译时获取数组中元素的数量(请参见(The only C++ item is a strange macro for getting the number of elements in an array at compile time in a typesafe manner (see) COUNTOF()宏(COUNTOF() macro) (伊万`约翰逊).(by Ivan J. Johnson).)
背景(Background)
最近(实际上是今年的大部分时间,2007年),我发现重新启动PC(在企业环境中为Windows XP,SP2)时,可能要花10到20分钟的时间,我才能获得迅速而可靠的键盘和鼠标响应.在这段时间里,我从任务管理器中看到(Recently (actually, most of this year, 2007) I have found that when I restart my PC (Windows XP, SP2, in an enterprise environment), it can take 10-20 minutes before I can get prompt and reliable keyboard and mouse response. During this interval, I see from the task manager that)**wmiprvse.exe(wmiprvse.exe)**正在占用99%的CPU.通过互联网进行研究后,我发现我并不孤单,很多人都遇到同样的问题.这个过程与他人的配合不好.它以正常优先级运行,但似乎并没有进行任何实时中断,这可能是因为它产生了如此多的线程,每个线程都认为它将阻塞足够多的线程,从而为其他正常优先级进程提供了运行的机会.当然,那部分只是推测.(is taking 99% of the CPU. Upon researching via the Internet, I found that I am not alone and that many people have the same problem. This process doesn’t play nicely with others. It runs at normal priority but it just doesn’t seem to take any real-time breaks, possibly because it spawns so many threads that each assumes it will block enough to give other normal priority processes a chance to run. That part is just conjecture, of course.)
对于某些人来说,问题在于(For some people, the problem with)**wmiprvse.exe(wmiprvse.exe)**是错误配置的硬件(例如丢失的打印机,其中有排队等待该打印机的东西),它将陷入某种紧密的循环.对于其他人,则是由于病毒(例如W32/Sonebot-B)引起的.对于其他方面,这是由于硬件清单操作(请参阅Microsoft文章,网址为(was mis-configured hardware (like a missing printer where there is something queued up for that printer) and it would go into some kind of tight loop. For others, it was because of a virus (W32/Sonebot-B, for instance). And for yet others, it was due to hardware-inventory operations (see the Microsoft article on) 硬件清单操作期间客户端计算机上的CPU使用率很高(High CPU usage on client computers during hardware-inventory operations) ).这最后一个是我的问题.在使用机器之前,不需要完成硬件清单,但是直到完成为止,对最简单的任务(例如,右键单击回收站)的响应可能需要几分钟!那不是夸张的;在WMI操作完成之前,它对人机界面没有用.(). This last one was my problem. The hardware-inventory did not need to be completed before I used the machine, but until it was finished, the response to even the simplest task (such as right-clicking on the Recycle Bin) could take several minutes! That is not hyperbole; it was useless for human interface until the WMI operations were finished.)
因此,为了改善响应时间和通用性,我不得不(So, to improve response time and general usability, I had to)减少(reduce)的优先(the priority of)wmiprvse.exe(wmiprvse.exe),这有点违反直觉.但是,通过此工具或Process Explorer将流程设置为"低于正常"时,在WMI流程中,人机界面得到了极大的改进(, which is somewhat counter-intuitive. However, when the process is set to “below normal” via this tool or via Process Explorer, the human interface was vastly improved while the WMI process)仍然(still)获得了99%的CPU!(got 99% of the CPU!)
使用代码(Using the Code)
如果您只想使用代码,则只需将可执行文件放入您的(If you just want to use the code, then merely drop the executable into your)**启动(Startup)**夹.可以将其放入注册表"运行"列表之一,但我不知道何时(folder. It may be possible to put it into one of the registry “Run” lists, but I don’t know when)**wmiprvse.exe(wmiprvse.exe)**已启动,并且必须运行该程序才能使该程序生效,因此您不想过早启动它.的(is started and that process has to be running for this program to be effective so you don’t want to start it too soon. The)**启动(Startup)**文件夹对我有用.现在,将代码设置为打开并在其中写入日志文件(folder works for me. Right now, the code is set to open and write a log file in)**C:/WMI_Tamer.txt(C:/WMI_Tamer.txt)**带有"被驯服"的过程数量的报告.在代码顶部附近有一个标记,用于调整详细程度(是的,您可以编写一个命令行解析器在运行时对其进行调整).(with a report of the number of processes that were “tamed”. There is a flag near the top of the code to adjust the level of verbosity (yes, you could write a command-line parser to adjust it at run time).)
注意(Note)注意:这可能在Win98上不起作用,因为它似乎没有"低于正常"进程优先级类.我希望这对大多数人来说都不是问题.(: This probably won’t work on Win98 as it doesn’t seem to have the “Below Normal” process priority class. That shouldn’t be a problem for most people, I hope.)
该代码是作为控制台程序编写的,我尝试使其与Unicode兼容,并使用基本I/O接口的"安全"版本.奇怪的是,这使我更难阅读,但是我试图在编程中变得更加轻便和安全,所以您在阅读时会陷入困境.(The code is written as a console program and I have tried to make it Unicode compatible and use the “safe” versions of the basic I/O interfaces. Oddly, this makes it harder for me to read, but I am trying to be more portable and safe in my programming, so you get stuck reading it.)
因为我非常喜欢嵌入代码文档(As I am a big fan of embedding documentation for the code)在(in)该代码,我用过(the code, I have used) 氧(doxygen) 记录下来并附上结果(to document this and have attached the resulting)**WMI_Tamer.chm(WMI_Tamer.chm)**帮助文件到本文.我将仅在此处触及代码的重点.(help file to this article. I will only touch on the highlights of the code here.)
获得权限(Getting Permissions)
奇怪的是,对我来说最难的部分是(Oddly, the hardest part for me was getting)允许(permission)改变过程. Microsoft充分记录了更改流程类(优先级)的各个步骤,以及必须获得更改流程类(优先级)的权限的要求.尽管一旦完成,建立连接就有点困难了.下面是代码(已删除错误检查的可读性):(to change the process. The individual steps for changing process class (priority) are well documented by Microsoft as well as the requirement that permissions to change process class (priority) must be obtained. Making the connection was a little harder although once done, it is easy. Below is the code (with the error checking removed for readability):)
TOKEN_PRIVILEGES tp; // adjust this to set the new privilege
TOKEN_PRIVILEGES previousPrivs; // store previous value here for later restoral
HANDLE hToken; // current process token used to adjust privileges
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
// This query is why we needed TOKEN_QUERY.
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &(tp.Privileges[0].Luid));
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
DWORD bufSize = 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(previousPrivs),
&previousPrivs, (PDWORD) &bufSize);
事实证明,更改进程优先级需要调试权限(谁知道?).文档中列出的值是(It turns out that changing process priority requires debugging permissions (who knew?). The value listed in the documentation is) SE_DEBUG_NAME
我以为是错字(which I thought was a typo for) SE_DEBUG_NAME
.不.的(. Nope. The) SE
手段(means)安全(Security)并不是(and not)组(Set).事后看来,这是有道理的,但是当我试图弄清楚这些东西时却无济于事!(. In hindsight, this makes sense, but it didn’t help when I was trying to figure this stuff out!)
我仍然不完全了解的另一点是,一旦设置了调试器权限,即使我的程序退出,它们仍会保留.因此,我必须保存先前的权限以供以后恢复.的(Another point that I still don’t completely understand is that once I have set debugger permissions, they stay on even after my program exits. So, I have to save the previous permissions for later restoral. The) previousPrivs
上面的值将在以后使用:(value above is used later:)
AdjustTokenPrivileges(hToken, FALSE, &previousPrivs, 0, NULL, NULL)
获得调试权限后,代码将调用该函数(Once the debugging permissions have been obtained, the code calls the function) GetProcessList()
获取所有正在运行的进程的快照,并逐步执行它们以查找" hog"进程.这是程序的主循环.(to get a snapshot of all running processes and step through them looking for the “hog” process. This is the main loop of the program.)
获取和处理所有进程的清单(Getting and Processing List of All Processes)
获取快照的代码很简单(一旦您知道怎么做):(The code for getting the snapshot is trivial (once you know how):)
// Take a snapshot of all processes in the system.
// last parameter is ignored here
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
现在列表与(Now the list is walked with) Process32First()
和(and) Process32Next()
.对于每个流程,我们都会获得详细信息,查看是否需要驯服该流程的实例,然后使用(. For each process, we get the gory details, see if it is an instance of the process that needs to be tamed, and use) SetPriorityClass()
将优先级降低为"低于正常水平".与往常一样,为清楚起见,删除了错误检查和详细报告:(to drop the priority to “below normal”. As usual, error checking and verbose reports are removed for clarity:)
// Set the size of the structure before using it.
pe32.dwSize = sizeof( PROCESSENTRY32 );
// Retrieve information about the first process
Process32First( hProcessSnap, &pe32 );
// Now walk the snapshot of processes
do
{
// Retrieve the priority class.
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
dwPriorityClass = GetPriorityClass( hProcess );
// Here is where we tame the wild beast by dropping its priority.
// Use a caseless comparison (which requires the call to setlocale() in _main())
if(_tcsicmp(hogProcessName, pe32.szExeFile) == 0)
{
SetPriorityClass(hProcess, BELOW_NORMAL_PRIORITY_CLASS);
dwNewPriorityClass = GetPriorityClass( hProcess );
}
CloseHandle( hProcess ); // avoid a memory leak
} while( Process32Next( hProcessSnap, &pe32 ) );
注意:(Note:)这是在Win98中会中断的部分(This is the part that will break in Win98 as) BELOW_NORMAL_PRIORITY_CLASS
在Win2K之前不可用.(is not available until Win2K.)
其他感兴趣的文章(Other Articles of Interest)
- 枚举过程:一种实用方法(Enumerating Processes : A Practical Approach) 通过Irfan Dawood(by Irfan Dawood)
- Win32进程挂起/继续工具(Win32 Process Suspend/Resume Tool) 由Daniel Turini(by Daniel Turini) 如果要将此项目转换为VC ++ 6.0,请参见(If you want to convert this project to VC++ 6.0, see) VC ++ 7至VC ++ 6项目转换器(VC++7 to VC++6 Project Converter) .(.)
历史(History)
- 1.0版10/20/2007:首次公开发行(Version 1.0 10/20/2007: First public release)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
VC7.1 VC8.0 VC7.0 WinXP Win2003 Win2K VS2005 Visual-Studio VS.NET2003 Dev 新闻 翻译