Enable In-App Product Purchases for Desktop Bridge Converted Desktop Applications

Desktop Bridge helps developers gradually migrate traditional apps to the Universal Windows Platform (UWP). The In-App Purchase (IAP) in Windows Store is an important scenario to monetize the converted apps. When working with developers on this scenario, I notice certain obstacles are in common,for example:

a. Porting old .Net or unmanaged applications to use the IAP UWP APIs.

b. Didn’t use async calls properly in UI apps and caused hang/deadlock

c. Default purchase windows failed to popup

d. Need accurate guide to follow IAP testing with current Windows Store APIs

Here I would like to explain a general solution to solve above issues, and also show four samples to use the IAPWrapper quickly:

a. WinForm in old .Net version

b. WPF app

c. Win32 App in C++

d. Unity App in old .Net version

All sample codes can be got from: https://github.com/appconsult/IAPWrapper

Many converted Win32 Desktop apps were developed in unmanaged code or old .NET version which cannot directly call current UWP Store APIs, in order to eliminate this gap, I create an .Net IAP Wrapper library. This wrapper will finally leverage DLLEXPORT nuget package to export function entries, which can be used by different kinds of Apps easily.

Create an IAP Wrapper Project:

1. Create a Win32 .NET class library project. The target frame work can be 4.6.1. I uses VS2017 as a quick start.

2. Add two references to allow this Win32 dll calls UWP APIs and async/await properly:

C:\Program Files (x86)\Windows Kits\10\UnionMetadata\Windows.winmd

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework

\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll

3. Add statements to use necessary namespaces:

clip_image002

4. Follow this guide to call a StoreContext object in class library project that will be uses the Desktop Bridge:

https://docs.microsoft.com/en-us/windows/uwp/monetize/in-app-purchases-and-trials#using-the-storecontext-class-with-the-desktop-bridge

In Converted Win32 Desktop App, it needs to configure the StoreContext object to specify which application window is the owner window for modal dialogs. The functional sample code is:

clip_image004

clip_image006

clip_image008

5. Install DLLExport nuget package to the project:

clip_image009

After installed the nuget package, you may see a setting dialog box pups up, can refer to this picture to configure (name space is still IAPWrapper here):

clip_image011

For more details of DLLExport, please refer to:

https://github.com/3f/dllexport

6. Add one statement to declare DLLExport on top of the Purchase (string storeID) method:

clip_image012

7. Use X86 or X64 option to build the library.

Note: AnyCPU option doesn’t give me the expected exported function entries.

If I build it in X64 option, using “dumpbin iapwrapper.dll /exports” can see the “Purchase” is listed in export section

clip_image013

This means we can load the library and function address to call it directly.

If build it in AnyCPU configuration option, the export function will not show up:

clip_image014

8. After above steps, we will get the IAPWRAPPER.dll, now can use it easily in various scenarios.

For all scenarios, please avoid below known issues:

1. Don’t call Task.Wait, this will cause UI apps deadlock issue. For detailed info, refer to: Async/Await – Best Practices in Asynchronous Programming https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

2. Don’t run app with admin privilege, otherwise may not see the purchase diaglog box popup.

3. Make sure the purchase option runs in the UI thread, refer to:

https://docs.microsoft.com/en-us/uwp/api/Windows.Services.Store.StoreProduct

clip_image016

4. The store ID used as parameter is the 12 characters of your add-on on your developer portal, not product display name.

Use IAPWRAPPER in .Net 2.0 Winform app

1. Add DLLImport statement and call the Purchase function:

clip_image017

2. Build the app, and put IAPWRAPPER.dll into the output folder. Run the app, and trigger the purchase, we can see default purchase windows pops up (depends on your account setting, authentication window may occur as well,):

clip_image019

clip_image021

Use IAPWRAPPER in .Net 4.6 WPF app

1. Add DLLImport and call purchase function:

clip_image022

2. Build the app, and put IAPWRAPPER.dll into the output folder. Run the app, it will show up the same purchase window.

Use IAPWRAPPER in C++ Win32 app

1. Use LoadLibrary and GetProcAddress to

clip_image024

2. Run the app, it will show up the same purchase window.

Use IAPWRAPPER in UNITY Win32 app

1. Put IAPWrapper into the Assets\Plugins folder

2. Add DLLImport and Purchase function as below:

clip_image025

3. Build the app as Win32 app, and run it.

Here I mainly explained how to quickly integrate the essential Windows IAP function to different kinds of Win32 Apps. You may expand your IAPWrapper for more specific usage scenarios, checking licensing, trail status, enumerate add-ons, etc. Can refer to:

https://github.com/Microsoft/DesktopBridgeToUWP-Samples/tree/master/Samples/StoreSample

After completing above tasks, please follow the 5 bullets exactly to ensure your applications are ready for IAP and Store function tests:

https://docs.microsoft.com/en-us/windows/uwp/monetize/in-app-purchases-and-trials#testing

Thanks,

Freist Li

(20)

How to fix “Invalid Package Identity Name” error when submit Desktop Bridge (Centennial) converted application to Windows Store

After successfully converted Win32 app with Desktop Application Convert, and passed Windows Application Certificate Kit test, you may still meet this kind of error message when submit this app to Windows Store:

Invalid package identity name: MyTestApp (expected: 38323MyAccount.MyTestApp)Invalid package family name: MyTestApp_xx232xxxxxxxx (expected: 38323MyAccount.MyTestApp_ xx232xxxxxxxx)

This is because the PackageName was not set correctly when converting the app with DAC. Try using below command pattern to solve this issue:

DesktopAppConverter.exe -Installer D:\Release -Destination d:\output -PackageName “38323MyAccount.MyTestApp -Publisher “CN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx” PackagePublisherDisplayName “My Account” -PackageDisplayName “MyTestApp” -AppDisplayName “MyTestApp” -AppID “MyTestApp” -Version 1.0.0.0 -makeappx -AppExecutable “MyTestApp.exe” -packagearch x86

Thanks,

Freist

(39)

How to resolve this DAC error [cannot set "Executable”, because only string can set XmlNode attribute]

When application folder contains “App.Publish“ folder [ClickOnce output folder], and run the Desktop Application Convert with similar command:

DesktopAppConverter.exe -Installer c:\release\output -Destination c:\result -PackageName “yourapp” -Publisher “CN=xxxxxxx-xxxx-xxxx-xx-xxxxxxxxxxx” -Version 1.0.0.0 -appid “yourapp” -makeappx -AppExecutable “yourapp.exe” -packagearch x86

you will meet this kind of error in the DAC log:

[2017-08-16T16:21:26] An error occurred converting your application. Here is the full error record:

[2017-08-16T16:21:26]

PowerShell Error Record:

[cannot set “Executable”, because only string can set XmlNode attribute]

無法設定 “Executable”,因為只能使用字串值設定 XmlNode 屬性。

PowerShell Stack Trace:

位於 SetExecutable,C:\Program Files\WindowsApps\Microsoft.DesktopAppConverter_2.0.2.0_x64__8wekyb3d8bbwe\manifest\Manifest.ps1: Line 517

To solve this, please remove the “App.Publish“ folder, which contains the executable exe and confused DAC.

Thanks,

Freist

(14)

How to enable bridge desktop Unity App (lower .Net version app) with latest IAP APIs for Windows Store

1. Create C# class library and follow this link to create purchase method:

https://docs.microsoft.com/en-us/windows/uwp/monetize/in-app-purchases-and-trials#desktop

here is the sample code:

public static string PurchaseAddon (…..)

{
     ….
     purchase(o);
     ….

}

static async void purchase(object o)
{  
    
     IInitializeWithWindow initWindow = (IInitializeWithWindow)(object)storeContext;
     var ptr = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
     initWindow.Initialize(ptr);   
     var result = await storeContext.RequestPurchaseAsync((o as PurchaseObject).Productid);
     if (result.ExtendedError != null)
     {
        MessageBox.Show( result.ExtendedError.Message,result.ExtendedError.HResult.ToString());
     }
      switch (result.Status)
     {
         …..
      }          
}

2. Install DLLExport nuget, and claim [DllExport] in the C# project:

image

3. In Unity script, import the above library:

[DllImport(“IAPWrapper”)]
    extern static IntPtr PurchaseAddon (….);

4. Exactly follow below five steps to test IAP:

https://docs.microsoft.com/en-us/windows/uwp/monetize/in-app-purchases-and-trials#testing

Important: The RequestPurchaseAsync must be raised from UI thread, refer to https://docs.microsoft.com/en-us/uwp/api/Windows.Services.Store.StoreContext

Thanks,

Freist

(36)

Get Rid of “The image file <…Tile.scale-400.png> must be smaller than 204800 bytes.” from WACK Report

When using Desktop Converter to auto produce APPX package, you may notice even the image file’s size is small enough in your app packagefiles folder, however the output APPX is still failed on WACK checking on image file size part, just similar to this error:

“The image file “AppMedTile.scale-400.png” must be smaller than 204800 bytes.”

To solve this:

1. Make sure the image file’s size is small enough in your app packagefiles folder (\PackageFiles\Assets), if not, use mspaint or other tool to reduce the picture size.

2. Get latest Windows 10 SDK, run this command to manually package the app:

D:\Projects\myapp>”C:\Program Files (x86)\Windows Kits\10\bin\x86\makeappx.exe” pack /d .\packagefiles /p D:\test\myapp.appx /l

3. Run below powershell scripts to sign myapp.appx manually as well (this is for your local installation and test purpose):

cd “C:\Program Files (x86)\Windows Kits\10\bin\x86”

.\MakeCert.exe -r -h 0 -n “CN=B1XXXXXX-990F-467C-B5C2-XXXXXXA0BDFA” -eku 1.3.6.1.5.5.7.3.3 -pe -sv d:\output\3d.pvk d:\output\3d.cer

.\pvk2pfx.exe -pvk d:\output\3d.pvk -spc d:\output\3d.cer -pfx d:\output\3d.pfx

.\signtool.exe sign -a -f d:\Output\3d.pfx -fd SHA256 -v D:\test\myapp.appx

4. Now run appcertui.exe to check the myapp.appx again:

Run “C:\Program Files (x86)\Windows Kits\10\App Certification Kit\appcertui.exe”, Select Store App (it will create a report,but need you set the output path everytime), make sure the report shows PASS result:

clip_image001

Thanks,

Freist

(127)

Build Assembly-UnityScript.dll as Release version in Unity

To solve the assembly-unityscript.dll debug version issue in Unity 5.6.1f1 (you may find this cannot be changed from Unity UI Settings), please follow below steps:

1. The Assembly-UnityScript.dll is generated when using .JS as scripts, if the project doesn’t need, remove the .JS files should avoid generating Assembly-UnityScript.dll.

2. If the .JS scripts are required in the App, can refer to below steps to get a release version of Assembly-UnityScript.dll:

a. In Unity project,open temp folder,can see some file names starting with unitytemp-。Open some latest files one by one, you will see some file has below content, fo example, in this sample, I saw below strings in Temp/UnityTempFile-23f957311d4e8c441a046557e457d203:

-debug

-target:library

-i:UnityEngine

-i:System.Collections

-base:UnityEngine.MonoBehaviour

…………

-out:Temp/Assembly-UnityScript.dll

1. Remove the  -debug line and save it.

2. Open CMD, go to the project folder, run below command:

“D:\Program Files\Unity\Editor\Data\Mono\bin\mono.exe” “D:\Program Files\Unity\Editor\Data\Mono\lib\mono\2.0\us.exe”  @Temp/UnityTempFile-23f957311d4e8c441a046557e457d203

It will generate /Assembly-UnityScript.dll with release version:

Successfully compiled ‘1’ file(s) to ‘D:\Projects\Hololens\DesktopObj\Temp\Assembly-UnityScript.dll’.

Then you can use it to replace the debug version.

Thanks,

Freist

(40)

How to Monetize Desktop Bridge App with Windows Store

1. Enable UWP API support in Converted App:

a. If the payment project is above .NET 4.6.1:

Announcing “UWPDesktop” NuGet Package Version 14393

  1. b. If the payment project is lower than .NET 4.6.1, or C++, or VB, create a UWP Wrapper, and call interop functions created in the UWP Wrapper. Refer to:

https://github.com/Microsoft/DesktopBridgeToUWP-Samples/tree/master/Samples/VB6withXaml/UWPWrappers

2. Call UWP API to implement the monetize logic in the payment project:

References:

https://docs.microsoft.com/zh-cn/windows/uwp/monetize/in-app-purchases-and-trials

使用桌面桥的 Windows 桌面应用程序必须执行额外步骤来配置 StoreContext 对象,然后才可以使用此对象。 有关详情,请参阅本部分

来自 <https://docs.microsoft.com/zh-cn/windows/uwp/monetize/in-app-purchases-and-trials>

Sample code:

https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/Store

Thanks,

Freist

(50)

How to correct Publisher ID and package the converted app

Install Win 10 SDK if you don’t have:

Latest version:

https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk

Anniversary version: 

10.01.14393.033

In the AppxManifest.xml file of your converted application you will find an entry similar to the following one:

<Identity Name=”myApp”

    ProcessorArchitecture=”x64″

    Publisher=”CN=test.com

Version=”0.6.1.0″ />

The value of the Publisher attribute should match the publisher id (CN=xxxxxxxxxxxxxxxxxxxxxxxxxxxx) of the Store account of your dev center:, for example.

clip_image001

After modifying the appxmanifest.xml, please use the makeappx.exe to package the application again:

C:\Program Files (x86)\Windows Kits\10\bin\x86>makeappx pack /d “C:\myapp\PackageFiles” /p c:\Output\myapp.appx

Thanks,

Freist

(53)

How to check if Centennial App is ready

Install latest Win 10 SDK if you don’t have (till 2017 April, its version is 15063), Windows 10 should be the matched version:

https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk

Run command:

C:\Program Files (x86)\Windows Kits\10\App Certification Kit>appcert test -appxpackagepath C:\Projects\app.appx -reportoutputpath C:\Output\MyReport.xml

The MyReport.xml contains test result and you can follow it to fix known issues. Digitally signed file test, File association verbs, Debug configuration test are optional.

For more details, refer to:

https://docs.microsoft.com/en-us/windows/uwp/debug-test-perf/windows-desktop-bridge-app-tests

Thanks,

Freist

(24)

How to create certificate, sign APPX package and install certificate on Win 10

Install Win 10 SDK if you don’t have:

Latest version:

https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk

Anniversary version: 

10.01.14393.033

1. Create Certificate:

C:\Program Files (x86)\Windows Kits\10\bin\x86>MakeCert.exe -r -h 0 -n “CN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx” -eku 1.3.6.1.5.5.7.3.3 -pe -sv c:\output\my.pvk c:\output\my.cer

C:\Program Files (x86)\Windows Kits\10\bin\x86>pvk2pfx.exe -pvk c:\output\my.pvk -spc c:\output\my.cer -pfx c:\output\my.pfx

2. Sign certificate on APPX:

C:\Program Files (x86)\Windows Kits\10\bin\x86>signtool.exe sign -a -f C:\Output\my.pfx -fd SHA256 -v C:\app\app.appx

3. Double click my.cer, install Certificate to local trusted root:

clip_image001clip_image002 clip_image003

clip_image004

Thanks,

Freist

(43)