Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Visual Studio中使用CreateProcess函数_C_Visual Studio_Winapi - Fatal编程技术网

如何在Visual Studio中使用CreateProcess函数

如何在Visual Studio中使用CreateProcess函数,c,visual-studio,winapi,C,Visual Studio,Winapi,我已经看到了一些关于堆栈溢出的CreateProcess()函数的示例,但是我无法让这些示例正常工作。我使用的是Visual Studio,但编程时使用的是C语言。这是我的最新尝试。我可以让它编译和执行,但我无法让它启动应用程序: PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter STARTUPINFO StartupInfo; //This is an [in] parameter Zero

我已经看到了一些关于堆栈溢出的CreateProcess()函数的示例,但是我无法让这些示例正常工作。我使用的是Visual Studio,但编程时使用的是C语言。这是我的最新尝试。我可以让它编译和执行,但我无法让它启动应用程序:

PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
STARTUPINFO StartupInfo; //This is an [in] parameter
ZeroMemory(&StartupInfo, sizeof(StartupInfo));

StartupInfo.cb = sizeof StartupInfo ; 

hr = CreateProcess((NULL, (LPTSTR) "C:\\Windows\\System32\\notepad.exe"), NULL,  
                    NULL,NULL,FALSE,0,NULL,
                    NULL,&StartupInfo,&ProcessInfo);

                int error_1 = 0;
                if(!hr)
                {
                    error_1 = GetLastError();
                }

当我读取“error_1”时,它返回一个“2”,它基于系统错误代码指示“系统找不到指定的文件”。但是,我确信路径是正确的,因为我可以使用命令行中的路径启动“记事本”。我看不出我做错了什么。

您需要去掉前两个参数值周围的额外括号

但是,更重要的是,您需要去掉
LPTSTR
类型转换。如果您的项目配置为针对Unicode进行编译,
CreateProcess()
将映射到
CreateProcessW()
,而
LPTSTR
将映射到
wchar\u t*
,因此您将键入一个狭窄的
const char[]
文本到
wchar\u t*
指针,并最终将垃圾传递到
CreateProcessW()
,这很容易解释您看到的错误。创建
TCHAR[]
字符串文字的正确方法是使用宏而不是类型转换(有关详细信息,请参阅MSDN上的):

但是,请注意:

lpCommandLine[输入、输出、可选]
要执行的命令行。此字符串的最大长度为32768个字符,包括Unicode终止空字符。如果
lpApplicationName
为空,则lpCommandLine的模块名称部分仅限于
MAX\u PATH
个字符

此函数的Unicode版本,
CreateProcessW
,可以修改此字符串的内容。因此,此参数不能是指向只读内存(例如常量变量或文字字符串)的指针。如果此参数为常量字符串,则函数可能会导致访问冲突。

您可以执行以下操作以避免出现这种情况:

TCHAR szCmdLine[] = TEXT("C:\\Windows\\System32\\notepad.exe");
hr = CreateProcess(NULL, szCmdLine, NULL,  
                    NULL, NULL, FALSE, 0, NULL,
                    NULL, &StartupInfo, &ProcessInfo);
或:

否则,直接使用ANSI版本的
CreateProcess()
,您可以安全地将字符串文本传递给:

hr = CreateProcessA(NULL, "C:\\Windows\\System32\\notepad.exe", NULL,  
                    NULL, NULL, FALSE, 0, NULL,
                    NULL, &StartupInfo, &ProcessInfo);
另外,您不需要指定notepad.exe的完整路径,因为Windows知道它的位置。您可以自己使用“notepad.exe”

但是,如果指定完整路径,则必须考虑应用程序的位。如果您的应用程序编译为32位,并且在64位系统上运行,
C:\Windows\System32\notepad.exe
将重定向到
C:\Windows\SysWOW64\notepad.exe
,这是32位版本的记事本。如果要运行64位版本的记事本,则必须根据WOW64文档使用
C:\Windows\Sysnative\Notepad.exe

%windir%\System32
目录是为64位应用程序保留的。创建64位版本的DLL时,大多数DLL文件名未更改,所以32位版本的DLL存储在不同的目录中。WOW64通过使用文件系统重定向器隐藏此差异

在大多数情况下,只要32位应用程序试图访问
%windir%\System32
,访问就会重定向到
%windir%\SysWOW64
。对
%windir%\lastgood\system32
的访问被重定向到
%windir%\lastgood\SysWOW64
。对
%windir%\regedit.exe的访问被重定向到
%windir%\SysWOW64\regedit.exe

32位应用程序可以通过将
%windir%\Sysnative
替换为
%windir%\System32
来访问本机系统目录。WOW64将
Sysnative
识别为一个特殊别名,用于指示文件系统不应重定向访问。此机制灵活且易于使用,因此,建议使用此机制绕过文件系统重定向。请注意,64位应用程序不能使用Sysnative别名,因为它是虚拟目录而不是真实目录

Sysnative
仅适用于在WOW64仿真器内运行的32位应用程序。您可以在32位系统上运行的32位应用程序和64位系统上运行的64位应用程序中使用
System32

TCHAR szCmdLine[MAX_PATH];

#ifndef _WIN64
BOOL bIsWow64Process = FALSE;
if (IsWow64Process(GetCurrentProcess(), &bIsWow64Process) && bIsWow64Process)
    lstrcpy(szCmdLine, TEXT("C:\\Windows\\Sysnative\\notepad.exe"));
else
#endif
    lstrcpy(szCmdLine, TEXT("C:\\Windows\\System32\\notepad.exe"));

hr = CreateProcess(NULL, szCmdLine, NULL,  
                    NULL, NULL, FALSE, 0, NULL,
                    NULL, &StartupInfo, &ProcessInfo);
但是,您应该考虑到并非每个人都在
C:\Windows
文件夹中安装Windows,因此您应该询问Windows系统文件夹的实际位置:

TCHAR szSysDir[MAX_PATH];

#ifndef _WIN64
BOOL bIsWow64Process = FALSE;
if (IsWow64Process(GetCurrentProcess(), &bIsWow64Process) && bIsWow64Process)
{
    TCHAR szWinDir[MAX_PATH];
    GetWindowsDirectory(szWinDir, MAX_PATH);
    PathCombine(szSysDir, szWinDir, TEXT("Sysnative");
}
else
#endif
    GetSystemDirectory(szSysDir, MAX_PATH);

TCHAR szCmdLine[MAX_PATH];
PathCombine(szCmdLine, szSysDir, TEXT("notepad.exe");

hr = CreateProcess(NULL, szCmdLine, NULL,  
                    NULL, NULL, FALSE, 0, NULL,
                    NULL, &StartupInfo, &ProcessInfo);

尝试交换前两个参数。第二个参数不能是文字字符串,但第一个可以。对
CreateProcess()
的第一个参数使用逗号运算符似乎有些奇怪。您有
(NULL,(LPTSTR)“C:\\Windows\\System32\\notepad.exe”)
作为第一个参数,它计算
NULL
并将其丢弃,然后计算字符串的转换。检查MSDN on-您没有指定命令行(但我不知道这是否重要)。@JonathanLeffler您是对的-我没有意识到附加的括号。我相信这不是故意的。问题之一是你的演员阵容。关于字符串文字的类型,您在向编译器撒谎。您不应该将
CreateProcess()
的第二个参数强制转换为
LPTSTR
,因为它是字符串文字,
CreateProcess()
可能会修改字符串。无法修改字符串文字,因为它存储在只读内存中。而是将路径存储在字符数组中,并将该数组传递给函数。此外,还应将路径用双引号括起来,以允许在路径中使用空格。保留空格字符是为了将路径与命令行参数分开。我要补充的是,路径应该用双引号括起来。虽然它在这种特定情况下工作,但由于路径不包含空格,因此不会工作
TCHAR szCmdLine[MAX_PATH];

#ifndef _WIN64
BOOL bIsWow64Process = FALSE;
if (IsWow64Process(GetCurrentProcess(), &bIsWow64Process) && bIsWow64Process)
    lstrcpy(szCmdLine, TEXT("C:\\Windows\\Sysnative\\notepad.exe"));
else
#endif
    lstrcpy(szCmdLine, TEXT("C:\\Windows\\System32\\notepad.exe"));

hr = CreateProcess(NULL, szCmdLine, NULL,  
                    NULL, NULL, FALSE, 0, NULL,
                    NULL, &StartupInfo, &ProcessInfo);
TCHAR szSysDir[MAX_PATH];

#ifndef _WIN64
BOOL bIsWow64Process = FALSE;
if (IsWow64Process(GetCurrentProcess(), &bIsWow64Process) && bIsWow64Process)
{
    TCHAR szWinDir[MAX_PATH];
    GetWindowsDirectory(szWinDir, MAX_PATH);
    PathCombine(szSysDir, szWinDir, TEXT("Sysnative");
}
else
#endif
    GetSystemDirectory(szSysDir, MAX_PATH);

TCHAR szCmdLine[MAX_PATH];
PathCombine(szCmdLine, szSysDir, TEXT("notepad.exe");

hr = CreateProcess(NULL, szCmdLine, NULL,  
                    NULL, NULL, FALSE, 0, NULL,
                    NULL, &StartupInfo, &ProcessInfo);