.net - 通过 ShellExecute 调用应用程序时,未读取应用程序配置文件

标签 .net delphi app-config shellexecute

我有一个 .NET 应用程序,它是使用 ShellExecute 通过 Delphi 程序启动的。不幸的是,当以这种方式启动时,应用程序似乎无法正确读取其 app.config 文件,就好像该文件不存在一样。

我尝试过在其他场景中测试该应用程序,例如从快捷方式调用,并将工作目录设置为不同的文件夹,并且运行正常。

[编辑]Environment.CurrentDirectory 属性返回 Delphi 程序的目录。

任何想法将不胜感激。

干杯,

詹姆斯

最佳答案

显然,您生成的进程无法处理工作目录不属于它自己的事实。

您可以使用 CreateProcess() 打开该文件。我有一个关于等待的小例子(但你可以将其剪掉):

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;

添加了一些缺失的实用函数:

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;

关于.net - 通过 ShellExecute 调用应用程序时,未读取应用程序配置文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2206410/

相关文章:

c# - 如何在 .NET 4.0 中使用 Microsoft.Bcl.Async 支持 TransactionScope 中的异步方法?

delphi - 当我尝试使用 Delphi 将文件上传到一个驱动器时出现错误请求错误

mysql - Visual Studio 设置文件损坏/MySQL 连接问题

c# - 如何从另一个程序集读取 app.config?

c# - 已加载事件未在 Silverlight 中触发

c# - 如何在 .NET 中使用 MasterDevs ChromeDevTools?

.net - .NET 语言中的错误关键字

delphi - 如何使用 Delphi 和 Indy 跟踪 URL 重定向?

delphi - 如何使组件编辑器在双击时执行原始处理程序?

oracle - 手动将条目添加到 Entity Framework 应用程序的 Oracle 存储过程的 app.config 中