我需要打开一个本地 .HTM 文件并导航到特定的锚点名称。
在这种情况下,它是一个包含 1,000 多个警报/锚点的警报信息文件。
在我的测试示例(下面的完整代码)中,Uri 片段没有进入浏览器。
我尝试了其他创建超链接的方法,但这是我所能得到的。
<Window x:Class="HyperlinkWithPageAnchor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="200">
<Grid>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Hyperlink NavigateUri="{Binding HyperlinkNavUri}" RequestNavigate="Hyperlink_RequestNavigate">
<TextBlock Text="Link Text"/>
</Hyperlink>
</TextBlock>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
namespace HyperlinkWithPageAnchor
{
using System;
using System.Windows;
using System.ComponentModel;
using System.Windows.Navigation;
public partial class MainWindow : Window, INotifyPropertyChanged
{
private Uri _hyperlinkNavUri;
public Uri HyperlinkNavUri
{
get { return _hyperlinkNavUri; }
set { _hyperlinkNavUri = value; OnPropertyChanged(nameof(HyperlinkNavUri)); }
}
public MainWindow()
{
InitializeComponent(); DataContext = this;
// Desired Address: file:///C:/OSP-P/P-MANUAL/MPA/ENG/ALARM-A.HTM#1101
UriBuilder uBuild = new UriBuilder(new Uri("file://"));
uBuild.Path = @"C:\OSP-P\P-MANUAL\MPA\ENG\ALARM-A.HTM";
uBuild.Fragment = "1101";
HyperlinkNavUri = uBuild.Uri;
}
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
try { string link = e.Uri.ToString(); MessageBox.Show(link); System.Diagnostics.Process.Start(link); }
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); }
}
}
Run Code Online (Sandbox Code Playgroud)
似乎如果您让操作系统识别默认浏览器本身,它将从 URI 中删除锚点。
您需要使用以下重载Process.Start来指定可执行文件和参数:
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = @"C:\Program Files\Internet Explorer\iexplore.exe";
processStartInfo.Arguments = "file:///C:/OSP-P/P-MANUAL/MPA/ENG/ALARM-A.HTM#1101";
Process.Start(processStartInfo);
Run Code Online (Sandbox Code Playgroud)
如果要使用用户定义的浏览器而不是硬编码的浏览器,则必须查询 Windows 注册表以检索它。
例如,在旧版本的 Windows 上(我认为在 Vista 之前),您必须使用以下注册表项:HKEY_CLASSES_ROOT\http\shell\open\command. 在以后的版本中,此键包含默认浏览器(如果浏览器未进行任何更改)。
private string GetDefaultBrowser()
{
string regKey = @"HTTP\shell\open\command";
using (RegistryKey registrykey = Registry.ClassesRoot.OpenSubKey(regKey, false))
{
return ((string)registrykey.GetValue(null, null)).Split('"')[1];
}
}
Run Code Online (Sandbox Code Playgroud)
在 Windows 10 上,由于允许选择默认应用程序的应用程序启动器,它有点复杂。要检索用户选择的浏览器,您必须查询以下注册表项:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice. 如果密钥不存在,您必须回退到前面提到的密钥:HKEY_CLASSES_ROOT\http\shell\open\command。
private string GetDefaultBrowserOnWin10()
{
string execPath;
try
{
string extension = ".htm"; // either .htm or .html
RegistryKey propertyBag = Registry.CurrentUser.OpenSubKey($@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\{extension}\UserChoice", false);
var browserProgId = propertyBag.GetValue("ProgId").ToString(); ;
using (RegistryKey execCommandKey = Registry.ClassesRoot.OpenSubKey(browserProgId + @"\shell\open\command", false))
{
execPath = execCommandKey.GetValue(null).ToString().ToLower().Replace("\"", "");
if (IsDefaultLauncherApp(execPath))
{
System.Diagnostics.Debug.WriteLine("No user-defined browser or IE selected; anchor will be lost.");
}
}
if (!execPath.EndsWith("exe"))
{
execPath = execPath.Substring(0, execPath.LastIndexOf(".exe") + 4);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
execPath = GetDefaultBrowser();
}
return execPath;
}
private bool IsDefaultLauncherApp(string appPath)
{
return appPath.Contains("launchwinapp.exe");
}
Run Code Online (Sandbox Code Playgroud)
这将适用于除Microsoft Edge之外的所有浏览器,目前还不允许这样做。你可以在你的程序中这样使用:
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
try {
string link = e.Uri.ToString();
System.Diagnostics.ProcessStartInfo processStartInfo = new System.Diagnostics.ProcessStartInfo();
processStartInfo.FileName = GetDefaultBrowserOnWin10();
processStartInfo.Arguments = link;
System.Diagnostics.Process.Start(processStartInfo);
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
Run Code Online (Sandbox Code Playgroud)
一些额外的答案: 如何使用 C# 找到默认的 Web 浏览器?