Building XML Web Services in Native Code for Windows CE .NET

 

Mike Hall
Microsoft Corporation

September 2002

Applies to:
    Microsoft® Windows® CE .NET
    XML Web Services
    SOAP
    Web Services Description Language
    Web Services Meta Language

Summary: Learn how to build an XML Web Service for Windows CE .NET using native code. (27 printed pages)

Contents

Introduction
Windows CE and SOAP
Implementing XML Web Services
Conclusion
For More Information

Introduction

Web Services are created using a set of industry standard protocols, which include SOAP, Hypertext Transfer Protocol (HTTP), Web Services Description Language (WSDL), and Extensible Markup Language (XML) that make it easy for systems to communicate without prior knowledge of each other. This, in many respects, is very similar to the way in which the Internet works today. Take a Web browser as an example. A Web browser does not need have information about the operating system being used by an Internet server; the client and server both use the same underlying HTTP protocol. The Web browser experience is all about presentation of data from a remote system whereas XML Web Services are about how arbitrary computing systems talk to each other based on an open set of protocols, which can be implemented on any device, any operating system, any language, and any object model. XML Web Services therefore allow for broad interoperability regardless of the underlying technologies. Web Services also provide a loosely coupled programming model; rather than a distributed object model using complex runtimes at each end, Web Services use a message-based system. If you post a message and the system at the other end is up and running, then it will get back to you.

Stand-alone, monolithic applications are difficult to customize or extend. The use of Component Object Model (COM)/DCOM and other distributed object technologies made customization and extension of applications simpler but also carries its own problems. Configuring DCOM to run across firewalls, for example, can be an interesting exercise. Embedded systems are becoming smarter and are increasingly shipping with network connectivity. This being the case, it would be extremely useful to have the ability to remotely configure or monitor an embedded device, have an embedded system integrate with other systems on a local network, or have the global networking infrastructure known as the Internet. Web Services use HTTP for communication, the lowest common denominator of communication technologies for Internet-based devices. This makes it simple to create a Web service client or server running on Microsoft® Windows® CE .NET.

This paper describes the tools and technologies used to build an XML Web Service for Windows CE .NET—the examples used in this paper are created by using native code, generated with Microsoft eMbedded Visual C++® 4.0.

Windows CE .NET does not support the creation of XML Web Services by using the .NET Compact Framework. The only option for creating XML Web Services for Windows CE .NET is to use native code. Applications written by using the .NET Compact Framework can, however, consume XML Web Services.

Windows CE and SOAP

Before you get started with a description of the process of building a platform which supports XML Web Services, it may be useful to take a look at the Windows CE .NET components which are required to support XML Web Services, and the way in which XML Web Services are supported on Windows CE .NET.

Required Components

In order to support XML Web Services, your Windows CE .NET project must contain the following components: HTTPD server, COM (in process), SOAP Server, and optionally Active Template Library (ATL). The samples used in this paper will be using ATL. Note that Windows CE .NET can support XML Web Services in devices that have a user interface and also on headless devices. Adding support for XML Web Services may be an interesting option for remotely configuring or querying a device. The following table shows the size of the required components.

Component Size
XML/HTTP 15 KB (this is pulled in by the SOAP Server component
COM (inproc) 111 KB
SOAP Server 270 KB—this includes HTTPD server and XML/HTTP
ATL 44 KB
HTTPD Server 61KB—this is pulled in by the SOAP Server component

Windows CE .NET—SOAP Support

Windows CE .NET includes SOAP Toolkit version 2.2 functionality, which is directly equivalent to the functionality in the Windows Desktop SOAP Toolkit 2.2. For more information about the Windows Desktop SOAP Toolkit and Web Services in general, refer to the MSDN Web Services Web site.

The compatibility between the desktop SOAP toolkit and Windows CE .NET support for SOAP makes it possible to develop and test SOAP servers on the desktop, and then port the code with minimal changes to Windows CE .NET. For the purposes of this document, we will be building the SOAP server code using eMbedded Visual C++ 4.0.

The SOAP server is simply a COM object, perhaps created by using the ATL COM AppWizard within eMbedded Visual C++ 4.0. There is some additional information needed to correctly invoke the functions exposed by the COM object and to return an appropriate XML packet to the client application, which is handled by the Windows CE .NET SOAP Server. The server component can be found in the following location within the Platform Builder Catalog: Applications and Services Development | SOAP Toolkit | Server.

You can use the Platform Builder dependency viewer to determine which additional components are needed by the SOAP Server on our platform, which include HTTPD, XML, and in-process COM. By selecting the SOAP Server component from the catalog, the required components will be added to your platform.

Figure 1.

There are a number of components involved in making a call from a Microsoft Visual C#™ Visual Studio® .NET application. Go through the process so that you understand how to go from the client application to the COM object running on Windows CE .NET and back again to the C# client application. XML Web Services and SOAP requests typically use HTTP as their transport. Start from the client application making the HTTP POST.

The client application makes an HTTP POST to the Windows CE .NET HTTPD Web Server. The HTTP packet will contain the name and location of the server side WSDL file. You can clearly see this by setting a breakpoint in some of the Windows CE .NET shared source. Take a look at Applications and Services Development | SOAP Toolkit | Server | Directory for SOAP ISAPI | SOAPISAP.CPP in your project workspace (note that you must have a shared source installed to open this file), set a breakpoint in the function ProcessRequest, line 646, then, using the watch window, take a look at the variable pECB->lpszPathTranslated. In this case, it contains the following: \windows\www\wwwpub\MyWebService.wsdl

There must be a mapping between the incoming HTTP POST and the SOAP Server components, which is handled by the HTTPD Server, Script Map, and registry entries. Take a look in the Windows CE .NET device registry at HKLM\Comm\HTTPD\ScriptMap. You will notice two entries (see the image below), one for WSDL and one for WSML. Both are linked to SOAPISAP.DLL. This is the DLL that is responsible for unpacking the incoming XML packet and verifying the content of the 'function call' parameters, invoking the correct COM object (hence the need for the Inprocess COM component in your platform), calling the appropriate COM object function, and creating the XML packet to be sent back to the client application.

Figure 2.

Web Services Description Language (WSDL) files

The Web Services Description Language (WSDL) is an XML-based language for describing the network services offered by the server. You use WSDL to create a file that identifies the services provided by the server and the set of operations within each service that the server supports. For each of the operations, the WSDL file also describes the message format that the client must follow in requesting an operation.

The WSDL document is like a contract between the client and server. The server is designed to provide certain services only if the client sends a properly formatted SOAP request message.

To illustrate, suppose a WSDL file defines a service called StockQuoteService, which describes operations such as GetLastTradePrice, GetLowestPriceOfTheDay, and GetHighestPriceOfTheDay. You place this WSDL file on the server. A client who wishes to send a SOAP request to this service obtains a copy of this WSDL file from the server, the client then uses the information in this file to format a SOAP request message. The client sends this request to the server. The server executes the requested operation and sends the resulting stock price back to the client as a SOAP response message.

Web Services Meta Language (WSML) files

In addition to creating a WSDL file describing the services and operations on the server, you also must create a Web Services Meta Language (WSML) file on the server.

A WSML file provides information that maps the operations of a service (as described in the WSDL file) to specific methods in the COM object. The WSML file determines which COM object to load in order to service the request for each operation. It should be noted that the object state is not maintained between successive operation invocations that map to method calls on the same object.

Here is a sample WSML file in which we can clearly see the PROGID for the COM object "MyWebService.TempSvr.1", the mapping between the functions, and the appropriate Dispatch ID. The callIndex attribute provides the parameter number (first parameter is "1", second parameter is "2", and so on). A callIndex value of "-1" identifies the parameter as the return parameter.

<?xml version='1.0' encoding='UTF-8' ?> 
 <!-- Generated 07/22/02 by Microsoft SOAP Toolkit WSDL File Generator,
Version 1.02.814.0 --> 
<servicemapping name='MyWebService'>
  <service name='MyWebService'>
    <using PROGID='MyWebService.TempSvr.1' cachable='0' ID='TempSvrObject'
/>
    <port name='TempSvrSoapPort'>
      <operation name='GetString'>
        <execute uses='TempSvrObject' method='GetString' dispID='2'>
          <parameter callIndex='-1' name='retval' elementName='Result' />
        </execute>
      </operation>
      <operation name='GetInt'>
        <execute uses='TempSvrObject' method='GetInt' dispID='1'>
          <parameter callIndex='-1' name='retval' elementName='Result' />
        </execute>
      </operation>
    </port>
  </service>
</servicemapping>

That completes the process. You build a Windows CE .NET operating system image, which contains support for HTTPD, SOAP Server, XML, ATL, and inproc COM objects. We use the eMbedded Visual C++ 4.0 ATL/COM AppWizard to create a COM object, which contains the functions we want to expose from our Web Service. You generate the appropriate WSDL and WSML files (more on how to do this later in the article). You also must register your COM object. This can be done at runtime or by including the appropriate registry entries into our operating system image at build time. You also must include the WSDL and WSML files in your operating system image.

In the following section, take a look at how to build the ATL/COM object, how to generate the WSDL and WSML files and how to put everything together to call the Web Service from a C# Visual Studio .NET application.

Implementing XML Web Services

There are a number of steps involved in putting the solution together, which are as follows:

  1. Build a Windows CE .NET operating system image that contains the appropriate components.
  2. Export a Software Development Kit in order to use eMbedded Visual C++ 4.0 to create an ATL/COM object.
  3. Use eMbedded Visual C++ to create our ATL/COM object.
  4. Generate the WSDL and WSML files.
  5. Register the ATL/COM object on the Windows CE .NET device and upload the WSDL and WSML files.
  6. Create the C# Visual Studio .NET application to consume our Web Service.

In this example, you will be using the Windows CE .NET 4.1 Emulator as your target. The steps within this document are also valid for other reference platforms.

Building the Windows CE .NET Operating System Image

For this paper, you will be using the Internet Appliance configuration and the Windows CE .NET 4.1 Emulator as your target reference platform. Targeting another reference platform requires only minor adjustments to the steps outlined in this document.

Here are the steps needed to create the initial platform:

  1. Launch the Platform Builder application.

  2. On the File menu, click New Platform.

  3. In the New Platform Wizard, click Next.

  4. From the list of available BSPs, select Emulator X86, and then click Next.

  5. From the list of available platform configurations, select Internet Appliance.

  6. In the Platform Name box, type XMLWS as the name for your platform, and then click Next.

  7. In the list of Internet Appliance Device variants, select Internet Appliance, and then click Next.

  8. On the Application & Media page, only select Internet Browser, disable all other options (note that any of the features can be added, using the component catalog), and then click Next.

  9. On the Networking & Communications page, clear Personal Area Network (PAN) | Bluetooth (note that this can be added at any time, using the component catalog), and then click Next.

  10. On the Congratulations page, click Done to close the New Platform Wizard.

  11. On the Build menu, click Set Active Configuration.

  12. From the list of platform configurations, select XMLWSEmulator: X86 Win32 (WCE emulator) Debug, and then click OK.

    At this point, the Windows CE .NET operating system could be built and downloaded to the emulator. There are some additional components to add which will add support for the SOAP server, Web Server, COM, XML, and ATL.

  13. Using the Windows CE .NET catalog, add the following components to the platform:

    • Display Based Devices | Applications & Services Development | Active Template Library

    • Display Based Devices | Applications & Services Development | Component Services (COM and DCOM) | Component Object Model (choose 1) | COM

    • Display Based Devices | Applications & Services Development | SOAP Toolkit | Server

      Note   Adding the SOAP Server will display a Security Warning—this indicates that additional work may be required to enhance the security of your device.

    • Display Based Devices | Applications & Services Development | XML | MSXML 3.0 (Choose 1) | XML HTTP

    • Display Based Devices | Communication Services and Networking | Servers | Web Server (HTTPD)

You also need a way to register our ATL/COM object after it has been downloaded to the appropriate folder. Windows CE .NET ships with a handy sample 'RegSvr32', and an associated Platform Builder Project (PBP) file, which is located in the following folder: C:\WINCE410\PUBLIC\DCOM\SDK\SAMPLES\REGSVR.

  1. In Platform Builder, on the Project menu, point to Insert and click Existing Project.

  2. Using the File Open dialog box, browse to the C:\WINCE410\PUBLIC\DCOM\SDK\SAMPLES\REGSVR folder.

  3. Select RegSvr32.pbp, and click OK.

    Note   The Platform Builder Project file (PBP) contains support for all Windows CE .NET supported processors/ Adding this component to a project which only uses the Windows CE .NET emulator will display a message box informing you that some of the configurations supported by this application will be disabled.

RegSvr32 simply calls LoadLibrary( ), GetProcAddress( ) on DllRegisterServer, which is exposed from the ATL/COM object, and then FreeLibrary( ), you could write your own code to register COM objects during initialization of the platform.

You are now ready to build the platform.

  1. On the Build menu, click Build Platform.

    The Windows CE .NET 4.1 emulator supports both incoming and outgoing network connections (inbound connection support is a feature which is new to Windows CE .NET 4.1). The default emulator option is to support only outbound connections. You must configure the emulator 'Virtual Switch' before you can test out the XML Web Service.

  2. In Platform Builder, on the Target menu, click Configure Remote Connection.

  3. Select Emulator for the Download and Kernel Transport services.

  4. Under Emulator Download Service, click Configure.

    The Configure Emulator Download Service dialog box will be displayed, which provides the ability to configure a number of options for the emulator including screen resolution, color depth, the amount of memory available to the emulator, desktop pass-through options for serial and parallel ports, and how the Ethernet connection will operate. There are three options: Disabled (no Ethernet support), NAT (outgoing only), which can be used to make connections from the emulator to Web servers, or other remote devices, and Virtual Switch, which provides both inbound and outgoing connections to the emulator. This is ideal for testing out our XML Web Service because the connection to the emulator will originate from an external source (in this case, the desktop Visual Studio .NET application).

  5. Select Virtual Switch for the Ethernet Communication option.

    Note   You may have multiple IP addresses, including your physical NIC, and any VPN or RAS/Dial-up connections—select your NIC IP address.

  6. To close the Configure Emulator Download Service dialog box, click OK.

  7. To close the Configure Remote Connection dialog box, click OK.

After the operating system image is built, you can test the Windows CE .NET Web Server to confirm that this was included into the operating system image and also take the opportunity to note the IP address used by the Windows CE .NET emulator.

  1. In Platform Builder, on the Target menu, click Download/Initialize. This will download the Windows CE .NET operating system to the emulator.

  2. You will be prompted with a KITL Security Warning. The emulator runs an installable file system driver, called RelFSD, which creates a folder within the emulator called \Release. This folder maps directly to the contents of your projects build output folder (known as the FLATRELEASEDIR). This is a nice feature because you can drop files or applications into your desktops FLATRELEASEDIR and have these picked up by the emulator. Click OK to enable the shared folder, or click Cancel to disable the shared folder.

  3. After the emulator is booted, double-click the networking icon on the Windows CE .NET emulator's task bar. This will display the following dialog box:

    Figure 3.

The dialog box clearly shows the IP address of the Windows CE .NET emulator session. In the following example, this is displayed as 192.168.0.48. Make a note of your IP address as you will be using this later.

  1. In the IP Information dialog box within the emulator, click Close. You only need to make note of the emulators IP address once. (Note that you could also set the name of the device using the HKEY_LOCAL_MACHINE\Ident registry key and refer to the device by name rather than IP address.)

  2. You can now test the Windows CE .NET Web server from your desktop Microsoft Internet Explorer—run Internet Explorer on your desktop PC, browse to the IP address that you captured from the Windows CE .NET emulators IP information dialog box, for example (http://192.168.0.48). You should see a Web page similar to the following displayed in your Internet browser. Displaying this Web page proves that the Web Server is running and that the inbound connections are working.

    Figure 4.

Exporting a Software Development Kit

At this point, you have a running Windows CE .NET operating system image. The next step is to create the ATL/COM object before you can use eMbedded Visual C++ to build and download the ATL/COM object you need to export a Software Development Kit from Platform Builder.

The Software Development Kit (SDK) contains the header files and libraries that define the functions supported by our Windows CE .NET platform and the communication transport used to communicate with the platform. Note that an SDK can only be exported after the platform has been built.

Exporting a Software Development Kit is handled in two stages: configuration and export. After it is exported, the SDK must be installed. The platform is called XMLWS (XML WebService). The SDK-creation process will generate an .MSI file in the following folder: C:\wince410\public\XMLWS\SDK (this is project dependent). If you are using another project name, then the SDK will be in the Project\SDK folder. This SDK could be shipped to both internal and external customers. Each could start writing applications for the platform even before final hardware has been created. This is especially compelling if you are building a project that targets emulation.

Here are the steps needed to export the Software Development Kit:

  1. In Platform Builder, on the Platform menu, click Configure SDK.
  2. On the Export SDK Wizard, click Next.
  3. On the Product Properties page, enter the product name as XMLWS (this is how the platform will be identified in eMbedded Visual C++), also add your name, or company name to the Manufacturer name field.
  4. Click Next.
  5. On the Development Languages page, select eMbedded Visual C++ 4.0 support, and enable support for ATL for Windows CE applications, MFC for Windows CE Applications, and MFC for Windows CE ActiveX® Controls (note that this is also the page that you would use to select support for the .NET Compact Framework).
  6. Click Next.
  7. On the Congratulations page, click Done.

Configuration of the SDK is now complete. You can further customize the SDK by clicking Configure SDK on the Platform menu a second time.

  1. To build the Software Development Kit, on the Platform menu, click Build SDK.
  2. After the SDK is built, use Windows Explorer to browse to C:\wince410\public\XMLWS\SDK.
  3. Run the XMLWS_SDK.MSI file.

You are now ready to create the ATL/COM component.

Using eMbedded Visual C++ to Create the ATL/COM Object

The real advantage of the compatibility between the desktop SOAP toolkit and the Windows CE .NET SOAP toolkit is that you can easily write and test my ATL/COM objects on the desktop and the move these over to Windows CE .NET. Alternatively, to think of this in a slightly different way, you can create for the desktop and get Windows CE .NET XML Web Services for very little additional work. Note that the Windows CE .NET SOAP toolkit is integrated with Windows CE .NET. There is no need to download any additional tools or SDKs.

Now you are ready to build the ATL/COM object. You create and build this by using eMbedded Visual C++ 4.0. The steps involved in building the ATL/COM object should be familiar to anyone who has already been through this process on the desktop.

Here is how to build the ATL/COM object.

  1. Launch eMbedded Visual C++ 4.0.

  2. On the File menu, click New.

  3. Click the Project tab and click WCE ATL COM AppWizard.

  4. Type MyWebService in the Project name box. The example project will be built to C:\Demo\MyWebService. This may differ to the output folder being used on your development PC.

    Note   This is typically C:\Program Files\Microsoft eMbedded C++ 4.0\Common\EVC\MyProjects\MyWebService for a default install of eMbedded Visual C++.

  5. Ensure that Win32 (WCE Emulator) is selected in the CPUs list box and click OK.

Figure 5.

There is only one step to the ATL/COM AppWizard, which is where you choose whether to create a DLL (in process COM object), or Executable (used with DCOM), and whether your project supports MFC. In this case, you do not need MFC, and you will create a DLL.

  1. In the WCE ATL COM AppWizardStep 1 of 1 dialog box, click Dynamic Link Library (DLL) and make sure that Support MFC is cleared.
  2. Click Finish.

Figure 6.

After the initial project has been created, you can then insert an ATL Object. This will expose the functions from your Web Service.

  1. On the Insert menu, click New ATL Object.
  2. Under Category, click Objects. Under Objects, click Next.

Figure 7.

You can now set the properties for the ATL Object. This includes the class (.CPP) and header file (.H) names, the ProgID. and so forth.

  • In the ATL Object Wizard Properties dialog box, enter CEWebSvr in the Short Name edit control. The additional fields will automatically be filled out when setting the short name.

You will notice that the ATL Object Wizard Properties dialog box contains two tabs. The first (default) shows the C++ and COM class names; whereas, ProgID, the second page of the dialog box, allows you to set the Threading Model and Interface type (Dual or Custom).

Figure 8.

The eMbedded Visual C++ ATL/COM AppWizard defaults to Single threaded—we need to change this to Free Threaded—if we continue and build the COM Object as single threaded we will get an error from the SOAP Server stating that the COM object could not be created.

  1. In the ATL Object Wizard Properties dialog box, click the Attributes tab.
  2. Under Threading Model, click Free.
  3. Click OK.

Figure 9.

At this point, you can build, deploy, and test the ATL/COM object. The ATL/COM object will build without warnings or errors and can be registered on the Windows CE .NET device. No functions have been exposed at this time, so the object is not that useful. Before building and registering the object, there is one project setting that should be changed.

  1. In eMbedded Visual C++, on the Project menu, click Settings.
  2. In the Project Settings dialog box, click the MIDL tab.
  3. Clear the MkTypLib compatible check box. This is only needed if you are having problems with a specific .ODL file.
  4. Click OK.

Figure 10.

For the purposes of this paper, add two functions to the COM object, one that returns an Integer (GetInt) and one that returns a string (GetString). The SOAP toolkit documentation explains how to work with more complex types.

Adding functions to our COM Object is simple.

  1. Right-click the ICEWebSvr item in the project workspace.
  2. A shortcut menu appears.
  3. Select Add Method on the shortcut menu.

Figure 11.

In this case, add a function that returns an integer. This could be the number of running processes, an item from the registry, or the number of candy bars packed during the last hour on a manufacturing system.

The Add Method to Interface dialog box appears.

  1. In the Add Method to Interface dialog box, type GetInt in the Method Name box.
  2. In the Parameters box, type [out, retval] int *pInteger.
  3. Click OK.

Figure 12.

This will add the function definition to the project, by default calling the function will return an HRESULT of S_OK to show that the function completed successfully. Some code must be added to the function for an integer to be returned.

You will now add the GetString function to the project.

  1. Right-click the ICEWebSvr item in the project workspace.
  2. A shortcut menu appears, which provides a number of options.
  3. Select Add Method on the shortcut menu.
  4. In the Add Method to Interface dialog box, type GetString in the Method Name box.
  5. Type [out, retval] BSTR *pStr
  6. Click OK.

The functions GetInt and GetString can be seen within the project workspace image that follows.

Figure 13.

In order to add code to each of the functions, double-click the function name within the project workspace.

The following code should be added for the GetInt function.

STDMETHODIMP CCEWebSvr::GetInt(int *piInteger)
{
   *piInteger=5;

   return S_OK;
}

The following code should be added for the GetString function.

STDMETHODIMP CCEWebSvr::GetString(BSTR *pStr)
{
   CComBSTR m_ReturnString;

   m_ReturnString=L"This is a String";
   *pStr=m_ReturnString.Copy( );

   return S_OK;
}

You can now build and deploy the ATL/COM object (DLL) to the emulation device. By default, the communications transport used by eMbedded Visual C++ is TCP/IP and Manual Server. Because there is already a Windows CE .NET image running and a connection to the emulator from Platform Builder, you can 'piggy back' this connection from eMbedded Visual C++.

  1. In eMbedded Visual C++, on the Tools menu, click Configure Platform Manager.
  2. Locate and expand XMLWS in the list of available devices (see below)—note that this is only listed because a Software Development Kit (SDK) was created and installed.

Figure 14.

  1. Select the XMLWS Emulator and click Properties.
  2. Select KITL Transport for Windows CE for the Transport.
  3. Select CESH Server for Windows CE (see below).

Figure 15.

  1. To close the Device Properties dialog box, click OK.

    **Note   **You may be prompted with a message box stating that the transport has not been tested. Click OK to continue.

  2. To close the Windows CE Platform Manager Configuration dialog box, click OK.

Before building the ATL/COM object, ensure that eMbedded Visual C++ is configured to deploy to the correct device (otherwise you may download to the Standard SDK platform).

  • Ensure that the eMbedded Visual C++ Build toolbar is showing the following (left to right):
    • MyWebService
    • XMLWS
    • Microsoft Win32® (WCE emulator) Debug
    • XMLWS Emulator

Build and download to the emulator and confirm that there are no errors or warnings during the build process. The output file MyWebService.dll will be downloaded and registered to the following folder: \Windows\MyWebService.dll. In order to use this COM object as an XML Web Service, you must move the DLL to the \Windows\WWW\WWWPub folder, and re-register the DLL (this is where RegSvr32 comes in). This will be covered later in the document.

Generating the WSML/WSDL Files

The SOAP toolkit for Windows CE .NET 4.1 ships with a tool called wsdlstb_ce.exe. This tool creates the WSDL and WSML files for our COM object. wsdlstb_ce.exe can be found in the following folder (assuming you have Windows CE .NET 4.1 installed)—C:\WINCE410\PUBLIC\COMMON\OAK\BIN\I386.

To have the correct path configured to use this tool, go to a command prompt from your Platform Builder workspace.

  1. In Platform Builder, on the Build menu, select Open Build Release Directory.
  2. Select the folder containing your ATL/COM Object. In this case, it is C:\Demo\MyWebService\emulatorDbg.

You are now ready to run the wsdlstb_ce tool.

The tool takes a number of command line parameters, as follows.

wsdlstb_ce -I <Exposed Class> -P <Class GUID> <ProgID> <Dll Name> <WebServer address and location of WSDL on the server> <name of WSDL file>

The parameters for generating the appropriate WSDL and WSML for "MyWebService" would be as follows (note that the GUID will be different for your build of "MyWebService").

  • -I CEWebSvr
  • -P {CB51D94E-0348-4D39-87EF-CFF90C39C21F} (note this is the GUID from my build of the project, by definition your GUID will be different)
  • MyWebService.CEWebSvr.1
  • MyWebService.dll
  • http://192.168.0.15/MyWebService.wsdl (note that the IP address for this emulator session may not match the IP address you have for your emulator session)
  • MyWebService.wsdl

All of the information needed to construct the command line can be found in the MyWebService.RGS file, which can be located in the project workspace, under Resource Files.

Here is how an .RGS file may look, this is the .RGS file for the MyWebService ATL/COM object—the Exposed Class, GUID, and ProgID are highlighted in the RGS file.

HKCR
{
   MyWebService.CEWebSvr.1 = s 'CEWebSvr Class'
   {
      CLSID = s '{E802DEB0-DA35-41E4-8850-9151A58D339A}'
   }
   MyWebService.CEWebSvr = s 'CEWebSvr Class'
   {
      CLSID = s '{E802DEB0-DA35-41E4-8850-9151A58D339A}'
      CurVer = s 'MyWebService.CEWebSvr.1'
   }
   NoRemove CLSID
   {
      ForceRemove {E802DEB0-DA35-41E4-8850-9151A58D339A} = s 'CEWebSvr 
        Class'
      {
         ProgID = s 'MyWebService.CEWebSvr.1'
         VersionIndependentProgID = s 'MyWebService.CEWebSvr'
         ForceRemove 'Programmable'
         InprocServer32 = s '%MODULE%'
         {
            val ThreadingModel = s 'Free'
         }
         'TypeLib' = s '{A4696BFA-BB78-4C54-8100-902716D35BCB}'
      }
   }
}

Here is MyWebService.WSML. You can clearly see the ProgID MyWebService.CEWebSvr.1. This is used by the SOAP Server to load the correct ATL/COM object. The function calls are exposed by method and dispID.

<?xml version='1.0' encoding='UTF-8' ?>
 <!-- Generated 07/23/02 by Microsoft SOAP Toolkit WSDL File Generator,
   Version 1.02.814.0 -->
<servicemapping name='MyWebService'>
  <service name='MyWebService'>
    <using PROGID='MyWebService.CEWebSvr.1' cachable='0'
      ID='CEWebSvrObject' />
    <port name='CEWebSvrSoapPort'>
      <operation name='GetInt'>
        <execute uses='CEWebSvrObject' method='GetInt' dispID='2'>
          <parameter callIndex='-1' name='retval' elementName='Result' />
        </execute>
      </operation>
      <operation name='GetString'>
        <execute uses='CEWebSvrObject' method='GetString' dispID='1'>
          <parameter callIndex='-1' name='retval' elementName='Result' />
        </execute>
      </operation>
    </port>
  </service>
</servicemapping>

Here is the WSML file that exposes the two functions, GetInt and GetString, and the location of the WSDL file on the server.

<?xml version='1.0' encoding='UTF-8' ?> 
 <!-- Generated 07/23/02 by Microsoft SOAP Toolkit WSDL File Generator,
   Version 1.02.814.0 -->
<definitions  name ='MyWebService'   targetNamespace =
'http://tempuri.org/wsdl/'
    xmlns:wsdlns='http://tempuri.org/wsdl/'
    xmlns:typens='http://tempuri.org/type'
    xmlns:soap='https://schemas.xmlsoap.org/wsdl/soap/'
    xmlns:xsd='http://www.w3.org/2001/XMLSchema'
    xmlns:stk='https://schemas.microsoft.com/soap-toolkit/wsdl-extension'
    xmlns='https://schemas.xmlsoap.org/wsdl/'>
  <types>
    <schema targetNamespace='http://tempuri.org/type'
      xmlns='http://www.w3.org/2001/XMLSchema'
      xmlns:SOAP-ENC='https://schemas.xmlsoap.org/soap/encoding/'
      xmlns:wsdl='https://schemas.xmlsoap.org/wsdl/'
      elementFormDefault='qualified'>
    </schema>
  </types>
  <message name='CEWebSvr.GetInt'>
  </message>
  <message name='CEWebSvr.GetIntResponse'>
    <part name='Result' type='xsd:int'/>
  </message>
  <message name='CEWebSvr.GetString'>
  </message>
  <message name='CEWebSvr.GetStringResponse'>
    <part name='Result' type='xsd:string'/>
  </message>
  <portType name='CEWebSvrSoapPort'>
    <operation name='GetInt' parameterOrder=''>
      <input message='wsdlns:CEWebSvr.GetInt' />
      <output message='wsdlns:CEWebSvr.GetIntResponse' />
    </operation>
    <operation name='GetString' parameterOrder=''>
      <input message='wsdlns:CEWebSvr.GetString' />
      <output message='wsdlns:CEWebSvr.GetStringResponse' />
    </operation>
  </portType>
  <binding name='CEWebSvrSoapBinding' type='wsdlns:CEWebSvrSoapPort' >
    <stk:binding preferredEncoding='UTF-8'/>
    <soap:binding style='rpc'
      transport='https://schemas.xmlsoap.org/soap/http' />
    <operation name='GetInt' >
      <soap:operation
        soapAction='http://tempuri.org/action/CEWebSvr.GetInt' />
      <input>
        <soap:body use='encoded' namespace='http://tempuri.org/message/'
        encodingStyle='https://schemas.xmlsoap.org/soap/encoding/' />
      </input>
      <output>
        <soap:body use='encoded' namespace='http://tempuri.org/message/'
        encodingStyle='https://schemas.xmlsoap.org/soap/encoding/' />
      </output>
    </operation>
    <operation name='GetString' >
      <soap:operation 
        soapAction='http://tempuri.org/action/CEWebSvr.GetString' />
      <input>
        <soap:body use='encoded' namespace='http://tempuri.org/message/'
        encodingStyle='https://schemas.xmlsoap.org/soap/encoding/' />
      </input>
      <output>
        <soap:body use='encoded' namespace='http://tempuri.org/message/'
        encodingStyle='https://schemas.xmlsoap.org/soap/encoding/' />
      </output>
    </operation>
  </binding>
  <service name='MyWebService' >
    <port name='CEWebSvrSoapPort' binding='wsdlns:CEWebSvrSoapBinding' >
      <soap:address location='http://192.168.0.15/MyWebService.wsdl' />
    </port>
  </service>
</definitions>

Registering the ATL/COM Object and Uploading the WSML/WSDL Files

You now have all the pieces in place—the ATL/COM object, exposing two functions, GetInt and GetString, the WSDL file which is used to define the functions our XML Web Service exposes, and the WSML file which creates the mapping between the incoming request and the functions exposed from our COM object. You need to place all the files into the appropriate folder on the Windows CE .NET Web Server, re-register the ATL/COM object (so it points at the correct location), and you are finished.

We can use the Windows CE .NET Remote File Viewer to upload the WSML, WSDL, and DLL files to the Windows CE .NET Emulator.

  1. In Platform Builder, on the Tools menu, click Remote File Viewer.
  2. Connect to the XMLWS Emulator (note that you could also connect to Windows CE .NET Default Device—this is always the last downloaded operating system image).
  3. In the Remote File Viewer, browse to XMLWS Emulator | Windows | WWW | WWWPUB.
  4. On the File menu, click Export File (this will upload a file from your desktop to the \Windows\www\wwwpub folder).
  5. Use the Open File dialog box to locate your project workspace (for example, C:\Demo\MyWebService\emulatorDbg).
  6. Select MyWebService.dll and click Open.
  7. Repeat for MyWebService.wsdl and MyWebService.wsml.
  8. Close the Remote File Viewer.

You now must register MyWebService.dll so that the registry points to the correct location.

  1. Switch to the Windows CE .NET Emulator.
  2. On the Start menu, click Run, type cmd and press ENTER.
  3. At the Command Prompt, type cd \windows\www\wwwpub and press ENTER. This will change the current directory to be the Web Server directory.
  4. You can confirm that the DLL, WSDL, and WSML files are in this folder by using the dir command. You should see the three files you uploaded and the Web server default Web page, Default.htm.
  5. Now register the DLL. At the command prompt, type \windows\regsvr32 \windows\www\wwwpub\mywebservice.dll and press ENTER.

The ATL/COM object is now registered. You can use the remote registry editor to confirm the path to our DLL, and you can also use the Platform Builder Debug Output window to confirm that the DLL has been registered correctly. The following is the output from running regsvr32 on MyWebService.dll.

101920 PID:62d914ca TID:62d910aa 0x82e3fb4c: >>> Loading module
mywebservice.dll at address 0x01EB0000-0x01EC0000
Loaded symbols for 
'C:\WINCE410\PUBLIC\XMLWS\RELDIR\EMULATOR_X86DEBUG\MYWEBSERVICE.DLL'
 101950 PID:62d914ca TID:62d910aa 0x82e3fb4c: >>> Loading module 
atlce400.dll at address 0x03810000-0x0381F000 (RW data at 0x01F76000-
0x01F76910)
Loaded symbols for 
  'C:\WINCE410\PUBLIC\XMLWS\RELDIR\EMULATOR_X86DEBUG\ATLCE400.DLL'
 102020 PID:62d914ca TID:62d910aa DllRegisterServer
 102030 PID:62d914ca TID:62d910aa  in \windows\www\wwwpub\mywebservice.dll 
   succeeded.
 102030 PID:62d914ca TID:62d910aa 0x82e3fb4c: <<< Unloading module 
atlce400.dll at address 0x03810000-0x0381F000 (RW data at 0x01F76000-
0x01F76910)
Unloaded symbols for 
'C:\WINCE410\PUBLIC\XMLWS\RELDIR\EMULATOR_X86DEBUG\ATLCE400.DLL'
 102050 PID:62d914ca TID:62d910aa 0x82e3fb4c: <<< Unloading module 
regsvr32.EXE at address 0x18010000-0x18016000
Unloaded symbols for 
  'C:\WINCE410\PUBLIC\XMLWS\RELDIR\EMULATOR_X86DEBUG\REGSVR32.EXE'
 102060 PID:62d914ca TID:62d910aa 0x82e3fb4c: <<< Unloading module 
mywebservice.dll at address 0x01EB0000-0x01EC0000
Unloaded symbols for 
'C:\WINCE410\PUBLIC\XMLWS\RELDIR\EMULATOR_X86DEBUG\MYWEBSERVICE.DLL'

The creation and registration of the Windows CE .NET XML Web Service is now complete. The next step is to test the Web Service from a desktop Visual Studio .NET application written in C#.

Testing the Web Service Using a C# Visual Studio .NET Application

Writing a C# application that consumes a Web Service is extremely simple. In this example, you will consume the Web Service that is running on the Windows CE .NET 4.1 Emulator.

  1. Start Visual Studio .NET.

  2. Create a new Microsoft Visual C#™ project of type Windows Application.

  3. Add a Button, and two Text Boxes (edit controls), textBox1, and textBox2 to the projects form.

  4. On the Project menu, click Add Web Reference. This will prompt for the location of a WSDL file, which is located on the Windows CE .NET Web Server. Enter the IP address and name of your WSDL File. In this case, the location is as follows: http://192.168.0.147/mywebservice.wsdl

  5. Click Add Reference. This will add a Web reference 'WebReference1' to the C# project. You can now reference the Web Service through this Web Reference in the C# project.

  6. Add the following code to the button handler of your project. Double-click the button to switch to Code view within Visual Studio .NET.

    WebReference1.MyWebService Foo = new WebReference1.MyWebService( );
    textBox1.Text=Foo.GetInt( ).ToString( );
    textBox2.Text=Foo.GetString( );
    

Here is how the C# application looks when running—the button has already been clicked. You can see the return values from the XML Web Service being shown in the two edit controls.

Figure 16.

Conclusion

Web Services offer a new platform for building distributed systems. The basic premise is to adapt the loosely coupled programming model at the heart of traditional browser-based Web applications to other sorts of applications. Building XML Web Services for Windows CE .NET using native code is fast and simple. The XML Web Services can be consumed by Visual Studio .NET client applications running on a Windows XP Desktop PC or by other applications that support SOAP. XML Web Services can be used to monitor or control a Windows CE .NET device, or to expose a specific set of features and functions. There are a number of resources available to assist with the development of XML Web Services, which are listed at the end of this article.

For More Information

For the latest information about Windows CE .NET, please visit the Microsoft Windows Embedded Web site.

The online documentation and context-sensitive Help included with Windows CE .NET also provide comprehensive background information and instructions for using Windows CE .NET.

To Access the Online Documentation for Windows CE .NET

  1. Start Platform Builder.
  2. To view the documentation, click the Contents tab on the Help menu.

You can also visit the product documentation for Windows CE .NET.

Further Information

Web Server Developer Center

XML Web Services Developer Center

Microsoft SOAP Toolkit

Understanding COM+—(ISBN 0-7356-0666-8)

Mr. Bunny's Guide to ActiveX—ISBN: 0-201-48536-2

ATL Internals—ISBN: 0-201-69589-8