Search
Close this search box.

Building Windows CE 6 or 7 Smart Device Application with Visual Studio 2012 (Part 1)

With every new release of Windows CE (Windows Embedded CE, Windows Embedded Compact Edition) version 4.x, 5.0, 6.0, 7.0, 2013 (aka 8.0), people ask what version of Visual Studio they should use for Smart Device development. And how much it is different from the Visual Studio you use for developing the OS image, or how much it is different from the latest Visual Studio version? For those people that don’t understand what I am talking, a summary:

  • OS image : the image (NK.BIN) that will include kernel, device drivers, servers (File, Ftp, Smb, Http, …), CRT and so. The thing required to run “Windows CE” (subset of desktop Windows API) on your hardware. With Windows CE you can choose what components you want to add in your image. To build the OS you need “Platform Builder”, nowadays a plug-in in Visual Studio.
  • Smart Device : many people are not interested in building their own drivers, neither a full OS. They just buy the hardware and want to get started with a prebuilt OS. For those developers the OS image builder supplies also a SDK that you need to compile & link your Smart Device application against. The SDK contains all headers and library files of all components you added in your OS image, so you cannot accidentally compile & link a program to an API that is not present in your (customized) OS.

For these 2 situations, you need 2 different tools.

Historical overview

VersionPlatform (OS) Builder -> NK.BINSmart Device application
Windows CE 4.xWindows CE Platform Builder 4.xEmbedded Visual Studio 4
Windows CE 5.0Windows CE Platform Builder 5.0Visual Studio 2005 + SDK
Windows CE 6.0Plugin for Visual Studio 2005Visual Studio 2008 + SDK
Windows CE 7.0Plugin for Visual Studio 2005Visual Studio 2008 + SDK
Windows CE 8.0Plugin for Visual Studio 2012Visual Studio 2012 + SDK

As you notice, Platform Builder and Smart Device application development required in the past a different version of Visual Studio. This bothered always people because they had to invest in and maintain different (older) versions of Visual Studio projects. Only with Windows CE 8.0 Microsoft finally succeeded in at least using the same (and latest!) version of Visual Studio. For older versions of Windows CE you still need to use the older versions of Visual Studio.

Not entirely true!

With Visual Studio 2010 and now Visual Studio 2012 you have a lot of control of the internal build system. I will show you how you can also use Visual Studio 2012 to build Windows CE 6.0 and 7.0 Smart Device applications, which gives us the following table:

VersionPlatform (OS) Builder ->NK.BINSmart Device application
Windows CE 6.0Plugin for Visual Studio 2005Visual Studio 2008 + SDK or Visual Studio 2012 + SDK
Windows CE 7.0Plugin for Visual Studio 2005Visual Studio 2008 + SDK or Visual Studio 2012 + SDK
Windows CE 8.0Plugin for Visual Studio 2012Visual Studio 2012 + SDK

Today we have already implemented this setup in my company’s build system, relieving all developers (except me as the Windows CE OS builder J/L) to maintain many project versions in different Visual Studio versions. It was only recent that we could upgrade to Visual Studio 2012, the last 5 years we were forced to stick with Visual Studio 2008 for all our C++ projects because we have some 30+ C++ libraries, few COM DLLs and executables that compile both for desktop Windows and Windows CE (both share the same subset of the Windows API). For convenience both configurations were present in 1 Visual Studio 2008 C++ vcproj file.

Now, let me explain how to achieve this. Many thanks also go to my colleague Marcus (The Build Guru) who did most of the initial research.

First of all we learned by studying how a Windows CE 8.0 SDK is installed. Basically the SDK (“MyDevice8.msi”) installs itself in folder C:\Program Files\Windows CE Tools\SDKs\MyDevice8. Roughly said, it contains subfolders for the OS APIs in Inc, Atl and Mfc headers in atlmfc and CRT in Crt. The Bin folder contains the tools (compiler, linker, midl, rc, …)

How does this look like in a Windows CE 6/7 SDK? There you also have a C:\Program Files\Windows CE Tools\wce600\MyDevice6 (x86) folder. But here you will find only the OS headers and libraries. The Atl, Mfc and Crt headers and libraries are located in C:\Program Files\Microsoft Visual Studio 9.0\VC\ce. In Visual Studio 2012 much of the build system internals is regulated through Property Sheets in C:\Program Files\MSBuild. After installing the Windows CE 8.0 SDK, a subfolder is added in C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\MyDevice8.

Notice “MyDevice6 (x86)”; the “(x86)” is typically added in a Windows CE 6/7 SDK name, in Windows CE 8 it is omitted. When I created the Visual Studio 2012 SDK for Windows CE 6/7 projects hereafter, I also omitted the “(x86)”, although it doesn’t really matter (it is just part of a SDK name)

What follows are the detailed steps you have to follow to transform your Windows CE 6 SDK (hereafter named “MyDevice6 (x86)”) for Visual Studio 2008 to a new SDK (hereafter named “MyDevice6”) for Visual Studio 2012. Although it might look like there are many steps to follow, we are just going to copy a few folders to a new location and edit a few files to create this new Visual Studio 2012 compatible SDK for Windows CE 6 (the same applies to a Windows CE 7 SDK):

Step 1: Property Sheets

Create a new C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6 folder by
        copying(and renaming) it from C
    :\Program Files\MSBuild\Microsoft.Cpp\v4 .0\V110\Platforms\MyDevice8
        .Rename the files to(“MyDevice8”-> “MyDevice6”) C :\Program
    Files\MSBuild\Microsoft.Cpp\v4 .0\V110\Platforms\MyDevice6\ Microsoft.Cpp
        .MyDevice6.Common.props C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\ Microsoft.Cpp.MyDevice6.default
        .props C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\ Microsoft.Cpp.MyDevice6
        .props C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\ Microsoft.Cpp.MyDevice6
        .targets C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\PlatformToolsets\wce600\ Microsoft
        .Cpp.MyDevice6.wce600.props C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\PlatformToolsets\wce600\ Microsoft
        .Cpp.MyDevice6.wce600.targets Open a Text Editor with Admin
    Rights(write access) to these folders(Run as Administrator) Go through all
    6 files and rename
    everything in those files that refers to MyDevice8 to MyDevice6,
    CE800 to wce600

Step 2: Registry

Open with a Text Editor C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\V110\Platforms\MyDevice6\PlatformToolsets\wce600\Microsoft.Cpp.MyDevice6.wce600.props
Look up <SdkRootPath>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Tools\SDKs\MyDevice6)sdk\</SdkRootPath>

This is a reference to a registry key that needs to exist on the system you wish to use for compiling the Windows CE 6/7 Smart Device projects. This key is used by Visual Studio 2012 to recognize your SDK (Windows CE platform configuration). Create this key manually with Regedit.exe. You will also find the “MyDevice8” SDK key there, use it as an example.

You need to create the key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Tools\SDKs\MyDevice6 with (default) REG_SZ data “C:\Program Files\Windows CE Tools\SDKs\MyDevice6\”

Step 3: Folder structure

Copy the Visual Studio 2008 “CE” folders from C
    :\Program Files\Microsoft Visual Studio 9.0\VC\ce to C
    :\Program Files\Windows CE Tools\SDKs\MyDevice6\Sdk Copy the “Windows CE
        Tools” folders from C
    :\Program Files\Windows CE Tools\wce600\MyDevice6(x86) to C
    :\Program Files\Windows CE Tools\SDKs\MyDevice6

Your folder structure should look like:

“Old” Visual Studio 2008 structure“New” Visual Studio 2012 structure
C:\Program Files\Windows CE Tools\wce600\MyDevice6 (x86)C:\Program Files\Windows CE Tools\SDKs\MyDevice6\wce600
C:\Program Files\Windows CE Tools\wce600\MyDevice6 (x86)\IncludeC:\Program Files\Windows CE Tools\SDKs\MyDevice6\wce600\Include
C:\Program Files\Windows CE Tools\wce600\MyDevice6 (x86)\LibC:\Program Files\Windows CE Tools\SDKs\MyDevice6\wce600\Lib
C:\Program Files\Microsoft Visual Studio 9.0\VC\ceC:\Program Files\Windows CE Tools\SDKs\MyDevice6\Sdk
C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\atlmfcC:\Program Files\Windows CE Tools\SDKs\MyDevice6\Sdk\atlmfc
C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\binC:\Program Files\Windows CE Tools\SDKs\MyDevice6\Sdk\bin
C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\crtC:\Program Files\Windows CE Tools\SDKs\MyDevice6\Sdk\crt
C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\dllC:\Program Files\Windows CE Tools\SDKs\MyDevice6\Sdk\dll
C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\includeC:\Program Files\Windows CE Tools\SDKs\MyDevice6\Sdk\include
C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\libC:\Program Files\Windows CE Tools\SDKs\MyDevice6\Sdk\lib

Step 4: Binary tools folders

Open with a Text Editor C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\PlatformToolsets\wce600\Microsoft
        .Cpp.MyDevice6.wce600.props Adapt the<ExecutablePath>
    </ ExecutablePath> tag as follows(mind the order)
        From<ExecutablePath Condition = "'$(ExecutablePath)' == ''"> $(
            SdkRootPath) bin\i386;
$(SdkRootPath) bin\i386\x86;
$(VSInstallDir) Common7\Tools\bin;
$(VSInstallDir) Common7\tools;
$(VSInstallDir) Common7\ide;
$(ProgramFiles)\HTML Help Workshop;
$(MSBuildToolsPath32);
$(FxCopDir);
$(PATH);
$(VCINSTALLDIR)\bin;
</ ExecutablePath> To<ExecutablePath Condition = "'$(ExecutablePath)' == ''"> $(
    SdkRootPath) bin\x86_cex86;
$(VSInstallDir) Common7\Tools\bin;
$(VSInstallDir) Common7\tools;
$(VSInstallDir) Common7\ide;
$(ProgramFiles)\HTML Help Workshop;
$(MSBuildToolsPath32);
$(FxCopDir);
$(PATH);
$(VCINSTALLDIR)\bin;
</ExecutablePath>

Step 5: C++ Include headers folders

Open with a Text Editor C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\PlatformToolsets\wce600\Microsoft
        .Cpp.MyDevice6.wce600.props Adapt the<IncludePath>
    </ IncludePath> tag as follows(mind the order)
        From<IncludePath Condition = "'$(IncludePath)' == ''"> $(
            SdkRootPath) crt\Include;
$(SdkRootPath) crt\Include\sys;
$(SdkRootPath) crt\Include\stl;
$(SdkRootPath) atlmfc\Include;
$(SdkRootPath) Inc;
</ IncludePath> To<IncludePath Condition = "'$(IncludePath)' == ''"> $(
    SdkRootPath) Include;
$(SdkRootPath) wce600\Include\x86;
$(SdkRootPath) atlmfc\Include;
</IncludePath>

Step 6: C++ Libraries folders

Open with a Text Editor C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\PlatformToolsets\wce600\Microsoft
        .Cpp.MyDevice6.wce600.props Adapt the<LibraryPath>
    </ LibraryPath> tag as follows(mind the order)
        From<LibraryPath Condition = "'$(LibraryPath)' == ''"> $(
            SdkRootPath) crt\Lib\x86;
$(SdkRootPath) atlmfc\lib\x86;
$(SdkRootPath) Lib\x86\debug;
$(SdkRootPath) Lib\x86\retail;
</ LibraryPath> To<LibraryPath Condition = "'$(LibraryPath)' == ''"> $(
    SdkRootPath) wce600\Lib\x86;
$(SdkRootPath) atlmfc\lib\x86;
$(SdkRootPath) Lib\x86;
</LibraryPath>

Step 7: CE Additional Files

Open with a Text Editor C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\PlatformToolsets\wce600\Microsoft
        .Cpp.MyDevice6.wce600.props Rename all “*
        110 *” files to “* 90 *” files in the<CEAdditionalFiles>
                               </ CEAdditionalFiles> tags Example
    : <CEAdditionalFiles Condition = "'$(Configuration)' == 'Debug'"> msvcr90d
          .dll |
    $(SdkRootPath) crt\bin\x86\| temp\$(ProjectName) | 0;
msvcp90d.dll | $(SdkRootPath) crt\bin\x86\| temp\$(ProjectName) | 0;
</CEAdditionalFiles>

Step 8: Linker Additional Dependencies

Open with a Text Editor C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\PlatformToolsets\wce600\Microsoft
        .Cpp.MyDevice6.wce600
        .props Adapt<AdditionalDependencies>
    </ AdditionalDependencies> tag in<ItemDefinitionGroup><Linker></ Linker>
    </ ItemDefinitionGroup> section From<AdditionalDependencies> coredll.lib;
% (AdditionalDependencies)</ AdditionalDependencies> To<
      AdditionalDependencies> coredll.lib;
corelibc.lib;
ole32.lib;
oleaut32.lib;
uuid.lib;
commctrl.lib;
atlosapis.lib;
% (AdditionalDependencies)</ AdditionalDependencies>

Step 9: Compiler Preprocessor Definitions

Open with a Text Editor C :\Program Files\MSBuild\Microsoft
        .Cpp\v4 .0\V110\Platforms\MyDevice6\PlatformToolsets\wce600\Microsoft
        .Cpp.MyDevice6.wce600.props Adapt<PreprocessorDefinitions>
    </ PreprocessorDefinitions> tag in<ItemDefinitionGroup><ClCompile>
    </ ClCompile>
    </ ItemDefinitionGroup> section From<PreprocessorDefinitions> UNDER_CE;
WINCE;
_WIN32_WCE = 0x800;
% (PreprocessorDefinitions)</ PreprocessorDefinitions> To<
      PreprocessorDefinitions> UNDER_CE;
WINCE;
_WIN32_WCE = 0x600;
%
    (PreprocessorDefinitions)</ PreprocessorDefinitions> Remove<
        AdditionalOptions> /
    arch : IA32 % (AdditionalOptions)</ AdditionalOptions>

Step 10: Avoid linker error ” LINK : fatal error LNK1104: cannot open file ‘OLDNAMES.lib’

Add <AdditionalOptions>/NODEFAULTLIB:"oldnames.lib" %(AdditionalOptions)</AdditionalOptions> to the <ItemDefinitionGroup><Linker></Linker></ItemDefinitionGroup> section

This will tell the linker to ignore the default library named “oldnames.lib” which has no use in Windows CE

Voila, if you have implemented all the previous steps, your Windows CE 6 SDK for Visual Studio 2008 is converted to a Windows CE 6 SDK for Visual Studio 2012. Once again, this also applies to a Windows CE7 SDK.

Geek note:

You might ask yourself; “how the hell did those geeks find what directories were searched (and in what order) by Visual Studio 2008?”

We needed this information to understand how to manipulate and set the C++ include and library directories in the Visual Studio 2012 Property Sheet files. The order is important as some header files exist more than once (in a slightly different variation).

We used Sysinternals Process Monitor (Procmon.exe) for that. We installed a filter for Process Name cl.exe, created a Smart Device project in Visual Studio 2008 with 1 C++ source file “test.cpp” with 1 statement

#include “search_it.h”

 As this header file does not exist, cl.exe had to search all its include directories. In Process Monitor, you find these traces (among many others):

cl.exeCreateFileC:\Users\werner\Documents\Visual Studio 2008\Projects\MyDevice6 (x86)\AtlDll\AtlDll\search_it.hNAME NOT FOUND
cl.exeCreateFileC:\Program Files\Microsoft Visual Studio 9.0\VC\ce\include\search_it.hNAME NOT FOUND
cl.exeCreateFileC:\Program Files\Windows CE Tools\wce600\MyDevice6 (x86)\Include\X86\search_it.hNAME NOT FOUND
cl.exeCreateFileC:\Program Files\Windows CE Tools\wce600\MyDevice6 (x86)\Include\search_it.hNAME NOT FOUND
cl.exeCreateFileC:\Program Files\Microsoft Visual Studio 9.0\VC\ce\atlmfc\include\search_it.hNAME NOT FOUND
cl.exeCreateFileC:\Program Files\Microsoft Visual Studio 9.0\SmartDevices\SDK\SQL Server\Mobile\v3.0\search_it.hPATH NOT FOUND
cl.exeCloseFileC:\Users\werner\Documents\Visual Studio 2008\Projects\MyDevice6 (x86)\AtlDll\AtlDll\Test.cppSUCCESS

When you do the same for a non existing search_it.lib and a filter on Process Name link.exe, you will find the library directories

link.exeCreateFileC:\Users\werner\Documents\Visual Studio 2008\Projects\MyDevice6 (x86)\AtlDll\AtlDll\search_it.libNAME NOT FOUND
link.exeCreateFileC:\Users\werner\Documents\Visual Studio 2008\Projects\MyDevice6 (x86)\AtlDll\AtlDll\search_it.libNAME NOT FOUND
ink.exeCreateFileC:\Program Files\Windows CE Tools\wce600\MyDevice6 (x86)\Lib\x86\search_it.libNAME NOT FOUND
link.exeCreateFileC:\Program Files\Microsoft Visual Studio 9.0\VC\ce\atlmfc\lib\x86\search_it.libNAME NOT FOUND
link.exeCreateFileC:\Program Files\Microsoft Visual Studio 9.0\VC\ce\lib\x86\search_it.libNAME NOT FOUND

Note the 3 root directories that are being searched:

  • The current project directory
  • C:\Program Files\Microsoft Visual Studio 9.0\VC\ce
  • C:\Program Files\Windows CE Tools\wce600\MyDevice6 (x86)

This order was preserved in the compiler (step 5) and linker (step 6) steps.

This article is part of the GWB Archives. Original Author: Werner Willemsens

Related Posts