1
votes

I am trying to activate my app from its own share contract (please - don't comment about whether or not this is okay to do from a Certification point of view... The app activation is done through a button on the share contract UI and will not happen unless the user proactively it. I am asking about the technical issue here, not about the user experience side of things - thanks!!)

The way I have it is set up is like this:

this.m_shareOperation.ReportStarted();

// ....

this.m_shareOperation.ReportCompleted();

await Launcher.LaunchUriAsync(new Uri("se-myapp:///something"));

Everything seems to work fine - the Activation event/override fires, the app actually activates and shows up, but then, AFTER my OnActivated code completes, the following error shows up:

The operation cannot be completed because the window is being closed. (Exception from HRESULT: 0x802A0201)

What can I do to make this work? Any idea?

The callstack where this appears is this (no user code, does not get handled by the UnhandledException event)...

mscorlib.dll!System.Threading.Tasks.AwaitTaskContinuation.ThrowAsyncIfNecessary.AnonymousMethod__1(object s) + 0x33 bytes mscorlib.dll!System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(object state) + 0x3e bytes mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xa7 bytes mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x16 bytes mscorlib.dll!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() + 0x60 bytes mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x149 bytes mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x5 bytes [Native to Managed Transition]

2

2 Answers

2
votes

The solution is fairly simple, if somewhat old school (though fully supported by WinRT)...

Step 0: Define a named event you are going to use in your app:

public static EventWaitHandle GetActivationEvent()
{
    EventWaitHandle sync = new EventWaitHandle(false, EventResetMode.ManualReset, Constants.ActivationEventName);
    return sync;
}

Step 1: In the OnActivate() override, get that event and set it:

using (var sync = Utils.GetActivationEvent())
{
    sync.Set();
}

Step 2: From the share target, activate yourself in the following way:

using (EventWaitHandle sync = Utils.GetActivationEvent())
{
    await Launcher.LaunchUriAsync(new Uri(String.Format("my-protocol:///?id={0}&operation={1}", id, op)));
    await Task.Run(() => sync.WaitOne(5000));
    this.m_shareOperation.ReportCompleted();
}

That's it. This will make sure Windows does not get confused and whines about the app closing and opening at the same time.

0
votes

You can't.

Unfortunately, you are attempting to mix things that are not meant to be mixed. If you create a custom protocol activation for your app, then calling the uri that contains the protocol will launch your app. The share charm will only activate apps that have a share target contract. No exceptions.

Here's a little more information on protocol activation. You might find it useful: http://blog.jerrynixon.com/2012/10/walkthrough-using-windows-8-custom.html