I'd like to open a local HTML file navigated to a specific headline with an ID.
string url = "file:///C:/myFile.html#myHeading"
If I paste the URL in the browser directly, it correctly navigates to the desired heading.
But when I try to have the system handle the URL, it omits the hash entirely.
ProcessStartInfo si = new ProcessStartInfo(url);
si.UseShellExecute = true;
Process.Start(si);
will simply open file:///C:/myFile.html
.
Is there a way I can make this work?
Sadly, I don't know where this stripping happens, so my research so far turned up empty.
I tried replacing the hash symbol with its escaped form %23
, which of course didn't work (could not find the file specified).
A work-around I'm using in the meantime:
From here, I wrote an extension which tells me the path to the executable set as the default app for opening files with a given extension.
public static string getDefaultAssociation(string extension)
{
if (extension.Substring(0, 1) != ".")
{
int os = extension.IndexOf('.');
if (os > 0)
{
extension = extension.Substring(os);
}
else
{
extension = "." + extension;
}
}
const int S_OK = 0;
const int S_FALSE = 1;
uint length = 0;
uint ret = AssocQueryString(AssocF.None, AssocStr.Executable, extension, null, null, ref length);
if (ret != S_FALSE)
{
//throw new InvalidOperationException("Could not determine associated string");
WriteLog("Could not determine associated string");
return "";
}
var sb = new StringBuilder((int)length); // (length-1) will probably work too as the marshaller adds null termination
ret = AssocQueryString(AssocF.None, AssocStr.Executable, extension, null, sb, ref length);
if (ret != S_OK)
{
//throw new InvalidOperationException("Could not determine associated string");
WriteLog("Could not determine associated string");
return "";
}
return sb.ToString();
}
[DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern uint AssocQueryString(
AssocF flags,
AssocStr str,
string pszAssoc,
string pszExtra,
[Out] StringBuilder pszOut,
ref uint pcchOut
);
[Flags]
public enum AssocF
{
None = 0,
Init_NoRemapCLSID = 0x1,
Init_ByExeName = 0x2,
Open_ByExeName = 0x2,
Init_DefaultToStar = 0x4,
Init_DefaultToFolder = 0x8,
NoUserSettings = 0x10,
NoTruncate = 0x20,
Verify = 0x40,
RemapRunDll = 0x80,
NoFixUps = 0x100,
IgnoreBaseClass = 0x200,
Init_IgnoreUnknown = 0x400,
Init_Fixed_ProgId = 0x800,
Is_Protocol = 0x1000,
Init_For_File = 0x2000
}
public enum AssocStr
{
Command = 1,
Executable,
FriendlyDocName,
FriendlyAppName,
NoOpen,
ShellNewValue,
DDECommand,
DDEIfExec,
DDEApplication,
DDETopic,
InfoTip,
QuickTip,
TileInfo,
ContentType,
DefaultIcon,
ShellExtension,
DropTarget,
DelegateExecute,
Supported_Uri_Protocols,
ProgID,
AppID,
AppPublisher,
AppIconReference,
Max
}
So I can use
string def = getDefaultAssociation("html");
ProcessStartInfo si = new ProcessStartInfo(def);
si.Arguments = url;
si.UseShellExecute = true;
Process.Start(si);
to directly tell my default browser to go to the file URL, INCLUDING the ID hash.