我正在发布该问题的另一个答案,因为这涉及完全不同的方法。
上下文
当 JavaScript 尝试访问 IE 10 中的位置对象时,您会看到安全栏,要求您允许访问您的位置。位于本地驱动器或网络共享上的文件的区别在于,您不会看到始终允许访问的选项,而只能选择一次(允许一次)。
无论出于何种原因,此安全栏不会显示在WebBrowser
控件中(即使我尝试为应用程序设置信息栏处理.exe
,但它似乎没有任何效果)。
这就是为什么每次执行脚本时,Web 浏览器控件中都不会发生任何事情。它实际上被信息栏挡住了。
解决方案
需要做什么:
模拟应用程序内部的 Web 服务器。我使用了一个简单的 C# Web 服务器类来提供内容。这样,即使本地机器上没有 Web 服务器,我们也可以拦截对特定 URL 地址和端口的请求,并提供我们想要的内容。
将test1.html
文档添加到项目中并在服务器响应中使用它的内容。只需将文件添加到您的项目中,在“Program.cs”文件旁边,并将其Copy to Output Directory属性值设置为Copy always。
这个怎么运作
首先,我们需要实例化一个 Web 浏览器控件。然后,导航到该test1.html
文件。加载文档时,我们首先检查 Web 服务器是否未实例化。如果是这样,我们创建它的一个实例,然后我们读取 Web 浏览器的 HTMl 源并将其存储在response
我们传递给WebServer
构造函数的变量中。
将http://localhost:9999
注册HttpListener
到该前缀,因此对该地址的每个请求都将由我们的简单 Web 服务器提供服务。
接下来,我们导航到该地址。当 Web 服务器接收到请求时,它将传递变量的内容,该_staticContent
变量的值在 Web 服务器的构造函数中分配。
服务器将文档传送到 Web 浏览器后,将webBrowser1_DocumentCompleted
触发处理程序。但是这一次,我们已经有了 web 服务器的实例,所以执行通过else
分支。需要注意的重要一点是,我们将异步等待 JavaScript 执行,获取位置并将其保存到input
HTML 中的隐藏元素中。
一个重要的说明:第一次启动应用程序时,您不会获得任何位置。您首先必须让应用程序保持打开状态,以便您可以使用自定义 HTTP 侦听器,然后执行我在另一个答案中描述的步骤,浏览位置为 http://localhost:9999
. 一旦你这样做,关闭并重新打开应用程序。
而已。每次运行应用程序时,您都会在消息框中获得位置坐标。
类Form1
文件(Form1.cs):
public partial class Form1 : Form
{
WebServer _ws;
WebBrowser _webBrowser1;
public Form1()
{
InitializeComponent();
_webBrowser1 = new WebBrowser();
_webBrowser1.Visible = false;
var location = Assembly.GetExecutingAssembly().Location;
_webBrowser1.Navigate(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\test1.html");
_webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
}
private void Form1_Load(object sender, EventArgs e)
{
}
async void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (_ws == null)
{
var html = _webBrowser1.Document.GetElementsByTagName("html");
var response = html[0].OuterHtml;
_ws = new WebServer(response, "http://localhost:9999/");
_ws.Run();
_webBrowser1.Navigate("http://localhost:9999/");
}
else
{
string latitude = "";
string longitude = "";
await Task.Factory.StartNew(() =>
{
while (string.IsNullOrEmpty(latitude))
{
System.Threading.Thread.Sleep(1000);
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
var latitudeEl = _webBrowser1.Document.GetElementById("latitude");
var longitudeEl = _webBrowser1.Document.GetElementById("longitude");
latitude = latitudeEl.GetAttribute("value");
longitude = longitudeEl.GetAttribute("value");
});
}
}
});
MessageBox.Show(String.Format("Latitude: {0} Longitude: {1}", latitude, longitude));
}
}
// credits for this class go to David
// http://www.codehosting.net/blog/BlogEngine/post/Simple-C-Web-Server.aspx
public class WebServer
{
private readonly HttpListener _listener = new HttpListener();
static string _staticContent;
public WebServer(string[] prefixes, string content)
{
_staticContent = content;
foreach (string s in prefixes)
_listener.Prefixes.Add(s);
_listener.Start();
}
public WebServer(string content, params string[] prefixes)
: this(prefixes, content) { }
public void Run()
{
ThreadPool.QueueUserWorkItem((o) =>
{
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem((c) =>
{
var ctx = c as HttpListenerContext;
try
{
byte[] buf = Encoding.UTF8.GetBytes(_staticContent);
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
catch { } // suppress any exceptions
finally
{
// always close the stream
ctx.Response.OutputStream.Close();
}
}, _listener.GetContext());
}
}
catch { } // suppress any exceptions
});
}
public void Stop()
{
_listener.Stop();
_listener.Close();
}
}
}
HTML 源代码 ( test1.html )
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<meta http-equiv="X-UA-Compatible" content="IE=10" />
<script type="text/javascript">
window.onload = function () {
var latitude = document.getElementById("latitude");
var longitude = document.getElementById("longitude");
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
}
else { }
}
function showPosition(position) {
latitude.value = position.coords.latitude;
longitude.value = position.coords.longitude;
}
getLocation();
}
</script>
</head>
<body>
<input type="hidden" id="latitude" />
<input type="hidden" id="longitude" />
</body>
</html>