背景 在宿舍里有电脑,上网,最大的麻烦就是共用。特别是人多机子少的时候。可谁的机子就那么情愿地给别人用,给别人玩啊。不是都说,男人对电脑,就象对自己的老婆一样,你会让别人天天玩你老婆吗?呵呵,说得过分了。 已经到大三的我,开始努力学习,准备考研了,可别人好象并不理解,也不知道是干什么。总之,十一的时候,我把我机子上所有的游戏都删了。唉,宿舍里就我这一台电脑,谁不想玩啊。删了之后,好象好一段时间了。这段时间又开始了,总要打QQ游戏。每天我都给删,然后他们再下载下来玩。虽然我说了很多回,可还是在玩。都在一个宿舍里住,我又不能太过分。 可总这么玩下去也不是个办法啊。一开始用卡巴封,没有太大效果。无奈了,我就想写个程序,filter了qqgame,这就是 这个程序的由来(哆嗦死了,写了这么一堆!) 战前准备 要实现filter,当然要先得到所有的进程名了,然后terminate之就OK,思想就是这样,非常的easy。虽然在win32下我也写过enum所有进程的程序,可现在不是已经clr了嘛,老盖不是说win32没有多长时间好活了嘛,所以本来想用.net framework里的东西写的。可在网上左找右找都不有找到。算了,还用老代码吧。于是凑出一个主程序:
void filter() { // Get the list of process identifiers. DWORD aProcesses[1024], cbNeeded, cProcesses; ULONG lCpuusage = 0;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) return;
// Calculate how many process identifiers were returned. cProcesses = cbNeeded / sizeof(DWORD); if(cProcesses > 100) { return; }
for(UINT index=0;index<cProcesses;index++) { wchar_t szProcessName[MAX_PATH] = L"unknown";
// Get a handle to the process. HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, aProcesses[index] );
// Get the process name.
if ( hProcess ) { HMODULE hMod; DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) ) { GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName) ); String^ str=gcnew String(szProcessName); str=str->ToUpper(); if(array<String^>::IndexOf(filer_list,str)!=-1) TerminateProcess(hProcess,0); } }
CloseHandle( hProcess ); } return; }
首战失利
vs2005发布以后,当然已经是我的首选了。还是vsts呢。开始之后,新建了一个windows服务程序。由于从来没有写过,所以先不加代码,编译,运行。结果当然是一个错误了,因为服务程序不是一般的程序,要注册到系统才能使用,还好错误里有个提示,用installutil这个工具就能注册。于是,运行之。又得一错误:没有RunInstallerAttribute.Yes段。唉,郁闷死了!
//过滤关键词列表 array<String^>^ keywords; //工作线程 Threading::Thread^ serviceThread;
virtual void OnStart(array<String^>^ args) override { // TODO: 在此处添加代码以启动服务。 //初始化key word列表 keywords=gcnew array<String^>(2);
//keywords->SetValue("notepad",1);
keywords->SetValue("qqgame",0);
//开启线程 System::Threading::ThreadStart^ threadStart=gcnew System::Threading::ThreadStart(this,&Program_filler::Program_fillerWinService::mainloop); serviceThread=gcnew Threading::Thread(threadStart); serviceThread->Start(); } //线程主程序 void mainloop() { int loopstep=1000*30;//30秒钟刷新一次 while (1) { Threading::Thread::Sleep(loopstep); filter(); } }
/// <summary> /// 停止此服务。 /// </summary> virtual void OnStop() override { // TODO: 在此处添加代码以执行停止服务所需的关闭操作。 serviceThread->Abort(); delete serviceThread; delete keywords; }
整鼓再战 看来是出了什么问题了,这个vs2005看来还不是很完善。上网找,虽然错误很明确,但vs2005相关的东西还是少,还好在csdn上找到了问题所在。其实很简单,只要在组件设计窗体上,右击,新建一个安装就OK。只不过,还要自己改一下,不要用用户名和密码,直接安装到本地系统就行了。
void InitializeComponent(void) { this->serviceProcessInstaller1 = (gcnew System::ServiceProcess::ServiceProcessInstaller()); this->serviceInstaller1 = (gcnew System::ServiceProcess::ServiceInstaller()); // // serviceProcessInstaller1 // this->serviceProcessInstaller1->Account = System::ServiceProcess::ServiceAccount::LocalSystem; //this->serviceProcessInstaller1->Password = nullptr; //this->serviceProcessInstaller1->Username = nullptr; // // serviceInstaller1 // this->serviceInstaller1->DisplayName = L"filter"; this->serviceInstaller1->ServiceName = L"filter"; this->serviceInstaller1->StartType = System::ServiceProcess::ServiceStartMode::Automatic; // // ProjectInstaller // this->Installers->AddRange(gcnew cli::array< System::Configuration::Install::Installer^ >(2) { this->serviceProcessInstaller1, this->serviceInstaller1});
}
小试牛刀 在过滤列表里加入了qqgame,notepad(呵呵,可怜的notepad)。安装,启动。打开一个notepad,呵呵,30秒就关了。爽!OK了! 重构 已经是一个完成品了,可是还是有非托管的代码,虽然没有什么不好的,可还是不爽,.net framework这么大个库,怎么可能没有这个功能呢,我找!终于在Process里找到一个GetProcesses()的方法。就是它了,改! 去了所有的非托管代码。正面是现在的程序。
void filter() { array<Process^>^ process_list=Process::GetProcesses();
for (int i=0;i<process_list->Length;i++) { Process^ p=(Process^) process_list->GetValue(i); for (int j=0;j<keywords->Length;j++) { String^ str=(String^) keywords->GetValue(j); str->ToLower(); if(p->ProcessName->Contains(str)) p->Kill(); } } return; }
小发现 都完成了,现在回头看看这个模板里还提供了什么。在main函数里居然发现在它自己就可以安装,用 program -install [-u]。呵呵,刚骂完该死的vs2005,看来还是有可圈可点的地方的! 有待改进 用taskmanager看了一下,这个破程序居然点了8M内存,虽然不多,但对于这个小程序来说,还是太大了,我想如果用c写,一定没这么大,可能就几十K,而且还有一点泄漏。看来对c++/cli还是拿不住啊。这一点有待改进! 初步分析可能是GetProcesses()造成的!