lag

lag
How To Create And Use A Setup DLL In Your Windows CE CAB File
IN THIS TASK
  • APPLIES TO
  • SUMMARY
  • MORE INFORMATION
    • Part 1: Getting Started
    • Part 2: Creating the DLL
    • Part 3: Adding the Setup DLL Code
    • Part 4: Building the DLL
    • Part 5: Adding the DLL to a CAB File
  • REFERENCES


APPLIES TO
WinCE CAB Manager

SUMMARY
This article describes how to create a "Setup DLL" for use in a Windows CE CAB file, and how to add the DLL to a CAB file using WinCE CAB Manager.

MORE INFORMATION

When deploying a Windows CE application, there are often times when the developer may wish to perform custom actions during the installation process. For Windows CE devices, this is accomplished by adding a "Setup DLL" to the CAB file used to install the application.


Part 1: Getting Started

A "Setup DLL" is simply a DLL that exports the following four pre-defined functions:
    Install_Init
    Install_Exit
    Uninstall_Init
    Uninstall_Exit
The Install_Init function is called just before the application is installed onto the device, while the Install_Exit function is called once installation is complete. Likewise, the Uninstall_Init function is called just before the application is un-installed, while the Uninstall_Exit function is called after the application has been un-installed.

There are a few important things to keep in mind when developing a Windows CE Setup DLL:

  • The DLL must be written and compiled using either eMbedded Visual C++ 3.0 or eMbedded Visual C++ 4.0.
  • The DLL must be compiled for each processor type supported by the application.
  • Since the compiled DLL is processor-specific, a separate CAB file must be created for each supported processor type.
The first step, then, is to determine which version(s) of eMbedded Visual C++ you will need to use. If the application is designed for Pocket PC 2003 or later devices, you will need eVC 4.0; for earlier devices, you will need eVC 3.0. Note that it is generally safe to install both versions, so long as the earlier version (3.0) is installed first.

Next you will need to install the Software Development Kits (SDKs) for each platform you wish to support. Some of these SDKs may be included with the eMbedded Visual Tools download, while others must be downloaded and installed separately.


Part 2: Creating the DLL

Once you have everything in place, you are ready to begin creating your Setup DLL:

  1. Open eVC and click on the 'File / New...' menu item.
  2. Make sure the 'Projects' tab is selected on the 'New' dialog, and select the 'WCE Dynamic-Link Library' option in the listbox on the left.
  3. Set the 'Project Name' to the name of the DLL you would like to create (i.e. 'SetupDLL').
  4. Set the 'Location' property to the directory where you would like to create the project.
  5. Select the CPU type(s) you would like to support, then hit OK.
  6. When you are asked what kind of DLL you would like to create, select the 'A simple Windows CE DLL project' option and click Finish, then click OK.
At this point, eVC will create the DLL project and open the workspace. By default, it will create a file named "[ProjectName].cpp", where [ProjectName] is the name you specified in step 3 above. The contents of this file should look something like this:

Code:
#include "stdafx.h"

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                )
{
    return TRUE;
}



Part 3: Adding the Setup DLL Code

Now we need to add the functions required for Windows CE Setup DLLs, as described in Part 1 above. Edit the main source file to look something like this:

Code:
#include "stdafx.h"
#include <ce_setup.h>

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved )
{
    return TRUE;
}

// Install_Init
codeINSTALL_INIT Install_Init( HWND hwndParent,
                               BOOL fFirstCall,
                               BOOL fPreviouslyInstalled,
                               LPCTSTR pszInstallDir )
{
   return codeINSTALL_INIT_CONTINUE;
}

// Install_Exit
codeINSTALL_EXIT Install_Exit( HWND hwndParent,
                               LPCTSTR pszInstallDir,
                               WORD cFailedDirs,
                               WORD cFailedFiles,
                               WORD cFailedRegKeys,
                               WORD cFailedRegVals,
                               WORD cFailedShortcuts )
{
   if( cFailedDirs || cFailedFiles || cFailedRegKeys ||
      cFailedRegVals || cFailedShortcuts )
   {
      return codeINSTALL_EXIT_UNINSTALL;
   }

   return codeINSTALL_EXIT_DONE;
}

// Uninstall_Init
codeUNINSTALL_INIT Uninstall_Init( HWND hwndParent,
                                   LPCTSTR pszInstallDir )
{
   return codeUNINSTALL_INIT_CONTINUE;
}

// Uninstall_Exit
codeUNINSTALL_EXIT Uninstall_Exit( HWND hwndParent )
{
   return codeUNINSTALL_EXIT_DONE;
}


Next we need to tell the C++ compiler to "export" these functions - that is, to make them available for external applications to call them. To do this, we need to add a "DEF" file:

  1. Click on the 'File / New...' menu item.
  2. Make sure the 'Files' tab is selected on the 'New' dialog, and select the 'Text File' option in the listbox on the left.
  3. Set the 'File name' property to the name of your main source file, except with a '.def' file extension. For example, if you set the name of your project to 'SetupDll', enter 'SetupDll.def' as the file name.
  4. Click OK to create the file and add it to the project.
Once you have created the DEF file, copy the following code into it:

Code:
EXPORTS
      Install_Init
      Install_Exit
      Uninstall_Init
      Uninstall_Exit

Now return to the main source file and add any custom code you need. (Note: A discussion of the possible custom code actions and the C++ language in general are beyond the scope of this article. Please refer to the Windows CE / C++ programming information widely available in books and on the Internet for more information.)


Part 4: Building the DLL

Once you have completed all of the preceding steps, you need to build the DLL for each platform and processor type supported by your application:

  1. Click on the 'Build / Set Active Platform...' menu item.
  2. Select the platform type you would like to build and press OK.
  3. Click on the 'Build / Batch Build...' menu item.
  4. In the 'Project configurations' listbox, select all of the 'Release' configurations. Note that you generally do not need to build the 'Debug' configurations, so it is safe to unselect those.
  5. Click the 'Rebuild All' button.
Note: Some of the Windows CE SDKs may not have the "ce_setup.h" header file in the proper place. If you see any compiler errors related to this file, use your computer's 'Find' feature to locate this file, and copy it into your Setup DLL project directory.


Part 5: Adding the DLL to a CAB File

The final step in the process is to add the finished Setup DLL to your application CAB file. Start by launching WinCE CAB Manager and creating the CAB file(s) for your application. Make sure to specify the same platform and processor type for each CAB file as you have compiled your Setup DLL for. Then simply click on the 'Cabinet / Setup DLL / Add...' menu item, browse to the location of the appropriate DLL, and click 'Open' to add it to the CAB file.

REFERENCES
Please refer to the Microsoft Mobile & Embedded Developer Center for detailed information on and download links for eMbedded Tools 3.0, eMbedded Visual C++ 4.0 and any Windows CE SDKs you may require.

 

 

 

the other code here

 

// ************************************************************
// setup.cpp
//
// Implementation of DllMain and setup functions
//
// Copyright 2003 Microsoft Corporation, All Rights Reserved
//
// ************************************************************

#include "stdafx.h"

HINSTANCE g_hinstModule;


BOOL APIENTRY DllMain(
    HANDLE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
    )
{
//    switch (ul_reason_for_call)
//    {
//        case DLL_PROCESS_ATTACH:
//        case DLL_THREAD_ATTACH:
//        case DLL_THREAD_DETACH:
//        case DLL_PROCESS_DETACH:
//            g_hinstModule = (HINSTANCE)hModule;
//            break;
//    }
    return TRUE;
}


// **************************************************************************
// Function Name: Install_Init
//
// Purpose: processes the push message.
//
// Arguments:
//    IN HWND hwndParent ?handle to the parent window
//    IN BOOL fFirstCall ?indicates that this is the first time this function is being called
//    IN BOOL fPreviouslyInstalled ?indicates that the current application is already installed
//    IN LPCTSTR pszInstallDir ?name of the user-selected install directory of the application
//
// Return Values:
//    codeINSTALL_INIT
//    returns install status
//
// Description: 
//    The Install_Init function is called before installation begins.
//    User will be prompted to confirm installation.
// **************************************************************************
SETUP_API codeINSTALL_INIT Install_Init(
    HWND        hwndParent,
    BOOL        fFirstCall,     // is this the first time this function is being called?
    BOOL        fPreviouslyInstalled,
    LPCTSTR     pszInstallDir
    )
{
    int iReply = IDYES;

    iReply = MessageBox(hwndParent,
                        (LPCTSTR)LoadString(g_hinstModule, IDS_INSTALL_PERMISSION, NULL, 0),
                        (LPCTSTR)LoadString(g_hinstModule, IDS_PERMISSIONTITLE, NULL, 0),
                        MB_YESNO | MB_ICONQUESTION);

    if (IDNO == iReply)
    {
        return codeINSTALL_INIT_CANCEL;
    }

    return codeINSTALL_INIT_CONTINUE;
}


// **************************************************************************
// Function Name: Install_Exit
//
// Purpose: processes the push message.
//
// Arguments:
//    IN HWND hwndParent ?handle to the parent window
//    IN LPCTSTR pszInstallDir ?name of the user-selected install directory of the application
//
// Return Values:
//    codeINSTALL_EXIT
//    returns install status
//
// Description: 
//    Register query client with the PushRouter as part of installation.
//    Only the first two parameters really count.
// **************************************************************************
SETUP_API codeINSTALL_EXIT Install_Exit(
    HWND    hwndParent,
    LPCTSTR pszInstallDir,      // final install directory
    WORD    cFailedDirs,
    WORD    cFailedFiles,
    WORD    cFailedRegKeys,
    WORD    cFailedRegVals,
    WORD    cFailedShortcuts
    )
{
//    PROCESS_INFORMATION pi      = {0};
//    DWORD               dwRes   = 0;
//    codeINSTALL_EXIT    cie     = codeINSTALL_EXIT_UNINSTALL;
 if( cFailedDirs || cFailedFiles || cFailedRegKeys ||
  cFailedRegVals || cFailedShortcuts )
 {
  return codeINSTALL_EXIT_UNINSTALL;
 }


 

    return codeINSTALL_EXIT_DONE;

//Error:
//    return cie;
}


// **************************************************************************
// Function Name: Uninstall_Init
//
// Purpose: processes the push message.
//
// Arguments:
//    IN HWND hwndParent ?handle to the parent window
//    IN LPCTSTR pszInstallDir ?name of the user-selected install directory of the application
//
// Return Values:
//    codeUNINSTALL_INIT
//    returns uninstall status
//
// Description: 
//    Query the device data using the query xml in the push message,
//    and send the query results back to the server.
// **************************************************************************
SETUP_API codeUNINSTALL_INIT Uninstall_Init(
    HWND        hwndParent,
    LPCTSTR     pszInstallDir
    )
{
    int                 iReply  = IDYES;
    PROCESS_INFORMATION pi      = {0};
    DWORD               dwRes   = 0;
    codeUNINSTALL_INIT  cui     = codeUNINSTALL_INIT_CANCEL;


    iReply = MessageBox(hwndParent,
                        (LPCTSTR)LoadString(g_hinstModule, IDS_UNINSTALL_PERMISSION, NULL, 0),
                        (LPCTSTR)LoadString(g_hinstModule, IDS_PERMISSIONTITLE, NULL, 0),
                        MB_YESNO | MB_ICONQUESTION);
    if (IDNO == iReply)
    {
        goto Error;
    }

    if (FALSE == CreateProcess(TEXT("cfgclient.exe"), TEXT("/unregister"), NULL, NULL, NULL, 0, NULL, NULL, NULL, &pi))
    {
        goto Error;
    }

    dwRes = WaitForSingleObject(pi.hProcess, REGISTER_WAIT_TIME);
    if (WAIT_OBJECT_0 != dwRes)
    {
        goto Error;
    }

    // Registered...Check result.
    if (FALSE == GetExitCodeProcess(pi.hProcess, &dwRes))
    {
        goto Error;
    }

    ASSERT(STILL_ACTIVE != dwRes);

    if (0 != dwRes)
    {
        goto Error;
    }

    cui = codeUNINSTALL_INIT_CONTINUE;

Error:
    return cui;
}


// **************************************************************************
// Function Name: Uninstall_Exit
//
// Purpose: processes the push message.
//
// Arguments:
//    IN HWND hwndParent ?handle to the parent window
//
// Return Values:
//    codeUNINSTALL_EXIT
//    returns uninstall status
//
// Description: 
//    Query the device data using the query xml in the push message,
//    and send the query results back to the server.
// **************************************************************************
SETUP_API codeUNINSTALL_EXIT Uninstall_Exit(
    HWND    hwndParent
    )
{
    return codeUNINSTALL_EXIT_DONE;
}

posted on 2008-10-23 07:36  彭鹏  阅读(4252)  评论(1编辑  收藏  举报