我的第一个服务程序

为了专注学习和考研,博主编写了一个Windows服务程序,定时终止指定进程,如QQ游戏等,以减少宿舍室友的打扰。

背景
在宿舍里有电脑,上网,最大的麻烦就是共用。特别是人多机子少的时候。可谁的机子就那么情愿地给别人用,给别人玩啊。不是都说,男人对电脑,就象对自己的老婆一样,你会让别人天天玩你老婆吗?呵呵,说得过分了。
已经到大三的我,开始努力学习,准备考研了,可别人好象并不理解,也不知道是干什么。总之,十一的时候,我把我机子上所有的游戏都删了。唉,宿舍里就我这一台电脑,谁不想玩啊。删了之后,好象好一段时间了。这段时间又开始了,总要打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()造成的!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值