[WIN] DLL Suche bei CreateProcess

  • Themenstarter Themenstarter Gelöschtes Mitglied 16444
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 16444

Guest
Moin!

Ich habe hier ein Problem einer mit CreateProcess() gestarteten Applikation die korrekte DLL mitzugeben.

Die Applikation, die ich starten möchte liegt in ihrem eigenen Verzeichniss zusammen mit ein paar DLLs, die sie benötigt. Bei diesen DLLs fehlt eine, die es mit der aufrufenden Applikation teilen muss.
Die Applikation, die CreateProcess() aufruft, liegt in einem zweiten Verzeichnis, in dem auch die gemeinsam genutzte DLL liegt.
Insgesamt gibt es zwei solcher aufrufenden Applikationen, die in unterschiedlichen Verzeichnissen liegen. Es soll jeweils die DLL verwendet werden, die im Verzeichnis der aufrufenden Applikation liegt.

Wenn eine Applikation versucht eine DLL zu laden wird ja unter anderem auch im CWD gesucht [1]. Also habe ich versucht CreateProcess() das Verzeichniss in dem die Aufrufende Applikation liegt als current directory mit zu geben. Leider ohne Erfolg, es wird in der Suche nach der DLL nicht berücksichtigt.

Das grundsätzliche Problem lässt sich sicher auch noch auf andere Arten lösen, aber mich wundert, warum diese nicht funktioniert? Was habe ich übersehen?

[1] http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx
 
Bist du sicher, dass du CreateProcess richtig verwendet hast?

Könntest du evtl. mal den Code-Abschnitt zeigen, wo du das Environment für CreateProcess erweiterst?
 
Du kannst die DLL auch dynamisch laden ohne dich auf den Suchpfad verlassen zu müssen.
 
Moment, damit wir uns nicht missverstehen. Ich manipuliere nicht das environment mit CreateProcess, sondern setze den Parameter für das current directory!
Für den Aufruf den PATH anzupassen war mir bisher zu viel Aufwand, wenn man es schön machen wollte ;)

Code:
STARTUPINFO startupinfo;
PROCESS_INFORMATION processinfo;
    
ZeroMemory( &startupinfo, sizeof(startupinfo) );
ZeroMemory( &processinfo, sizeof(processinfo) );
    
startupinfo.cb = sizeof(startupinfo);

CString callingPath("");
if( !GetModuleFileName(NULL, callingPath.GetBuffer(dwBufferSize), dwBufferSize) )
{
    callingPath.ReleaseBuffer();
    ASSERT(FALSE);
    return;
}

callingPath.ReleaseBuffer();
callingPath = callingPath.Left(callingPath.ReverseFind('\\'));

DWORD dwExitCode(0);
BOOL started = CreateProcess(application,
                             arguments,
                             NULL, NULL, FALSE,
                             NORMAL_PRIORITY_CLASS,
                             NULL,
                             callingPath.GetBuffer(dwBufferSize),
                             &startupinfo,
                             &processinfo);

callingPath.ReleaseBuffer();
Dynamisches Laden wäre auch eine Möglichkeit, aber etwas aufwändiger und fehleranfälliger.
 
Moment, damit wir uns nicht missverstehen. Ich manipuliere nicht das environment mit CreateProcess, sondern setze den Parameter für das current directory!

Ok, dann haben wir uns missverstanden. Könntest du evtl. mal mit einem kleinen Testprogramm, welches du über CreateProcess aufrufst, überprüfen, ob denn das CurrentDir richtig gesetzt wird? Evtl. ist da ein kleiner Fehler drin. Reicht vielleicht auch schon, wenn du nach der Manipulation vom Pfad mal eine Debug-Ausgabe machen könntest.
 
Ja, das Verzeichnis wird korrekt gesetzt.

Was mich jetzt noch mehr verwundert ist, dass die Applikation startet, sobald eine Kopie der DLL in ihrem Verzeichnis liegt. Eigentlich dürfte das nicht passieren, da die DLL erst durch ein drittes Programm initialisiert werden muss. Wird beim Laden einer DLL die Versionsnummer o.ä. geprüft um zu schauen, ob die gleiche DLL schon geladen ist? Da muss ich mich mal schlau machen...
 
Was mich jetzt noch mehr verwundert ist, dass die Applikation startet, sobald eine Kopie der DLL in ihrem Verzeichnis liegt. Eigentlich dürfte das nicht passieren, da die DLL erst durch ein drittes Programm initialisiert werden muss. Wird beim Laden einer DLL die Versionsnummer o.ä. geprüft um zu schauen, ob die gleiche DLL schon geladen ist? Da muss ich mich mal schlau machen...

Ok, zumindest diese Frage ist nun gelöst. Es werden natürlich keine Versionsnummer o.ä. geprüft, sondern das Phänomen war auf einen Fehler in der DLL zurück zu führen. Jetzt, da dieser Fehler behoben ist, funktioniert die obige Methode nicht mehr, da die DLL wie gesagt erst initialisiert werden muss.
 
So, ich habe nochmal etwas herumprobiert und festgestellt, dass es funktionieren würde, wenn ich nicht meinen Kindprozess direkt starte, sondern erst cmd.exe und darüber dann meine Anwendung. Das war aber eigentlich auch klar, da ich ja sehen kann, dass das CWD in der gestarteten Anwendung meinen Wünschen entsprechend gesetzt wird.

Wirklich weiterhelfen tut mir mir diese Erkenntnis jedoch nichts, da der zusätzliche Prozess dazwischen bewirkt, dass einige andere Dinge nicht mehr korrekt funktionieren.

Sollte also doch noch jemandem etwas einfallen - immer her damit :)
 
Zurück
Oben