探究Win32 API中CreateProcess的使用方法与场景

作者:深圳麻将开发公司 阅读:34 次 发布时间:2023-07-10 12:35:04

摘要:Win32 API 中的 CreateProcess 是一个强大的函数,用于创建新的进程。在 Windows 操作系统中,每个程序都运行在自己独立的进程中,CreateProcess 可以让我们通过代码启动新的进程,并在其中运行我们想要的程序。本文将探究 CreateProcess 在 Win3...

Win32 API 中的 CreateProcess 是一个强大的函数,用于创建新的进程。在 Windows 操作系统中,每个程序都运行在自己独立的进程中,CreateProcess 可以让我们通过代码启动新的进程,并在其中运行我们想要的程序。本文将探究 CreateProcess 在 Win32 API 中的使用方法和常见场景,并介绍一些相关的注意事项。

探究Win32 API中CreateProcess的使用方法与场景

一、CreateProcess 函数的调用方法

CreateProcess 函数的原型如下:

```

BOOL CreateProcess(

LPCWSTR lpApplicationName,

LPWSTR lpCommandLine,

LPSECURITY_ATTRIBUTES lpProcessAttributes,

LPSECURITY_ATTRIBUTES lpThreadAttributes,

BOOL bInheritHandles,

DWORD dwCreationFlags,

LPVOID lpEnvironment,

LPCWSTR lpCurrentDirectory,

LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATION lpProcessInformation

);

```

其中,各个参数的含义如下:

1. `lpApplicationName`:要启动的应用程序的名称或路径。

2. `lpCommandLine`:要传递给应用程序的命令行参数。如果要启动的应用程序是控制台应用程序,则命令行参数应该传递到应用程序的 main 函数中。

3. `lpProcessAttributes`:一个指向 SECURITY_ATTRIBUTES 结构体的指针,该结构体描述了新创建的进程的安全属性。如果为 NULL,则新创建的进程将继承当前进程的安全属性。

4. `lpThreadAttributes`:一个指向 SECURITY_ATTRIBUTES 结构体的指针,该结构体描述了新创建的主线程的安全属性。如果为 NULL,则新创建的线程将继承当前线程的安全属性。

5. `bInheritHandles`:一个 BOOL 值,指示新进程是否应该继承当前进程的所有句柄。如果为 TRUE,则新进程将继承当前进程的所有句柄;如果为 FALSE,则新进程将不会继承任何句柄。

6. `dwCreationFlags`:指定进程的创建标志。这些标志可以使用单个标志或多个标志的组合。取值可以参考 https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags。

7. `lpEnvironment`:指向环境变量字符串的指针。如果为 NULL,则新创建的进程将继承当前进程的环境变量。

8. `lpCurrentDirectory`:指定当前工作目录。如果为 NULL,则新创建的进程将继承当前进程的当前目录。

9. `lpStartupInfo`:一个指向 STARTUPINFO 结构的指针,该结构指定新进程的主窗口的外观和默认的输入输出处理方式。此参数是可选的。如果为 NULL,则使用默认的 STARTUPINFO。

10. `lpProcessInformation`:一个指向 PROCESS_INFORMATION 结构的指针,该结构包含新进程的标识符和主线程的标识符。创建进程成功后,可以使用此结构体中的信息与该进程进行交互。这是一个输出参数,必须传递有效的指针。

CreateProcess 函数使用非常灵活,可以通过不同的参数组合来控制新进程的行为,比如:

1. 启动控制台应用程序:

```

STARTUPINFO si;

PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));

si.cb = sizeof(si);

ZeroMemory(&pi, sizeof(pi));

CHAR cmd[] = "cmd.exe";

if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))

{

printf("Error: %d\n", GetLastError());

return 1;

}

```

2.启动 GUI 应用程序:

```

STARTUPINFO si;

PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));

si.cb = sizeof(si);

ZeroMemory(&pi, sizeof(pi));

WCHAR cmd[] = L"notepad.exe";

if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))

{

printf("Error: %d\n", GetLastError());

return 1;

}

```

3. 在新的进程中指定当前目录:

```

STARTUPINFO si;

PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));

si.cb = sizeof(si);

ZeroMemory(&pi, sizeof(pi));

WCHAR cmd[] = L"path/to/myprog.exe";

WCHAR dir[] = L"path/to/";

if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, dir, &si, &pi))

{

printf("Error: %d\n", GetLastError());

return 1;

}

```

二、CreateProcess 在常见场景下的使用

1. 启动应用程序:

CreateProcess 函数最常见的用途就是启动应用程序。我们可以使用 CreateProcess 函数来启动各种类型的应用程序,包括控制台应用程序、Windows 应用程序、DLL 等。

2. 启动监控子进程:

有时候我们需要在一个进程中监控其它进程的行为。这时候可以使用 CreateProcess 函数来启动子进程,并通过 `lpProcessInformation` 参数来获取子进程的句柄和 ID。然后使用 WaitForSingleObject 函数等待子进程退出,并在退出之后进行处理。

下面是一个示例代码,用于启动一个控制台应用程序,并监视其输出:

```

STARTUPINFO si;

PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));

si.cb = sizeof(si);

ZeroMemory(&pi, sizeof(pi));

CHAR cmd[] = "cmd.exe";

if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))

{

printf("Error: %d\n", GetLastError());

return 1;

}

// 等待子进程退出

if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED)

{

printf("WaitForSingleObject failed: %d\n", GetLastError());

}

else

{

printf("Process exited with code %d.\n", pi.dwExitCode);

}

// 关闭句柄

CloseHandle(pi.hProcess);

CloseHandle(pi.hThread);

```

3. 启动服务:

在 Windows 操作系统中,许多系统服务都是通过启动子进程来实现的。CreateProcess 函数是启动服务的最佳选择之一。

在创建服务时,可以通过 SERVICE_CONTROL_STOP 消息来关闭进程,也可以使用 SendMessageTimeout 函数向进程发送 WM_CLOSE 消息。

以下是一个示例代码,用于启动一个服务,并在收到 SERVICE_CONTROL_STOP 消息时关闭进程:

```

// 启动服务

SC_HANDLE svc = OpenService(

scm, // SCM 句柄

L"ServiceName", // 要启动的服务名称

SERVICE_QUERY_STATUS | // 需要查询服务状态

SERVICE_START // 需要启动服务

);

if (svc == NULL)

{

// 处理错误

return 1;

}

// 启动服务

if (!StartService(svc, 0, NULL))

{

// 处理错误

return 1;

}

// 等待服务启动完毕

while (TRUE)

{

SERVICE_STATUS status;

if (!QueryServiceStatus(svc, &status))

{

// 处理错误

return 1;

}

// 服务已启动

if (status.dwCurrentState == SERVICE_RUNNING)

{

break;

}

// 等待一段时间后再次查询服务状态

Sleep(status.dwWaitHint);

}

// 等待服务停止

while (TRUE)

{

SERVICE_STATUS status;

if (!QueryServiceStatus(svc, &status))

{

// 处理错误

return 1;

}

// 收到 SERVICE_CONTROL_STOP 消息

if (status.dwCurrentState == SERVICE_STOPPED)

{

break;

}

// 发送 WM_CLOSE 消息

if (status.dwCurrentState == SERVICE_RUNNING)

{

if (!GenerateConsoleCtrlEvent(CTRL_CLOSE_EVENT, 0))

{

// 处理错误

return 1;

}

if (SendMessageTimeout(

HWND_BROADCAST,

WM_CLOSE,

0,

0,

SMTO_ABORTIFHUNG | SMTO_BLOCK,

5000,

NULL

) == 0)

{

// 处理错误

return 1;

}

}

// 等待一段时间后再次查询服务状态

Sleep(status.dwWaitHint);

}

// 关闭服务句柄

CloseServiceHandle(svc);

```

三、注意事项

在使用 CreateProcess 函数时,需要注意以下几点:

1. 路径和命令行参数中需要使用完整路径和引号进行包装,以避免出现无法识别的空格和文件名。

2. 如果要继承当前进程的安全属性和环境变量,请将 lpProcessAttributes 和 lpEnvironment 参数设置为 NULL。

3. 使用 `CREATE_SUSPENDED` 标志启动进程时,新进程将被挂起,直到调用 ResumeThread 函数。

4. 使用 `CREATE_NEW_CONSOLE` 标志启动控制台应用程序时,必须将 `bInheritHandles` 参数设置为 TRUE,否则将无法从子进程读取控制台输出。

5. 使用 `CREATE_NO_WINDOW` 标志启动应用程序时,新进程将在后台运行,并且不会显示任何窗口或图标。

四、总结

CreateProcess 函数是 Win32 API 中最常用的函数之一,它可以用于启动各种类型的应用程序,并且还可以用于创建新的进程,以及监控子进程的行为。通过使用不同的标志和参数组合,我们可以根据自己的需求来控制新进程的行为。在使用 CreateProcess 函数时,需要特别注意路径和命令行参数的格式,以及参数的正确组合。

  • 原标题:探究Win32 API中CreateProcess的使用方法与场景

  • 本文链接:https:////zxzx/120022.html

  • 本文由深圳飞扬众网小编,整理排版发布,转载请注明出处。部分文章图片来源于网络,如有侵权,请与飞扬众网联系删除。
  • 微信二维码

    CTAPP999

    长按复制微信号,添加好友

    微信联系

    在线咨询

    点击这里给我发消息QQ客服专员


    点击这里给我发消息电话客服专员


    在线咨询

    免费通话


    24h咨询☎️:166-2096-5058


    🔺🔺 棋牌游戏开发24H咨询电话 🔺🔺

    免费通话
    返回顶部