Inter-Process Communication with file association in WinRT – Part 2

The previous post presented the WinRT Contracts that are available to exchange information between WSAs and WSAs/DAs. It is time to dig into the details of leveraging the file association feature of Windows to let one application activate another application.

FileActivationHighLevel

WARNING: all these techniques are violating the point 3.1 from the Windows Store Requirements that states: “Your app may only depend on software listed in the Windows Store“. Therefore, you should not use them for a WSA that you plan to publish into the Windows Store because it will be rejected.

Using file association to communicate between applications

In Windows, the file association mechanism allows automatic creation of a process to open a file based on its extension.

How to activate another application?

The first step is to figure out how to trigger the file-based activation. For a WSA, you simply need to create a file with the expected extension and pass the corresponding StorageFile object to the Launcher.LaunchFileAsync method and Windows does the rest. The other LauncherOptions parameter lets you decide if you want the confirmation dialog to appear.

UPDATE – 2013/03/09: If there is no application (either DA or WSA) associated to the file extension, the dialog will always popup, even if you did not ask for it.

FindStoreAppAssociatedToFileExtension

As you can see from the flyout, the end user is able to “look for an app in the Store” that would support the file extension. If there is no such an application, the search page will be empty

WindowsStoreSearchPerFileExtension

It is good to see that the Windows Store is able to find a WSA based on a file extension but you won’t be able to find a DA that way into the Store.

Last point to take into account when you try to activate another application via Launcher.LaunchFileAsync: this method will always return true even if no application was found locally or into the Store!


In my sample WSA, the file is created inside its local folder given by ApplicationData.Current.LocalFolder. I’ve first tried to create it in the user Document library folder but a WSA is allowed to create a file in this folder only if the file has an extension supported by the WSA itself… this is definitively not compatible with what I’m trying to achieve since the DA already handles the files with this extension and I don’t want that a confirmation dialog pops up to let the user pick which application should open the file!

In the case of a DA, you call CreateProcess with the filename as parameter. In both cases, you write the parameters you want to pass to the other application into the file.

How to associate an application to a file extension?

Both a WSA and a DA can register its execution with a file extension. The former requires changes in the manifest:

WSAFileTypeDeclarationManifest

The latter requires more work in the Registry:

DAFileTypeRegistryAssociation

As you can see, the registration happens in two places under HKEY_CLASSES_ROOT. The default value associated to the extension name (without forgetting the “dot” character) gives the name of the next key where to look at for the shell/open/command default value. This is where the command line to execute is defined: note the %1 used as placeholder for the command line corresponding to the filename that triggers the launch.

The DAFileAssociation project calls the AssociationRegistrationHelper.RegisterFileAssociation method that takes care of all the Registry setup. The returned enumeration value lets you know what happened

public enum AssociationRegistrationStatus
{
Created,
AlreadyExist,
DoesNotExist,
WrongRegistration,
SecurityFailure
}

The calling process must run under an elevated administrator account to update the Registry or the SecurityFailure value will be returned because the updated failed.

Last but not least, if you need to check that the file associations are correct on a machine, Control Panel is your friend via the WIN+X|Control Panel shortcut.

ControlPanel4FileAssociation

How to handle application activation?

The activation process will work but the activated WSA will have to carefully access the file. As you may know, a WSA is very restricted in term of file access: it is allowed to access a file without going through the File Picker if the capability corresponding to the containing folder (from Documents, Music and Pictures libraries) has been added into its manifest. As I just mentioned, there is another condition to open or create a file there: its extension must also be added into the Declarations section of the manifest. This is perfect for the WSA that we want to activate but not possible for another WSA because we don’t want to have both activated for the same type of file.

Hopefully, the OnFileActivated override from the Application-derived class allows you to access files without going through the File Picker. The FileActivatedEventArgs event argument provides two important parameters. Its string Verb property has the “open“ value in this kind of activation but other are supported such as print. The IReadOnlyList<Windows.Storage.IStorageItem> Files property lets you get to the list of files that activate the WSA. However, there is a trick here: only the pathname of a file is accessible by the IStorageItem interface via its Name or Path string property as shown in the MSDN documentation.

MSDNOnFileActivatedHelp

If you try to access the file by calling the StorageFile.GetFileFromPathAsync method passing the pathname, an UnauthorizedAccessException is thrown with AccessDenied.

The solution is to cast the IStorageItem into a StorageFile and use a stream/data reader pair to read the file content:

StorageFile sf = file as StorageFile;

if (sf!= null)

{

IRandomAccessStream stream = await sf.OpenAsync(FileAccessMode.Read);

DataReader reader = new DataReader(stream.GetInputStreamAt(0));

UInt32 size = await reader.LoadAsync((UInt32)stream.Size);

string content = reader.ReadString(reader.UnconsumedBufferLength);

}

For DA, the filename is available from Environment.CommandLine with the following format:

“C:\…\DaFileAssociation.exe” C:\Users\<user>\ AppData\Local\Packages\8fe887ce-3234-45e3-9f00-71c02429fd5f_2g303v4t3xrhw\LocalState\2269fc55-6189-4d9a-b2d9-3d45a5a095ee.daparams

The sample application code looks for the last “ character to extract the filename. In a DA, the limits to read the file contents do not exist and StreamReader.ReadToEnd() is your friend:

using (StreamReader sr = new StreamReader(filename))
{

String line = sr.ReadToEnd();

tbWorkload.Text = line;

}

What data to exchange?

The simple examples shown since the beginning of the post are exchanging plain text. It would be better to be able to exchange more structured data. If you try to use basic .NET serialization, you will find out that the binary serializer is not available for a WSA written in .NET; use my BCLDiff tool to have the complete list of missing types:

MissingSerializableAttributeWithBCLDiff

Fortunately, the DataContract-based serialization is usable from both sides which makes it a good candidate to exchange strongly typed objects. Then, you need to decide which formatter to use; for example Json could be used to exchange smaller payload than with XML. Also note that WinRT JsonArray and JsonObject types make it easy to manipulate and parse Json structures for a WSA, while a DA could use a JsonDataContractSerializer.

As you may know, there is no API for a WSA to change the Windows desktop wallpaper. However, Microsoft provides C# code sample to do so in a DA. The WSA built for this post allows the end user to use the webcam to take a picture and send the fill option with the image filename as a workload serialized in Json

ComplexDataWorkloadExchange

to the DA that use it to change the Windows wallpaper

ChangingDesktopWallpaperFromWSA

Download source code for the sample WSA and DA

The next post will describe how to achieve the same kind of features but with custom protocols.

About these ads
This entry was posted in .NET, C#, Store App, WinRT and tagged , , , , , . Bookmark the permalink.

3 Responses to Inter-Process Communication with file association in WinRT – Part 2

  1. Pingback: Windows Store Developer Links – 2013-03-11 | Dan Rigby

  2. Pingback: Inter-Process communication with protocol association in WinRT – Part 3 | Anything about WinRT

  3. Pingback: Inter-Process Silent Communication in WinRT – Part 4 | Anything about WinRT

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s