我已经在Stack Overflow上看到了一些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',根据系统错误代码表示"系统无法找到指定的文件。&# 34 ;.但是,我确定路径是正确的,因为我可以使用命令行中的路径来启动记事本"。我无法看到我做错了什么。
答案 0 :(得分:1)
你需要摆脱你传递的前两个参数值的额外括号。
但是,更重要的是,你需要摆脱LPTSTR
类型转换。如果您的项目配置为针对Unicode进行编译,CreateProcess()
将映射到CreateProcessW()
,LPTSTR
将映射到wchar_t*
,因此您将输入一个狭窄的const char[]
1}}文字到wchar_t*
指针并最终将垃圾传递给CreateProcessW()
,这可以很容易地解释您所看到的错误。创建TCHAR[]
字符串文字的正确方法是使用TEXT()
宏而不是类型转换(有关详细信息,请参阅MSDN上的Working with Strings):
hr = CreateProcess(NULL, TEXT("C:\\Windows\\System32\\notepad.exe"), NULL,
NULL, NULL, FALSE, 0, NULL,
NULL, &StartupInfo, &ProcessInfo);
但请注意CreateProcess()
documentation:
lpCommandLine [in,out,optional]
要执行的命令行。此字符串的最大长度为32,768个字符,包括Unicode终止空字符。如果lpApplicationName
为NULL,则lpCommandLine的模块名称部分限制为MAX_PATH
个字符。此函数的Unicode版本
CreateProcessW
可以修改此字符串的内容。因此,此参数不能是只读内存的指针(例如const变量或文字字符串)。如果此参数是常量字符串,则该函数可能会导致访问冲突。
您可以执行以下操作以避免这种情况:
TCHAR szCmdLine[] = TEXT("C:\\Windows\\System32\\notepad.exe");
hr = CreateProcess(NULL, szCmdLine, NULL,
NULL, NULL, FALSE, 0, NULL,
NULL, &StartupInfo, &ProcessInfo);
或者:
WCHAR szCmdLine[] = L"C:\\Windows\\System32\\notepad.exe";
hr = CreateProcessW(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位版本的记事本,则必须使用C:\Windows\Sysnative\notepad.exe
代替WOW64文档:
%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位应用程序中使用System32
,在64位系统上运行64位应用程序:
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询问System文件夹的实际位置:
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);