_spawn
、_wspawn
函数
每个 _spawn
函数将创建并执行一个新进程:
%>
%>
%>
%>
%>
%>
%>
%>
函数名称的结尾字母确定变体。
信件 | 变量 |
---|---|
e |
指向环境设置的指针的数组 envp 将传递给新进程。 |
l |
将命令行参数单独传递给 _spawn 函数。 一般将在预先知道新进程的一些参数时使用此后缀。 |
p |
PATH 环境变量用于查找要执行的文件。 |
v |
指向命令行参数的指针的数组 argv 将传递给 _spawn 函数。 一般在新进程的几个参数可变时使用此后缀。 |
注解
每个 _spawn
函数都将创建并执行一个新进程。 它们将根据情况自动处理多字节字符串参数,根据当前正在使用中的多字节代码页识别多字节字符序列。 _wspawn
函数是 _spawn
函数的宽字符版本;它们不处理多字节字符串。 否则,_wspawn
函数的行为将与其 _spawn
对等函数的一致。
一般文本例程映射
Tchar.h 例程 |
_UNICODE 和 _MBCS 未定义 |
_MBCS 已定义 |
_UNICODE 已定义 |
---|---|---|---|
_tspawnl |
_spawnl |
_spawnl |
_wspawnl |
_tspawnle |
_spawnle |
_spawnle |
_wspawnle |
_tspawnlp |
_spawnlp |
_spawnlp |
_wspawnlp |
_tspawnlpe |
_spawnlpe |
_spawnlpe |
_wspawnlpe |
_tspawnv |
_spawnv |
_spawnv |
_wspawnv |
_tspawnve |
_spawnve |
_spawnve |
_wspawnve |
_tspawnvp |
_spawnvp |
_spawnvp |
_wspawnvp |
_tspawnvpe |
_spawnvpe |
_spawnvpe |
_wspawnvpe |
加载和执行新进程必须有足够的内存可用。 mode
参数确定调用进程在 _spawn
之前以及期间将执行的操作。 mode
的下列值是在 Process.h
中定义的:
值 | 说明 |
---|---|
_P_OVERLAY |
使用新进程覆盖调用进程,销毁调用进程(效果与 _exec 调用相同)。 |
_P_WAIT |
在新进程执行完成之前挂起调用线程(同步 _spawn )。 |
_P_NOWAIT 或 _P_NOWAITO |
继续与新进程一起并发执行调用进程(异步 _spawn )。 |
_P_DETACH |
继续执行调用进程;新进程将在后台运行,而且不会访问控制台或键盘。 针对新进程调用 _cwait 将失败(异步 _spawn )。 |
cmdname
参数指定将作为新进程执行的文件,并可以指定完整路径(从根)、部分路径(从当前工作目录)或仅指定文件名。 如果 cmdname
没有文件扩展名或不是以句点 (.) 结尾的,则 _spawn
函数将先依次尝试 .com 文件扩展名、.exe 文件扩展名、.bat 文件扩展名和 .cmd 文件扩展名。
如果 cmdname
具有文件扩展名,则仅使用该扩展名。 如果 cmdname
以句点结尾,则 _spawn
调用将搜索不带文件扩展名的 cmdname
。 _spawnlp
、_spawnlpe
、_spawnvp
和 _spawnvpe
函数将在 PATH
环境变量指定的目录中搜索 cmdname
(使用相同过程)。
如果 cmdname
包含驱动器说明符或任何斜线(即,如果它是相对路径),则 _spawn
调用将仅搜索指定文件;不会执行路径搜索。
以前,这些函数中部分函数在成功时将 errno
设置为零;当前行为是在成功时保持不改动 errno
,如 C 标准所指定。 如果需要模拟这一旧行为,请在调用这些函数之前将 errno
设置为零。
注意
若要确保正确覆盖初始化和终止,请勿使用 setjmp
或 longjmp
函数进入或离开覆盖例程。
生成进程的参数
若要将参数传递给新进程,请在 _spawn
调用中将一个或多个指向字符串的指针作为参数提供。 这些字符串构成了生成进程的参数列表。 构成新进程参数列表的字符串的组合长度不得超过 1024 个字节。 每个字符串的终止 null 字符(“\0”)不包含在计数中,但是空格字符(自动插入以分隔自变量)包括在内。
注意
嵌入字符串中的空格可能导致意外行为;例如,将字符串 _spawn
传递给 "hi there"
会导致新进程获得两个参数:"hi"
和 "there"
。 如果想要让新进程打开名为“hi there”的文件,则该进程将失败。 你可以通过引用字符串 "\"hi there\""
来避免此问题。
重要
如果没有显式地检查其内容,请不要将用户输入传递给 _spawn
。 _spawn
将导致调用 CreateProcess
,因此请牢记,未限定的路径名称可能会导致潜在安全漏洞。
您可以将参数指针作为不同的参数传递(在 _spawnl
、_spawnle
、_spawnlp
和 _spawnlpe
中)或作为指针数组传递(在 _spawnv
、_spawnve
、_spawnvp
和 _spawnvpe
中)。 必须至少将自变量 arg0
或 argv[0]
中的其中一个传递到生成进程。 按照约定,此参数是程序的名称,因为您将在命令行上键入该名称。 不同的值不会产生错误。
一般将在提前知道参数数量的情况下使用 _spawnl
、_spawnle
、_spawnlp
和 _spawnlpe
调用。 arg0
参数通常是指向 cmdname
的指针。 参数 arg1
到 argn
是指向构成新参数列表的字符字符串的指针。 在 argn
之后,必须是一个 NULL
指针,用以标记参数列表的末尾。
_spawnv
、_spawnve
、_spawnvp
和 _spawnvpe
调用在新进程具有数量可变的自变量时很有用。 指向自变量的指针将作为数组 argv
传递。自变量 argv[0]
通常是一个指向实际模式中的路径或保护模式中的程序的指针,从 argv[1]
到 argv[n]
都是指向构成新自变量列表的字符串的指针。 自变量 argv[n +1]
必须是一个 NULL
指针,用以标记自变量列表的末尾。
生成进程的环境
调用 _spawn
时打开的文件在新进程中仍处于打开状态。 在 _spawnl
、_spawnlp
、_spawnv
和 _spawnvp
调用中,新进程将继承调用进程的环境。 您可以使用 _spawnle
、_spawnlpe
、_spawnve
和 _spawnvpe
调用更改新进程的环境,方式为通过 envp
参数传递环境设置的列表。 参数 envp
是字符指针的数组,其中每个元素(除了最后一个元素)均指向一个定义环境变量的不以 null 结尾的字符串。 此类字符串通常具有 NAME
=value
格式,其中 NAME
是环境变量的名称,value
是为该变量设置的字符串值。 (必须将 value
放在双引号中。)envp
数组的最后一个元素应该是 NULL
。 当 envp
本身为 NULL
时,生成进程将继承父进程的环境设置。
_spawn
函数可将所有有关打开的文件(包括转换模式)的信息传递到新进程。 此信息将在实模式下通过环境中的 C_FILE_INFO
条目传递。 启动代码通常会处理此条目,然后将其从环境中删除。 但是,如果 _spawn
函数生成一个非 C 进程,则此条目仍将保留在环境中。 打印环境将在此条目的定义字符串中显示图形字符,因为环境信息在实模式下是以二进制格式传递的。 它不应对正常操作具有任何其他影响。 在保护模式下,环境信息是以文本形式传递的,因此不包含图形字符。
在调用 fflush
函数之前,您必须显式刷新(使用 _flushall
或 _spawn
)或关闭任何流。
通过调用 _spawn
例程创建的新进程不会保留任何信号设置。 而生成进程会将信号设置重置为默认值。
重定向输出
如果从 DLL 或 GUI 应用程序调用 _spawn
并希望将输出重定向至管道,则你有两个选择:
使用 Win32 API 创建管道,然后调用
AllocConsole
,在启动结构中设置句柄值,然后调用CreateProcess
。调用
_popen
或_wpopen
以创建管道并使用cmd.exe /c
(或command.exe /c
)调用应用程序。
示例
// crt_spawn.c
// This program accepts a number in the range
// 1-8 from the command line. Based on the number it receives,
// it executes one of the eight different procedures that
// spawn the process named child. For some of these procedures,
// the CHILD.EXE file must be in the same directory; for
// others, it only has to be in the same path.
//
#include <stdio.h>
#include <process.h>
char *my_env[] =
{
"THIS=environment will be",
"PASSED=to child.exe by the",
"_SPAWNLE=and",
"_SPAWNLPE=and",
"_SPAWNVE=and",
"_SPAWNVPE=functions",
NULL
};
int main( int argc, char *argv[] )
{
char *args[4];
// Set up parameters to be sent:
args[0] = "child";
args[1] = "spawn??";
args[2] = "two";
args[3] = NULL;
if (argc <= 2)
{
printf( "SYNTAX: SPAWN <1-8> <childprogram>\n" );
exit( 1 );
}
switch (argv[1][0]) // Based on first letter of argument
{
case '1':
_spawnl( _P_WAIT, argv[2], argv[2], "_spawnl", "two", NULL );
break;
case '2':
_spawnle( _P_WAIT, argv[2], argv[2], "_spawnle", "two",
NULL, my_env );
break;
case '3':
_spawnlp( _P_WAIT, argv[2], argv[2], "_spawnlp", "two", NULL );
break;
case '4':
_spawnlpe( _P_WAIT, argv[2], argv[2], "_spawnlpe", "two",
NULL, my_env );
break;
case '5':
_spawnv( _P_OVERLAY, argv[2], args );
break;
case '6':
_spawnve( _P_OVERLAY, argv[2], args, my_env );
break;
case '7':
_spawnvp( _P_OVERLAY, argv[2], args );
break;
case '8':
_spawnvpe( _P_OVERLAY, argv[2], args, my_env );
break;
default:
printf( "SYNTAX: SPAWN <1-8> <childprogram>\n" );
exit( 1 );
}
printf( "from SPAWN!\n" );
}
child process output
from SPAWN!
另请参阅
进程和环境控制
abort
atexit
_exec
、_wexec
函数
.- .
_flushall
_getmbcp
%>
_setmbcp
%>