How to start default browser with a URL(with spaces and #) for a local file? Delphi

后端 未结 6 1153
天涯浪人
天涯浪人 2021-01-21 06:15

I want to open a local HTML file in the default browser.

For example: Default Browser is Mozilla Firefox.

The file to be opened: C:\\My Custom Path\\New Folde

相关标签:
6条回答
  • 2021-01-21 06:24

    i think this is better way:

    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;
    
    0 讨论(0)
  • 2021-01-21 06:25

    Here is my implementation that supports all common web browsers and Microsoft Edge (Windows Store App).
    It refers to the issues with queries (?) and fragments (#) in the URI and the issue with file:/// protocol in combination with the Edge browser.
    (I use it for HTML output of "Flare" software, that's why the "help" in the naming of variables)

    // 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;
    
    0 讨论(0)
  • 2021-01-21 06:36

    ShellExecute/Ex() won't work directly using "open" verb with the anchor (#) in the URL. even if you use file:// protocol the anchor will be omitted.

    The best way is to get the path for the default browser, you can use FindExecutable, and then execute it and pass the URL as a parameter.

    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('"file:///%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;
    

    EDIT: Looks like the file:/// URI scheme is important in cases where the URL includes query string parameters (e.g file.html?param=foo#bar) or else the ? is escaped to %3F (tested in Chrome)

    0 讨论(0)
  • 2021-01-21 06:38

    One can also create a process launching CMD.EXE with the following parameters :

    '/C start '+Url
    

    Quick and dirty, but it should work OK

    0 讨论(0)
  • 2021-01-21 06:39

    I ended up doing this. I get the default browser, and used the CreateProcess API to launch the browser with my custom URL. Notice, I add the 'file:///' in the beginning and also surround the string with double quotes.

    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;
    
    0 讨论(0)
  • 2021-01-21 06:48

    Unfortunately you can't do it only with ShellExecute. But there is some hack.

    For example you want to open url like this:

    C:\Users\User\Desktop\Some sitename with spaces.htm with the anchor #myAnchor

    To make ShellExecute open file:

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

    It's Important to use "file:///" in the beginning, but ShellExecute open this page without anchor.

    To open with the anchor you can dynamically create html file with content like this:

    <html>
    <meta http-equiv=Refresh content="0; url=file:///C:\Users\User\Desktop\Some sitename with spaces.htm#MyAnchor">
    <body></body>
    </html>
    

    And open this dynamic file with ShellExecute.

    Hope it helps.

    0 讨论(0)
提交回复
热议问题