I have a Silverlight 5.1.10411.0 Out-of-Browser application that is NOT trusted and I am trying to close the application using the App.Current.MainWindow.Close method. According to the documentation I can only use this mechanism if one of these conditions is true:
In my attempts to get this to work I have kept things extremely simple and am calling the method directly in a code behind button click event handler as shown below but it has no effect.
void closeButton_Click(object sender, RoutedEventArgs e)
{
var mainWindow = Application.Current.MainWindow;
mainWindow.Close();
}
When I attach the debugger and set "Break when an exception is Thrown" I can see the exception
SecurityException: Access to the property or method call is not allowed unless the application has elevated permissions, or the code was called through a user initiated action.
Any ideas why my code is not being considered a user initiated action?
I have tried attaching the event handler in both XAML and in the code-behind (not at the same time)
<Button x:Name="closeButton" Content="Close" Click="closeButton_Click" />
or
closeButton.Click += closeButton_Click;
without success. I have read the User-Initiated Events documentation very carefully and cannot see why my code is not considered user initiated. I have tried this in both debug and release mode as well as when no debugger is attached without success. If I change "Require elevated trust when running outside the browser" to be true, the close call works as expected.
I have redefined my application requirements to work around this issue but I would really like to understand what I am doing wrong ;-)
Update: SonOfPirate's answer indicate that the documentation for this method is not accurate but I'm not convinced. Using the reflection tool dotPeek the method that is throwing the exception is
private void CheckForPermissions()
{
if (!Application.Current.HasElevatedPermissions && !XcpImports.IsUserInitiatedAction() && Application.Current.ApplicationStarted)
throw new SecurityException(Resx.GetString("Window_AccessNotAllowed"));
}
I find this a bit confusing to read so I've mocked the code and written unit tests for it as shown by this gist and as you can see from the results I should be able to call close from an untrusted application, provided it is user initiated.
The security exception message
Access to the property or method call is not allowed unless the application has elevated permissions, or the code was called through a user initiated action.
also indicates that it should be possible so I am back to the question - why is this code not considered user initiated?
The mistake is in the very first paragraph when you state that you "can only use this mechanism if one of these conditions is true:" Re-read the MS documentation a little closer and you will see that they do not say "one" of these conditions. Here is the exact text from the MS reference page for the Close method:
You can call this method only in the following cases:
- In response to a user-initiated action, for example, in a button Click event handler.
- Before the Application.Startup event has completed (that is, in an IApplicationService.StartService method, an IApplicationLifetimeAware.Starting method, or a Startup event handler).
- In a trusted application.
As you have seen, you need to enable elevated trust.
UPDATE
I concede that the wording used by Microsoft is a bit misleading with either of the first two cases required in combination with the third. Perhaps it would be clearer if worded more accurately as:
You can call this method only in a trusted application in either of the following cases:
- In response to a user-initiated action, for example, in a button Click event handler.
- Before the Application.Startup event has completed (that is, in an IApplicationService.StartService method, an IApplicationLifetimeAware.Starting method, or a Startup event handler).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With