C#桌面应用程序不共享我的物理位置 [英] C# desktop application doesn't share my physical location

查看:94
本文介绍了C#桌面应用程序不共享我的物理位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在web应用程序中获取当前位置(经度和纬度),它可以很好地处理以下HTML5代码。

 <!DOCTYPE html> 
< html>
< body>
< p id =demo>点击按钮以获取您的坐标:< / p>
< button onclick =getLocation()>试试< / button>
< script>
var x = document.getElementById(demo);
函数getLocation()
{
if(navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(showPosition);
}
其他
{
x.innerHTML =此浏览器不支持地理位置。;
}
}

函数showPosition(position)
{
x.innerHTML =纬度:+ position.coords.latitude +
< br>经度:+ position.coords.longitude;
}
< / script>
< / body>
< / html>

但我想在桌面应用程序中获取用户的经度和纬度。没有选择在桌面应用程序中使用JavaScript,所以我试图使用Web浏览器访问它。
当我尝试使用webbrowser控件(IE10)从dektop应用程序访问上面创建的网页时,它不共享物理位置,当我通过按钮点击调用脚本时没有任何反应。



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

解决方案

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



上下文



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



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



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



解决方案



需要什么需要完成的工作:


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


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

    li>

工作原理



首先,我们需要实例化Web浏览器控件。然后,导航到 test1.html 文件。当文档被加载时,我们首先检查Web服务器是否未实例化。如果这样,我们创建它的实例,然后我们读取并存储Web浏览器的HTMl源代码在响应变量中,我们将其传递给 WebServer http:// localhost:9999 注册<$ c $>构造函数。



$ c> HttpListener 到该前缀,因此每个对此地址的请求都将由我们的简单Web服务器提供。



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



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



一个重要的评论:首次启动应用程序时,您将无法获取任何位置信息。首先必须让应用程序保持打开状态,以便您可以使用自定义HTTP侦听器,然后执行我在其他中描述的步骤答案,浏览地点是 http:// localhost:9999 。一旦你这样做,关闭并重新打开应用程序。



就是这样。每次运行应用程序时,都会在消息框中获取位置坐标。


$ b $ < Form1 类文件(

  public partial class Form1:Form 
{$ b $ Form1.cs b
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;

$ b $ private void Form1_Load(object sender,EventArgs e)
{

}

异步void webBrowser1_DocumentCompleted(object发件人,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 =;

等待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));
}
}

//这个类的学分转到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 []前缀,字符串内容)
{
_staticContent = content;
foreach(前缀中的字符串s)
_listener.Prefixes.Add(s);
_listener.Start();
}

公共WebServer(字符串内容,params字符串[]前缀)
:this(前缀,内容){}

public void Run( )
{
ThreadPool.QueueUserWorkItem((o)=>
{
尝试
{
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 {} //禁止任何的exceptio ns
finally
{
//总是关闭流
ctx.Response.OutputStream.Close();
}
},_listener.GetContext());
}
}
catch {} //禁止任何异常
});
}

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-Compatiblecontent =IE = 10/>
< script type =text / javascript>
window.onload = function(){
var latitude = document.getElementById(latitude);
var longitude = document.getElementById(longitude);

函数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 =hiddenid =latitude/>
< input type =hiddenid =longitude/>
< / body>
< / html>


I am trying to get my current location( latitude and longitude ) in web application it works fine with following HTML5 code.

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

But I want to get latitude and longitude of user in desktop app. There is no option to use JavaScript in desktop app, so I am trying to access it using the web browser. When I am trying to access the above created web page from dektop application using webbrowser control (IE10) it doesn't share physical location, and nothing happens when I call the script by button click.

Can anyone help me to get my location(latitude and longitude) in a desktop app(C#)?

解决方案

I'm posting another answer to the question as this involves a completely different approach.

The Context

When JavaScript tries to access the location object in IE 10 you are presented with the security bar asking for you to allow the access to your location. The difference for a file which is on the local drive or a network share is that you are not presented with the option to always allow access, but only once (Allow once).

For whatever reason, this security bar doesn't show up in the WebBrowser control (even if I've tried setting the Information Bar Handling for the aplication's .exe, but it seems not to have any effect).

This is why every time when the script executes nothing happens in the web browser control. It is actually blocked by the information bar.

The Solution

What needs to be done:

  1. Emulate a web server inside the application. I've used a Simple C# Web Server class to serve the content. This way, even if there is no web server on the local machine, we may intercept requests to a specific URL address and port and serve the content we want to.

  2. Add the test1.html document to the project and use it's content in the server response. Just add the file into your project, next to the "Program.cs" file and set it's Copy to Output Directory property value to Copy always.

How It Works

First, we need to instantiate a web browser control. Then, navigate to the test1.html file. When the document is loaded, we first check if the web server is not instantiated. If this, we create an instance of it and then we read and store the web browser's HTMl source in the response variable, which we pass to the WebServer constructor.

The http://localhost:9999 registers the HttpListener to that prefix, so every request to this address will be served by our simple web server.

Next, we navigate to that address. When the web server will receive the request, it will deliver the content of the _staticContent variable, which had it's value assigned in the web server's constructor.

After the server delivers the document to the web browser, the webBrowser1_DocumentCompleted handler is triggered. But this time, we already have the web server's instance, so execution goes through the else branch. The important thing to notice is that we will asynchronously wait for the JavaScript to execute, get the location and save it to the hidden input elements in the HTML.

One important remark: the first time you launch the application you will not get any location. You first have to leave the application open, so that you have the custom HTTP listener available, and then, perform the steps I described in my other answer, the browsing location being http://localhost:9999. Once you do that, close and reopen the application.

That's it. Everytime you run the application, you will get the location coordinates in a message box.

The Form1 class file (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();
        }
    }
}

The HTML source (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>

这篇关于C#桌面应用程序不共享我的物理位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆