How to use Geolocator.RequestAccessAsync in WPF desktop app - c#

I've built a WPF app in C# which needs to know the user's location, and currently requires that it be entered manually. I'm using the Desktop Bridge to make it be able to run as a UWP app. When it's running as a UWP app, I want to take advantage of the Windows 10 location API if it is enabled. I'm using the following code to request for location access when the program starts:
public static async void RequestAccess()
{
var accessStatus = await Windows.Devices.Geolocation.Geolocator.RequestAccessAsync();
switch (accessStatus)
{
case Windows.Devices.Geolocation.GeolocationAccessStatus.Allowed:
UwpDesktop.hasLocationAccess = true;
break;
case Windows.Devices.Geolocation.GeolocationAccessStatus.Denied:
UwpDesktop.hasLocationAccess = false;
break;
case Windows.Devices.Geolocation.GeolocationAccessStatus.Unspecified:
MessageBox.Show("Failed to access Windows 10 location API", "Error");
UwpDesktop.hasLocationAccess = false;
break;
}
}
However I get the following error when I run my app if the location permission is not enabled for it:
System.Exception: 'Element not found. (Exception from HRESULT: 0x80070490)'
The cause of this error as far as I can tell is that the RequestAccessAsync function needs to be run in the main UWP UI thread. The reason it only happens when the location permission is not enabled is because Windows tries to launch a UWP dialog requesting that the user grant location access, but fails to do so in a Desktop Bridge app.
I'm aware of two solutions to this problem. One would be to launch the Location section of the Settings app and show a messagebox to users asking them to grant location access there, which could work but I would really prefer to use the official API. The other option is to create a new UWP code project and write this code there, and then run it from the WPF app.
Microsoft has some documentation that is supposed to explain how to do the second option, but their examples are complicated and I don't know how to apply them to what I'm trying to do. I don't want to create a XAML UI or a background service, all I need is a way to safely call RequestAccessAsync and return a value based on the outcome. I'm wondering if I really need to create a UWP project to make this behave the way I want, or what the simplest way would be to go about it.

Related

extendedExecutionSession : Can we run UWP like Desktop app without Suspending?

I'm planing to start a UWP application that monitor a sensor data for 365 days and save all data to database(Sqlite).
I still worry about UWP capability. Please advice me Which should I use (UWP/WPF) ? I want to use better UI, than, I want to use UWP if possible...
UWP-Suspending is my worry.
With this post, Some people said a way to prevent a UWP application from suspending..
var extendedExecutionSession = new ExtendedExecutionSession();
extendedExecutionSession.Reason = ExtendedExecutionReason.Unspecified;
var extendedExecutionResult = await extendedExecutionSession.RequestExtensionAsync();
if (extendedExecutionResult != ExtendedExecutionResult.Allowed)
{
//extended execution session revoked
extendedExecutionSession.Dispose();
extendedExecutionSession = null;
}
Question
If I wrote this code in UWP app, Can I use a UWP application like Desktop WPF application ? I want to run my UWP application for 365 days without stopping
.. even if user do "minimized" on desktop... Please advice it...
Yes, you can do that with ExtendedExecution. One thing to note is when you run on battery (e.g. laptop, tablet) you will get suspended after some time - however you can prevent that as well by going into the Battery settings page and set your app as "Always Allowed".
Details are documented here: https://learn.microsoft.com/en-us/windows/uwp/launch-resume/run-minimized-with-extended-execution

Check if Windows.System.Launcher.LaunchUriAsync was handled

I try to solve problem with the Windows Phone Launcher.
I have application and I would like to call another application using the uri and pass it some data. And I would like to know if the second application started. If the application was not started I would like to do some fallback.
Example:
bool result = await Windows.System.Launcher.LaunchUriAsync(new Uri("secondApp://data/123", UriKind.RelativeOrAbsolute));
if (!result)
{
// Opps. The second application is not installed.
ShowToast("Oops. The applications is not installed.");
UseInternalTinyFunctionalityInstead();
}
But the result is always true. Even though the second application is not installed. And additionally the windows message box is displayed "Search for app in the Store? You need to install an app for this task. Would you like to search for one in the Store? yes, no".
Is it possible to check if the second application was started/ is installed?
Is it possible NOT to display this dialog?
Thank you.
Myth Rush

Run C# app on Startup?

I have created a simple weather application and I added the code below to let the user let it run on Startup:
RegistryKey rk = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
if (startupCheck.Checked) {
rk.SetValue("WeTile", "\"" + Application.ExecutablePath.ToString() + "\"");
} else {
rk.DeleteValue("WeTile", false);
}
Now this runs fine on both my computers. But when I gave the app to my girlfriend. She said the app does not run on windows start up. I read it online that it could be because of the user permission or the location so I told her to move the app to c:/ and try checking the box again and then restarting. Now it works but on every startup she has the default windows message saying you want to run this app?
How do I get rid of this? What is the best way to add to windows startup that works with both windows 32/64 bit without any user permission disruptions?
It sounds like you may have run afoul of Windows' file blocking security function. Applications created on another computer are automatically blocked from executing unless the user specifically "unblocks" the file. Have your girlfriend right-click on the executable, select "Properties" and see if there is a button at the bottom of the dialog to unblock the file.
Once unblocked, you should no longer see the confirmation prompt at startup.
You could add it to the Windows startup folder, check if it's not there already and if not, add it (assuming this is what the user wants).
See How do I set a program to launch at startup

Process.Start won't work

I am trying to launch a process from a web page's back-end code/app pool. This process will launch an App that i built myself.
For some reason, the process only works / runs when i start it from VS2013... it never works when i launch it from IIS(7.5) itself.
I am on a Windows 7 machine (both IIS host, and App location), and I've setup my web site to only be accessible via internal network.
Here's the code, followed by the config / attempts to fix the issue:
protected void btn_DoIt_Click(object sender, EventArgs e)
{
string file_text = this.txt_Urls.Text;
if (!String.IsNullOrWhiteSpace(file_text))
File.WriteAllText(ConfigurationManager.AppSettings["filePath"], file_text);
ProcessStartInfo inf = new ProcessStartInfo();
SecureString ss = GetSecureString("SomePassword");
inf.FileName = #"........\bin\Release\SomeExecutable.exe";
inf.Arguments = ConfigurationManager.AppSettings["filePath"];
inf.UserName = "SomeUserName";
inf.Password = ss;
inf.UseShellExecute = false;
//launch desktop app, but don't close it in case we want to see the results!
try
{
Process.Start(inf);
}
catch(Exception ex)
{
this.txt_Urls.Text = ex.Message;
}
this.txt_Urls.Enabled = false;
this.btn_DoIt.Enabled = false;
this.txt_Urls.Text = "Entries received and process started. Check local machine for status update, or use refresh below.";
}
Here are the things I've tried to resolve the issue:
Made sure the executing assembly was built with AnyCPU instead of
x86
Ensured that the AppPool that runs the app, also runs under the same account (SomeUsername) as the ProcessStartInfo specified.
Ensured that the specific user account has full access to the executable's folder.
Ensured that IIS_USR has full access to the executable's folder.
Restarted both the app pool and IIS itself many times over implementing these fixes
I am now at a loss as to why this simply will not launch the app... when i first looked into the event log, i saw that the app would die immediately with code 1000:KERNELBASE.dll, which got me on the AnyCPU config instead of X86 fix... that fixed the event log entries but the app still doesn't start (nothing comes up in task manager), and i get no errors in the event log...
if someone could help me fix this problem i would really appreciate it. This would allow me to perform specific tasks on my main computer from any device on my network (phone, tablet, laptop, etc etc) without having to be in front of my main PC...
UPDATE
The comment to my OP, and ultimate answer from #Bradley Uffner actually nailed the problem on the head: My "app" is actually a desktop application with a UI, and in order to run that application, IIS would need to be able to get access to the desktop and the UI, just like if it were a person sitting down in front of the PC. This of course is not the case since IIS is running only as a service account and it makes sense that it shouldn't be launching UI programs in the background. Also see his answer for one way of getting around this.
Your best bet might be to try writing this as 2 parts. A web site that posts commands to a text file (or database, or some other persistent storage), and a desktop application that periodically polls that file (database, etc) for changes and executes those commands. You could write out the entire command line, including exe path command arguments, and switches.
This is the only way I can really think of to allow a service application like IIS to execute applications that require a desktop context with a logged in user.
You should assign a technical user with enough high priviliges to the running application pool. By default the application pool is running with ApplicationPoolIdentity identy which has a very low priviliges.

Reinstantiation issue using Inter App Communication with Windows Phone

I am developing an WP8 app that uses a webbrowser control that shows statefull server content. On WP8 you can switch between apps manually. E.g. if you want to copy&paste some information from one app into a browser input field. If you switch that way, the current app instance stays alive. That means the web session and the current page of the browser control will stay available.
Now I want another app to send some data directly into the app with the browser control - without restarting it...
From what I know, there are three ways to handle inter app communication:
register a file type that will open the app by launching that file from local storage
register an app protocol and use Launcher.LaunchUriAsync() to submit parameters in a query string
use a shared storage file
Detailed information can be found here.
I think the last approach is not usefull, because after you have started the second app, there is now way to activate the calling app or is there any usefull way to reactivate the webbrowser app?
I tried the second approach, but I am running in an issue, because it starts a new instance by design. That means InitializePhoneApplication is called. There is the entry point for the custom UriMapper that reads the incoming parameters. So the old app instance is killed and all session data, cookies and input fields are gone. With WP webbrowser control you are not able to store the cookie and page state, so a fast app resume is not possible also.
private void InitializePhoneApplication()
{
if (this.phoneApplicationInitialized)
{
return;
}
RootFrame = new TransitionFrame();
RootFrame.Navigated += this.CompleteInitializePhoneApplication;
RootFrame.UriMapper = new AssociationUriMapper();
//...
this.phoneApplicationInitialized = true;
}
Is there any other way or a possibility to use the shown approaches to send data between apps without restarting them using LanchUri()?
That means, to send some data back to a running instance without reinitializing the whole app, so that the page state and session state are still available on the target app.
Best regards
Holger
FastAppResume is the solution. I haven't used it and thought it also reinitiates the app. But it doesnt. This example shows how to reuse the existing instance.
Regards
Holger

Categories