3

我正在尝试在 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 浏览器访问它。当我尝试使用 webbrowser 控件(IE10)从 dektop 应用程序访问上面创建的网页时,它不共享物理位置,并且当我通过按钮单击调用脚本时没有任何反应。

谁能帮我在桌面应用程序(C#)中获取我的位置(纬度和经度)?

4

2 回答 2

2

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

上下文

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

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

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

解决方案

需要做什么:

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

  2. 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 执行,获取位置并将其保存到inputHTML 中的隐藏元素中。

一个重要的说明:第一次启动应用程序时,您不会获得任何位置。您首先必须让应用程序保持打开状态,以便您可以使用自定义 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>
于 2013-02-01T11:59:26.483 回答
0

发生这种情况的原因是该WebBrowser控件使用 Internet Explorer 早期版本的兼容模式。

您可以使用该功能为每个应用程序设置 Internet Explorer 的默认仿真模式。FEATURE_BROWSER_EMULATION这就是您WebBrowser在自己的应用程序中实际设置控件的兼容模式的方式。

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

互联网功能控制 (B..C)

[更新]

  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

就是这样。

于 2013-01-22T09:55:08.660 回答