2017-08-07 19 views
0

我在Stack Overflow上看到了一些CreateProcess()函數的例子,但是我無法得到這些例子的工作。我使用的是Visual Studio,但是編寫了直線C.這是我最近的嘗試。我可以得到它的編譯和執行,但我不能讓它啓動應用程序:如何在Visual Studios中使用CreateProcess函數

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」,其基於系統錯誤代碼指示「系統找不到指定的文件」。但是,我確定路徑是正確的,因爲我可以使用命令行中的路徑啓動「記事本」。我看不到我做錯了什麼。

+0

嘗試交換前兩個參數。第二個參數不能是一個文字字符串,但第一個可以。 – SBS

+0

對CreateProcess()的第一個參數使用逗號運算符似乎很奇怪。你有'(NULL,(LPTSTR)「C:\\ Windows \\ System32 \\ notepad.exe」)'作爲第一個參數,它計算NULL並拋出它,然後評估字符串的強制轉換。在['CreateProcess()'](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v = vs.85).aspx)上檢查MSDN - 你不指定一個命令(但我不知道這是否重要)。 –

+0

@JonathanLeffler你說得對 - 我沒有意識到附加的括號。我確信它不是這種意圖。 – SBS

回答

0

您需要擺脫傳遞的前2個參數值附近的額外括號。

但是,更重要的是,您需要擺脫LPTSTR類型。如果你的項目配置爲編譯對於Unicode,CreateProcess()將映射到CreateProcessW(),並LPTSTR將映射到wchar_t*,這樣你就會型鑄造窄const char[]文字的wchar_t*指針,並最終通過垃圾CreateProcessW(),這很容易解釋因爲你看到的錯誤。創建TCHAR[]字符串字面正確的方法是使用,而不是一個類型轉換的TEXT()宏(見Working with Strings MSDN上有詳細介紹):

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

然而,要注意CreateProcess() documentation

lpCommandLine [輸入,輸出,可選]
要執行的命令行。該字符串的最大長度爲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); 

否則,直接使用的CreateProcess() ANSI版本,可以放心地傳遞一個字符串字面到:

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%\System32%windir%\Sysnative訪問本地系統目錄。 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); 

但是,你應該考慮到,並不是每個人都安裝帳戶Windows在C:\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); 
+0

我會補充道路應該用雙引號括起來。雖然它適用於這種特定情況,但由於路徑不包含空格,因此它不適用於像C:\\ Program Files \\ Sub Folder \\ Some.exe這樣的路徑。 – zett42

+0

謝謝雷米。我刪除了將我認爲是兩個參數的圓括號合併爲一個,並根據您的建議修改了代碼。像魅力一樣工作。 –

+0

謝謝你們的支持。 –