如何在Visual Studio

时间:2017-08-07 18:43:33

标签: c visual-studio winapi

我已经在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 ;.但是,我确定路径是正确的,因为我可以使用命令行中的路径来启动记事本"。我无法看到我做错了什么。

1 个答案:

答案 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文档:

File System Redirector

  

%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);