I wanted to let you all know that starting September 2nd, I'll be taking on a new role as Senior Content Developer for Azure and Visual Studio, as part of the Developer Answers team in Microsoft's Cloud & Enterprise Division. This means that content production will be even more of my focus than it has been in the past, when having a Program Manager title often meant getting involved in a variety of other activities!

Blogging will certainly continue, both on Windows and also on Azure and other topics as I expand into those areas. In the meantime, I've been blessed to have a little break between this and my former job, which has provided lots of time for home projects and spending time with family before my son's school starts up again.


Thanks to Michael Scherotter for the details explained in this post.

Say you have an x-ms-webview element on a page in your app:

ms-webview id="webview" class="Content" src="ms-appx-web:///contenthost.html">
</x-ms-webview>    

and you want to print only the contents of the WebView. To do this, it seems at first that you need to get a DOM document object for the Webview to pass to MSApp.getHtmlPrintDocumentSource within a PrintTaskSourceRequested event. However, as noted in an earlier post, the Webview's DOM isn't accessible by the host app, for many good reasons, so it seems you're left with solutions like obtaining a bitmap of the Webview and printing that.

But there's another way that can work in a number of scenarios, especially when you know the content you're loading into the Webview and aren't wanting to print arbitrary pages. The trick is to load that content into a new document fragment and use that to obtain a source:

    //content is what you load in the Webview; printTask and printDeferral come from the WinRT print event

    var fragment = document.createDocumentFragment();
    var printSource;
    div = document.createElement("div");

    fragment.appendChild(div);
    WinJS.Utilities.setOuterHTMLUnsafe(div, content);

    source = MSApp.getHtmlPrintDocumentSource(fragment);
    printTask.setSource(source);
    printDeferral.complete();

You new methods like setOuterHTMLUnsafe had a use somewhere!


When you have a Webview hosting an iframe element, it's possible to monitor what's going on in the iframe using the MSWebViewFrame* events, which are documented with the x-ms-webview element. These are MSWebViewFrameNavigationStarting, MSWebViewFrameContentLoading, MSWebViewFrameDOMContentLoaded, and MSWebViewFrameNavigationComplete.

In the event you have multiple iframe elements in a webview, the way to distinguish between frames is with the e.uri property, where e is the event args object for the event in question. This property is presently undocumented, but should be–this comes directly from the engineers who built the webview, so we can trust that it's there!

Generally speaking, the content of a Webview is generally a black box from the host app's perspective, and for this reason you can't get into the Webview's DOM, you can't get element references (e.g. to an iframe), and so on. There'd be serious overhead to go that route.

Which brings us to the question of what happens when code within an iframe or Webview crashes. You've certainly seen some of those sites–the ones that cause the browser to pop up debugging messages about JavaScript exceptions and whatnot. Overall, crashes in a Webview or iframe should not crash the host app.

However, there is the possibility that long-running scripts within whatever web page you're hosting are taking so long that your app is considered to be unresponsive. Those are messages you've seen in the browser as well, and if the app gets blocked on the same kind of script, it's possible the Windows will take the app down. This is a known issue that might be addressed in future releases of the operating system. At present, you can consider watching the Webview/iframe NavigationStarting and setting up your own timeout so you can catch an unresponsive site before Windows takes down the app.


I've seen the question come up on occasion about using WinJS within a webview. This is entirely supported, and has been since the introduction of WinJS–the library always checks whether WinRT is present and adjusts itself accordingly. For example, if WinRT is available, then it will use WinRT app data for saving its settings; if WinRT isn't available, it uses standard HTML5 APIs instead.

This strategy wisely foresaw the day when WinJS was licensed for use in web page. This wasn't originally the case (as the copyright headers in the WinJS files made clear), but with WinJS going open source in April 2014, WInJS can be used anywhere.

When using WinJS, and especially WinJS controls, inside a webview or web page, it's important to remember steps that are included by default within the Windows app templates, most notable the step of calling WinJS.UI.processAll. That is, when you create a new Windows app, the templates in Visual Studio supply the following default activation code:

var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;

app.onactivated = function (args) {
    if (args.detail.kind === activation.ActivationKind.launch) {
        if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
            // TODO: This application has been newly launched. Initialize
            // your application here.
        } else {
            // TODO: This application has been reactivated from suspension.
            // Restore application state here.
        }
        args.setPromise(WinJS.UI.processAll());
    }
};

Clearly, if you're using WinJS outside of an app, then the Windows.ApplicationModel.Activation namespace won't mean anything, so naturally you'll delete all the code inside the onactivated handler here. But if you delete WinJS.UI.processAll then none of your WinJS controls will show up. This can be confusing and might lead to the idea that WinJS doesn't work in a webview. But it does, because in the end WinJS is just a JavaScript library using standard HTML5/DOM to do its work. So just make sure that somewhere you have a line like this:

<script>
    WinJS.UI.processAll();
</script>

 


[For full details on working with the Windows Store, see Chapter 20 of my free ebook Programming Windows Store Apps with HTML, CSS, and JavaScript.]
 

For this final post, I wanted to provide the list of ms-windows-store URIs that you can launch for various purposes (using Windows.System.Launcher.LaunchUriAsync). These are in my book, but are good to have as a blog post:

  • ms-windows-store:PDP?PFN=<package_family_name> links directly to the app’s page; the package family name is what comes back from Windows.ApplicationModel.Package.current.id.familyName.
  • ms-windows-store:REVIEW?PFN=<package_family_name> goes to the Ratings and Reviews section of the Store for your app, which is what the Rate And Review command in your Settings pane does. You can launch this URI from your app directly when inviting a review. Note, however, that there is not presently a means to determine whether the user left a rating or review.
  • ms-windows-store:Publisher?name=<publisher_display_name> Links to a page that shows all your apps, which you might do from an About pane in your Settings. The publisher name can be from Package.current.id.publisher.
  • ms-windows-store:Updates opens the Store’s updates page (no arguments). You can use this when you detect that the user is running an older version
  • of your app, which suggest they’ve opted out of auto-updates.
  • ms-windows-store:Search?query=<search_string> executes a search in the Store.

[For full details on working with the Windows Store, see Chapter 20 of my free ebook Programming Windows Store Apps with HTML, CSS, and JavaScript.]

 

Q. I want to have my app load and show in-app purchase listings, but until the app is in the Store, such listing information won't be available. As a result, my app will look non-functional and could fail certification. What can I do about that?

A. The right approach is to remember that Windows.ApplicationModel.Store.CurrentApp.LoadListingInformationAsync is not ever guaranteed to work. Having no listing information in the Store is one case where it would fail, but so is lacking connectivity. Therefore you should always write your code to fail gracefully is no in-app purchase listings can be obtained. Arik Cohen of the Store team suggests these approaches:

  • Manage your list of in-app purchases in your own service (or have the list built into the app) and use the ListingInformation only for pricing.
  • Don't show the prices within your app
  • Show the purchases as presently unavailable and suggest the user checks back later.

Know too that the unavailability of ListingInformation doesn’t mean that you don’t have in-app purchase information; CurrentApp.LicenseInformation maintains a local cache of all durable in-app purchases that the user has made.

Gracefully handling the case when you're unable to retrieve in-app purchase listing information should avoid any problems in certification.

 

Q. Is there a way to add or edit in-app purchases to an app that is currently published without having to submit a new build of the app?

A. To change the listing information you always have to submit an update, but you don't have to upload a new app package or change the app's version number. And because you're not changing the package, certification should be quick.

To avoid having to resubmit, you'll need to manage your own in-app purchase catalog, which enables you to generate your list of available purchases dynamically. For more details, see Chapter 20 of (my free ebook) Programming Windows Store Apps with HTML, CSS, and JavaScript, in the section "Handling Large Catalogs" starting on page 1145.


[For full details on working with the Windows Store, see Chapter 20 of my free ebook Programming Windows Store Apps with HTML, CSS, and JavaScript. Note also that CurrentApp refers to Windows.ApplicationModel.Store.CurrentApp for convenience.]
 

Q. Why does CurrentApp.GetProductReceiptAsync return a not implemented exception for a Windows Store app?

A. This API is not implemented for Windows, just for Windows Phone. Windows Store apps should use the CurrentApp.GetAppReceiptAsync API and examine the in-app purchase receipts contained within it. (In short, this is one area of non-convergence with universal Windows apps at present.) 

 

Q. Can an trial version of an app provide in-app purchases?

A. No, by design the CurrentApp.RequestProductPurchaseAsync API does not work when the app is running under a trial license if the app is paid. The API can be invoked, but will fail. However, if the app is free, then in-app purchases will work (see the next question).

This is important to understand when testing an app with the CurrentAppSimulator: by default, the simulator assumes a trial version, so CurrentAppSimulator.LicenseInformation.isTrial will be true and in-app purchases won't work. To fix this, make sure your WindowsStoreProxy.xml file contains the following:

<LicenseInformation>
  <App>
    <IsActive>true</IsActive>
    <IsTrial>false</IsTrial>
  </App>
  …
</LicenseInformation>

Q. I have a free trial app in the Windows Store with features that turn on when the full app is purchased. Can I change this to a free app (no trial) with in-app purchases?

A. Then question here is reall about handling the transition between licensing states, that is the information provided by CurrentApp.LicenseInformation. Prior to the app update, you'll have users with two possible states with the desired transition logic:

  • LicenseInformation.isTrial= true : convert to non-trial (full) version with no-in app purchases
  • LicenseInformation.isTrial = false : turn on licenses for in-app purchases that match the paid version.

When the update happens, it's important to note that the trial state of the all (isTrial) will continue to be true, but because the app is now free, in-app purchases will work properly. In this case, then, the app wouldn't bother to make any differentiations between trial and non-trial; that is, the updated app wouldn't ever check the isTrial flag at all.

The trick is then differentiating new installs of the app, which will have isTrial = false and isActive = true, from those who previously purchased the app and for whom these flags have the same values. You'll need another mechanism, then, other than the LicenseInformation itself, to differentiate the upgrades. 

This is straightforward to do. The best way is to CurrentApp.GetAppReceiptAsync to retrieve the app purchase receipt and check the receipt date against when you made the conversion. Any customers who purchases the app prior to that date were ones who paid for the license and should thus be granted all the rights that you otherwise now only grant through in-app purchases. Thus in your code to enable features, you would check that either (a) the appropriate in-app purchase license is set or (b) a previous purchase was made.

 

Q. I'm having trouble getting my licensing logic to work correctly; what's the best practice for checking license states?

A. The most reliable place to put your licensing logic is inside a handler for CurrentApp.LicenseInformation.LicenseChanged event. If you consolidate everything here, then you naturally handle any change made through purchase APIs, as well as trial expirations and other license-affecting events. You can check specific license flags after one of the async purchasing APIs completes, but as those should invoke LicenseChanged it's much cleaner to keep everything in the event handler.


I have a few bits related to the Windows Store and apps that I thought I'd share this week and next as a kind of Q&A. (And if you're curious why I like Q&A formats, it's because I collect a lot of answers from developer questions I see on different forums, and then consolidate related ones here.)

[For full details on working with the Windows Store, see Chapter 20 of my free ebook Programming Windows Store Apps with HTML, CSS, and JavaScript.]

 

Q: Is there a way to persist unique data for an app after it's uninstalled? Put another way, how can an app save a piece of data (like an ID) so that it knows it was previously installed on a particular device?

A: Some background first. As you might already know, when a Windows Store/Phone app is uninstalled, all of its app data is also uninstalled. Roaming data lives on in the cloud for a time even if the app is uninstalled from all of the user's devices, but nothing remains on the device itself. So you can use roaming data for the purpose in the question, but after some time (like 30 days) the roaming data might disappear. Roaming data, in other words, is reliable only if you want to save user-specific data so long as the app is installed on at least one device.

Although you could consider saving something as user data–which would require asking the user to pick a location through the file picker–that would be clumsy and end up polluting user data areas with stuff that doesn't make sense to the user directly.

The only alternative, then, is to store that data in the cloud (a table within Azure Mobile Services comes to mind here) indexed by some kind of per-user app-specific identifier so it can be precisely retrieved later on. (This is, in fact, the scenario that prompted the question: the developer wanted some unique ID for a guest account to which to associate in-app purchases that did not go through the Store itself.) This leads to the next question.

 

Q: Where can I get a unique per-user per-app identifier that's unique across devices for the same user? And what about a device-specific identifier?

A: There are good answers to both of these questions. For the latter, a device-specific ID, also know as an App Specific Hardware ID (ASHWID), ca be obtained from the Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken method (Windows 8 and Windows Phone 8.1; for Windows Phone 8, try HostInformation.PublisherHostId). For additional details on this API, refer to also Guidance on using the App Specific Hardware ID (ASHWID) to implement per-device app logic.

OK, that was easy–what about a per-user ID? For this one, use the App Receipt ID available through the Windows Store API, namely Windows.ApplicationModel.Store.CurrentApp.GetReceiptAsync. This returns you a piece of XML from which you'll need to parse the AppReceipt > Id property, a process that's straightforward with the XmlDocument class in WinRT:

Windows.ApplicationModel.Store.CurrentApp.getAppReceiptAsync().done(function (receipt) {
    var doc = new Windows.Data.Xml.Dom.XmlDocument();
    doc.loadXml(receipt);
    var appReceipt = doc.getElementsByTagName("AppReceipt");

    if (appReceipt != null && appReceipt[0] != null) {
        console.log("AppReceipt.Id = " + appReceipt[0].getAttribute("Id"));
    }
});

Again, the AppReceipt ID will be unique per user across all installations on all devices, which includes universal Windows apps in Windows and Windows Phone where those apps share the same package family name.  

Remember that the ASHWID is unique for a device, but not for multiple users of that device, so if you want a per-user and per-device ID, you'll need to combine the user-specific ID from the app receipt and the ASHWID.

 

Q; Speaking of uninstallation, are old versions of an app still available in the Store? That is, if I uninstall and app and then it gets updated in the meantime, can I install the version I previously had?

A: No, only the current version of an app is maintained in the Store. If you uninstall and reinstall, you'll get the latest version.



A question on the MSDN JavaScript apps forum recently asked why the app data APIs were in Windows.Storage.ApplicationData whereas the app's package folder property is off in Windows.ApplicationModel.Package. I responded with the following comments, which Howard Kapustein confirmed (he did much of this wrangling early on).

I don't know the exact history (this would've been taking place in early 2011) but I imagine it could've gone either way and someone eventually had to make a decision. Generally speaking, Windows.ApplicationModel has package information along with a bunch of APIs that deal with app-to-app communication, contracts, activation, suspend/resume, and background tasks. Windows.Storage, on the other hand, has everything to do with the file system.

Because appdata folders are probably more closely aligned with the file system than with the "app model" stuff, I can see why Windows.Storage was the landing place. After all, that's where you find all the other file I/O APIs, and I can imagine that if the ApplicationData APIs were in Windows.ApplicationModel, we'd be having the same question about why they weren't in Windows.Storage. :)

I would guess that there was probably an argument for putting the package information classes into Windows.Management.Deployment, which is probably it's most natural home. However, the rest of the APIs there are desktop-only and not accessible to Store apps, so it made some sense to put the Package class elsewhere. I expect this decision was probably made well after the decision to put ApplicationData into Windows.Storage.

It's also worth noting that the appdata folders are not technically part of the package, so it's really the installedLocation property that's the aberration. The rest of the Package and PackageId properties come from the Store and describes the package characteristics more than runtime state. Thus installedLocation just so happens to be the link between all the package info and the file system.

In the end, I think the structure that we have actually makes the most sense, because when you start talking about appdata you automatically end up in Windows.Storage.

Knowing the guys in API naming team that bandied all this kind of stuff about (guys like Harry Pierson, Jason Olson, and Brent Rector–and now I can add Howard Kapustein as well), I expect that they discussed all these pros and cons before making a decision. Howard describes it as "sausage making" if you want a great visual image!