qt调win做的一些 搜索进程关闭窗口 还有关机的繁杂东西

15 篇文章 0 订阅

首先 include进来window.h可能会有“\qtcore\qdatetime.h(121): warning C4003: “min”宏的实参不足”类似的问题,库冲突可能,可以去改库文件,但其实才发现有 #include <qt_windows.h> 这个.. 这些很多的问题已经在里面修改了。

关机的很简单.. 顺带就提一下。在默认的情况下进程的一些访问权限是没有被启用(Enabled)的,所以我们要做的首先是启用这些权限。与此相关的一些API函数有OpenProcessToken、LookupPrivilegevalue、AdjustTokenPrivileges。

下面百度到的说的很清楚的了。我就贴一下:

我们要修改一个进程的访问令牌,首先要获得进程访问令牌的句柄,这可以通过OpenProcessToken得到,函数的原型如下:
BOOL OpenProcessToken(
__in HANDLE ProcessHandle, //要修改访问权限的进程句柄
__in DWORD DesiredAccess, //指定你要进行的操作类型
__out PHANDLE TokenHandle //返回的访问令牌指针
);
第一参数是要修改访问权限的进程句柄;第三个参数就是返回的访问令牌指针;第二个参数指定你要进行的操作类型,如要修改访问令牌的特权,我们要指定第二个参数为TOKEN_ADJUST_PRIVILEGES = &H20(其它一些参数可参考Platform SDK)。通过这个函数我们就可以得到当前进程的访问令牌的句柄(指定函数的第一个参数为GetCurrentProcess()就可以了)。接着我们可以调用AdjustTokenPrivileges对这个访问令牌进行修改。AdjustTokenPrivileges的原型如下:
BOOL AdjustTokenPrivileges(
HANDLE TokenHandle, // handle to token
BOOL DisableAllPrivileges, // disabling option
PTOKEN_PRIVILEGES NewState, // privilege information
DWORD BufferLength, // size of buffer
PTOKEN_PRIVILEGES PreviousState, // original state buffer
PDWORD ReturnLength // required buffer size
);
第一个参数是访问令牌的句柄;第二个参数决定是进行权限修改还是丧失(Disable)所有权限;第三个参数指明要修改的权限,是一个指向TOKEN_PRIVILEGES结构的指针,该结构包含一个数组,数据组的每个项指明了权限的类型和要进行的操作; 第四个参数是结构PreviousState的长度,如果PreviousState为空,该参数应为NULL;第五个参数也是一个指向TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息,可空;最后一个参数为实际PreviousState结构返回的大小。在使用这个函数前再看一下TOKEN_PRIVILEGES这个结构,其声明如下:
typedef struct _TOKEN_PRIVILEGES {
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[];
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
PrivilegeCount指的数组元素的个数,接着是一个LUID_AND_ATTRIBUTES类型的数组,再来看一下LUID_AND_ATTRIBUTES这个结构的内容,声明如下:
typedef struct _LUID_AND_ATTRIBUTES {
LUID Luid;
DWORD Attributes;
} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES
第二个参数就指明了我们要进行的操作类型,有三个可选项: SE_PRIVILEGE_ENABLED、SE_PRIVILEGE_ENABLED_BY_DEFAULT、SE_PRIVILEGE_USED_FOR_ACCESS。要使能一个权限就指定Attributes为SE_PRIVILEGE_ENABLED。第一个参数就是指权限的类型,是一个LUID的值,LUID就是指locally unique identifier,我想GUID大家是比较熟悉的,和GUID的要求保证全局唯一不同,LUID只要保证局部唯一,就是指在系统的每一次运行期间保证是唯一的就可以了。另外和GUID相同的一点,LUID也是一个64位的值,相信大家都看过GUID那一大串的值,我们要怎么样才能知道一个权限对应的LUID值是多少呢?这就要用到另外一个API函数LookupPrivilegevalue,其原形如下:
BOOL LookupPrivilegevalue(
LPCTSTR lpSystemName, // system name
LPCTSTR lpName, // privilege name
PLUID lpLuid // locally unique identifier
);
第一个参数是系统的名称,如果是本地系统只要指明为NULL就可以了,第三个参数就是返回LUID的指针,第二个参数就是指明了权限的名称,如“SeDebugPrivilege”。在Winnt.h中还定义了一些权限名称的宏,如:
#define SE_BACKUP_NAME TEXT("SeBackupPrivilege")
#define SE_RESTORE_NAME TEXT("SeRestorePrivilege")
#define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege")
#define SE_DEBUG_NAME TEXT("SeDebugPrivilege")
这样通过这三个函数的调用,我们就可以用OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessID)来打获得任意进程的句柄,并且指定了所有的访问权

然后其实代码贴上来就懂了:

HANDLE hToken;
    TOKEN_PRIVILEGES tkp;
    //获取handle
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
         return false;
    //获取LUID
    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,    &tkp.Privileges[0].Luid);
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    //获取关机特权
    AdjustTokenPrivileges(hToken, false, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
    if (GetLastError() != ERROR_SUCCESS) return false;
    //关机
    if ( !ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0))
          return false;
    return true;


然后下面说一下进程的搜索还有发窗口的消息,其实如果粗暴一点,可以直接用QProcess Process; Process.start(comandstr);去直接杀了进程之类的,比如用taskkill:

QString comandstr = "taskkill /f /im 进程.exe“之类的,使用进程的名字来结束。

但是有时候可能需要实现正常的串口关闭的效果,不想杀进程出现其它的问题之类的。

下面是实现通过CreateToolhelp32Snapshot扫当前的所有进程,找到进程的id然后利用EnumWindows来遍历当前窗口,取得相同id的窗口,执行关闭操作。对于里面的函数还有结构百度资料什么的讲的很清楚了。

 HANDLE hSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
       //将从hSnapShot中抽取数据到一个PROCESSENTRY32结构中(存储快照的结构体)
       PROCESSENTRY32* processInfo=new PROCESSENTRY32;
       // 必须设置dwSize值
       processInfo->dwSize=sizeof(PROCESSENTRY32);
       int index=0;

       int ID = 0;
       while(Process32Next(hSnapShot,processInfo)!=FALSE)
       {
           index++;
           int size=WideCharToMultiByte(CP_ACP,0,processInfo->szExeFile,-1,NULL,0,NULL,NULL);
           char *ch=new char[size+1];
           //取进程的取名然后对比
           if(WideCharToMultiByte(CP_ACP,0,processInfo->szExeFile,-1,ch,size,NULL,NULL))
           {
               //结束的进程
               if(strstr(ch,"进程.exe"))
             {
                    ID = processInfo->th32ProcessID;
                    qDebug()<<processInfo->th32ParentProcessID;
                    qDebug()<<"ID ="<<ID;
                    HANDLE hProcess;
                    hProcess=OpenProcess(PROCESS_ALL_ACCESS,TRUE,ID);
                    //terminateprocess 和杀进程一个效果
                    //TerminateProcess(hProcess,0);
                    //得到所有窗口列表然后判断关闭
                    EnumWindows(closeTheWnd,ID);
                    CloseHandle(hProcess);
               }
           }
       }
       CloseHandle(hSnapShot);
       delete processInfo;

里面调用的一个函数用来遍历窗口

BOOL CALLBACK closeTheWnd(HWND hWnd, LPARAM lparam)
{
    DWORD ProcID = 0;
    GetWindowThreadProcessId(hWnd,&ProcID);
    //processid等于参数ID
    if(ProcID==lparam&&lparam!=0)
    {
        HWND pWnd = GetParent(hWnd);
        //得到父窗口的句柄
        while(GetParent(pWnd)!=NULL)
            pWnd = GetParent(pWnd);
       // 正常的关闭信息
        PostMessage(pWnd,WM_CLOSE,0,0);
        return true;
    }
    return true;
}
post send的区别就很简单了,还有消息的这里也有很多。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值