如何使用URL(带空格和#)为本地文件启动默认浏览器?德尔福

时间:2016-12-08 16:41:39

标签: html delphi browser

我想在默认浏览器中打开本地HTML文件。

例如: 默认浏览器是Mozilla Firefox。

要打开的文件:C:\ My Custom Path \ New Folder \ AFile.htm

请注意路径有空格。根据条件,我想在URL的末尾附加一个Id。

最终网址为C:\ My Custom Path \ New Folder \ AFile.htm#12345

如果我手动打开浏览器,并粘贴URL“C:\ My Custom Path \ New Folder \ AFile.htm#12345”。

工作正常。无法通过代码找到最佳方法。

6 个答案:

答案 0 :(得分:3)

ShellExecute/Ex()无法使用"open"动词直接使用网址中的锚点(#)。即使您使用file://协议,也会省略锚点。

最好的方法是获取默认浏览器的路径,您可以使用FindExecutable,然后执行它并将URL作为参数传递。

uses
  ShellAPI;

procedure TForm1.Button1Click(Sender: TObject);
var
  Res: HINST;
  Buffer: array[0..MAX_PATH] of Char;
  SEInfo: TShellExecuteInfo;
  HtmlFile, Anchor: string;
begin
  HtmlFile := 'd:\1 - Copy.html';
  Anchor := '#123';

  FillChar(Buffer, SizeOf(Buffer), 0);
  Res := FindExecutable(PChar(HtmlFile), nil, Buffer);
  if Res <= 32 then
    raise Exception.Create(SysErrorMessage(Res));

  FillChar(SEInfo, SizeOf(SEInfo), 0);
  SEInfo.cbSize := SizeOf(SEInfo);
  with SEInfo do
  begin        
    lpFile := PChar(string(Buffer));
    lpParameters := PChar(Format('"%s"', [HtmlFile + Anchor]));
    nShow := SW_SHOWNORMAL;
    fMask := SEE_MASK_FLAG_NO_UI; // Do not display an error message box if an error occurs.
  end;
  if not ShellExecuteEx(@SEInfo) then
    RaiseLastOSError;
end;

答案 1 :(得分:1)

不幸的是,你不能只用ShellExecute来做。 但有一些黑客攻击。

例如,您想要打开这样的网址:

C:\ Users \ User \ Desktop \一些sitename with spaces.htm ,锚点 #myAnchor

使ShellExecute打开文件:

raise ParamValidationError(report=report.generate_report())
ParamValidationError: Parameter validation failed:
Unknown parameter in input: "PhoneNumber", must be one of: TopicArn,TargetArn, Message, Subject, MessageStructure, MessageAttributes

在开头使用“file:///”很重要,但 ShellExecute打开此页面时没有锚

要使用锚点打开,您可以使用以下内容动态创建html文件:

vS := 'file:///C:\Users\User\Desktop\Some sitename with spaces.htm#MyAnchor';
ShellExecute(0, 'OPEN', PChar(vS), '', '', SW_SHOWNORMAL);

使用ShellExecute打开此动态文件。

希望它有所帮助。

答案 2 :(得分:0)

我最终这样做了。我获得了默认浏览器,并使用CreateProcess API使用我的自定义URL启动浏览器。 请注意,我添加了&#39; file:///&#39;在开头,并用双引号括起字符串。

function GetDefaultBrowser(): String;
var
    ExecName: array[0..MAX_PATH] of Char;
    FHandle: THandle;
    MyPath: String;
begin
    Result := '';
    MyPath := small.GetTempPath;
    FHandle := System.SysUtils.FileCreate(MyPath + 'AFile.htm');

    if FHandle <> INVALID_HANDLE_VALUE then
    begin
        FillChar(ExecName, Length(ExecName), #0);
        if FindExecutable('AFile.htm', PChar(MyPath), ExecName) > 32 then
            Result := ExecName;
        System.SysUtils.FileClose(FHandle);
        System.SysUtils.DeleteFile(MyPath + 'AFile.htm');
    end;
end;


procedure LaunchHTMLPage(NumberToAppend : string);
var
    Start: TStartupInfo;
    Process: TProcessInformation;
    FileNameString, AppPathAndName, AppPathOnly: string;
begin
    AppPathAndName := GetDefaultBrowser ;

    //Break the AppPathAndName and get the path name to use later

    //I am adding double quotes in the path name to escape the spaces and the '#'
    FileNameString := AnsiQuotedStr('file:///' + Application.HelpFile + '#' + NumberToAppend, '"');
    AppPathAndName := AppPathAndName + ' ' + FileNameString;
    FillChar(Start, SizeOf(StartUpInfo), #0);
    FillChar(Process, SizeOf(TProcessInformation), #0);

    CreateProcess(nil, PChar(AppPathAndName), nil, nil, false, CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS, nil, PChar(AppPathOnly), StartUpInfo, ProcessInfo);

end;

答案 3 :(得分:0)

还可以创建一个使用以下参数启动CMD.EXE的进程:

'/C start '+Url

快速又脏,但它应该可以正常工作

答案 4 :(得分:0)

我认为这是更好的方式:

function OpenHtmlFile(FileAdr :string):Boolean;
var
  vTempFile :string;
  vData     :TStrings;
begin
  Result:= False;
  vTempFile:= GetTempFolder + '_tmphtmlrunfile.html';
  vData:= TStringList.Create;
  vData.Text:= '<html><head><meta http-equiv="refresh" content="0;URL=''file:///' + FileAdr + '''">';
  try
    try
      vData.SaveToFile(vTempFile, TEncoding.UTF8);
    finally
      vData.Free;
    end;
    ShellExecute(Handle,
             'open',
             PChar(vTempFile),
             nil,
             nil,
             SW_SHOWNORMAL);
    Result:= True;
  except
  end;
end;

答案 5 :(得分:0)

这是我的实现,它支持所有常见的浏览器和Microsoft Edge(唯一的Store App浏览器)。
它涉及URI中的查询(?)和片段(#)的问题,以及与边缘浏览器结合使用的file:///协议的问题。
(我将其用于“ Flare”软件的HTML输出,这就是为什么在变量命名中使用“帮助”的原因)

// AHelpFileName := 'C:\temp\Default.htm';
// AHelpID := '123';

procedure TSomeClass.OpenHelp(const AHelpFileName, AHelpID: string);
var
  URL: string;
  BrowserPath, FileName, Parameters: PWideChar;
begin
  URL := Format('file:///%s', [AHelpFileName]);
  if AHelpID <> '' then
    URL := Format('%s#cshid=%s', [URL, AHelpID])

  URL := StringReplace(URL, '\', '/', [rfReplaceAll]);
  URL := StringReplace(URL, ' ', '%20', [rfReplaceAll]);

  BrowserPath := StrAlloc(MAX_PATH);
  Parameters := nil;

  if FindExecutable(PWideChar(AHelpFileName), nil, BrowserPath) > 32 then
  begin
    Parameters := PWideChar(URL);

    if SameText(ExtractFileName(BrowserPath), 'LaunchWinApp.exe') then
      // Default browser is a Windows Store App (and most likely it is Edge)
      FileName := 'shell:AppsFolder\Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge'
    else
      // IE, Chrome, Firefox, Opera, Vivaldi, ...
      FileName := BrowserPath;
  end
  else
    FileName := PWideChar(URL);

  ShellExecute(0, nil, FileName, Parameters, nil, SW_SHOWNORMAL);
end;