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#)?
我对这个问题给出了另一个答案,因为这涉及到一个完全不同的方法。
当JavaScript试图访问IE 10中的位置对象时,会出现安全栏,要求您允许访问您的位置。对于位于本地驱动器或网络共享上的文件,不同之处在于,您不会提供始终允许访问的选项,而是只允许访问一次( allow once)。
无论出于什么原因,这个安全栏没有显示在WebBrowser
控件中(即使我已经尝试为应用程序的.exe
设置信息栏处理,但似乎没有任何效果)。
这就是为什么每次脚本执行时,web浏览器控件中什么都没有发生的原因。它实际上被信息栏挡住了。
解决方案需要做什么:
在应用程序中模拟web服务器。我使用了一个简单的c# Web Server类来提供内容。这样,即使本地机器上没有web服务器,我们也可以拦截到特定URL地址和端口的请求,并提供我们想要的内容。
将
test1.html
文档添加到项目中,并在服务器响应中使用其内容。只需将文件添加到您的项目中,在"Program.cs"文件旁边设置它的Copy to Output Directory属性值为Copy always
首先,我们需要实例化一个web浏览器控件。然后,导航到test1.html
文件。当加载文档时,我们首先检查web服务器是否没有实例化。如果是这样,我们创建它的一个实例,然后在response
变量中读取并存储web浏览器的HTMl源,并将其传递给WebServer
构造函数。
http://localhost:9999
将HttpListener
注册到该前缀,因此对该地址的每个请求都将由我们的简单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)
(更新)- 进入互联网选项->隐私
- 在
Location
部分下,确保Never allow websites to request your physical location
为未选中 - 点击
Clear Sites
打开 - 触发
getLocation()
功能(在您的情况下,点击Try It
按钮) - 当浏览器在窗口下方显示包含
yourSite wants to know your physical location.
的安全栏时,单击Options for this site
,选择Always allow
。
Internet Explorer
(不是您的应用程序)并浏览到包含地理定位脚本的文件的URL