Windows Phone 7 close application - silverlight

Is there any possibility to programatically close Silverlight application on Windows Phone 7?

If you write an XNA Game, you will have access to an explicit Exit() method. If you are writing traditional Silverlight project, then NO, there is no way to programatically close your app. See also Peter Torr's Blog entry on Exiting Silverlight Apps in Windows Phone 7. There he also mentions the option of throwing an unhandled exception, which IMO is a terrible programing style.
An option you may try, is using the WP7 Navigation Service to programatically navigate back out of the application. Not sure if that would work though. Why do you need to Exit?

You can always call an exit by doing this at your landing page use this code on click of your application back button:
if (NavigationService.CanGoBack)
{
while (NavigationService.RemoveBackEntry() != null)
{
NavigationService.RemoveBackEntry();
}
}
This will remove back entries from the stack, and you will press a back button it will close the application without any exception.

Short answer for Silverlight is No.
You should not provide a way to close the applicaiton. Closing the applicaiton should be the users choice and implemented by using the back button the appropriate number of times. This is also a marketplace requirement.
That said, a silverlight application will close if there is an unhandled exception. I have seen a few people try and create programmatic closing by throwing a custom error which is explicitly ignored in error handling. This can work but there is still the marketplace issue.
XNA applications can explictly call Exit().

Some good info here already. Adding to this..
The platform is fully capable of managing closure of apps. The more apps don't provide an exit, the quicker users will become accustomed to not thinking about app house keeping, and let the platform manage it.
The user will just navigate their device using start, back, etc.
If the user wants out of the current app to go do something else quickly - easy - they just hit start.
.Exit(), whilst available for xna, really isn't required anymore either. There was a cert requirement during CTP that games had to provide an exit button. This is now gone.
Non game apps never had the need to implement this.
The more this topic's discussed (and it really has been given a good run around the block), the more the indicators to me suggest there is no need to code an exit.
Update: For those thinking of an unhandled exception as a suitable way of closing an app intentionally or letting the app close due to subpar operating conditions, I would recommend reviewing the comments concerning Application Certification Requirements in this answer. Is there a way to programmatically quit my App? (Windows Phone 7)

Here is another solution.
If you have an error page that i.e. displays error to the end user you can use the
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
base.OnBackKeyPress(e);
e.Cancel = true;
}
And you can instruct user to press start button to exit application.

Add a reference to Microsoft.Xna.Framework.Game, then call:
new Microsoft.Xna.Framework.Game().Exit();

private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
{
while (NavigationService.CanGoBack)
NavigationService.RemoveBackEntry();
}
That works for me fine.

You can close the app using this statement
Application.Current.Terminate();

This worked perfectly on Windows phone 7
System.Reflection.Assembly asmb = System.Reflection.Assembly.Load("Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553");
asmb = System.Reflection.Assembly.Load("Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553");
Type type = asmb.GetType("Microsoft.Xna.Framework.Game");
object obj = type.GetConstructor(new Type[] { }).Invoke(new object[] { });
type.GetMethod("Exit").Invoke(obj, new object[] { });
Link - source

My 2 pence worth, reasons for an exit
1) there is no interent connection the first time it is run and it needs to create an account on a web service somewhere to run.
2) You need to force an upgrade for the user, again when tied to a web service, you may discover a bug in your app, or have web service changes that mean the user needs to be forced to upgrade, at that point you will want to inform the user that they must upgrade and then exit the app.
Currently in my app I am forced to take the user to a form that says "they" must exit, and if they click back they are again forced back to this page. not very nice.

In Silverlight, I throw an un-handled exception when I have to exit the application. I know that this isn't the graceful method to handle this but it is still the most convenient and easiest solution.
I know that according to the guidelines there shouldn't be any un-handled exceptions in the code but I write why I am explicitly throwing an un-handled exception in the Exception Request document at the time of submission.
Till now this method has always worked and never failed me.

Easiest way to do this is to add a reference to Microsoft.Xna.Framework.Game, then add
using Microsoft.Xna.Framework.GamerServices; before namespace. Then we have a button in our Example.xaml with Click="quit_button". In out Example.xaml.cs we put this code inside our page-class:
private void quit_Click(object sender, EventArgs e)
{
new Microsoft.Xna.Framework.Game().Exit();
//This will close our app
}

var buttonInfo = MessageBox.Show("Are you sure you want to exit?", "Exit", MessageBoxButton.OKCancel);
if (buttonInfo == MessageBoxResult.OK)
{
if (NavigationService.CanGoBack)
{
while (NavigationService.RemoveBackEntry() != null)
{
//
}
}
e.Cancel = false;
}
else
{
//Stop page from navigating
e.Cancel = true;
}

Navigate to App.xaml.cs in your solution explorer and
add a static method to the App class
public static void Exit()
{
App.Current.Terminate();
}
so that you can call it anywhere from your application , as below
App.Exit();

Related

How to detect URI activation on a WPF desktop package (WAP) after it has already launched?

I have a WPF desktop application that is MSIX-packaged using a Windows Application Package (WAP) project. I already know how to launch my WPF desktop app the first time using URI activation, by calling AppInstance.GetActivatedEventArgs() and then analyzing the arguments:
if (activatedEventArgs.Kind == ActivationKind.Launch)
{
if (((LaunchActivatedEventArgs)activatedEventArgs).Arguments == "myactivationcode")
// .. do something
}
But if a user runs the URI activation a 2nd time, while my app is already launched, I have learned that a new instance of my app is launched. This doesn't happen with UWP apps, just desktop apps. I can kill the 2nd instance to follow a desired singleton pattern, but what I want is for the first instance of my WPF app to get some event that lets it know to come back into view.
Things I've researched that have no answers that I can see:
How to handle URI activation in a Windows Application Packaging Project?
How can I handle file activation from a WPF app which is running as UWP?
https://learn.microsoft.com/en-us/windows/uwp/launch-resume/handle-uri-activation#step-3-handle-the-activated-event
Does any such API or event exist for URI re-activation? Or do I need to do some other form of IPC, like named pipes or WCF on the 2nd instance of my app? Any help here would be greatly appreciated.
But if a user runs the URI activation a 2nd time, while my app is already launched, I have learned that a new instance of my app is launched.
Whether a second instance is launched depends on the implementation of your custom Main method.
In your second link, there is a link to blog post and a code example that demonstrates how to prevent another instance from being launched.
It uses named pipes to communicate with the already running app instance and passes a serialized IActivatedEventArgs to it:
[STAThread]
static void Main(string[] args)
{
IActivatedEventArgs activatedEventArgs = AppInstance.GetActivatedEventArgs();
using (Mutex mutex = new Mutex(false, AppUniqueGuid))
{
if (mutex.WaitOne(0, false))
{
new Thread(CreateNamedPipeServer) { IsBackground = true }
.Start();
s_application = new App();
s_application.InitializeComponent();
if (activatedEventArgs != null)
s_application.OnProtocolActivated(activatedEventArgs);
s_application.Run();
}
else if (activatedEventArgs != null)
{
//instance already running
using (NamedPipeClientStream namedPipeClientStream
= new NamedPipeClientStream(NamedPipeServerName, AppUniqueGuid, PipeDirection.Out))
{
try
{
namedPipeClientStream.Connect(s_connectionTimeout);
SerializableActivatedEventArgs serializableActivatedEventArgs = Serializer.Serialize(activatedEventArgs);
s_formatter.Serialize(namedPipeClientStream, serializableActivatedEventArgs);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, string.Empty, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}
}
Does any such API or event exist for URI re-activation?
No
Or do I need to do some other form of IPC, like named pipes or WCF on the 2nd instance of my app?
Yes. Again, please refer to the mentioned blog post and accompanied code sample.

Silverlight CaptureDeviceConfiguration.RequestDeviceAccess() - how does it know?

CaptureDeviceConfiguration.RequestDeviceAccess() method must be invoked by user interaction, otherwise it fails. My question is how does Silverlight know the invocation came from user (i.e. via Button.Click())?
Have a look at this: http://liviutrifoi.wordpress.com/2011/05/18/silverlight-isolatedstoragefile-increasequotato/
Quote:
I was curios though how exactly does silverlight know what a user
initiated event is, but after digging through .net framework source
code I’ve got to a dead end:
if ((browserService == null) || !browserService.InPrivateMode())
{
//..
}
return false; //means that IncreaseQuota will fail
where browser.IsInPrivateMode is:
[SecuritySafeCritical]
public bool InPrivateMode()
{
bool privateMode = false;
return (NativeMethods.SUCCEEDED(UnsafeNativeMethods.DOM_InPrivateMode(this._browserServiceHandle, out privateMode)) && privateMode);
}
where DOM_InPrivateMode is in a DllImport["agcore"], which according
to microsoft is confidential :( So it looks like I won’t find out soon
how they’re detecting user initiated events, although I’m guessing
they have some centralized private method that detects clicks for
example, and then probably sets a flag that this was indeed “a user
initiated event”, and since you can’t forge clicks or keypresses using
javascript and since you can’t call those private methods using
reflection, it’s “safe”.

Runtime debugging tips for Windows Service?

I have a Windows Service that monitors a COM port connected to a vendors hardware. This is a very busy piece of hardware that is constantly polling other devices on the wire (this is a twisted-pair RS485 "network"). My software needs to emulate X number of hardware devices on this wire, so I've got a multi-threaded thing going on with a multi-tiered state machine to keep track of where the communications protocol is at any moment.
Problem is with a Windows Service (this is my first one, BTW) is that you need some debugging to let you know if stuff is working properly. When I was first developing this state machine/multi-thread code I had a windows form with a RichTextBox that displayed the ASCII chars going back-n-forth on the line. Seems like I can't really have that GUI niceness with a service. I tried opening a form in the service via another program that sent the service messages that are received via the OnCustomCommand() handler but it didn't seem to work. I had "Allow service to interact with desktop" checked and everything. I was using the Show() and Hide() methods of my debug form.
I guess I don't need to see all of the individual characters going on the line but man that sure would be nice (I think I really need to see them :-) ). So does anyone have any crazy ideas that could help me out? I don't want to bog down the system with some IPC that isn't meant for the voluminous amount of data that is sure to come through. It will only be very short-term debugging though, just confirmation that the program, the RS485-to-USB dongle, and hardware is all working.
Use OutputDebugString to write to the debugging buffer and then use DebugView to watch it. If you're running on Windows XP or earlier, then you can use PortMon to see the raw bytes going through the serial port. The advantage over a log file is that there's very little overhead, particularly when you're not watching it. You can even run DebugView from another machine and monitor your service remotely.
I dunno if it will work for you, but I always build my services with a extra Main that build them as console app to get debug output.
Edit:
Some example:
class Worker : ServiceBase
{
#if(RELEASE)
/// <summary>
/// The Main Thread where the Service is Run.
/// </summary>
static void Main()
{
ServiceBase.Run(new Worker());
}
#endif
#if(DEBUG)
public static void Main(String[] args)
{
Worker worker = new Worker();
worker.OnStart(null);
Console.ReadLine();
worker.OnStop();
}
#endif
// Other Service code
}
You could write the output to a log file and then use another application to watch that file. This question about "tail" outlines several options for watching log files with windows.
What I usually do when working on a Windows Service is to create it so that it can be run either as a service, or as a plain old command-line application. You can easily check whether you are running as a service by checking Environment.UserInteractive. If this property is true, then you are running from the command line. If the property is false, then you are running as a service. Add this code to Program.cs, and use it where you would normally call ServiceBase.Run(servicesToRun)
/// <summary>Runs the provided service classes.</summary>
/// <param name="servicesToRun">The service classes to run.</param>
/// <param name="args">The command-line arguments to pass to the service classes.</param>
private static void RunServices(IEnumerable<ServiceBase> servicesToRun, IEnumerable args)
{
var serviceBaseType = typeof(ServiceBase);
var onStartMethod = serviceBaseType.GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic);
foreach (var service in servicesToRun)
{
onStartMethod.Invoke(service, new object[] { args });
Console.WriteLine(service.ServiceName + " started.");
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
var onStopMethod = serviceBaseType.GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic);
foreach (var service in servicesToRun)
{
onStopMethod.Invoke(service, null);
Console.WriteLine(service.ServiceName + " stopped.");
}
}
Now you can debug your service, set breakpoints, anything you want. When you run your application, you'll get a console window, appropriate for displaying console messages, and it will stay open until you hit a key.
I'm answering my own question here. I tried a couple of suggestions here but here's what I ended up doing...
I created a Windows Form application with a single Button and RichTextBox. This application constructed a NamedPipeServerStream on it's end. The Button's job was to send either "debug on" (command 128) or "debug off" (129) to the Windows Service. The initial value was "debug off". When the button was clicked, a command of 128 was sent to the Windows Service to turn debugging on. In the Windows Service this triggered an internal variable to be true, plus it connected to the Form application with a NamedPipeClientStream and started sending characters with a BinaryWriter as they were received or sent on the COM port. On the Form side, a BackgroundWorker was created to WaitForConnection() on the pipe. When it got a connection, a BinaryReader.ReadString() was used to read the data off of the pipe and shoot it to the RichTextBox.
I'm almost there. I'm breaking my pipe when I click the debug button again and a subsequent click doesn't correctly redo the pipe. All in all I'm happy with it. I can post any code if anyone is interested. Thanks for the responses!

Internet Explorer 9 RC stops my WinForms WebBrowser control to work in editing mode

Using the IHtmlDocument2.designMode property set to On to switch a WebBrowser control hosted on a Windows Forms form to editing mode suddenly stopped working after installing Microsoft Internet Explorer 9 RC.
Question:
Any chance to fix this?
I already tried to tweak with doctype or with the EmulateIE7 meta tag but without success.
(An example would be this project)
Update 2011-02-21:
As Eric Lawrence suggested, I adjusted the "Zeta" example to set the document text before setting the edit mode.
Unfortunately I did not manage to switch to design mode, either.
Update 2011-02-24:
Parts of the discussion also take place in Eric's blog.
Update 2011-02-26:
What I currently eperience is that the behaviour seems to be different for HTTP URLs and for content that was added via WebBrowser.DocumentText.
First tests seems to prove this assumption.
I'm now going to build a solution around this assumption and post updates and a proof-of-concept here.
Update 2011-02-26 (2):
I've now built a proof-of-concept with a built-in web server which I believe is also working well with IE 9. If anyone would like to download and test whether it is working and give me a short feedback, I can clean up and release the source code for this.
Update 2011-02-26 (3):
No feedback yet, I still updated the HTML Edit Control article and demo over at the Code Project.
Update 2011-03-16:
Since Internet Explorer 9 was released yesterday, we updated our major products to use the idea with the integrated web server as described in the HTML Edit Control article.
After nearly a month of testing, I think it works quite well.
If you do experience any issues in the future with this approach, please post your comments here and I can investigate and fix.
I had a similar problem and got around it by adding the following line to the DocumentCompleted event:
((HTMLBody)_doc.body).contentEditable = "true";
We just need an empty editable control. I did however step through debugger and add value to the control's InnerHtml and it displayed it fine, and I could edit it.
Small update, we were able to get the control editable using this line also:
browserControl.browser.Document.Body.SetAttribute("contentEditable", "true");
This allows us to avoid referencing mshtml, (don't have to include Microsoft.mshtml.dll)
This lets us avoid increasing our installation size by 8 megs.
What's your exact code?
If I set the following code:
private void cbDesign_CheckedChanged(object sender, EventArgs e){
var instance =
Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(
wbView.ActiveXInstance,
null,
#"Document",
new object[0],
null,
null, null );
var objArray1 = new object[] { cbDesign.Checked ? #"On" : #"Off" };
Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateSetComplex(
instance,
null,
#"designMode",
objArray1,
null,
null,
false,
true );
The IE9 Web Browser instance enters designMode without any problems. If you change the "Zeta" example to not set the document text after entering design mode, it also works fine.
Just want to add that I am also unable to enter designmode (using a WebBrowser control in my case). This was not an issue in the beta. Definitely new with the RC.
Another Code Project user suggested to use the following code:
First, add event DocumentCompleted:
private void SetupEvents()
{
webBrowser1.Navigated += webBrowser1_Navigated;
webBrowser1.GotFocus += webBrowser1_GotFocus;
webBrowser1.DocumentCompleted += this.theBrowser_DocumentCompleted;
}
Then write the function:
private void theBrowser_DocumentCompleted(
object sender,
WebBrowserDocumentCompletedEventArgs e)
{
webBrowser1.Document.Write(webBrowser1.DocumentText);
doc.designMode = "On";
}
Although I did not test this, I want to document it here for completeness.
It's fixed if the property is set after the document is loaded
private void DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
IHTMLDocument2 Doc = Document.DomDocument as IHTMLDocument2;
Doc.designMode = #"On";
}
Yesterday, Internet Explorer 9 RTM finally was released.
I did some more tiny adjustments to my control, but basically the idea with the intergrated, small web server seems to work rather well.
So the solution is in this Code Project article:
Zeta HTML Edit Control
A small wrapper class around the Windows Forms 2.0 WebBrowser control
This was the only solution that worked for me.
I hope it is OK to answer my own question and mark my answer as "answered", too?!?
I was also able to get this to work using the following inside the DocumentCompleted event:
IHTMLDocument2 Doc = browserControl.browser.Document.DomDocument as IHTMLDocument2;
if (Doc != null) Doc.designMode = #"On";
Thanks everyone!
I use HTML Editor Control, I solved this problem adding the DocumentComplete event
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
(((sender as WebBrowser).Document.DomDocument as IHTMLDocument2).body as HTMLBody).contentEditable = "true";
}

How should OOB Silverlight 4 app show unhandled errors to UI? (HtmlPage)

I have a SL OOB app (it only runs OOB) and was wondering about the ReportErrorToDOM code in the app.xaml.css:
From what I understand, HtmlPage wont work in OOB as there is no DOM/HTML? Is that why this code is wrapped in a TryCatch block? (this is the default for a new SL4 app).
To get my OOB app to display unhandled errors to the UI, should I judt replace the HTMLPage with a MessageBox.Show?
I can't find anything on Google about this, opinions appreciated...
private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
{
try
{
string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", #"\n");
System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
}
catch (Exception)
{
}
}
As an initial starting position yes you should replace the code with code that uses MessageBox.Show to display the error.
What is appropriate for a production quality release will depend on the type of application. Strictly speaking if your application has encountered an unhandled exception it would be in an indeterminate state so a message box and/or the replacing of the root visual might make sense.
If its a game then simply swallowing the error might even be appropriate or just noting it in some log.
Take a look at the Silverlight Navigation Application template in VS - it uses a ChildWindow to show errors, and this works OOB as well. You could just generate a dummy project from this template and copy/paste most of the code over to your app to get going quickly, then tweak the UI to suit your needs.

Resources