初衷:
之前windows有些问题,下了个金山毒霸来了套全家福,但是由于它每次开机都会自动启动,本人又不忍心一下删了它(其实是不想下次急需时再安装=。=),觉得每次开机后都要手动关太心累了!!!于是乎便写了个弱弱的程序让电脑开机自动执行—— Kill Kingsoft。(ps:其实没有太多含量,只是能按需求work,和我有一样烦恼的小伙伴可以参考。。。大神请绕道😳 )
代码:
// KillKingSoft.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h>
#include <tlhelp32.h>
DWORD GetProcessIdFromName(TCHAR *szTargetProcessName)
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hSnap == INVALID_HANDLE_VALUE)
return 0;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
DWORD dwProcessId = 0;
BOOL bResult = Process32First(hSnap, &pe);
while(bResult){
if(!lstrcmp(pe.szExeFile, szTargetProcessName)){
dwProcessId = pe.th32ProcessID;
break;
}
bResult = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
return dwProcessId;
}
void killProcessByName(TCHAR *szTargetProcessName)
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hSnap == INVALID_HANDLE_VALUE)
return;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
DWORD dwProcessId = 0;
BOOL bResult = Process32First(hSnap, &pe);
while(bResult){
if(!lstrcmp(pe.szExeFile, szTargetProcessName)){
wprintf(L"processname: %s -- pid: %d ", szTargetProcessName, pe.th32ProcessID);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, (DWORD)pe.th32ProcessID);
if (hProcess != NULL)
{
int res = TerminateProcess(hProcess, 0);
wprintf(L"terminate res: %d\n", res);
CloseHandle(hProcess);
}
}
bResult = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
int _tmain(int argc, _TCHAR* argv[])
{
Sleep(60000); //wait 1 min for process kxescore.exe... starting up
TCHAR processNames[6][20] = {L"kxescore.exe",L"kxetray.exe",L"kwsprotect64.exe",L"kislive.exe",L"ntsd.exe"};
DWORD pids[6],
for(int i=0;i<3;i++)
{
pids[i] = GetProcessIdFromName(processNames[i]);
wprintf(L"process: %s | pid:%d\n", processNames[i], pids[i]);
CHAR kill_cmd[20] = "ntsd -c q -p ";
CHAR pid_str[6];
_itoa_s(pids[i], pid_str, 10);
strcat_s(kill_cmd,pid_str);
printf("kill cmd: %s\n", kill_cmd);
WinExec(kill_cmd, SW_HIDE);
}
Sleep(2000);
killProcessByName(processNames[4]);
return 0;
}
将编译生成的可执行程序放在 【开始菜单->启动】文件夹下即可。
简单分析:
GetProcessIdFromName()这个没什么好说的,就是遍历系统当前所有进程,逐一匹配进程名,一旦相同即返回进行pid。
当获得pid时,直接调用OpenProcess()和TerminateProcess()来杀死金山毒霸的几个进程是会失败的,因为权限不够(和你直接在任务管理器或process explorer里手动杀掉进程是一样的)
网上查到有这么一个用户态进程调试工具ntsd,它能杀掉除几个系统进程之外的所有进程;由于工作在用户态,因此对于拥有内核态保护机制的程序(主要指杀毒软件),ntsd无法将其结束。
工具原理:调试器关闭时,由它打开的进程会随着调试器一起退出,因此能起到关闭进程的作用。
命令:ntsd -c q -p pid
-c:表示执行接下来的调试命令
q:表示quit的命令,即-c q表示退出调试器
-p:表示添加要调试的进程pid
(后来一查,它还支持利用进程名结束进程:ntsd -c q -pn xxx.exe,那就不用先获取pid了=。=)
这里我们使用WinExec来执行命令,其中第一个参数为命令行,第二个参数为窗口显示。由于我们希望该程序能在后台执行,不需要人参与,因此第二个参数设置为SW_HIDE,即隐藏窗口。
正常来说,若存在目标进程,ntsd即能正常运行,然后自己就退出了;但如果目标进程不存在,ntsd会打开一个窗口,输出错误信息,等待用户按键退出,但又由于我们设置为隐藏窗口了,因此该ntsd.exe进程会一直存在,所以这里我们最后还通过TerminateProcess()把可能未正常结束的ntsd.exe进程关闭。又由于ntds是调试工具,执行命令需要些时间,因此我们等待2s后再关闭ntsd.exe进程。
最后一点:由于金山毒霸相关进程开启需要一些时间,而我们的KillKingsoft.exe进程运行得会比它早,因此这里我们先sleep1分钟等待相关进程启动后再work。
最后的最后:对于开机启动的程序,它们一般有这几种常见的途径来实现开机启动(下面展示是window7版本的)
(1) “启动”文件夹:【开始菜单->启动】,对应的文件夹:"C:\Users\<用户名字>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
(2) 注册表: 最常见的为 "HKEY_LOCALMACHINE(或 HKEY_CURRENT_USER)-> SOFTWARE -> Micrsoft (或 Wow6432Node -> Microsoft) -> Windows -> CurrentVersion -> Run"
(3) 任务计划程序:输入Taskschd.msc命令,或者打开【控制面板->系统和安全->管理工具->任务计划程序】,可以创建任务,选择只在用户登录时运行,这样的话也能实现开机用户登录启动目标程序
上面前2种设置方法,最后可以在启动项中查看到。查看启动项的方法:msconfig命令,或者打开 【控制面板->系统和安全->管理工具->系统配置->启动】
【后记】
后来有一次偶然发现,在它的设置中可以选择“取消开机启动”。。。。。。
这个故事告诉我们,凡事还是要搞清楚再行动,不然就是吃力不讨好了zzz