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

本文关键字:位置 我的 共享 桌面 应用程序 | 更新日期: 2023-09-27 17:54:57

我试图在web应用程序中获得我当前的位置(纬度和经度),它与以下HTML5代码一起工作。

<!DOCTYPE html>
<html>
<body>
    <p id="demo">Click the button to get your coordinates:</p>
    <button onclick="getLocation()">Try It</button>
    <script>
        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 + 
                "<br>Longitude: " + position.coords.longitude;  
        }
    </script>
</body>
</html>

但是我想在桌面应用程序中获得用户的纬度和经度。在桌面应用程序中没有使用JavaScript的选项,所以我试图使用web浏览器访问它。当我试图使用web浏览器控件(IE10)从桌面应用程序访问上述创建的网页时,它不共享物理位置,当我通过按钮单击调用脚本时,什么也不会发生。

谁能帮助我得到我的位置(纬度和经度)在桌面应用程序(c#)?

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

我对这个问题给出了另一个答案,因为这涉及到一个完全不同的方法。

当JavaScript试图访问IE 10中的位置对象时,会出现安全栏,要求您允许访问您的位置。对于位于本地驱动器或网络共享上的文件,不同之处在于,您不会提供始终允许访问的选项,而是只允许访问一次( allow once)。

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

这就是为什么每次脚本执行时,web浏览器控件中什么都没有发生的原因。它实际上被信息栏挡住了。

解决方案

需要做什么:

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

  2. test1.html文档添加到项目中,并在服务器响应中使用其内容。只需将文件添加到您的项目中,在"Program.cs"文件旁边设置它的Copy to Output Directory属性值为Copy always

首先,我们需要实例化一个web浏览器控件。然后,导航到test1.html文件。当加载文档时,我们首先检查web服务器是否没有实例化。如果是这样,我们创建它的一个实例,然后在response变量中读取并存储web浏览器的HTMl源,并将其传递给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)

<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>

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

您可以通过使用FEATURE_BROWSER_EMULATION特性为每个应用程序设置Internet Explorer 的默认仿真模式。这就是如何在您自己的应用程序中为WebBrowser控件设置兼容模式。

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

Internet功能控件(B..C)

(更新)

  1. 进入互联网选项->隐私
  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