7.2 通过API创建新进程

通过,api,创建,进程 · 浏览次数 : 17

小编点评

**WinExec()函数** * 使用者可以传递字符串类型的参数,包括进程名称和参数等信息。 * 函数没有提供区分进程成功和失败的返回值,且无法从函数返回的进程句柄中获得与进程相关的信息。 **ShellExecute()函数** * 提供了更高级的功能,例如可以控制进程启动方式、传递命令参数等。 * 可以通过传递参数来控制启动进程的方式,例如最大化或最小化窗口,或者在后台启动进程等。 **CreateProcess()函数** * 提供了最灵活的进程控制功能,可以设置进程窗口大小、位置、输入/输出和错误信息等。 * 可以获取到新进程的标识符以及进程句柄,方便后续管理。 * 具有更高的系统安全性。 **主要区别:** | 功能 | WinExec() | ShellExecute() | CreateProcess() | |---|---|---|---| | 参数类型 | 字符串 | 字符串或指针 |指针或字符串 | | 进程启动方式 | 不提供 | 可控制 | 可设置 | | 返回值 | 无 | 可设置 | 指向进程信息结构 | | 安全性 | 低 | 高 | 高 |

正文

创建新的进程是Windows程序开发的重要部分,它可以用于实现许多功能,例如进程间通信、并行处理等。其中,常用的三种创建进程的方式分别是WinExec()ShellExecute()CreateProcessA(),这三种创建进程的方式各有特点。如果需要创建简单进程或从其他程序启动新进程,可以使用WinExec()ShellExecute()函数。如果需要对新进程进行更精细的配置,例如控制进程参数、指定安全级别、传递特定的命令和参数等,可以使用CreateProcessA()函数。

首先介绍WinExec函数,该函数是创建进程的一种方式,它使用较为简单,但缺乏对进程参数和安全性等方面的控制。使用WinExec()函数,可以传递一个字符串类型的参数,该参数中指定了要启动的进程名和参数等信息。但是,由于WinExec()函数没有提供区分进程启动成功和失败的返回值,且无法从函数返回的进程句柄获得与进程相关的信息,因此使用较为有限。

该函数的原型为:

UINT WinExec(
  LPCSTR lpCmdLine,
  UINT   uCmdShow
);

其参数说明如下:

  • lpCmdLine:需要执行的命令行字符串
  • uCmdShow:指定程序窗口最初显示方式,如SW_SHOW,即窗口正常大小和位置显示

WinExec 函数的返回值是一个无符号整数,它表示进程是否成功启动。若成功启动,则返回值为任务句柄。否则,返回值为0。但是该函数也存在一些问题,例如ANSI编码、不支持进程标识符等,建议在实际开发中使用更为灵活的CreateProcess()ShellExecute()函数。

#include <iostream>
#include <Windows.h>

BOOL WinExec(char *pszExePath, UINT uiCmdShow)
{
  UINT uiRet = 0;
  uiRet = WinExec(pszExePath, uiCmdShow);
  if (31 < uiRet)
  {
    return TRUE;
  }
  return FALSE;
}

int main(int argc, char * argv[])
{
  int ret = 0;
  ret = WinExec("c:\\windows\\system32\\notepad.exe",TRUE);
  printf("执行状态: %d \n", ret);

  system("pause");
  return 0;
}

创建进程的第二个函数是ShellExecute,该函数提供了很多功能,例如可以启动进程、打开文件、运行脚本等等。ShellExecute()函数的优点是可以控制进程的启动方式、传递命令参数,并对返回值进行判断,通过传递参数来控制启动进程的方式,比如最大化或最小化窗口,或者在后台启动进程。

该函函数原型如下:

HINSTANCE ShellExecute(
  HWND    hwnd,
  LPCTSTR lpOperation,
  LPCTSTR lpFile,
  LPCTSTR lpParameters,
  LPCTSTR lpDirectory,
  INT     nShowCmd
);

参数说明:

  • hwnd:执行的窗口的句柄。可以为NULL,如果为NULL则表示没有窗口。
  • lpOperation:操作类型,可以是open或print。如果为NULL,则此函数将尝试打开文件。
  • lpFile:需要执行的目标文件、应用程序或者URL地址。
  • lpParameters:命令行参数。
  • lpDirectory:指定被启动程序的执行路径,如果为NULL,则使用当前程序路径。
  • nShowCmd:指定被启动程序的窗口状态。

该函数返回HINSTANCE类型的值,如果没有执行或则执行失败,它将返回一个值为ERROR_FILE_NOT_FOUNDERROR_BAD_FORMAT的值。

#include <iostream>
#include <Windows.h>

BOOL MyShellExecute(char *pszExePath, UINT uiCmdShow)
{
  HINSTANCE hInstance = 0;
  hInstance = ShellExecute(NULL, NULL, pszExePath, NULL, NULL, uiCmdShow);
  if (32 < (DWORD)hInstance)
  {
    return TRUE;
  }
  return FALSE;
}

int main(int argc, char * argv[])
{
  int ret = 0;
  ret = MyShellExecute("c:\\windows\\system32\\notepad.exe", TRUE);
  printf("执行状态: %d \n", ret);

  system("pause");
  return 0;
}

最后一个创建进程的函数是CreateProcess()该函数提供了比较灵活的进程控制,相比于其他API函数,例如WinExec()ShellExecute() ,它可以更详细地控制进程的执行,如进程窗口的大小和位置,输出、输入和错误信息的控制等,并且能够获取到新进程的标识符以及进程句柄。同时CreateProcess()也具有更高的系统安全性。因此,在实际开发中,开发人员往往使用 CreateProcess()函数进行进程控制、管理和处理。

其函数原型如下:

BOOL CreateProcess(
  LPCSTR                lpApplicationName,   // 可执行文件名或命令行调用
  LPSTR                 lpCommandLine,       // 字符串形式的命令行参数
  LPSECURITY_ATTRIBUTES lpProcessAttributes,// 进程的安全属性
  LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性
  BOOL                  bInheritHandles,     // 建立进程时是否继承父句柄
  DWORD                 dwCreationFlags,     // 进程标记
  LPVOID                lpEnvironment,       // 进程环境空间块的指针
  LPCSTR                lpCurrentDirectory,  // 当前工作目录的指针
  LPSTARTUPINFOA        lpStartupInfo,       // 指向 StartupInfo 结构的指针
  LPPROCESS_INFORMATION lpProcessInformation // 指向 ProcessInformation 结构的指针
);

参数说明:

  • lpApplicationName:需要执行的可执行文件名或命令行调用。如果为NULL,则将使用lpCommandLine参数中的文件名
  • lpCommandLine:命令行参数,可以传递参数给可执行文件
  • lpProcessAttributes:进程的安全属性。一般为NULL
  • lpThreadAttributes:线程的安全属性。一般为NULL
  • bInheritHandles:指定新进程是否继承父进程的句柄
  • dwCreationFlags:指定进程的标记。常用的标记有NORMAL_PRIORITY_CLASS,表示新进程在普通优先级类中运行
  • lpEnvironment:进程环境空间块的指针,用于设置新进程的环境变量
  • lpCurrentDirectory:指定新进程的初始工作目录,如果为NULL,则使用与调用进程相同的当前目录
  • lpStartupInfo:指向STARTUPINFO结构体的指针
  • lpProcessInformation:进程信息结构,包括新进程的句柄和进程ID

如果仅仅只是需要将一个进程拉起来,那么只需要传递三个参数即可,其余参数可以全部使用0进行填充,如下所示;

#include <iostream>
#include <Windows.h>

BOOL ExecRun(LPCSTR exe_file)
{
 PROCESS_INFORMATION pi = { 0 };
 STARTUPINFO si = { 0 };
 si.cb = sizeof(STARTUPINFO);

 BOOL bRet = CreateProcessA(exe_file, 0, 0, 0, 0, 0, 0, 0, &si, &pi);

 if (bRet != FALSE)
   CloseHandle(pi.hProcess);
 return TRUE;
 return FALSE;
}

int main(int argc, char * argv[])
{
 int ret = 0;
 ret = ExecRun("c:\\windows\\system32\\notepad.exe");
 printf("执行状态: %d \n", ret);

 system("pause");
 return 0;
}

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/89068d1f.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

与7.2 通过API创建新进程相似的内容:

7.2 通过API创建新进程

创建新的进程是`Windows`程序开发的重要部分,它可以用于实现许多功能,例如进程间通信、并行处理等。其中,常用的三种创建进程的方式分别是`WinExec()`、`ShellExecute()`和`CreateProcessA()`,这三种创建进程的方式各有特点。如果需要创建简单进程或从其他程序启动新进程,可以使用`WinExec()`或`ShellExecute()`函数。如果需要对新进程进行

推荐2款开源、美观的WinForm UI控件库

前言 今天大姚给大家分享2款开源、美观的WinForm UI控件库,希望可以帮助到有需要的同学。 WinForm介绍 WinForm是一个传统的桌面应用程序框架,它基于 Windows 操作系统的原生控件和窗体。通过简单易用的 API,开发者可以快速构建基于窗体的应用程序,并且可以利用多种控件和事件

7.2 C/C++ 实现动态链表

动态链表是一种常用的动态数据结构,可以在运行时动态地申请内存空间来存储数据,相比于静态数组和静态链表,更加灵活和高效。在动态链表中,数据元素被组织成一条链表,每个元素包含了指向下一个元素的指针,这样就可以通过指针将所有元素串联起来。使用动态链表存储数据时,不需要预先申请内存空间,而是在需要的时候才向内存申请。当需要添加新的元素时,可以使用`malloc`函数动态地申请内存空间,然后将新的元素插入到

时间片 线程切换 指令周期 流水线 TPS的初步了解

时间片 线程切换 指令周期 流水线 TPS的初步了解 情况说明 Redis 单线程提供服务, 可以支撑十万级别的TPS 通过以个非常简单的测试 redis-benchmark -c 50 -n 50000 ping Intel 8369HB 3.3Ghz 14万TPS 阿里 倚天710 2.7Ghz

CUDA C编程权威指南:2.2-给核函数计时

本文主要通过例子介绍了如何给核函数计时的思路和实现。实现例子代码参考文献[7],只需要把相应章节对应的CMakeLists.txt文件拷贝到CMake项目根目录下面即可运行。 1.用CPU计时器计时(sumArraysOnGPU-timer.cu)[7] 在主函数中用CPU计时器测试向量加法的核函数

Docker 必知必会2----跟我来一步步执行基本操作

通过前文(https://www.cnblogs.com/jilodream/p/18177695)的了解,我们已经大致明白了什么是docker,为什么要用docker,以及docker的基本设计思路是什么。今天来看下,docker的基本操作有哪些? 1、linux下安装docker 首先我们来安装

使用ensp搭建路由拓扑,并使用isis协议实现网络互通实操

转载请注明出处: 1.通过拓扑搭建如下拓扑: 其中R7、R8为L1,R6为L1/2,R9为L2。 2.配置isis实现网络互通 R7配置如下: [Huawei]isis 1 [Huawei-isis-1]di th # isis 1 is-level level-1 network-entity 1

Angular 集成 StreamSaver 大文件下载

应用场景: 实现目标: 在网页端实现大文件(文件大小 >= 2 G) 断点续传 实际方案: 发送多次请求, 每次请求一部分文件数据, 然后通过续写将文件数据全部写入. 难点: 无法实现文件续写, 最后采用 StreamSaver 来解决这个问题. 1. 首先从 git hub 将 StreamSav

NetMvc通过亚马逊方式服务器端和客户端上传MinIO顺利解决

前言: 1、由于项目是.NET Framework 4.7 MVC LayUI,所以需要找一个资源站点存放项目中静态资源文件; 2、需要支持服务端和客户端都支持上传文件方式; 3、调用简单,涉及库越少越好。 结果: 调用 AWSSDK.S3 和 AWSSDK.Core 实现文件上传到 MinIO ;

《吐血整理》高级系列教程-吃透Fiddler抓包教程(35)-Fiddler如何抓取微信小程序的包-下篇

1.简介 通过前边和宏哥的学习,我们了解到Android 7.0 之后增加了对第三方证书的限制,抓包工具(charles、fiddler等)提供的证书都无法通过校验,也就无法抓取HTTPS请求了,对测试工作影响很大。 最近更新的微信 7.0 也增加了第三方证书校验,导致无法正常抓包。 2.解决思路