2014-09-18 21 views
8

Ich versuche, CreateProcess zu verwenden, um einen neuen Umgebungsblock zu starten, und eine Stapelverarbeitungsdatei in dem neuen Umgebungsblock auszuführen. Ich habe das msdn-Beispiel für CreateProcess gelesen und kam mit dem unten gezeigten Code.Verwenden Sie CreateProcess, um eine Batchdatei auszuführen

Was passiert, wird es die neue Eingabeaufforderung öffnen und dort aufhören. Meine .bat-Datei wird aus irgendeinem Grund nicht ausgeführt. Die Verwendung von System ("CALL-Pfad") ruft die .bat-Datei auf.

#include <iostream> 

#define WINDOWS_LEAN_AND_MEAN 
#include <Windows.h> 

#include <strsafe.h> 

#define BUFSIZE 4096 

int main() 
{ 
    //system("CALL C:\\HFSS\\setup_vars.bat"); 

    //return 0; 

    LPWCH chNewEnv; 
    LPTSTR lpszCurrentVariable; 
    DWORD dwFlags = 0; 
    TCHAR szAppName[] = TEXT("C:\\windows\\system32\\cmd.exe"); 
    TCHAR cmdArgs[] = TEXT("C:\\HFSS\\setup_var.bat"); 

    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 
    BOOL fSuccess; 

    // Copy environment strings into an environment block. 
    chNewEnv = GetEnvironmentStrings(); 

    lpszCurrentVariable = (LPTSTR)chNewEnv; 
    if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MySetting=A")))) 
    { 
     printf("String copy failed\n"); 
     return FALSE; 
    } 

    lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1; 
    if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MyVersion=2")))) 
    { 
     printf("String copy failed\n"); 
     return FALSE; 
    } 

    // Terminate the block with a NULL byte. 

    lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1; 
    *lpszCurrentVariable = (TCHAR)0; 

    // Create the child process, specifying a new environment block. 

    SecureZeroMemory(&si, sizeof(STARTUPINFO)); 
    si.cb = sizeof(STARTUPINFO); 

#ifdef UNICODE 
    dwFlags = CREATE_UNICODE_ENVIRONMENT; 
#endif 

    fSuccess = CreateProcess(szAppName, cmdArgs, NULL, NULL, TRUE, dwFlags, 
     (LPVOID)chNewEnv, // new environment block 
     NULL, &si, &pi); 

    if (!fSuccess) 
    { 
     printf("CreateProcess failed (%d)\n", GetLastError()); 
     return FALSE; 
    } 

    std::cout << "In new environment\n"; 
    WaitForSingleObject(pi.hProcess, INFINITE); 

    return TRUE; 
} 
+0

Auf welcher Linie hat es einen Haltepunkt auslösen? Die Zeilen, von denen Sie nicht sicher sind, versuchen, dem Umgebungsblock des Prozesses, der gestartet werden soll, zwei neue Umgebungsvariablen hinzuzufügen, und Sie haben angegeben, dass Sie das versuchen, also bin ich mir nicht sicher, was Sie tun sollen Frage nach ihnen könnte sein. –

+0

Ich versuche tatsächlich, die Umgebungsvariablen in der Batchdatei festzulegen. Zu dem Zeitpunkt, zu dem ich die Stapelverarbeitungsdatei öffne (ohne den neuen Prozess zu erstellen), enthält die Variable% PATH% jedoch alle Baumdaten von Visual Studio. Wenn ich also versuche, den neuen Pfad an die Variable% PATH% anzufügen, werden überflüssige und überflüssige Informationen eingeschlossen. Außerdem fand ich den Absturz wegen der Verwendung von "\" anstelle von "\\" – user2970916

+0

Ihr Edit adressiert nicht alle Punkte, die ich angesprochen habe. –

Antwort

15

Einige Probleme:

  1. Sie benötigen die /C Option cmd.exe passieren, um ihm die .bat-Datei zu machen auszuführen.
  2. Der zweite Parameter zu CreateProcess muss eine änderbare Zeichenfolge sein. Kein Literal.
  3. Sie müssen Backslash-Zeichen in Literalen vermeiden.
  4. lpszCurrentVariable verweist auf den von GetEnvironmentStrings zurückgegebenen Puffer. Sie können diesen Puffer nicht ändern. Sie müssen einen neuen Puffer ausreichender Länge zuweisen und die Umgebung darin kopieren. Fügen Sie dann Ihre Änderungen hinzu.
  5. Umgebungsblöcke sind doppelt null-terminiert. Standard-String-Funktionen sind bei doppelt null-terminierten Strings nicht sinnvoll.
  6. Die Verwendung von Funktionen wie StringCchCopy anstatt C-Laufzeitfunktionen ist nur verwirrend. Nehmen Sie den MSDN-Beispielcode nicht als Musterbeispiel.
  7. C-Saiten sind eine Bindung, um mit zu arbeiten. Aber Sie verwenden C++, also verwenden Sie std::wstring und andere Standard-Bibliothek Klassen und Funktionen.
  8. Sie müssen WINDOWS_LEAN_AND_MEAN vor dem Importieren Windows.h definieren.
  9. Für C++ ist int main(void) falsch. Das Nein-Argument main ist int main().

Der folgende Code zeigt Ihnen, wie dies zu tun:

#include <cstring> 
#include <string> 
#include <iostream> 

#define WINDOWS_LEAN_AND_MEAN 
#include <Windows.h> 

std::wstring GetEnvString() 
{ 
    wchar_t* env = GetEnvironmentStrings(); 
    if (!env) 
     abort(); 
    const wchar_t* var = env; 
    size_t totallen = 0; 
    size_t len; 
    while ((len = wcslen(var)) > 0) 
    { 
     totallen += len + 1; 
     var += len + 1; 
    } 
    std::wstring result(env, totallen); 
    FreeEnvironmentStrings(env); 
    return result; 
} 

int main() 
{ 
    std::wstring env = GetEnvString(); 
    env += L"myvar=boo"; 
    env.push_back('\0'); // somewhat awkward way to embed a null-terminator 

    STARTUPINFO si = { sizeof(STARTUPINFO) }; 
    PROCESS_INFORMATION pi; 

    wchar_t cmdline[] = L"cmd.exe /C C:\\Desktop\\MyBatFile.bat"; 

    if (!CreateProcess(NULL, cmdline, NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT, 
     (LPVOID)env.c_str(), NULL, &si, &pi)) 
    { 
     std::cout << GetLastError(); 
     abort(); 
    } 

    CloseHandle(pi.hProcess); 
    CloseHandle(pi.hThread); 
} 
+0

Danke für all die Hilfe David, die jedoch läuft, gibt mir immer noch mein ursprüngliches Problem: Meine Batch-Datei liest% PATH% Variable als lokale Kopie (aus Visual Studio). Hier ist ein Link zu dem ursprünglichen Problem: http://stackoverflow.com/questions/25917796/setting-path-variable-is-not-working – user2970916

+0

Funktioniert hier gut. Außerdem wirst du beobachten, dass der Code, den ich zeige, viel einfacher ist als deiner und zeigt dir, wie man all die schrecklichen C-Boilerplates vermeidet. –

+0

Wie auch immer, beginnen Sie mit meinem genauen Programm. Ersetzen Sie den Namen der .bat-Datei durch einen gültigen Dateinamen auf Ihrem System. Setzen Sie in Ihrer .bat-Datei den 'set'-Befehl, der die Umgebungsvariablen auflistet. Was passiert, wenn Sie das tun? –

Verwandte Themen