How to start default browser with a URL(with space

2020-04-11 06:33发布

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 Folder\AFile.htm

Please note the path has spaces. Depending on conditions I want to append an Id at the end of the URL.

Final URL is C:\My Custom Path\New Folder\AFile.htm#12345

If I open the browser manually, and paste the URL "C:\My Custom Path\New Folder\AFile.htm#12345".

It works fine. Unable to find the best way to do this through code.

6条回答
我只想做你的唯一
2楼-- · 2020-04-11 07:08

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;
查看更多
兄弟一词,经得起流年.
3楼-- · 2020-04-11 07:14

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;
查看更多
forever°为你锁心
4楼-- · 2020-04-11 07:18

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

'/C start '+Url

Quick and dirty, but it should work OK

查看更多
够拽才男人
5楼-- · 2020-04-11 07:19

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.

查看更多
霸刀☆藐视天下
6楼-- · 2020-04-11 07:21

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)

查看更多
劳资没心,怎么记你
7楼-- · 2020-04-11 07:23

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;
查看更多
登录 后发表回答