Introduction
In my previous article Creating Pocket PC Application Setup Packages with Cabwizard 1 we saw how to use Cabwizard utility to create application setup files. While the installation / uninstallation of application is in progress we might need to do custom actions like delete some files, add a new entry to today screen etc. These actions cannot be specified in the application cab files generated as they are executed when the installation / uninstallation of application is taking place. In these cases we can write a DLL, integrate it with cab files generated. The DLL will be invoked during installation and uninstallation of the application. This article discusses how to create this DLL and integrate it with the application cab files.
At the end of this article you will know
- What is the need for implementing Custom actions in cab files?
- How to integrate custom actions with cab file?
Prerequisites
Tools needed:
What is a custom action?
A Custom action is a piece of code executed during the installation / uninstallation process of a application.
What is the need for Custom actions during application installation / uninstallation process?
- Cleanup of files created by Pocket PC application
- Installing external or runtime libraries like .NET Compact Framework required for proper functioning of Pocket PC application
- Executing external applications
Example Case study:
Assume there is a pocket pc application which gives options to add / modify / delete / view data from database. The database is getting created when you first start the application. You start the application, populate data, manipulate it and view the data. But when you uninstall the application from the device, the application doesn't uninstall properly. You get a message telling that some files were not removed.
Why? Because of the database file the application created when it was first started. Whatever files which are copied or created when the application installs to the device will get automatically deleted (except when they are shared files like COM objects) when the application is uninstalled from device. But the files or databases or things like log files which are created after the application gets installed or during runtime doesn't get deleted. In this scenario we can use custom actions to accomplish these cleanup tasks.
When can we execute Custom actions?
- Before installation process starts
- After installation process ends
- Before Uninstallation process starts
- After Uninstallation process ends
So basically in VB terms, we will be writing event handlers for these events and attaching the code to cab files.
Who executes the custom actions?
These event handlers will be called during the installation / uninstallation process by WCELOAD.exe which executes the .cab files These event handlers can be written only in a WIN32 or MFC DLL and integrated with the cab files. Please note that this cannot be implemented using .NET CF. There are four event handlers or functions which need to be exported from DLL
Install_Init
Install_Exit
Uninstall_Init
Uninstall_Exit
As the names suggest,Install_Init()
gets called before installation process starts. Install_Exit()
gets called after installation process gets over. Uninstall_Init()
gets called before uninstalltion process starts and Uninstall_Exit()
gets called after the Uninstallation process gets over.
How to implement custom actions with cab file:
We will see how to implement custom actions with cab files through a example. The following are the sub steps which need to be implemented for the example.
- Creating a simple EVB application
- Generating the setup package of EVB application using Application Setup wizard
- Creating a WIN32 DLL containing the custom code to be called during installation and uninstallation
- Integrating the DLL with the cab files generated.
Creating EVB application
- Open EVB and create a new Pocket PC 2002 project named TestApp
- Set the ShowOK property of Form to true
- Include SQL CE, ADOCE 3.1, ADOXCE libraries by selecting Project => References.
- Add a Command Button to the form, set name property of Command Button to 'cmdcreate'
-
In the click event of button include the following code
Private Sub cmdcreate_Click()
On Error Resume Next
Dim objcatalog As ADOXCE.Catalog
Dim strconn As String
Set objcatalog = CreateObject("ADOXCE.Catalog.3.1")
strconn = "Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0; data source="
& App.Path & "\test.sdf"
objcatalog.Create strconn
If Err.Number <> 0 Then
MsgBox Err.Number & " : " & Err.Description, , "error"
Else
MsgBox "database created"
End If
Set objcatalog = Nothing
End Sub
- Select File = > Make TestApp.vb. Now the EVB application is ready.
Generating the setup package of EVB application using Application Setup wizard
- Select Tools => Remote Tools => Application Install Wizard
- Follow the steps in the wizard
Creating a WIN32 DLL containing the custom code to be called during installation and uninstallation
- Start EVC++ and create a empty WCE Dynamic Link library project named 'setupdll'
- Add a header file 'ce_setup.h" to the project. This header file contains the declarations of the 4 functions mentioned above and is normally located in \Windows CE Tools\wce300\Pocket PC 2002\include subdirectory of path where you have installed the Pocket PC SDKs. Copy the file to your project directory and include it in the project workspace by selecting Project => Add to Project => Files and selecting the file.
- To add source files select File => New => C++ source file. give the name as 'setupdll' in the Filename field and click ok button. A new file named 'setupdll.cpp' will be created and included in the project workspace.
-
Include the following code in the .cpp file
#include <windows.h>
#include "ce_setup.h"
codeINSTALL_INIT Install_Init(HWND hwndparent,
BOOL ffirstcall,BOOL fpreviouslyinstalled,LPCTSTR pszinstalldir)
{
return codeINSTALL_INIT_CONTINUE;
}
codeINSTALL_EXIT Install_Exit(
HWND hwndparent,LPCTSTR pszinstalldir,
WORD cfaileddirs,WORD cfailedfiles,WORD cfailedregkeys,
WORD cfailedregvals,
WORD cfailedshortcuts)
{
return codeINSTALL_EXIT_DONE;
}
codeUNINSTALL_INIT Uninstall_Init(
HWND hwndparent,LPCTSTR pszinstalldir)
{
WIN32_FIND_DATA findfiledata;
HANDLE hfind;
TCHAR pszfilepath[50];
memset(pszfilepath,0,sizeof(pszfilepath));
wcscpy(pszfilepath,pszinstalldir);
wcscat(pszfilepath,TEXT("\\test.sdf"));
hfind = FindFirstFile(pszfilepath,&findfiledata);
if(hfind != INVALID_HANDLE_VALUE) {
DeleteFile(pszfilepath);
}
return codeUNINSTALL_INIT_CONTINUE;
}
codeUNINSTALL_EXIT Uninstall_Exit(HWND hwndparent)
{
return codeUNINSTALL_EXIT_DONE;
}
- Now we have added the code for the DLL. Inside Uninstall_Init() which gets called when uninstallation process starts we are checking for the existence of the database file and if it exists we are deleting it. the DLL.
-
To make the functions accessible from external applications we need to make them public. This process is called 'exporting'. For that create a .def file by selecting File = > New = >Text File. Give the name as setupdll.def and press ok. The .def file contains the functions or symbols exported by the DLL. Include the following lines in the file.
EXPORTS
Install_Init
Install_Exit
Uninstall_Init
Uninstall_Exit
- Compile the DLL for ARM and X86 platforms by selecting Build => Build setupdll.dll. Set the respective platforms for which DLL is compiled by selecting Build = > Set Active Configuration.
Integrating the DLL with the cab files generated:
We now have to integrate the DLL with the setup package. The Cabwizard generates the setup package by reading the .inf file. We will edit the .inf file, include the path of the setup dll in the .inf file and again invoke Cabwizard utility with this .inf file as argument to generate setup packages. Here are the steps to follow for integrating the setup dll with cab files
- Navigate to directory where setup files are generated. If the setup package has generated correctly the directory will have following sub directories App, Arm 1100 (4K) v3.00, I486 (4K) v3.00, CD1 and following files Readme.txt, TestApp.inf
- Copy the DLL files compiled for ARM and X86 platforms to Arm 1100 (4K) v3.00 and I486 (4K) v3.00 directories respectively.
- Open the TestApp.inf file and remove the following sections [CEDevice.I486 (4K) v3.00] and [CEDevice.Arm 1100 (4K) v3.00] from the .inf file. If these sections are present, the cab files will not get executed in Pocket PC emulator.
- Navigate to [DefaultInstall] section and insert the key/value CESETUPDLL="setupdll.dll" before other keys. By this entry we are specifying to execute custom actions from setupdll.dll
- Now we have to give path details of DLL. For that add a entry setupdll.dll=3 at end of [SourceDisksFiles.I486 (4K) v3.00] and [SourceDisksFiles.Arm 1100 (4K) v3.00] sections.
- Add a entry setupdll.dll,,0x80000000 at end of [Files.I486 (4K) v3.00] and [Files.Arm 1100 (4K) v3.00] sections
For more details regarding .inf file please refer to my previous article
Thats all. .inf file is ready. Now we have to invoke Cabwizard utility with the .inf file as argument. For that open the Readme.txt file. As given in the file copy the command line text in command prompt and execute it. If everything goes well the cab files should be generated in the directory where the setup files are created by Application Install Wizard utility. Copy the cab files to CD1 folder.
Testing the .cab files
Now to see whether the setup dll is being called. In case of testing in the Pocket PC device just execute the setup.exe file in CD1 directory and cab files generated for ARM platform are automatically copied to device and executed. . In case of Pocket PC emulator copy the cab file generated for X86 platform and execute the file. The application gets installed. Invoke the EVB application. create the SQL Server CE database by clicking on the 'create' command button and close the application. Now select Start Menu => Settings => System => Remove Programs and click on TestApp application and click the Remove button. The application gets removed cleanly. Our Custom action code executes before uninstallation process deleting the database file.
Conclusion
So we saw how custom actions can be integrated with .cab files making our application install package even more powerful and feature oriented. Hopefully in my next article we will see how to integrate custom COM DLLS into cab files. Please give your valuable suggestions on this article.
References