2010-02-05 7 views
2

J'ai une application .NET lancée via un programme Delphi à l'aide de ShellExecute. Malheureusement, lorsqu'il est lancé de cette manière, l'application ne semble pas lire correctement son fichier app.config, comme si le fichier n'existait pas.Le fichier de configuration d'application n'est pas lu lorsque l'application appelée via ShellExecute

J'ai essayé de tester l'application dans d'autres scénarios, par ex. appeler à partir d'un raccourci avec le répertoire de travail défini dans un dossier différent et il fonctionne bien. [Modifier] La propriété Environment.CurrentDirectory renvoie le répertoire du programme Delphi.

Toutes les idées seraient très appréciées.

Cheers,

James

Répondre

1

Eh bien je l'ai étudié un peu et il ne semble pas être une solution à la fois simple et élégante. Le moyen le plus simple semble être d'appeler un programme .NET intermédiaire qui exécute ensuite l'application cible via Process.Start et transmet les paramètres. Pas idéal mais c'est plus simple que les autres solutions que j'ai trouvées jusqu'ici.

1

Apparemment, le processus que vous engendrez ne peut pas gérer le fait que le répertoire de travail est pas propre.

Vous pouvez ouvrir le fichier en utilisant CreateProcess(). J'ai un petit exemple avec attendre (mais vous pouvez Clip out):

procedure ExecuteAndWaitFor(CommandLine, CurrentDirectory: string; Environment: TStrings); 
var 
    List: TList; 
    ActiveWin: HWnd; 
    i: Integer; 
    Ret: Longword; 
    SI: TStartupInfo; 
    PI: TProcessInformation; 
    MadeForeground: Boolean; 
    AssociatedCommandLine: string; 
begin 
    // find the association ot use 
    AssociatedCommandLine := GetAssociatedCommandLine(CommandLine); 
    // first we create a list of windows which we need to block... 
    List := TList.Create; 
    try 
    ActiveWin := Windows.GetForegroundWindow; 
    // get the list of all visible and active top windows... 
    if not Windows.EnumThreadWindows(GetCurrentThreadId,@InternallyThreadWindowCallback,Integer(List)) then RaiseLastOSError; 
    // disable all those windows... 
    for i := 0 to List.Count - 1 do Windows.EnableWindow(HWnd(List[i]),False); 
    try 
     // create the process 
     System.FillChar(SI,sizeof(SI),0); 
     SI.cb := sizeof(SI.cb); 
     // todo: environment 
     if not Windows.CreateProcess(nil,PChar(AssociatedCommandLine),nil,nil,False,NORMAL_PRIORITY_CLASS,nil,PChar(CurrentDirectory),SI,PI) then RaiseLastOSError; 
     // wait until the process is finished... 
     MadeForeGround := False; 
     repeat 
     // process any pending messages in the thread's message queue 
     Application.ProcessMessages; 
     if not MadeForeground then begin 
      Windows.EnumThreadWindows(PI.dwThreadId,@InternallyTopWindowToForeMost,Integer(@MadeForeGround)); 
     end; 
     // wait for a message or the process to be finished 
     Ret := Windows.MsgWaitForMultipleObjects(1, PI.hProcess, False, INFINITE, QS_ALLINPUT); 
     if Ret = $FFFFFFFF then RaiseLastOSError; 
     until Ret = 0; 
     // free the process handle 
     Windows.CloseHandle(PI.hProcess); 
     WIndows.CloseHandle(PI.hThread); 
    finally 
     // enable all those windows 
     for i := 0 to List.Count - 1 do Windows.EnableWindow(HWnd(List[i]), True); 
    end; 
    Windows.SetForegroundWindow(ActiveWin); 
    finally 
    List.Free; 
    end; 
end; 

Ajout de certaines fonctions utilitaires manquantes:

uses 
    SysUtils, Registry; 

function GetAssociatedFile(const Extension: string; const RemoveParameters: Boolean = False): string; 
var 
    FileClass: string; 
    Reg: TRegistry; 
    Position: Integer; 
begin 
    // initialize 
    Result := ''; 
    // create registry entry 
    Reg := TRegistry.Create(KEY_EXECUTE); 
    try 
    // find the given extension 
    Reg.RootKey := HKEY_CLASSES_ROOT; 
    FileClass := ''; 
    if Reg.OpenKeyReadOnly(ExtractFileExt(Extension)) then begin 
     FileClass := Reg.ReadString(''); 
     Reg.CloseKey; 
    end; 
    if FileClass <> '' then begin 
     if Reg.OpenKeyReadOnly(FileClass + '\Shell\Open\Command') then begin 
     Result := Reg.ReadString(''); 
     Reg.CloseKey; 
     end; 
    end; 
    finally 
    Reg.Free; 
    end; 
    // remove the additional parameters 
    Position := Pos('"%1"', Result); 
    if RemoveParameters and (Position > 0) then 
    Result := Trim(Copy(Result, 1, Position - 1)) 
    else 
    Result := Trim(Result); 
end; 

function GetAssociatedCommandLine(const CommandLine: string): string; 
begin 
    // build the command line with the associated file in front of it 
    Result := Trim(GetAssociatedFile(CommandLine, True) + ' ') + '"' + CommandLine + '"'; 
end; 

function InternallyThreadWindowCallback(Window: HWnd; Data: Longint): Bool; stdcall; 
var 
    List: TList; 
begin 
    Result := True; 
    if (not IsWindowVisible(Window)) or (not IsWindowEnabled(Window)) then Exit; 
    List := TList(Data); 
    List.Add(Pointer(Window)); 
end; 

function InternallyTopWindowToForeMost(Window: HWnd; Data: LongInt): Bool; stdcall; 
begin 
    Result := True; 
    if (not IsWindowVisible(Window)) or (not IsWindowEnabled(Window)) then Exit; 
    SetForegroundWindow(Window); 
    PBoolean(Data)^ := True; 
end; 
+0

Merci, Malheureusement, il est peu probable que je puisse changer le programme Delphi. Si possible, je vais changer le programme .NET. – James

+0

Dans ce cas, essayez de vous assurer que vous avez lu le fichier de paramètres d'un chemin complet, par exemple, récupérez le répertoire appdata local et utilisez un sous-répertoire fixed à partir de là. –

+0

Je ne l'ai probablement pas précisé dans mon article original, mais j'avais besoin que le fichier app.config soit utilisé automatiquement partout où la classe ConfigurationManager était utilisée. Mon programme utilise des bibliothèques tierces qui chargent automatiquement leurs paramètres à partir du fichier app.config et qui ne fonctionnaient pas correctement. – James