次の方法で共有


IPC between Windows Store Apps on the same machine

Windows Store Apps are the new modern way to build applications for the Windows 8 platform. For many of us coming from WinForms on WPF backgrounds, one area of difficulty is with the way Windows Store Apps are sandboxed. This isolation makes it nearly impossible for them to talk to each other. Just to be clear, IPC is not a use-case most consumer-facing applications need. However when you start developing LOB apps, IPC suddenly becomes important, and in some cases a must-have.

One approach to get around the Sandboxing is to use the oldest form of IPC – the file system. However this still needs a common file/folder that all apps can access. By default, apps have their own private isolated storage that is not accessible by other apps. But you can give the apps the capability to access the user’s Documents folder for specific file types. So I went down the road of using a shared folder with a bunch of files as a means of communications and was surprised how well it worked. Off course you can’t expect the file system notification to handle very rapid changes, but for many scenarios, this scale works (think FileSystemWatcher).

I’ve wrapped all the functionality into an easy-to-use WinMD module (that is accessible from both WinJS and C# apps). Here are some of the highlights of the library:

Overview

The general idea is fairly simple, implement a Publish/Subscribe mechanism by using shared files. WinRT has a mechanism to detect changes to a folder so we leverage that facility to detect the changes and call a delegate within the registered application. As a convention, I used a folder named Topics and in that folder are various files with the .topic extension. This allows various types of publish/subscribe events to be fired and applications need only listen to the one they are interested in.

File Notification 

First here is the snippet to write the application provided payload to the file. The application calls the NotifyApps method to Publish something new:

 public async void NotifyApps(string Payload)
{
     StorageFolder folder = KnownFolders.DocumentsLibrary;
     folder = await folder.CreateFolderAsync(TopicsFolder, CreationCollisionOption.OpenIfExists);
     StorageFile f = await folder.CreateFileAsync(SharedFile, 
         CreationCollisionOption.OpenIfExists);
     await Windows.Storage.FileIO.WriteTextAsync(f, Payload);
}

 

Now there is no FileSystemWatcher in WinRT but we do have a mechanism to monitor a folder for changes. So we can leverage that to achieve our goal as follows. Note we take a delegate from the application and save it for later. And we set the StorageFileQueryResult to call our delegate when any changes are detected via the ContentsChanged event. Applications using the library call Subscribe if they wish to receive notifications for a particular topic:

 public async void Subscribe(NotificationReceived NotificationCallback)
{
    callback = NotificationCallback;
    folder = KnownFolders.DocumentsLibrary;
    folder = await folder.CreateFolderAsync(TopicsFolder, 
        CreationCollisionOption.OpenIfExists);
    QueryOptions qo = new QueryOptions();
    qo.FileTypeFilter.Add(SharedFileExtension);
    query = folder.CreateFileQueryWithOptions(qo);
    query.ContentsChanged += query_ContentsChanged;
    await query.GetFilesAsync();
}
 
 
 
 
 
 
 

And in the ContentsChanged event we simply read the file and call the application registered delegate. Note we also check if the Payload has changed since the last event.

 f = await folder.GetFileAsync(SharedFile);

IInputStream stream = await f.OpenReadAsync();
using (DataReader reader = new DataReader(stream))
{
    var read = await reader.LoadAsync(MAX_PAYLOAD_LENGTH);
    string CurrentPayload = reader.ReadString(read);
    if (CurrentPayload != LastPayload)
    {
        callback(CurrentPayload);
        LastPayload = CurrentPayload;
    }
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Sample App code to publish information:

 StartupTech.WindowsStore.Library.ApplicationNotification notify = 
 new StartupTech.WindowsStore.Library.ApplicationNotification("AccountNumber");
notify.NotifyApps(StatusTextBox.Text);
 
Sample App code to consume notifications
 StartupTech.WindowsStore.Library.ApplicationNotification notify = new 
 StartupTech.WindowsStore.Library.ApplicationNotification("AccountNumber");
notify.Subscribe(ReceivedNotification);
 void ReceivedNotification(string Payload)
{
     SetStatus("Payload received : " + Payload);
}

The complete project for the AppNotification library can be found here.

 
 
 
 
 
 
 

Just a reminder to add the Documents folder capability to your Windows Store application and configure it for the .topic file extension. That is the only file extension you can access from your app.

If you need Windows Apps to communicate across machines you can look at SignalR instead. See my post on this scenario.