Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Silverlight Out-of-Browser application will not close using MainWindow.Close method

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:

  • It is a trusted application (not true for my application)
  • Before the Application.Startup event has completed (not true for my application)
  • In response to a user-initiated action, for example, in a button Click event handler (This is what I am trying to get to work)

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. Window Close Security Test Results

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?

like image 885
Martin Hollingsworth Avatar asked Jun 29 '12 02:06

Martin Hollingsworth


1 Answers

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).
like image 103
SonOfPirate Avatar answered Sep 27 '22 23:09

SonOfPirate