C#桌面应用程序不共享我的物理位置

我试图在Web应用程序中获取当前位置(经度和纬度),它可以使用以下HTML5代码。

   

Click the button to get your coordinates:

var x = document.getElementById("demo"); function getLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); } else { x.innerHTML = "Geolocation is not supported by this browser."; } } function showPosition(position) { x.innerHTML="Latitude: " + position.coords.latitude + "
Longitude: " + position.coords.longitude; }

但我希望在桌面应用中获得用户的经纬度。 没有在桌面应用程序中使用JavaScript的选项,因此我尝试使用Web浏览器访问它。 当我尝试使用webbrowser控件(IE10)从dektop应用程序访问上面创建的网页时,它不共享物理位置,并且当我通过按钮单击调用脚本时没有任何反应。

任何人都可以帮助我在桌面应用程序(C#)中获取我的位置(经度和纬度)吗?

我正在发布另一个问题的答案,因为这涉及一种完全不同的方法。

上下文

当JavaScript尝试访问IE 10中的位置对象时,系统会向您显示安全栏,要求您允许访问您的位置。 本地驱动器或网络共享上的文件的区别在于,您不会看到始终允许访问的选项,但只有一次( 允许一次 )。

无论出于何种原因,此安全栏不会显示在WebBrowser控件中(即使我已尝试为应用程序的.exe设置信息栏处理 ,但似乎没有任何效果)。

这就是为什么每次脚本执行时都不会在Web浏览器控件中发生任何事情。 它实际上被信息栏阻止了。

解决方案

需要做什么:

  1. 模拟应用程序内的Web服务器 。 我使用了一个简单的C#Web Server类来提供内容。 这样,即使本地计算机上没有Web服务器,我们也可以拦截对特定URL地址和端口的请求,并提供我们想要的内容。

  2. test1.html文档添加到项目中,并在服务器响应中使用它的内容 。 只需将文件添加到项目中,“Program.cs”文件旁边,并将其“ 复制到输出目录”属性值设置为“始终复制”

这个怎么运作

首先,我们需要实例化Web浏览器控件。 然后,导航到test1.html文件。 加载文档时,我们首先检查Web服务器是否未实例化。 如果是这样,我们创建它的一个实例,然后我们读取并将Web浏览器的HTMl源存储在response变量中,并将其传递给WebServer构造函数。

http://localhost:9999HttpListener注册到该前缀,因此每个对此地址的请求都将由我们的简单Web服务器提供。

接下来,我们导航到该地址。 当Web服务器将接收请求时,它将传递_staticContent变量的内容,该变量在Web服务器的构造函数中赋值。

服务器将文档传送到Web浏览器后,将触发webBrowser1_DocumentCompleted处理程序。 但这一次,我们已经拥有了Web服务器的实例,因此执行会通过else分支。 需要注意的重要一点是,我们将异步等待JavaScript执行,获取位置并将其保存到HTML中的隐藏input元素。

一个重要的评论 :第一次启动应用程序时,您将无法获得任何位置。 首先必须让应用程序保持打开状态,以便您可以使用自定义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

            

这可能是因为WebBrowser控件使用以前版本的Internet Explorer的兼容模式。

您可以使用FEATURE_BROWSER_EMULATIONfunction为每个应用程序设置Internet Explorer的默认模拟模式。 这就是您在自己的应用程序中实际设置WebBrowser控件的兼容性模式的方法。

您可以按照以下链接中的指示进行配置:

互联网function控制(B..C)

[UPDATE]

  1. 转到Internet选项 – >隐私
  2. 在“ Location部分下,确保未选中“ Never allow websites to request your physical location
  3. 单击“ Clear Sites
  4. 打开Internet Explorer (而不是您的应用程序)并浏览到包含地理位置脚本的文件的URL
  5. 触发getLocation()函数(在您的情况下,单击Try It按钮)
  6. 当浏览器在窗口的下半部分显示安全栏时,包含yourSite wants to know your physical location. ,单击Options for this site然后选择“ Always allow

就是这样。