skip to Main Content

I am trying to open a local html help file.

Currently i have this code:

        string filePath = @"C:Testdocs.html";
        string headlineId = "anotherH";

        string url = $"file://{filePath}#{headlineId}";

        System.Diagnostics.Process.Start(url);

This does work and opens the defined standard browser on the machine but unfortunately it does not jump to the defined anchor anotherH.

The anchor is a headline inside my HTML file:

<h2 id="anotherH">Another Headline</h2>

I have also tried to open the HTML using the normal path without the file:// to no avail.

I did find this and this stackoverflow thread but unfortunately they could not resolve my issue.

What am I doing wrong? Did some browser specifications change?

EDIT:
I have also tried to change the separator from to / unsing the String.Replace() function.

        string filePath = @"C:Testdocs.html";
        string headlineId = "anotherH";
        filePath = filePath.Replace('\', '/');

        string url = $"file://{filePath}#{headlineId}";

        System.Diagnostics.Process.Start(url);

In this case the finished path becomes: file://C:/Test/docs.html#anotherH

Unfortunately this does not help either.

2

Answers


  1. Chosen as BEST ANSWER

    I found an easier way to open the standard browser of a pc and scroll to a object with a specified ID regardless of what browser the user is using! And the best part: No command line hacks or other stuff needed!

    First we need the browser Id from the registry:

        private string GetDefaultBrowserId()
        {
            const string userChoice = @"SoftwareMicrosoftWindowsShellAssociationsUrlAssociationshttpUserChoice";
            string progId;
            //BrowserApplication browser;
            using (RegistryKey userChoiceKey = Registry.CurrentUser.OpenSubKey(userChoice))
            {
                if (userChoiceKey == null)
                {
                    throw new NotSupportedException("No standard browser id found in registry");
                    //break;
                }
                object progIdValue = userChoiceKey.GetValue("Progid");
                if (progIdValue == null)
                {
                    throw new NotSupportedException("No standard browser id found in registry");
                    //break;
                }
                progId = progIdValue.ToString();
                return progId;
            }
        }
    

    Then we look up the browser path by the browser id up in the registry:

        private FileInfo GetDefaultBrowserPath(string defaultBrwoserId)
        {
            const string exeSuffix = ".exe";
            string path = defaultBrwoserId + @"shellopencommand";
            FileInfo browserPath = null;
            using (RegistryKey pathKey = Registry.ClassesRoot.OpenSubKey(path))
            {
                if (pathKey == null)
                {
                    throw new NotSupportedException("Standard browser not properly registred in registry!");
                    //return;
                }
    
                // Trim parameters.
                try
                {
                    path = pathKey.GetValue(null).ToString().ToLower().Replace(""", "");
                    if (!path.EndsWith(exeSuffix))
                    {
                        path = path.Substring(0, path.LastIndexOf(exeSuffix, StringComparison.Ordinal) + exeSuffix.Length);
                        browserPath = new FileInfo(path);
                    }
                }
                catch
                {
                    // Assume the registry value is set incorrectly, or some funky browser is used which currently is unknown.
                    throw new NotSupportedException("Standard browser not properly registred in registry!");
                }
            }
    
            return browserPath;
    
        }
    

    Now we have the path to the browser executable. Something like C:Program FilesGoogleChromeApplicationchrome.exe

    After that we need to convert our file path e.g C:My DocsDocs of important SoftwareMydoc.html to a readable format for the browser because certain characters need to be escaped in the url or replaced by others.

    First we need to convert the local file path and escape characters like empty spaces " ":

    private string ConvertFilesystemStringToBrowserString(string filePath)
    {
    
        filePath = filePath.Replace("\", "/");
        filePath = Uri.EscapeUriString(filePath);
        //filePath = filePath.Replace(" ", "%20");
    
        return filePath;
    }
    

    Now we have the escaped file path e.g C:/My%20Docs/Docs%20of%20important%20Software/Mydoc.html. We still need to convert it to a browser command and pass the ID of the html object:

        private string GenerateFileUri(string uri, string elementId)
        {
            string localUri = $"file:///{uri}#{elementId}";
            return localUri;
        }
    

    Now we have the finished command with the id e.g file:///C:/My%20Docs/Docs%20of%20important%20Software/Mydoc.html#Headline-5, in this case Headline-5

    Now we only need to call

        Process.Start(defaultBrowserPath.Value, fileUri);
    

    And the default browser opens and scrolls down to the element with the right ID!

    This post helped me out to get the registry keys for the browser.


  2. In short you should specify a browser to open the URL, e.g.

    Process.Start("C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe", url);
    

    When you try to open a file protocol url, Windows will open the file with the associate program, so the fragment is dropped. (This is my guess because you cannot set a default program for the file protocol in Windows settings)


    Maybe you want to use the default browser, then you need to query the register to look for its path. You need to search for two places: How to find the default browser via the registry on Windows 10

    var progID = (string)Registry.CurrentUser
                .OpenSubKey("SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice")
                .GetValue("ProgID");
    var command = (string)Registry.ClassesRoot
                .OpenSubKey($"{progID}\shell\open\command")
                .GetValue(null);
    

    The command variable is a command line contains the executable and its arguments, I use Firefox, so the value I got looks like this:

    "C:Program FilesMozilla Firefoxfirefox.exe" -osint -url "%1"
    

    The last work is to run the command line with the Process class. It’s not easy because you have to parse the command line. But if you don’t mind an extra black window there is a trick that you can use cmd /c + start command to run it. Note that you need to replace %1 with the url.

    Process.Start("cmd", $@"/c ""start """" {command.Replace("%1", url)} """);
    

    BTW the above operations are all based on the file protocol. If your URL is http/https, you can directly start it

    Process.Start("https://stackoverflow.com/#onetrust-banner-sdk")
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search