The title of this article is perhaps a little misleading. Everybody who has developed Managed Applications for Windows Mobile Devices knows that it takes some time until the application is up and running. Amongst others, this is caused by the fact that the Common Language Runtime (CLR) needs to be initialized, assemblies need to be loaded and, in order to execute, quite a few methods need to be JIT’d.
In this article, you will learn how to create a small native application that can start a managed application programmatically. While the managed application is starting, the native application can for instance display a splash screen to the user. As soon as the managed application is fully initialized, it can programmatically terminate the native 'starter' application.
This simple managed application takes a little over a second to start.

If you take a look at Remote Performance Monitor for a simple ‘Hello, World’ application, you will see that it takes a little over a second to start the application. This sample application is simply measuring the time from the moment it enters the Main entry point until the time the one and only form in the application is visible. Taking a closer look at some values recorded with Remote Performance Monitor (after the initial run in which RPM was disabled, because RPM itself causes a performance penalty of around 10%), you can see that the JIT Compiler and the Loader have been very active to get the application up and running.
| Category |
Name |
Value |
Description |
| JIT |
Native Bytes Jitted |
75368 |
The count of bytes of native code generated by the JIT compiler. |
| JIT |
Methods Jitted |
243 |
The count of methods generated by the JIT compiler. |
| Loader |
Classes Loaded |
301 |
The count of classes that have been loaded across all App Domains. |
| Loader |
Methods Loaded |
485 |
The total count of methods loaded across all App Domains. |
| Loader |
Assemblies Loaded |
5 |
The count of assemblies that have been loaded across all App Domains. |
| Loader |
App Domains Created |
1 |
The count of App Domains created in the process. |
A native application, written in C++, will start much faster. In fact, it only takes about 10% of the time to start a comparable simple managed application. Again, the time is measured from reaching the main entry point until the moment the one and only window of the application becomes visible.

Of course, the native application is already compiled to executable code, so it can start immediately, an important reason why it is starting much faster than the managed application. Once an application is up and running, the performance difference between a managed application and a native application is not that noticeable anymore. A native application will still execute faster, but, especially if the managed application calls methods that are already JIT’d, its performance will be close to that of the native application. If there is a way to start the managed application a bit faster, the end user will have a better experience when running our application, especially if the managed application has functionality beyond “Hello, World” and thus takes even longer to start.
Even though there are a few things you can do inside a managed application to start it faster, like delay loading assemblies that are not immediately needed or for instance by making use of a splash screen to initialize the application in the background while the user is already experiencing some activity in the application, the initial 1 second starting time is something you can’t do much about. So what if you would be able to combine the starting speed of a native application with the developer productivity of a managed application? The overall performance of the application will even be slower, because now two different processes must start, but for the end user it seems that the application is starting very fast. Here is an approach you can take for your own managed applications.
-
Create a very simple native application (for instance by taking a typical ‘Hello, World’ application as starting point).
-
Inside the native application you can show a splash screen, maybe even show some progress about the starting managed application.
-
Use the native application to start your real (managed) application by calling the CreateProcess API, passing the name of the managed application.
-
Once the managed application is initialized, it can kill the native application that was used to start it.
If you deploy the native starter and the managed application to the same folder on the device, and create a shortcut to the native starter application that shows up in the Programs menu on the device, this slightly more complex way to start a managed application is completely transparent for the end user. Especially if you make use of a CAB installer to install the application on the device, with the CAB installer taking care of properly setting up the application and its starter.
The native starter in the following picture shows a full screen window. As you can see, the time to start this native application is slightly longer than the original ‘Hello, World’ application, but it still starts very fast. In this sample, its only responsibility is starting a managed application, which needs almost 10 times as long to start, with the difference that the end-user sees immediate action. The native application in this sample only shows a blank window with one text in it, but of course you could show a splash screen here. Once the managed application is up and running, it becomes visible and it terminates the native starter application.

To create the native starter application, you can simply create a new native application in Visual Studio 2008. Simply select a typical ‘Hello, World’ application. You can remove a lot of the code in this auto generated application. For instance, it does not need to have a menu, nor an about box. It needs to display itself in full screen mode and it is responsible to start the managed application. When starting the managed application, it passes its own Window Handle to the managed application to allow the managed application to terminate the native starter.
Here is the implementation of the main function of the native starter. As you can see, the current time at the moment of application start is stored. Besides that, an application instance is initialized and the main message loop is entered.

The interesting part of the native starter is the Windows Procedure, in which the managed application is started and where the native starter’s window is switched to full screen. In the sample, the WM_PAINT message is only responsible for displaying the time it took to show the application on the device. In a real starter application, you can use the WM_PAINT message to display a splash screen. You can even make it fancier by for instance showing some sort of a progress indicator in combination with a WM_TIMER message. In this sample, the first WM_PAINT message triggers the code to start the managed application. This approach is taken to make sure that the native starter is visible before we try to start the managed application. To start the managed application, the native application posts a WM_USER message to itself. The code that handles the WM_USER message first determines the path from which the native starter is invoked. It assumes that the managed application to start can be found at the same location. It then calls the CreateProcess API to start the managed application, and it passes its own Window Handle to the managed application. To display the Window of the native starter in full screen, some code is available in the WM_ACTIVATE message handling. The size of the desktop is used to resize the native starter application’s window. This is all the logic there is to create the native starter application. Of course this code can be extended to make it more interesting and to give the starter application more functionality.

To store the native starter at the same location as the managed application it needs to start, you can modify the project properties of the native starter application. Just modify its deployment settings to point to the same folder where the managed application will be deployed.

If you want to debug the native starter application, you also need to inform the debugger where the native starter application is deployed. This can also be done through the project properties of the native starter application by setting the path to the remove application to match the path that you just set in the deployment properties.

In the managed application that is started by the native starter, we also need to make a few small modifications. Again, the starting point for this sample application is a simple ‘Hello, World’ application. It displays one single form that contains a label in which the startup time for the managed application is displayed. The first thing you need to do is modify the program.cs file of the managed application slightly, since the native starter passes its own Windows Handle as a command line argument. Here is the modified Main method of the managed application.

As you can see, the command line argument is passed to the constructor of the form if it is available. If no command line arguments are available, we just pass an empty handle. In that way, the managed application can both be started through a native starter application or directly on the device by the user.
Once the managed application is up and running, it needs to terminate the native application. Since the managed application has the handle to the native starter application, it can easily do so by sending a message to the native starting application. To create a better viewing experience for the end user, the managed application also makes sure to hide the native starter application when it tries to terminate it. This guarantees that the native starter window is immediately replaced by the managed main window on the device, without the device’s desktop being visible for a split second.
Here is the complete code for the form of the managed application that can be activated through the native starter.

As you can see, the native starter is only terminated when there is a valid Window Handle available to it inside the managed application. The sample code has some limitations. The starter application does not display a splash screen, but an empty screen. Also, no code is provided to prevent multiple instances of the starter application to be activated by the user. You can of course extend the sample code to add this kind of functionality.
The sample code consists of one single solution that contains both the managed application and the native starter application. You can download the sample code here. Feel free to play with it, modify it and create your own, superfast starting managed applications, making use of the approach that is described in this article. |