修改启动的进程的窗口标题

2023-05-16

最近在改一个项目里的小功能:原先的情况是在网页上点击按钮,ocx控件写临时.rdp文件,根据这个文件启动mstsc.exe。现在要做的工作是把远程桌面连接窗口的标题改成能显示特定信息的标题。
感谢 http://blog.csdn.net/icedmilk/article/details/5278371,还有http://www.cctry.com/forum.php?mod=viewthread&tid=11857&page=1&authorid=51等。

程序调用mstsc,修改mstsc窗口名。
1、调用通过CreateProcess函数来实现;
/***************************************/
BOOL WINAPI CreateProcess
(
    _In_opt_     LPCTSTR lpApplicationName,
    _Inout_opt_  LPTSTR lpCommandLine,
    _In_opt_     LPSECURITY_ATTRIBUTES lpProcessAttributes,
    _In_opt_     LPSECURITY_ATTRIBUTES lpThreadAttributes,
    _In_         BOOL bInheritHandles,
    _In_         DWORD dwCreationFlags,
    _In_opt_     LPVOID lpEnvironment,
    _In_opt_     LPCTSTR lpCurrentDirectory,
    _In_         LPSTARTUPINFO lpStartupInfo,
    _Out_        LPPROCESS_INFORMATION lpProcessInformation
);    
//最后一个参数返回新进程的信息
typedef struct _PROCESS_INFORMATION
{
    HANDLE hProcess;
    HANDLE hThread;
    DWORD  dwProcessId;
    DWORD  dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
/***************************************/
    
DWORD CreateProcessMstsc(STARTUPINFO *si,PROCESS_INFORMATION *pi, CString strComLine)
{
    memset(si,0,sizeof(STARTUPINFO));
    si->cb=sizeof(STARTUPINFO);	

    LPSTR szCommandLine;
    szCommandLine=strComLine.GetBuffer(strComLine.GetLength());
    if(!CreateProcess(NULL,szCommandLine,NULL,NULL,FALSE,0,NULL,NULL,si,pi))    
    {        
        return 0;
    }    
    return pi->dwProcessId;
}
2、得到mstsc进程的pid。XP下mstsc的pid就是pi.dwProcessId。Win7下CreateProcess打开mstsc时,会先起一个中间进程,再由中间进程起mstsc,所以不能简单地把pi.dwProcessId作为mstsc的pid,这里还要找mstsc的pid。
DWORD find_sub_pid(DWORD parentpid)
{
    PROCESSENTRY32 pe32={0};
    pe32.dwSize=sizeof(PROCESSENTRY32);

    BOOL bRet;
    DWORD found_pid=0;
    HANDLE hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
    bRet=Process32First(hProcessSnap,&pe32);

    while(bRet&&g_found_flag==0)
    {
        if(pe32.th32ParentProcessID==parentpid)
        {
            found_pid = pe32.th32ProcessID;
            break;
        }
        bRet=Process32Next(hProcessSnap,&pe32);
    }
    CloseHandle(hProcessSnap);
    return found_pid;
}
     上面的代码不具有通用性,鉴于中间进程只会起mstsc这一个进程,所以在处理时,只要满足,就返回退出了。如果中间进程起了好几个进程,返回哪个进程还要做个判断。
3、通过mstsc的pid来找到正确的窗口。网上查阅资料,没有找到好的通过pid找HWND的方法,基本都是枚举窗口,对比窗口所属进程pid和目标pid。每个进程有多个窗口,必须要判断哪个窗口是目标窗口。
BOOL CALLBACK EnumWindowsCallBack(HWND hwnd, LPARAM lParam)
{
    //printf("进入处理函数\n");
    DWORD ProcID=0;
    GetWindowThreadProcessId(hwnd,&ProcID);

    if(ProcID==lParam)
    {    
        //下面开始验证这个窗口的窗口类名是不是我想要的,以及其他的限制条件
        char lpWinClass[256]={0};
        GetClassNameA(hwnd,lpWinClass,sizeof(lpWinClass)-1);
        if((strcmp(lpWinClass,"TSSHELLWND")==0)||(strcmp(lpWinClass,"TscShellContainerClass")==0))
        {
            g_hwnd_to_find=hwnd;
            g_found_flag=1;
            return FALSE;
        }
    }
    return TRUE;
}

int find_window_through_pid(DWORD pid)
{
    EnumWindows(EnumWindowsCallBack,pid);
    return 0;
}
4、通过HWND设置窗口标题。由于mstsc窗口并不是立刻显示在屏幕上的,如果设置标题比窗口显示出来早,那窗口显示的时候会把已经设置好的标题给改回来(这个问题困扰了我好久),所以在这里要判断一下窗口的显示状态,结合Sleep等来使用。
while(!(::IsWindowVisible(g_hwnd_to_find)))
{
    Sleep(100);
    count++;
    if((count%20)==0)
    {
        if(find_pid(pid_to_find)==0)
        {
            break;
        }
    }
}
::SetWindowTextA(g_hwnd_to_find,IPRemAddr);
5、总结:
     我是个菜鸟,上面这段程序前前后后搞了一个多星期,在关键性问题上还是实验室的大牛崔哥给解决的,犯了很多错误,现指出如下,希望看到的人也能有所启发。
     不能通过投机取巧的方式(比如枚举窗口,将含有“远程桌面连接”的标题的窗口改掉),这方法不可靠,而且还会带来其他不需要改的窗口被篡改的后果;
     Process会有多个Thread,Thread会有多个HWND,在做查找时不能想当然地把他们之间的关系当做是一对一的;
     单步调试正确,但是执行不正确的程序,多半是和时序有关系(比如第4点说的,没有加判断条件的时候,单步调试正确,直接执行就有问题了);
     找准目标,简化问题,不要被中间过程搞乱。mstsc的启动过程,中间有好几个弹窗(可能有3个甚至更多,也可能1个也没有,看怎么起),只要知道最后的目标是mstsc的窗口,窗口类型是什么即可。

6、知识点:
     6、1 关于Process Thread HANDLE HINSTANCE HMODULE HWND          
     进程          
     被当前操作系统加载到内存的、正在运行的应用程序的实例。每一个进程都是由内核对象和地址空间所组成的,内核对象可以让系统在其内存放有关进程的统计信息并使系统能够以此来管理进程,而内核空间则包括了所有程序模块的代码和数据以及线程堆栈、堆分配空间等动态分配的空间。    
     线程     
     进程仅仅是一个存在,是不能独自完任何操作的,必须拥有至少一个在其环境下运行的线程,并由其负责执行在进程地址空间内的代码。在进程启动的同时即同时启动了一个线程,该线程被称作主线程或是执行线程,游戏线程可以继续创建子线程。如果主线程退出,那么进程也就没有存在的可能了,系统将自动撤销该进程并完成对其地址空间的释放。
     HANDLE
     句柄是一种特殊的智能指针。当一个应用程序需要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄。
     主要是代表系统的内核对象,如文件句柄,线程句柄,进程句柄。
     系统对内核对象以链表的形式进行管理,载入到内存中的每一个内核对象都有一个线性地址,同时相对系统来说,在串列中有一个索引位置,这个索引位置就是内核对象的handle。     句柄和普通指针的区别在于,指针包含的是引用对象的内存地址,而句柄是由系统所管理的引用标识,该标识可以被系统重新定位到一个内存地址上。这种间接访问对象的模式增强了系统对引用对象的控制。通俗的说,调用句柄就是调用句柄的服务,即句柄已经把他能做的操作都设定好了,我们只能在句柄所提供的操作范围内进行操作,但是普通指针的操作却不受限制。
     HINSTANCE HMODULE
     A handle to an instance. This is rhe base address of the module in memory. HMODULE and HINSTANCE are the same today, but represented different things in 16-bit Windows.     
     HWND
     typedef HANDLE HWND;
     6、2 关于进程如何管理资源
     内核对象、GDI对象、和user对象     
     系统会维护一张进程列表,进程列表里记录着当前的进程,其中包含了pid,进程名,引用数(关于这个引用数比较直观的表现是在Windows资源管理器下面查看进程,勾选上句柄数、线程数、用户对象和GDI对象,可以看到某个进程引用的句柄数、线程数、用户对象数目和GDI对象数)等等。            内核对象的直接拥有者是操作系统内核,所有进程共享这些内核对象,因此要有一种机制保证内核对象的正确构造、销毁,Windows采用引用计数的计数;内核对象维护着一个引用计数成员。一个进程创建了一个内核对象,对象的引用计数为1,如果该对象又被另外的进程共享,每多一个进程引用数就会加1,当一个进程调用CloseHandle之后,引用计数会减1,如果引用计数变为0,操作系统会销毁该内核对象。内核对象使用完之后,要调用CloseHandle。这个函数的作用就是将内核对象的引用计数-1,当这个计数变为0时,改内核对象会变成Signal状态,并被操作系统销毁。
     GDI对象和user对象的销毁不需要调用CloseHandle。每一个GDI对象和user对象的销毁都有其对应的Destory或Delete方法。
     进程、线程、窗口
     一个进程可以拥有多个线程,一个线程可以有多个窗口。    
     在Windows下遍历进程可以用获取进程快照,然后调用Process32First和Process32Next来完成对进程的逐个访问;     
     访问线程列表也同样可以获取线程快照,调用Thread32First和Thread32Next来完成对线程的逐个访问;
     访问窗口可以通过Windows API函数EnumWindows来完成逐个访问;
     要获得某个进程的所有线程可以通过如下方法来完成,获得父进程pid,遍历线程列表,如果线程的THREADENTRY32结构体中th32OwnerProcessID和父进程pid一致,则该线程就是属于父进程的;     
     要回的某个进程的所有窗口可以通过如下方法来完成,获得进程pid,遍历窗口,在EnumWindows的回调函数里,用GetWindowThreadProcessId得到当前窗口的进程pid,比对这个pid和父进程pid,如果一致,该窗口属于父进程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

修改启动的进程的窗口标题 的相关文章

  • 基于STM32F10X的GPIO驱动

    完善我的文章 MCU BSP Driver分层设计 xff0c 本次提供GPIO控制驱动 本片完成了GPIO控制驱动操作 本人是基于野火指南者STM32开发板 本驱动基于STM32F10X官方固件库 主程序 int main void WH
  • 基于STM32F10X的GPIO驱动V0.1

    基于上篇 基于STM32F10X的GPIO驱动 增加GPIO的操作功能 xff0c 并且优化提高部分函数效率 最重要的添加了未带操作 xff0c 这样就可以高效的控制GPIO了 3 未解决的问题 xff1a 当前我无法将WHT GPIO P
  • CPU供电(路由器)万用表测量“短路”现象分析

    在维修路由器产品时发现CPU供电1 1V对地阻值50 100 之间 xff0c 在用万用表的蜂鸣档测量时会报 短路 xff0c 本以为是cpu或者供电芯片损坏 xff0c 原来我测量好板子也是这个现象 xff0c 故这个1 1 V cpu供
  • Lenovo ThinkPad T450s更换WiFi模块、指纹模块、维修SD卡针

    本电脑2015年8月份购买的 xff0c 2018年4月份之后开始出现问题 xff0c 首先指纹很难开机 xff0c 很难录入 xff0c 然后就是SD卡不知道什么时候无法使用了 xff0c 由于笔记本不常完也就没太注意 xff0c 最近有
  • 2.4G&5G WiFi 5V供电大短路,维修更换5G芯片

    故障类别 xff1a 无WiFi信号 故障现象 xff1a 漏电 xff0c 无2 4G和5GWiFi 故障描述 xff1a 开机后发现电流比其它板子大一点 xff0c 并且无异常发热情况 附件 xff1a 分析过程 xff1a 根据故障找
  • 路由器不开机——维修更换MT7621AT CPU

    故障类别 xff1a 不开机 故障现象 xff1a 210mA横流不开机 故障描述 xff1a 发现CPU异常发烫不开机 xff0c 其它地方未有发热现象 附件 xff1a 原因分析 xff1a 开机测量各路电压 xff0c 发现均有电压
  • 编译QT 5.9.7 msvcr2013 x86 32位版本

    因为项目需要 xff0c 用到了qt msvcr2013 x86 版本 但是官方下载的qt安装包里面只有x64的 xff0c 因此决定自己编译x86的版本 编译所需要的工具 xff1a qt源码包 xff0c python xff0c vs
  • <C语言>打印 n 阶魔方阵( n 为奇数),魔方阵的每一行、每一列和对角线元素之和都相等

    打印魔方阵 xff0c 首先我们得知道魔方阵的编写规律 xff1a 魔方阵的填充规律如下 xff1a 假设当前创建了一个矩阵 span class token keyword int span matrix span class token
  • 矩阵连乘之求最优值与构造最优解——呕心沥血篇

    矩阵连乘 详细讲解 初次接触dp xff0c 就看到很多位大佬给出自己的见解 xff0c dp算是最难的算法之一吧 xff0c 主要在于灵活度高 xff0c 需要自己推出动态规划方程 100个动态规划方程传送门涉及到dp问题那么for循环一
  • (C)数组,指针

    数组 xff1a int a 8 指针数组 xff0c 每个单元存放一个指针 每个指针是占8个字节在64位 xff0c 32位占4个字节 int xff08 a xff09 8 数组指针 xff0c 一个指向数组的指针 数组定义 xff1a
  • week5 单调栈 最大矩形

    Titile 给一个直方图 xff0c 求直方图中的最大矩形的面积 例如 xff0c 下面这个图片中直方图的高度从左到右分别是2 1 4 5 1 3 3 他们的宽都是1 xff0c 其中最大的矩形是阴影部分 Input 输入包含多组数据 每
  • ERROR 1238 (HY000): Variable ‘secure_file_priv‘ is a read only variable

    在进行数据导出操作的时候 xff0c 报错 xff1a ERROR 1238 HY000 Variable secure file priv is a read only variable 该变量是可读的 xff0c 不能用set设置 xf
  • kali安装目录扫描工具-dirsearch和git泄露利用脚本GitHack

    目录扫描工具 dirsearch 下载dirsearch git clone https github com maurosoria dirsearch 进入dirsearch目录 xff0c 进行扫描 这里我尝试了几次不同的用法 xff0
  • C语言—写一个函数求unsigned int型变量x在内存中二进制1的个数

    题目 xff1a 写一个函数求unsigned int型变量x在内存中二进制1的个数 思路 xff1a 先把num除2取余 xff0c 余数为1 xff0c count 43 43 再让num 61 num 2 取整 循环 xff0c 直到
  • Proteus 8.9下载安装指南

    因为Keil中的代码需要进行仿真 xff0c 除了用实际的开发板 xff0c 仿真软件也很实用 虽然已经装了AD xff0c 但是网上关于AD仿真的资料相对较少 今天装一个Proteus用用 安装包 xff1a Proteus8 9 提取码
  • STM32烧录

    资源包 xff1a STLink驱动 软件包 提取码 xff1a cgcg 结构 xff1a 通过RX TX脚连接到MCU芯片串口引脚 xff0c USB串口转换器 xff08 USB TTL的电路 xff09 一边连接RX TX引脚 xf
  • stm32使用串口进行通讯之发送数据

    前提准备 xff1a 1 库函数基础模板 2 stlink下载器 USB TTL下载器 单片机最小开发板stm32F103C8T6 3 面包板及相关接线 4 vscode与keil的联合开发更流畅 5 串口软件 xff0c 这个下面视频有
  • ubuntu 16.04挂载磁盘,开机丢失

    一般磁盘可能要先格式化为指定格式 sudo mkfs t ext4 dev sdb1 直接mount磁盘分区 xff0c 比如 sudo mount dev sdb1 var 当时起作用了 xff0c 但是reboot之后 xff0c 就会
  • stm32使用外部flash w25Q128实现读写操作

    前言 数据保存是所有项目的基本功能 xff0c 但是对于STM32C8T6的原flash进行操作 xff0c 一方面大小有可能不够 xff0c 另一方面单片机的运行程序本来就放在这个里面 xff0c 所以还是外接的好 这里选用w25Q128

随机推荐

  • Keil(MDK)STM32和51版本详细安装

    前言 保姆级教程 xff0c 多次反复安装 xff0c 实测可用 链接包失效可留言 安装注意 keil公司被ARM公司收购 xff0c 收购后就改名MDK xff0c 所以keil的下载包也是以MDK命名 安装路径不能带有中文 目录不能和5
  • STM32 使用LCD12864显示屏(串行方式)

    LCD12864 简介 12864LCD液晶显示模块是一款4位 8位并行 2线或3线接口方式 xff0c 内部含有国际一级 二级简体中文字库的图形点阵液晶模块 显示分辨率为12864 xff0c 内置8198个1616点汉字 xff0c 和
  • 快速学习C语言指针操作

    一 了解底层 指针说到底是在对数据进行操作 先了解数据的存储 xff0c 看看指针操作的位置 一位数据的存储 xff1a 将一位数据置1 xff0c 如图所示 xff0c 首先地址位需要置1 xff0c 再将数据输入位置1 xff0c 那么
  • MG90S 舵机180°角度驱动

    MG90S简介 舵机 xff1a 是一种角度伺服电机 xff0c 一般是由齿轮组 电位器 舵机控制电路 直流电机构成 由发送控制信号来控制输出轴的位置 数字舵机与模拟舵机的区别 xff1a MG90S是一款常用的数字舵机 xff0c 还有一
  • MPU6050 6轴姿态传感器的分析与使用(一)

    一 MPU6050简介 MPU6050是一个6轴姿态传感器 xff08 3轴加速度计和3轴陀螺仪传感器 xff09 xff0c 可以测量芯片自身X Y Z轴的加速度 角度参数 xff0c 通过数据融合 xff0c 可以得到姿态角 二 简介分
  • 基于51单片机的步进电机驱动,亲测无误

    文章目录 前言一 我们该如何实现电机驱动 xff1f 二 驱动实现1 硬件准备2 软件编写3 实物 总结 前言 这一次要分享的项目是最近接单做的一个小玩意儿 xff0c 基于51单片机的步进电机驱动 最近积压了两个月的小项目会在后面陆续发出
  • 对 string 类的输入(直接看总结)

    一 简述 cin get 和 cin getline 解决 char 中的问题 xff0c 遇到换行符时才停止 对于 string 类 xff0c 不能使用cin get 和cin getline 进行输入 xff0c 会报错 xff0c
  • C++中字符串的比较(针对C-风格字符串)

    一 简述 在头文件 lt cstring gt 中 xff0c 有一个函数strcmp 二 详细介绍 strcmp 比较字符串 格式为 strcmp const char Str1 const char Str2 xff0c 由此可见 xf
  • 关于文件结束符EOF

    一 简述 我们知道 xff0c C 43 43 中可以通过cin xff0c cin get xff0c cin getline xff0c getline 等对字符串进行输入 xff08 若对这些输入模糊 xff0c 可以阅读这篇文章 x
  • ubuntu 1810上snap安装nextcloud

    尝试在ubuntu1810上安装nextcloud 因为服务器配置好了xrdp远程访问 xff0c 所以直接准备在sofware center进行安装 安装了半天却提示 unable to install nextcloud snap xx
  • 关于cout 输出 char 型字符 ++ch和 ch+1 不同的结果(直接看详解)

    一 简述 今天在做练习题时注意到了之前所没有注意到的问题 xff1a 若给同样的 ch xff0c cout lt lt 43 43 ch 与 cout lt lt ch 43 1 输出后的结果不一样 浅思之后明白了 xff0c 其实这个现
  • C++定义与声明

    一 简述 什么是定义 xff1f 什么是说明 xff1f 相信很多小伙伴都对这两个概念模糊不清 xff0c 下面我就对其简单介绍一下 二 详细说明 定义 全称为定义声明 xff0c 给变量分配空间 声明 全称为引用声明 xff0c 不给变量
  • MySQL学习日记(六)用户管理、权限安全

    文章目录 用户管理和权限安全1 user权限表1 1 用户列1 2 权限列1 3 安全列1 4 资源控制列 2 其他权限表 xff08 db tables priv columns priv procs priv xff09 2 1 db表
  • Linux上的网络配置——bonding配置

    网络接口配置bonding Bonding 将多块网卡绑定同一IP地址对外提供服务 xff0c 可以实现高可用或者负载均衡 直接给两块网卡设置同一IP地址是不可以的 通过bonding xff0c 虚拟一块网卡对外提供连接 xff0c 物理
  • python--直接通过cmd找到pip所安装库的位置

    https blog csdn net weixin 44345862 article details 87003478
  • 家中闲置旧电脑改装家用NAS(入门教程)

    家中闲置旧电脑改装家用NAS xff08 纯小白入门教程 xff09 什么是NAS xff1f NAS的基本知识在国内的常用品牌 NAS品牌的配置问题作者的硬件配置 装机正文准备工作旧电脑的准备工作 xff08 已经完成或无这方面问题的可跳
  • 适用于 Linux 的 Windows 子系统 (WSL)

    适用于 Linux 的 Windows 子系统 xff08 WSL xff09 描述什么是 适用于 Linux 的 Windows 子系统 系统要求Windows 10 Windows 11 查看计算机系统的版本 虚拟化功能启用虚拟化功能禁
  • python爬取4399页面

    提示 xff1a 该段代码只可爬取4399页面的代码和图片 xff0c 适合新手爬虫入门学习 python爬取4399页面 代码总结 代码 代码如下 xff1a import urllib span class token punctuat
  • Arduino手动安装esp8266开发板

    Arduino手动安装esp8266开发板可以用离线安装包 xff0c 确定就是离线安装包网上不好找 xff0c 版本也不齐全 xff0c 无法找到某个特定版本的离线安装包 xff0c 好处是直接双击运行 xff0c 傻瓜式安装就好了 xf
  • 修改启动的进程的窗口标题

    最近在改一个项目里的小功能 原先的情况是在网页上点击按钮 xff0c ocx控件写临时 rdp文件 xff0c 根据这个文件启动mstsc exe 现在要做的工作是把远程桌面连接窗口的标题改成能显示特定信息的标题 感谢 http blog