创建新的进程是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;
}

7.2 通过API创建新进程的更多相关文章

  1. Linux内核分析— —创建新进程的过程

    分析Linux内核创建一个新进程的过程 实验过程 要求:使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证对Linux系统创建一个新进程的理解,推荐在实验楼Linux虚拟机环 ...

  2. linux进程学习-创建新进程

    init进程将系统启动后,init将成为此后所有进程的祖先,此后的进程都是直接或间接从init进程“复制”而来.完成该“复制”功能的函数有fork()和clone()等. 一个进程(父进程)调用for ...

  3. Win32 API编程:使用CreateProcess创建新进程

    #include <windows.h> #include <tchar.h> #include <stdio.h> int main(int argc, char ...

  4. Go:创建新进程(os.StartProcess源码解读)

    关于如何使用go语言实现新进程的创建和进程间通信,我在网上找了不少的资料,但是始终未能发现让自己满意的答案,因此我打算自己来分析这部分源代码,然后善加利用,并且分享给大家,期望大家能从中获得启发. 首 ...

  5. fork函数创建新进程过程分析

    gdb调试执行流程,首先设置断点b sys_clone,当在shell下输入fork命令后,系统执行至断点,接下来按步执行: 判断是否被跟踪 判断是否被创建为轻量级进程(vfork) 判断父进程是否被 ...

  6. Linux内核分析-创建新进程的过程

    分析Linux内核创建一个新进程的过程 task_struct结构体分析 struct task_struct{ volatile long state; //进程的状态 unsigned long ...

  7. VC++ 使用CreateProcess创建新进程

    https://www.cnblogs.com/fancing/p/6477918.html #include <windows.h> #include <tchar.h> # ...

  8. 创建新进程,就三个函数CreateProcessAsUser CreateProcessWithLogonW CreateProcessWithTokenW(附网友的流程)

    CreateProcessAsUser 怎么会还需要密码呢~~~ 先WTSGetActiveConsoleSessionId 得到当前的处理激活状态的SessionId OpenProcessToke ...

  9. Linux内核创建一个新进程

    张雨梅   原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10000 创建新进程 如果同一个程序被多 ...

  10. 第六周——分析Linux内核创建一个新进程的过程

    "万子恵 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 &q ...

随机推荐

  1. 2024-01-17:lc的30. 串联所有单词的子串

    2024-01-17:用go语言,给定一个字符串 s 和一个字符串数组 words. words 中所有字符串 长度相同. s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接 ...

  2. CMake 禁用 MSVC 编译警告 C4819

    warning C4819:该文件包含不能在当前代码页(936)中表示的字符.请将该文件保存为 Unicode 格式以防止数据丢失 if (win32) add_complie_options(/W4 ...

  3. MongoDB 和 MySQL 之间有何区别?

    MongoDB 和 MySQL 是两个可用于存储和管理数据的数据库管理系统.MySQL 是一个关系数据库系统,以结构化表格格式存储数据.相比之下,MongoDB 以更灵活的格式将数据存储为 JSON ...

  4. HashMap非线程安全到底有什么问题

    HashMap是Java中常用的数据结构,用于存储键值对,并且提供了快速的查找和插入操作.下面挖掘一下HashMap内部的架构设计思维: 哈希函数的设计: HashMap使用哈希函数将键映射到数组索引 ...

  5. 如何使用VNC进行远程桌面控制

    VNC是一款很实用的可以实现远程桌面控制的小工具,我遇到的有两种情况比较常见,一是有时候时候可能你会外出或离开自己办公室(但可以访问到办公司的网络),而很多资料都保存在办公室的台式机上,这时如果突然有 ...

  6. 【TouxhGFX】集成 之 《Using C code with TouchGFX》

    在TouchGFX中使用C代码 您可能已经知道,TouchGFX是用C ++实现的,而TouchGFX API也是C ++.这意味着至少直接与UI相关的代码必须是C ++代码.但是,并不需要整个系统都 ...

  7. NewStarCTF 2023 公开赛道 WEEK4|CRYPTO WP

    RSA Variation II 1.题目信息 提示:"Schmidt Samoa" 附件信息 from secret import flag from Crypto.Util.n ...

  8. Laravel - 配置 数据库

  9. Qt5.9 UI设计(五)——将Tabwidget与treeWidget相互关联

    前言 前面一章介绍了ControlTabWidget ControlTreeWidget maintitlebar 三个子页面同时布局到 mainwindow 的方法,本章介绍如何将ControlTr ...

  10. cri-docker的学习和了解-番外

    cri-docker的学习和了解-番外 前言 因为已经有足足两年多没再详细接触K8S了. 然后利用两个晚上搭建了IPV6 SingleStack的K8S单机版 中间一直使用的docker的方式学习和工 ...