7.2 通过API创建新进程

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

创建新的进程是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进行填充,如下所示;
    ```c

    include

    include

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 许可协议。转载请注明出处!

相关文章
|
1月前
|
存储 SQL Shell
【OSTEP】Abstraction Process | 进程 | 虚拟化 | 进程API
【OSTEP】Abstraction Process | 进程 | 虚拟化 | 进程API
19 0
|
7月前
|
Unix Shell API
Unix 进程 API 介绍
Unix 进程 API 介绍
|
Java API 调度
Java多线程基础(线程与进程的区别,线程的创建方式及常用api,线程的状态)
每一个线程都是一个执行流,都按照自己的顺序执行自己的代码,多个线程之间“同时”(并发并行)的执行多份代码。Java中的线程是以轻量级进程来实现的。
Java多线程基础(线程与进程的区别,线程的创建方式及常用api,线程的状态)
|
测试技术 API Windows
利用global API hooks在Win7系统下隐藏进程
本文讲的是利用global API hooks在Win7系统下隐藏进程,在之前的文章《Powershell tricks::Hide Process by kd.exe》介绍过通过kd.exe隐藏进程的技巧,最大的缺点是需要开启Local kernel debugging模式,等待重启才能生效
1732 0
|
网络协议 Unix API
《UNIX网络编程 卷1:套接字联网API(第3版)》——8.9 服务器进程未运行
我们下一个要检查的情形是在不启动服务器的前提下启动客户。如果我们这么做后在客户上键入一行文本,那么什么也不发生。客户永远阻塞于它的recvfrom调用,等待一个永不出现的服务器应答。然而这是一个很好的例子,它要求我们更多地了解底层协议以理解网络应用进程将发生什么。
1617 0
|
缓存 Linux API
linux 进程(二) --- 进程的创建及相关api
一、进程的创建fork()函数  由fork创建的新进程被称为子进程(child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是 新子进程的进程ID。
1025 0
|
JavaScript Shell Linux
node.js入门 - 12.api:进程(process)
  虽然node对操作系统做了很多抽象的工作,但是你还是可以直接和他交互,比如和系统中已经存在的进程进行交互,创建工作子进程。node是一个用于事件循环的线程,但是你可以在这个事件循环之外创建其他的进程(线程)参与工作。
878 0
|
安全 API 调度
14、Windows API 进程、线程、模块
一、基本概念  1、进程是应用程序的实例。进程包括一个虚拟地址空间及代码、数据、对象等程序运行所需环境和资源的集合。在内存空间中包括若干可执行的代码、数据、资源、一系列对系统对象操作的句柄,安全上下文、进程标识符(PID),环境变量等程序执行的环境。
843 0
|
API Windows
5、Windows API,进程和线程、控件与消息
11. API之进程和线程函数 CancelWaitableTimer 这个函数用于取消一个可以等待下去的计时器操作 CallNamedPipe 这个函数由一个希望通过管道通信的一个客户进程调用 ConnectNamedPipe 指示一台服务器等待下去,直至客户机同一个命名管道连接 CreateEvent 创建一个事件对象 CreateMailslot 创建一个邮路。
894 0
热门文章
最新文章
相关产品
云迁移中心
推荐文章
更多