Sei sulla pagina 1di 133

Developing Microsoft Windows Mobile 5.

0 Applications Using Microsoft Visual Studio 2005

Developing Microsoft Windows Mobile 5.0 Applications Using Microsoft Visual Studio 2005
This 12 hour collection teaches how to develop, deploy and maintain Windows Mobile 5.0 applications. These courses will also prepare candidates for exam 70-540: TS: Microsoft Windows Mobile Application Development. Topics covered within the collection include:

Developing Windows Mobile 5.0 applications User interface design Accessing data using Microsoft SQL Server 2005 Compact Edition Accessing Microsoft SQL Server data from a mobile device Interoperability and platform functionality Deploying and maintaining mobile applications

Student prerequisites:

Visual Studio 2005 (1 year) Microsoft.NET Framework / .NET Compact Framework. (1-2 years) Microsoft Visual Basic .NET or C# (1-2 years) Working knowledge of Microsoft SQL Server 2000/2005 (1 year) Enterprise application development (1 year) Smart Device development using Visual Studio 2005 (recommended)

Designing and Developing a Microsoft Windows Mobile 5.0 User Interface Managing Device Data by Using Microsoft SQL Server Mobile Managing Enterprise Data by Using Microsoft SQL Server 2005 and SQL Server Mobile Developing Connection Capabilities in Microsoft Windows Mobile 5.0Based Applications Implementing Interoperability and Platform Features in Windows Mobile 5.0Based Applications Optimizing, Packaging, and Deploying Microsoft Windows Mobile 5.0Based Applications

DESIGNING AND DEVELOPING A MICROSOFT WINDOWS MOBILE 5.0 USER INTERFACE .......................... 8 DESIGNING AND DEVELOPING A MICROSOFT WINDOWS MOBILE 5.0 USER INTERFACE .................................................... 9 USING MICROSOFT VISUAL STUDIO 2005 FOR WINDOWS MOBILE DEVELOPMENT ......................................................... 9 Lesson Introduction.................................................................................................................................... 9 Features of the Visual Studio 2005 Environment for Mobile Development ............................................. 10 Features of the Windows Mobile 5.0 SDK for Visual Studio 2005 ............................................................ 10 Features of the Windows Mobile 5.0 SDK for Visual Studio 2005 ............................................................ 11 Configure the Visual Studio 2005 Environment ....................................................................................... 11 Using the Connect to Device dialog box................................................................................................... 12 Using Device Emulator Manager ............................................................................................................. 12 CREATING THE USER INTERFACE FOR A MOBILE APPLICATION .................................................................................... 13 User Interface Considerations for Mobile Devices ................................................................................... 13 Set the Screen Orientation of the Mobile Device ..................................................................................... 14 Resize Controls to Respond to Orientation Changes ................................................................................ 14 Set the Screen Resolution......................................................................................................................... 16 Create DPI-Aware Applications ................................................................................................................ 16 Add Help to a Mobile Form ...................................................................................................................... 17 ADDING AND CONFIGURING CONTROLS ................................................................................................................. 18 Supported Controls for Windows Mobile Development........................................................................... 18 Supported Event Handlers for Windows Mobile Controls ........................................................................ 19 Collect User Input by Using the Soft Input Panel (SIP) ............................................................................. 19 Programming the InputPanel (SIP) .......................................................................................................... 20 Collect User Input by Using the Soft Input Panel (SIP) ............................................................................. 20 Configure a Hardware Button on a Mobile Device .................................................................................. 20 Configure a Hardware Button on a Mobile Device .................................................................................. 21 IMPLEMENT NOTIFICATIONS ON A MOBILE DEVICE .................................................................................................. 22 Implement Notifications on a Mobile Device ........................................................................................... 22 CREATING AND CONFIGURING TOOLBARS AND MENUS............................................................................................. 23 Create and Configure Standard Toolbar Buttons on Mobile Devices ....................................................... 23 Create and Configure Standard Toolbar Buttons on Mobile Devices ....................................................... 24 Create and Configure Menus and Soft Keys ............................................................................................. 25 Create and Configure Menus and Soft Keys ............................................................................................. 25 CREATING CUSTOM CONTROLS ............................................................................................................................ 26 Create a Custom Control by Extending an Existing Windows Forms Control ........................................... 26 Packaging a custom control..................................................................................................................... 27 Create a Custom Control by Extending an Existing Windows Forms Control ........................................... 27 Define Properties, Methods, and Events for Custom Controls ................................................................. 28 Expose the Properties of Composite Controls .......................................................................................... 28 Expose the Properties of Composite Controls Example............................................................................ 29 Customize a Control to Paint and Render ................................................................................................ 30 Customize a Control to Paint and Render ................................................................................................ 30 MULTITHREADING AND USER INTERFACE CONSIDERATIONS ....................................................................................... 32 Update the User Interface Across Thread Boundaries ............................................................................. 32 Update the User Interface Across Thread Boundaries ............................................................................. 33 MANAGING DEVICE DATA BY USING MICROSOFT SQL SERVER MOBILE ................................................ 34

INTRODUCTION TO SQL SERVER MOBILE ............................................................................................................... 35 Considerations for Using SQL Server Mobile ............................................................................................ 35 Create a Database by Using the Data Source Configuration Wizard ....................................................... 36 Create a Database by Using the Data Source Configuration Wizard ....................................................... 36 Create a Database by Using the Data Source Configuration Wizard ....................................................... 37 Create a Database by Using SQL Server Management Studio ................................................................. 37 Create a Database by Using SQL Server Mobile Query Analyzer ............................................................. 38 Steps to create a database by using SQL Server Mobile Query Analyzer. ................................................ 38 Create a Database Programmatically ...................................................................................................... 38 SqlCeEngine Members ............................................................................................................................. 39 CONNECTING TO A SQL SERVER MOBILE DATABASE ................................................................................................ 40 Connect to a SQL Server Mobile Database by Using Server Explorer ....................................................... 40 Connect to a SQL Server Mobile Database Programmatically ................................................................. 40 Connect to a SQL Server Mobile Database Programmatically ................................................................. 41 Implement SQL Server Mobile Exception Handling .................................................................................. 41 Implement SQL Server Mobile Exception Handling Example ................................................................... 43 RETRIEVING DATA FROM A SQL SERVER MOBILE DATABASE ..................................................................................... 44 Supported SQL Statements ...................................................................................................................... 44 Supported SQL Statements ...................................................................................................................... 44 Execute a SQL Statement ......................................................................................................................... 47 Return and Update a DataSet by Using SqlCeDataAdapter ..................................................................... 48 Retrieve Data by Using SqlCeDataReader................................................................................................ 50 Retrieve Data by Using SqlCeResultSet .................................................................................................... 51 Retrieve Data by Using Direct Table Access ............................................................................................. 51 IMPLEMENTING DATA-BOUND CONTROLS WITH A SQL SERVER MOBILE DATABASE....................................................... 53 Set Data-Bound Control Properties .......................................................................................................... 53 Implement Data Binding .......................................................................................................................... 54 PERFORMING TRANSACTIONS WITH A SQL SERVER MOBILE DATABASE ....................................................................... 56 Introduction to Transaction Support for Mobile Devices ......................................................................... 56 Start a Transaction by Creating a SqlCeTransaction Object .................................................................... 57 Commit or Roll Back a Transaction by Using a SqlCeTransaction Object ................................................ 57 MANAGING ENTERPRISE DATA BY USING MICROSOFT SQL SERVER 2005 AND SQL SERVER MOBILE.. 58 SECURING A SQL SERVER MOBILE DATABASE ......................................................................................................... 59 Considerations for Password-Protecting and Encrypting a Database ..................................................... 59 Secure a Database by Using SQL Server Management Studio ................................................................. 60 Secure a Database Programmatically ...................................................................................................... 60 Accessing password-protected or encrypted databases .......................................................................... 61 MAINTAINING A SQL SERVER MOBILE DATABASE ................................................................................................... 62 Compact a Database................................................................................................................................ 62 Conditions for compacting a database .................................................................................................... 63 Effects of compacting a database............................................................................................................ 63 Verify a Database .................................................................................................................................... 63 Repair a Database ................................................................................................................................... 64 Shrink a Database .................................................................................................................................... 64 Automatically Adjust the Size of a Database ........................................................................................... 65

Flush a Database ..................................................................................................................................... 65 WORKING WITH RDA ........................................................................................................................................ 66 Submit SQL Statements by Using RDA ..................................................................................................... 67 Pull Data by Using RDA ............................................................................................................................ 68 Push Data by Using RDA .......................................................................................................................... 69 Detect and Resolve Conflicts .................................................................................................................... 69 SYNCHRONIZING SQL SERVER MOBILE DATA BY USING MERGE REPLICATION ............................................................... 71 Compare Merge Replication with Remote Data Access ........................................................................... 72 Subscribe to a SQL Server Publication ...................................................................................................... 73 Multiple Subscriptions and the AddSubscription Method ........................................................................ 74 Synchronize with SQL Server Data ........................................................................................................... 74 Reinitialize a Subscription ........................................................................................................................ 75 Detect and Resolve Merge Replication Conflicts ..................................................................................... 76 DEVELOPING CONNECTION CAPABILITIES IN MICROSOFT WINDOWS MOBILE 5.0BASED APPLICATIONS .................................................................................................................................................................. 77 DEVELOPING HTTP CONNECTION CAPABILITIES ...................................................................................................... 78 Connect to a Web Resource by Using WebRequest ................................................................................. 78 Connect to a Web Page by Using HttpWebRequest ................................................................................ 79 Set Authentication Credentials ................................................................................................................ 80 Send Data to a Web Page ........................................................................................................................ 81 Handle WebRequest Exceptions .............................................................................................................. 83 Set and Retrieve HTTP Headers and Cookies ........................................................................................... 84 CALLING WEB SERVICES ..................................................................................................................................... 86 Add a Reference to a Web Service ........................................................................................................... 86 Make Synchronous Web Service Calls ...................................................................................................... 86 Make Asynchronous Web Service Calls .................................................................................................... 87 Preauthenticate a Web Service Call ......................................................................................................... 87 Maintain Session State in a Web Service ................................................................................................. 88 SENDING AND RECEIVING MESSAGES BY USING MESSAGE QUEUING........................................................................... 90 What is Message Queuing? ..................................................................................................................... 90 Perform Operations on a Message Queue ............................................................................................... 90 Send Messages to a Message Queue ....................................................................................................... 92 Retrieve Synchronous Messages from a Message Queue ........................................................................ 93 Retrieve Asynchronous Messages from a Message Queue...................................................................... 95 WORKING WITH ADVANCED COMMUNICATION TECHNIQUES FOR MOBILE DEVICES ....................................................... 97 Communicate with a Remote Server by Using a TCP Client ..................................................................... 97 Initiate a TCP Connection to a Remote Server ......................................................................................... 98 Write Data to a TCP Client ....................................................................................................................... 98 Communicate by Using a Serial Port ........................................................................................................ 99 IMPLEMENTING INTEROPERABILITY AND PLATFORM FEATURES IN WINDOWS MOBILE 5.0BASED APPLICATIONS ......................................................................................................................................... 101 RETRIEVING SYSTEM STATE BY USING STATE AND NOTIFICATIONS BROKER ................................................................. 102 Available System State Values ............................................................................................................... 103 Query the Current System State Values ................................................................................................. 103

Monitor Phone Radio Status .................................................................................................................. 104 Manage Device Power Usage ................................................................................................................ 104 INTEGRATING OUTLOOK MOBILE FEATURES IN A WINDOWS MOBILEBASED APPLICATION ........................................... 106 Overview of the Microsoft.WindowsMobile.PocketOutlook Namespace .............................................. 106 Send and Intercept SMS Messages ........................................................................................................ 106 Create and Send E-Mail Messages ......................................................................................................... 108 Add, Modify, and Delete Contacts, Tasks, and Appointments ............................................................... 108 USING PLATFORM INVOKE TECHNOLOGY TO CALL UNMANAGED DLL FUNCTIONS ....................................................... 111 Overview of Platform Invoke Technology .............................................................................................. 111 Call an Unmanaged DLL Function .......................................................................................................... 112 Marshal Data from Managed to Unmanaged Code .............................................................................. 112 IMPLEMENTING INTER-PROCESS COMMUNICATION ............................................................................................... 113 Why Use Inter-Process Communication? ............................................................................................... 113 Send and Receive Win32 Messages ....................................................................................................... 113 OPTIMIZING, PACKAGING, AND DEPLOYING MICROSOFT WINDOWS MOBILE 5.0BASED APPLICATIONS ................................................................................................................................................................ 116 MEASURING AND TUNING SYSTEM RESOURCES..................................................................................................... 117 Guidelines for Managing Memory and Power on Mobile Devices ......................................................... 117 Techniques for Managing Memory on Mobile Devices.......................................................................... 118 Techniques for Diagnosing Performance on Mobile Devices ................................................................. 120 Enable Performance Counters on a Mobile Device ................................................................................ 120 Enable Trace on a Mobile Device ........................................................................................................... 123 OPTIMIZING, PACKAGING, AND DEPLOYING MICROSOFT WINDOWS MOBILE 5.0BASED APPLICATIONS ......................... 124 Introduction to the Application Security Model ..................................................................................... 124 Sign the Application Assembly ............................................................................................................... 124 Sign the Application by Using a Trusted Privilege or Un-Privilege Certificate ....................................... 125 PACKAGING AND DEPLOYING WINDOWS MOBILEBASED APPLICATIONS ................................................................... 127 Create a Mobile Device CAB Project ...................................................................................................... 127 From the list of output options, select Primary output, and then click OK. ............. 128 Customize the CAB Project ..................................................................................................................... 128 Deployment Options for Windows MobileBased Applications ............................................................ 129 WORKING WITH REMOTE TOOLS FOR VISUAL STUDIO 2005 ................................................................................... 130 Remote Tools for Visual Studio 2005 ..................................................................................................... 130 Run the Remote Tools for Visual Studio 2005 ........................................................................................ 131 View the File System by Using the Remote File Viewer ......................................................................... 131 View the Registry by Using the Remote Registry Editor ........................................................................ 132 View Running Processes by Using the Remote Process Viewer ............................................................. 132 LABS ....................................................................................................... ERROR! MARCADOR NO DEFINIDO. LAB: CREATING A WINDOWS MOBILE 5.0BASED APPLICATION USER INTERFACE ............ ERROR! MARCADOR NO DEFINIDO. Task 1: Creating a Visual Studio Project and Using Device Emulator .......... Error! Marcador no definido. Task 2: Designing and Creating the User Interface for a Windows Mobile 5.0based Application. .. Error! Marcador no definido. Task 3: Creating a Custom Control .............................................................. Error! Marcador no definido. LAB: CREATING AND USING A SQL SERVER MOBILE DATABASE ..................................... ERROR! MARCADOR NO DEFINIDO.

Task 1: Creating and Connecting to a SQL Server Mobile Database ............ Error! Marcador no definido. Task 2: Querying and Retrieving Data from a SQL Server Mobile Database Error! Marcador no definido. LAB: MANAGING ENTERPRISE DATA BY USING SQL SERVER 2005 AND SQL SERVER MOBILE ........... ERROR! MARCADOR NO DEFINIDO. Task 1: Performing Security Operations on a SQL Server Mobile Database Error! Marcador no definido. Task 2: Performing Maintenance Operations on a SQL Server Mobile Database ....... Error! Marcador no definido. LAB: CREATING COMMUNICATION CAPABILITIES IN WINDOWS MOBILE APPLICATIONS ...... ERROR! MARCADOR NO DEFINIDO. Task 1: Creating an asynchronous call to a Web service ............................. Error! Marcador no definido. Task 2: Creating an Asynchronous Call to Retrieve a Web Page ................. Error! Marcador no definido. LAB: IMPLEMENTING INTEROPERABILITY AND PLATFORM FEATURES IN WINDOWS MOBILE 5.0BASED APPLICATIONS . ERROR! MARCADOR NO DEFINIDO. Task 1: Responding to Platform-Specific Events by Using State and Notifications Broker ................ Error! Marcador no definido. Task 2: Checking Battery State Levels .......................................................... Error! Marcador no definido. LAB: OPTIMIZING, PACKAGING, AND DEPLOYING A WINDOWS MOBILEBASED APPLICATION............ ERROR! MARCADOR NO DEFINIDO. Task 1: Signing a Windows MobileBased Application ............................... Error! Marcador no definido. Task 2: Packaging the Application ............................................................... Error! Marcador no definido. Task 3: Deploying the Application to Device Emulator by Using ActiveSync Error! Marcador no definido. Task 4: Using Remote Tools to Ensure Deployment of the Application ....... Error! Marcador no definido.

Designing and Developing a Microsoft Windows Mobile 5.0 User Interface


Course Information
The Developing Windows Mobile 5.0 Applications Using Microsoft Visual Studio 2005 collection introduces you to the Windows Mobile 5.0 platform and Microsoft SQL Server 2005 Mobile Edition. It also describes how to develop Windows Mobile 5.0based applications by using Visual Studio 2005. The Developing Windows Mobile 5.0 Applications Using Microsoft Visual Studio 2005 collection requires you to meet the following prerequisites:
One to two years experience working with the Microsoft .NET Framework or the Microsoft .NET Compact Framework. One to two years of programming experience in Microsoft Visual Basic .NET or Microsoft Visual C#. One year of working knowledge of Microsoft SQL Server 2000 or Microsoft SQL Server 2005. One year of enterprise application development experience. These courses assume that you are familiar with enterprise-level concepts such as Web services, Transmission Control Protocol (TCP) communication, interoperability, and deployment. One year of application development experience for smart devices using Visual Studio 2005 (recommended).

This audience for this course includes experienced Independent Software Vendors (ISVs) and corporate developers that have prior working experience with the following products and technologies:
The .NET Framework 2.0 or the .NET Compact Framework 2.0 Visual Studio 2005 SQL Server 2000 or SQL Server 2005 Smart Device development with Microsoft Visual Studio .NET (recommended) SQL Mobile (recommended)

At the end of this course, you will be able to:


Configure the Visual Studio 2005 environment and supporting tools for Windows Mobile 5.0 development. Design and develop a user interface that responds to different screen resolutions, sizes, and orientations. Add and configure standard controls and mobile devicespecific controls to a form. Create and configure toolbars, menus, and soft keys on mobile devices. Create a custom control for a mobile device form. Implement multithreading in a Windows Mobile 5.0based application.

This collection Development.

will

prepare

you

for

taking Exam 70-540Windows

Mobile

5.0 Application

Designing and Developing a Microsoft Windows Mobile 5.0 User Interface


Module Introduction

You can use Microsoft Windows Mobile 5.0, along with Microsoft Visual Studio 2005 and Microsoft SQL Server 2005 Mobile Edition, to create Windows Mobile 5.0based applications. Visual Studio 2005 supports Microsoft .NET Compact Framework 2.0 and Windows Mobile 5.0 software development kits (SDKs) that help you create Windows Mobilebased applications that use constrained resources.

Module Objectives

After completing this module, you will be able to:


Configure the Visual Studio 2005 environment and supporting tools for Windows Mobile 5.0 development. Design and develop a user interface that responds to different screen resolutions, sizes, and orientations. Add and configure standard controls and mobile devicespecific controls to a form. Create and configure toolbars, menus, and soft keys on mobile devices. Create a custom control for a mobile device form. Implement multithreading in a Windows Mobile 5.0based application.

Using Microsoft Visual Studio 2005 for Windows Mobile Development

Lesson Introduction

Microsoft Visual Studio 2005 includes features for developing applications for smart devices, such as Windows Mobile 5.0based Pocket PCs and Smartphones. With Visual Studio 2005, you can design, create, and deploy Windows Mobile 5.0based applications by using the .NET Compact Framework and the Windows Mobile 5.0 SDKs.

Lesson Objectives

After completing this lesson, you will be able to:


Describe the Visual Studio 2005 mobile device development features. Describe the technology architecture for mobile development. Describe the features of Windows Mobile 5.0 SDK required for Smartphone or Pocket PC devices. Configure the Visual Studio 2005 environment for creating Windows Mobile 5.0based applications.

Features of the Visual Studio 2005 Environment for Mobile Development


You can use the smart device programmability features of Visual Studio 2005 to develop Pocket PC and Smartphone applications for Windows Mobile 5.0. Visual Studio 2005 provides the following support and features for device development:
.NET Compact Framework 2.0 support Windows Mobile 5.0 support Microsoft ActiveSync support Device Emulator Device-specific controls Multi-platform support Enhanced debugger New data and WYSIWYG user interface designers

Note
You need to install ActiveSync 4.2 on the computer running Visual Studio 2005. This installation on the computer running Visual Studio 2005 is essential even if the Windows Mobile 5.0 SDKs are installed.

Features of the Windows Mobile 5.0 SDK for Visual Studio 2005
To develop applications for Windows Mobile 5.0based devices, you need to download and install the Windows Mobile 5.0 SDK for Pocket PC and the Windows Mobile 5.0 SDK for Smartphone. These SDKs integrate the Windows Mobile 5.0based developer tools with Visual Studio 2005, and they include device emulator images, headers, libraries, interface definition language (IDL) files, reference assemblies, and other tools that are required for developing Windows Mobile 5.0 applications. The following API features are included in the Windows Mobile 5.0 SDKs. Use the Microsoft.WindowsMobile.Telephony.Phone class for programming applications that can initiate a phone call. You can also prompt users to verify the numbers before the call is placed. The Pocket Outlook object model helps you incorporate Personal Information Manager (PIM) data into Windows Mobile 5.0 applications by using the Microsoft.WindowsMobile.PocketOutlook namespace and assembly. The Pocket Outlook object model also provides managed support for both e-mail and Short Message Service (SMS) messages through the Microsoft.WindowsMobile.PocketOutlook.EmailAccount and Microsoft.WindowsMobile.PocketOutlook.SmsAccount namespaces respectively. You can use the new messaging APIs to display existing e-mail messages, use the messaging system's SMS and Email forms to compose new messages, and control the currently active account in the messaging system. You can use the Microsoft.WindowsMobile.Configuration.ConfigurationManager namespace and assembly to configure a device. This namespace uses XML to transmit the configuration to the Windows Mobile 5.0 device. This simplifies configuration and deployment of Windows Mobile projects. The State and Notification Broker API provides a mechanism for storing device, application, and system-state information. You can access the State and Notifications Broker API by using the Microsoft.WindowsMobile.Status namespace. You can use this API to perform the following activities:

Notify the applications about events occurring in the device or in the other applications. For example, a power-intensive application can be notified about the changes in the battery power status, and an application that requires Internet connectivity can be notified about the connection status. Monitor any registry key in the system. The header file (snapi.h) contains definitions for the registry key, path, value, and bitmask for all the base notifications that are provided by the system.

Features of the Windows Mobile 5.0 SDK for Visual Studio 2005
The following enhancements have been introduced in the Windows Mobile 5.0 SDKs:
Development Environment. You can develop native (C++) and managed code (C# and Visual Basic) applications by using Visual Studio 2005 and .NET Compact Framework. Documentation. The Windows Mobile Help feature contains task-based information to help developers to create, test, and deploy applications for Windows Mobile 5.0based Pocket PC and Smartphone devices. In addition, the Developer's Reference section includes information about more Windows Mobile features. Windows Mobile Help is updated monthly. File Systems and Data Store. Windows Mobile supports Enterprise Database (EDB). Managed Code Development. The Windows Mobile 5.0 SDKs include the Microsoft.WindowsMobile class library, which is designed to supplement the .NET Compact Framework class library. They also support rapid application development (RAD) for creating new Windows Mobilebased applications and for enhancing existing applications. Security. Windows Mobilebased Pocket PCs provide support for a one-tier security mode, which distinguishes between signed and unsigned applications.

Configure the Visual Studio 2005 Environment


Before creating Windows Mobile 5.0based applications, you first need to configure the Visual Studio 2005 environment. Complete the following steps to set up the Visual Studio 2005 environment. To develop a Windows Mobile 5.0based application, install the development tools in the following recommended order:
1. 2. 3. 4. ActiveSync 4.2 Visual Studio 2005 SQL Server 2005 Windows Mobile 5.0 SDKs for Pocket PC and/or Smartphone

Click to download ActiveSync 4.2. Click to download the Windows Mobile 5.0 SDK for Smartphone. Click to download the Windows Mobile 5.0 SDK for Pocket PC.

Note
You can also install the development tools in the following order: Install Visual Studio 2005, then install SQL Server 2005, then install ActiveSync 4.2, and finally install Windows Mobile 5.0 SDKs.

To ensure that you are prompted to select a device when you deploy your solution, perform the following steps:
1. 2. In Visual Studio 2005, on the Tools menu, click Options, click Device Tools, and then click General. If Device Tools is not visible, select Show All Settings at the bottom of the Options dialog box. Select the Show Device Choices Before Deploying a Device Project check box.

To create a new Windows Mobile 5.0based application, perform the following steps:

1. 2. 3. 4. 5. 6.

In Visual Studio 2005, on the File menu, point to New, and then click Project. On the New Project dialog box, in the Project Types pane, expand the Visual Basic or Visual C# node. Expand the Smart Device node, select Windows Mobile 5.0 Pocket PC or Windows Mobile 5.0 Smartphone. In the Templates pane, select Device Application. In the Name box, specify a name for the project. In Location box, specify the path where you want to store the project, and then click OK. A representation of a Pocket PC or a Smartphone device appears in the Windows Forms Designer.

Note
After you create the new application project, the process of adding controls and event handling is similar to the process for accomplishing these tasks in desktop projects. The major difference is that there are fewer classes available in the .NET Compact Framework for designing Windows Mobile 5.0based applications.

Device Emulator replicates a hardware device. You can use it to preview, test, and debug applications before deploying them on an actual device. You can launch Device Emulator by using one of the following methods.

Using the Connect to Device dialog box


To launch Device Emulator, perform the following steps:
1. 2. In Visual Studio 2005, click Tools, and then click Connect to Device. In the Connect to Device dialog box, from the Platform list, select a device platform, from the Devices box, select an emulator, and then click Connect.

Using Device Emulator Manager


To launch Device Emulator, perform the following steps:
1. 2. 3. In Visual Studio 2005, click Tools, and then click Device Emulator Manager. In the Device Emulator Manager window, right-click the emulator you want to launch. Click Connect.

To build and test the application in Device Emulator, perform the following steps:
1. 2. In Visual Studio 2005, click Debug, and then click Start (or Start Debugging). In the Deploy dialog box, select the emulator, and then click Deploy. You can view the progress in the status bar.

Creating the User Interface for a Mobile Application


Lesson Introduction
Different mobile devices have different screen resolutions and sizes, depending on the manufacturer and device functionality. To provide a good user experience, design your application to adjust to variations in screen resolution, size, and orientation by setting the appropriate property for the controls and forms.

Lesson Objectives
After completing this lesson, you will be able to:
Apply user interface design considerations that conform to Designed for Windows Mobile guidelines. Set the screen orientation of a Mobile device programmatically. Resize controls to automatically respond to screen orientation changes. Set the device screen resolution during the design phase. Set controls to automatically scale to different screen resolutions. Add Help to a Mobile form.

User Interface Considerations for Mobile Devices


When developing Windows Mobile 5.0based applications, you must create a user interface that helps the user to easily interact with the user interface elements. For example, ensure that there is no disparity between the location of a target on the touch screen and the location of the underlying pixels when the display is viewed at an angle. Use the following guidelines to provide an accessible user interface and a good user experience:
Avoid using fixed font sizes and small font sizes. Ensure that the user interface elements are clearly visible in low light. Ensure effective and easy-to-read color combinations. Group related objects on the screen. Ensure that the tap region and size of the user interface element are ergonomic. Ensure that the number of commands in a menu is limited to 11 entries for a Pocket PC and 8 entries for a Smartphone. Avoid scrolling menus. Avoid creating a submenu of a submenu. Minimize the amount of textual information displayed on the device.

Click to view more information about the guidelines for General Windows Mobile Design. Click to view a document about the Designed for Windows Mobile requirements.

Microsoft has developed the Designed for Windows Mobile logo program to help users identify devices and software products that meet certain standards of quality and compatibility with the Windows Mobile operating system. A product is certified as being designed for Windows Mobile after it has been tested and verified for the features defined by the Designed for Windows Mobile requirements.

Set the Screen Orientation of the Mobile Device


You can programmatically set the screen orientation of a mobile device by using the SystemSettings.ScreenOrientation property. This property can be assigned four values: Angle0, Angle90, Angle180, and Angle270. Angle0 is the default orientation. To change the orientation of the screen programmatically, use the following syntax.

SystemSettings.ScreenOrientation = ScreenOrientation.<Angle>
The following are the effects of the different values of the SystemSettings.ScreenOrientation property on the screen orientation.

Resize Controls to Respond to Orientation Changes


For your application to run on different Windows Mobile 5.0based devices, you must design the application to adjust automatically to different screen orientations. Resize the form controls so that the form content adapts to changes in the screen orientation. You can achieve this effect by using the Anchor, Dock, and AutoScroll properties. The Anchor and Dock properties are mutually exclusive and override each other, with the most recently set property taking precedence over the previously set one. The following table explains the functionality of the Anchor, Dock, and AutoScroll properties with code examples. The Anchor property places a control at a specified distance from the edges of its parent control. The anchored edges will remain in the same position relative to the edges of the parent control when the parent control is resized. You can anchor a control to one or more edges of the container, as shown in the following image.

The following code example adds a Button control to the form and anchors it to the bottom-right corner of the form.
Button button1 = new Button(); button1.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right); button1.Size = new Size(10,10); this.Controls.Add(button1);

The Dock property places a control at the edge of its parent control and automatically resizes the control when the parent control is resized. For example, if you set the Dock property to DockStyle.Left, the control will align itself with the left edges of its parent control and will resize when its parent control is resized. You can also dock a control to all the edges of the container and fill the container, as shown in the following image.

The following code example creates a panel and a text box, adds the text box to the panel, and docks the text box to the bottom edge of the panel.
Panel Panel1 = new Panel (); TextBox textBox1 = new TextBox(); textBox1.Location = new Point(15, 15); Panel1.Controls.Add(textBox1); Panel1.Dock = DockStyle.Bottom; this.Controls.Add(groupBox1);

The AutoScroll property indicates whether the control will display scroll bars. This property is available only for controls that are inherited from the ScrollableControl class, such as the ContainerControl. To enable a control to display scroll bars, set the AutoScroll property to true. The following image shows the effect of enabling the AutoScroll property of a form.

The following code example evaluates the location of a text box and changes the appearance and behavior of its parent containerthe Panel control.
if (text1.Location.X > panel1.Location.X || text1.Location.Y > panel1.Location.Y) { panel1.AutoScroll = true; if( panel1.AutoScrollMargin.Width < 5 || panel1.AutoScrollMargin.Height < 5) { Panel1.Height = Panel1.Height + 10; } }

Set the Screen Resolution


Different mobile devices have different screen resolutions or even screens of different shapes, such as square screens. You must change the device screen resolution to display your application properly on all types of Windows Mobilebased devices. You can change the device screen resolution during the design phase by setting the FormFactor property to the required value. When you create applications for the Windows Mobile 5.0based Pocket PC, you can set the value of the FormFactor property to one of the following:
Windows Mobile 5.0 Pocket PC Windows Mobile 5.0 Pocket PC Phone Windows Mobile 5.0 Pocket PC Phone Square Windows Mobile 5.0 Pocket PC Phone Square VGA Windows Mobile 5.0 Pocket PC Phone VGA Windows Mobile 5.0 Pocket PC Square Windows Mobile 5.0 Pocket PC Square VGA Windows Mobile 5.0 Pocket PC VGA

Create DPI-Aware Applications


If your application is run on a device with a different dots-per-inch (DPI) resolution than that of the device used for its development, the form will appear either too large or too small. For the application to be displayed correctly on the device, forms and controls must be adjusted to the current screen resolution of the device. In Visual Studio 2005, you can create applications containing forms and controls that automatically adjust to the screen resolution of the device. Visual Studio 2005 Designer provides code to automatically scale controls according to the screen resolution of the device. The AutoScaleMode property of a control specifies the current automatic scaling mode of the control. Windows Forms supports the following three automatic scaling modes. To disable automatic scaling, set the AutoScaleProperty to None by using the following code. Visual Basic
Me.AutoScaleMode = _ System.Windows.Forms.AutoScaleMode.None

Visual C#
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;

When you set the AutoScaleMode property to the DPI mode, you can size a control or form relative to the screen. For example, to set DPI scaling on a control that displays a graphic, use the following code. Visual Basic
Me.AutoScaleMode = _ System.Windows.Forms.AutoScaleMode.Dpi

Visual C#
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;

The following code specifies that the application has been developed for a device with a resolution of 96 DPI. Visual C#
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96f);

To scale a control according to the scaling mode of its parent control, set the AutoScaleMode property of the control to Inherit, as shown in the following code. Visual C#
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;

Add Help to a Mobile Form


You can provide Help in Windows Mobile 5.0 by using HTML Help format files. One of the methods of adding Help to a Windows Mobile 5.0based application is to call the Help files when an event is raised by a control on the form. In the event handler of the control, call the ShowHelp method to display the required information. Another method of adding Help to an application is to call the ShowHelp method when the Help option from the Start menu is selected. When the Help menu item is selected, the HelpRequested event of Windows Mobile 5.0 is raised. This event is received by the form that is currently active. To handle the HelpRequested event on the currently active form, override the OnHelpRequested method. Call the ShowHelp method within your implementation of the OnHelpRequested method. The following code example shows how to add Help to a Windows Mobile form. Visual C#
protected override void OnHelpRequested(HelpEventArgs hlpevent) { Help.ShowHelp(this,@"\windows\myAppHelp.htm#Main_Contents"); base.OnHelpRequested(hlpevent); } private void button1_Click(object sender, System.EventArgs e) { Try { Help.ShowHelp(this,@"\windows\myappHelp.htm#overview"); } catch (Exception ex) { MessageBox.Show(ex.Message); } }

Adding and Configuring Controls

Lesson Introduction
To develop applications for a Windows Mobile 5.0based device, the .NET Compact Framework provides controls, such as TextBox, Label, and Button. The .NET Compact Framework provides support for common Windows functionalities such as focus, activation, capture, overlapping, and parent-child relationships. However, it does not provide resourceintensive features, such as enumerations and events that are not appropriate for Windows Mobilebased applications.

Lesson Objectives
After completing this lesson, you will be able to:
Identify the controls you can use when developing Smartphone or Pocket PC applications. Identify the control event handlers you can use for Windows Mobile 5.0based applications. Add an InputPanel control to a form and manipulate it programmatically. Override the default behavior of a hardware button on a Pocket PC device. Display a notification to the user and capture the users response.

Supported Controls for Windows Mobile Development


You can use only a few Windows form controls to develop a Windows Mobile 5.0based application. The controls available for application development depend on the device platform for which the application is being developed. The following table lists some of the common controls that you can use for developing a Windows Mobile 5.0based application for a Smartphone or a Pocket PC.

Control Button TextBox Label PictureBox Notification HardwareButton InputPanel CheckBox DataGrid TabControl RadioButton ToolBar

Pocket PC Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes

Smartphone No Yes Yes Yes No No No Yes Yes No No No

Supported Event Handlers for Windows Mobile Controls


When you develop Windows Mobile 5.0based applications, the events of the controls that you can use are a subset of the events exposed by the same controls in the .NET Framework 2.0. The following events are the most commonly used.

Event Click DoubleClick HandleCreated HandleDestroyed HelpRequested Paint EnabledChanged KeyDown KeyPress

Description Raised when the user clicks the control Raised when the user double-clicks the control Raised when you create a handle for the control Raised when the control's handle is in the process of being destroyed Raised when the user requests help for a control Raised when the user redraws the control Raised when the Enabled property value changes Raised when the user presses a key while a control has focus Raised when the user presses a key while a control has focus

Collect User Input by Using the Soft Input Panel (SIP)


The .NET Compact Framework provides the InputPanel component, which controls the SIP for entering data on Pocket PCs and other devices that run Windows Mobile 5.0. To include the SIP in your application, you can either drag the InputPanel component to your form or write code to add the SIP in your application. The SIP appears as shown in the image.

Note
A MainMenu control is required to use the InputPanel control. The MainMenu control is automatically added to a form when you create the form.

Adding the SIP in your application


To add the SIP to your application, in Visual Studio 2005, from the Toolbox, drag the InputPanel control to your form. A SIP button will be added automatically to the menu bar. Users can toggle the SIP display by tapping the SIP icon. The control that is in focus when the user taps the icon receives the input. You can also add the SIP programmatically to your application, as shown in the following code sample. Visual C#
InputPanel inputPanel1= new InputPanel();

Programming the InputPanel (SIP)


You can program the SIP if you want to reposition or resize a control on the form. You might also want to show or hide the SIP automatically when a control receives or loses focus. The following are the properties of the SIP:
Enabled. This property shows the SIP. Bounds. This property returns the size of the SIP. The Bounds property always returns a width of 240 pixels and a height of 80 pixels for PocketPCs, regardless of whether the SIP is enabled. VisibleDesktop. This property determines the size of the form area that the SIP does not occupy.

The EnabledChanged event is supported by the SIP. This event is raised when the SIP is enabled or disabled, either programmatically or by the user.

Collect User Input by Using the Soft Input Panel (SIP)


The following code example displays the SIP when the text box receives focus. The EnableChanged event checks whether the SIP is enabled or disabled. If the SIP is disabled, the TabControl control reclaims the full screen area. If the SIP is enabled, the TabControl control is resized to occupy the available screen area. Visual C#
private void inputPanel1_EnabledChanged(object sender, EventArgs e { if (inputPanel1.Enabled == false) { VisibleRect = inputPanel1.VisibleDesktop; tabControl1.Height = TabOriginalHeight; } else { VisibleRect = inputPanel1.VisibleDesktop; tabControl1.Height = VisibleRect.Height; } }

Configure a Hardware Button on a Mobile Device


You can override the default behavior of a button on a Pocket PC device so that it activates a form, panel, or custom control by using the HardwareButton control. Smartphones do not support the HardwareButton control. To use the HardwareButton control, perform the following steps:
1. 2. 3. Add the HardwareButton control to a form. Set the AssociatedControl property to the form or control that you want to activate. Set the HardwareKey property to one of the HardwareKeys enumeration values. You can configure up to six buttons.

When you associate a hardware button with a control on the device, a KeyDown event is raised when the user presses the button and a KeyUp event is raised when the user releases the button. To return the hardware button to its original state, set the AssociatedControl property to Nothing in Visual Basic and to a null reference in Visual C#.

Note
The number of hardware buttons available on a Pocket PC device depends on the manufacturer of the device.

Configure a Hardware Button on a Mobile Device


The following code example sets the first and the fourth hardware buttons to activate a form. Visual C#
public Form1() { InitializeComponent(); this.KeyPreview = true; this.KeyUp += new KeyEventHandler(this.OnKeyUp); ConfigHWButton (); } private void ConfigHWButton () { Try { hwb1 = new HardwareButton(); hwb4 = new HardwareButton(); hwb1.AssociatedControl = this; hwb4.AssociatedControl = this; hwb1.HardwareKey = HardwareKeys.ApplicationKey1; hwb4.HardwareKey = HardwareKeys.ApplicationKey4; } catch (Exception exc) { MessageBox.Show(exc.Message + " Check if the hardware " + "button is physically available on this device."); } } private void OnKeyUp(object sender, KeyEventArgs e) { switch ((HardwareKeys)e.KeyCode) { case HardwareKeys.ApplicationKey1: statusBar1.Text = "Button 1 pressed."; break; case HardwareKeys.ApplicationKey4: statusBar1.Text = "Button 4 pressed."; break; default: break; } }

Implement Notifications on a Mobile Device

A notification is triggered in response to an event or when a condition is met. You can display notifications in a notification bubble that can capture and respond to user input, as shown in the image. For example, you can display a notification bubble that informs the user about an incoming call and provides options to accept or reject the call. The Notification class implements Windows Mobile 5.0 functionality for displaying and responding to user notifications. The following properties are supported by the Notification class:
Text. This property specifies the notification text. It can be set to HTML or plain text. HTML is rendered by the Pocket PC HTML control. You can use the Response property of the ResponseSubmittedEventArgs class to retrieve the response string. The response string is then parsed to respond to values in the HTML form. Visible. This property creates notifications and displays them as required. InitialDuration. This property sets the initial display time of the notification balloon.

If you set InitialDuration to zero and Visible to true, the message balloon will not appear, but the corresponding icon will be available in the title bar. You can reactivate the balloon by clicking this icon. The BalloonChanged event of the Notification class is raised when the balloon is shown or hidden. You can show or hide the notification balloon either by setting the Visible property of the Notification object or through user interaction. To use the Notification class, perform the following steps:
1. 2. 3. 4. Create an instance of the Notification class. Create an event handler to display the notification. Add code to handle the ResponseSubmitted event. You can use this event handler only if the Text property is set to HTML. Retrieve and process the users response by using the Response property.

Implement Notifications on a Mobile Device


The following code example adds a Notification and a Button control to a form. Visual C#
SystemState battery; battery = new SystemState(SystemProperty.PowerBatteryState); battery.Changed += new ChangeEventHandler(battery_Changed); void battery_Changed(object sender, ChangeEventArgs args) { BatteryState batteryState = (BatteryState)args.NewValue; if (batteryState == BatteryState.Low) notification1.Text = "Your battery is low, you will need to charge soon."; else if (batteryState == BatteryState.Critical) notification1.Text = "You must charge your battery now!"; notification1.InitialDuration = 5; notification1.Visible = true; }

Creating and Configuring Toolbars and Menus


Lesson Introduction

The toolbars in a mobile device application are different from those in a standard desktop application. A toolbar in a mobile device application displays a limited number of buttons on the mobile screen. In addition to the toolbar, the soft keys on a mobile device display menus and commands. Two soft keys appear on the soft key bar that is located at the bottom of the mobile device screen. These soft keys display an action and a menu that are context-sensitive and can be changed dynamically by an application.

Lesson Objectives

After completing this lesson, you will be able to:


Create and configure a standard toolbar for a Windows Mobilebased application. Create and configure menus and soft keys for a Windows Mobilebased application.

Create and Configure Standard Toolbar Buttons on Mobile Devices

You can add multiple toolbars in a desktop application. However, you can add only one toolbar to a mobile device application. A standard desktop application uses the ToolBarStrip control to implement a standard toolbar, whereas a Pocket PC uses the ToolBar control.

Note
In the .NET Compact Framework, the ToolBar control supports a subset of properties, methods, and events that are supported by the ToolBar control in the .NET Framework. Click to view a list of properties, methods, and events that are supported by the ToolBar control.

The toolbar in a Pocket PC is located at the bottom of the interface and displays a limited number of buttons, as shown in the image. To create a toolbar, perform the following steps:

1. Add a ToolBar control to the form. Note In a desktop application, you can add a toolbar to the forms and other controls, such as the Panel control. However, in a mobile device application, you can add a toolbar only to a form. 2. Add ToolBarButton controls to the ToolBar control depending on the number of buttons you want on the toolbar. 3. Add and configure an ImageList control. The ImageList control holds the images to be displayed on the toolbar buttons. 4. Assign a list of images to the ImageList control. 5. Assign the ImageList control to the ImageList property of the ToolBar control. 6. Assign an image index value to the ImageIndex property of each ToolBarButton control. 7. Write an event handler to respond to the click of the toolbar buttons. The ButtonClick event of the ToolBar control is raised when a toolbar button is clicked. To determine which toolbar button is clicked, evaluate the Button property of ToolBarButtonClickEventArgs and perform the appropriate action.
You can add buttons on the toolbar, but you cannot access all these buttons if they exceed the screen size. You can also divide buttons on a toolbar by using separators. A separator is a toolbar button with the Style property set to ToolBarButtonStyle.Separator. To change the appearance of the toolbar, you can use the Style property of each toolbar button. You can set the Style property to PushButton, ToggleButton, Separator, DropDownButton.

Create and Configure Standard Toolbar Buttons on Mobile Devices


Visual C#
ToolBar toolBar1 = new ToolBar(); public void InitializeMyToolBar() { ToolBar toolBar1 = new ToolBar(); ToolBarButton toolBarButton1 = new ToolBarButton(); ToolBarButton toolBarButton2 = new ToolBarButton(); toolBar1.Buttons.Add(toolBarButton1); toolBar1.Buttons.Add(toolBarButton2); toolBar1.ImageList = imageList1; toolBarButton1.ImageIndex = 0; toolBarButton2.ImageIndex = 1; toolBar1.ButtonClick += new ToolBarButtonClickEventHandler(this.toolBar1_ButtonClick); Controls.Add(toolBar1); } private void toolBar1_ButtonClick (Object sender, ToolBarButtonClickEventArgs e) { switch(toolBar1.Buttons.IndexOf(e.Button)) { case 0: . case 1: . } }

Create and Configure Menus and Soft Keys

Soft keys display menus and commands when you press a corresponding hardware button on Windows Mobilebased devices. The soft keys are located on the soft key bar at the bottom of the screen, as shown in the image. The right soft key displays a menu, and the left soft key provides access to the most common action based on the currently displayed user interface. A user can select a soft key by pressing the corresponding hardware button located immediately below the key. In a Windows Mobilebased Pocket PC, a user can also select a soft key by tapping it. The soft key bar should always be present to enable users to access the SIP.

Note
In a Windows Mobilebased Smartphone, soft keys are the only mode of navigating through the application. You can create only two menu items if you use a soft key. More than two menu items make the soft keys inoperable.

When you create a form, the MainMenu control is automatically added to it. The MainMenu control makes the soft keys available to the user. In a Windows Mobilebased Pocket PC, you can also implement one-handed operation. The onehanded operation feature helps the user work with the Pocket PC without using the stylus.

Create and Configure Menus and Soft Keys


Apply the following guidelines when you implement one-handed operation in a Windows Mobilebased Pocket PC:
Eliminate the stylus when you design the application. Use soft keys that are invoked by using hardware buttons. Soft keys act as menus for your application. Dynamically change the menu as different forms in the application are displayed. Incorporate features such as arrow keys and tabs to make your application stylus-free. Correctly set the TabIndex property of all controls used in the application. This property defines the order in which the user can navigate through an application. Try to support navigation by using the direction hardware key for controls. Extend controls to navigate to the next control when a certain key, such as the ENTER key, is pressed.

Creating Custom Controls


Lesson Introduction

The controls available in the .NET Compact Framework 2.0 do not support all the inherited properties, methods, and events that are supported by the controls available with the .NET Framework 2.0. To incorporate the missing functionality, you can derive your own custom controls from common controls. You can create a custom control by defining a public type that inherits either from the Control class or from the UserControl class. You can also create your own classes, properties, methods, and events. You can create a custom control by extending the existing Windows Forms controls. You can also create a composite control, which is a custom control that is built by using multiple Windows Forms controls.

Lesson Objectives

After completing this lesson, you will be able to:


Create a custom control by extending an existing Windows Forms control. Define properties, methods, and events for custom controls. Create a composite control and expose properties of the control. Implement painting and rendering in a custom control.

Create a Custom Control by Extending an Existing Windows Forms Control


Using Visual Studio 2005, you can create custom controls that inherit the functionalities of standard Windows Forms controls. You can also incorporate custom functionality within this custom control that you create. For example, you can create a control named ValueButton that will inherit functionality from the standard Button control and will expose a custom-made property named ButtonValue. You can derive custom controls from common controls to achieve the following goals:
Override properties, methods, and events of common controls. Define additional properties, methods, and events for a control. Define how a control responds to user actionsfor example, a TextBox control that accepts only numeric data.

To create a custom control by extending an existing Windows Forms control, perform the following steps:
1. 2. In Visual Studio 2005, create a Windows Control Library project. Specify a name for the project and the location where you want to save the project. The Component Designer appears.

Note
The project name is also assigned to the root namespace by default. The root namespace is used to qualify the names of components in the assembly.

3. 4. 5. 6. 7. 8. 9.

In Solution Explorer, rename the UserControl1.vb file or the UserControl1.cs file. The name you specify for this file will be the name of the custom control. Open the designer-generated code file in the Code Editor. Locate the partial class and change the inheritance in the declaration from UserControl to the control requiredfor example, Button or TextBox. Add the required properties and methods to the control. Build the control. Create an application that will use the custom control. In the application, add a reference to the control library of the custom control. From the Toolbox, add the custom control to the form.

Packaging a custom control


To distribute a custom control for use by other developers, you can distribute the assembly so that the developers can reference the assembly in the Visual Studio project. You can also distribute the control as an MSI installation to install on development machines. To distribute a custom control to devices, you need to create a Smart Device Cab project and distribute the project to the users.

Create a Custom Control by Extending an Existing Windows Forms Control


This code example creates a custom control by extending the standard Button control by using Visual C#.
//ValueButton.Designer.cs namespace ValueButtonLib { partial class ValueButton { private System.ComponentModel.IContainer components = null; protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } private void InitializeComponent() { components = new System.ComponentModel.Container(); } } } //ValueButton.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; namespace ValueButtonLib { public partial class ValueButton : Button { private int varValue; public int ButtonValue { get { return varValue; } set { varValue = value; } } public ValueButton() { InitializeComponent(); } } }

Define Properties, Methods, and Events for Custom Controls


You can define custom properties, methods, or events for your custom control. The following code examples define a property, a method, and an event for a custom control The following code example creates a property for the background image to be drawn behind the button text. Visual C#
public Image BackgroundImage { get { return this.backgroundImage; } set { this.backgroundImage = value; } }

The following code example creates a bitmap object, fills it with the specified color, and draws an ellipse in the bitmap object to make the object look like a custom image. Visual C#
Bitmap MakeBitmap(Color color, int width, int height) { Bitmap bmp = new Bitmap(width, height); Graphics g = Graphics.FromImage(bmp); g.FillRectangle(new SolidBrush(color), 0, 0, bmp.Width, bmp.Height); g.DrawEllipse(new Pen(Color.DarkGray), 3, 3, width - 6, height - 6); g.Dispose(); return bmp; }

The following code example sets the pressed flag to True when the mouse button is pressed and invalidates the form to cause a repaint. It also resets the pressed flag when the mouse button is released and invalidates the form to redraw the button. Visual C#
protected override void OnMouseDown(MouseEventArgs e) { this.pressed = true; this.Invalidate(); base.OnMouseDown (e); } protected override void OnMouseUp(MouseEventArgs e) { this.pressed = false; this.Invalidate(); base.OnMouseUp (e); }

Expose the Properties of Composite Controls


A composite control is a component with a visual representation. It can consist of one or more Windows Forms controls, components, or blocks of code that can extend functionality by validating user input, modifying display properties, or performing other tasks required by the developer. You can use composite controls on forms in the same manner as other controls. To create a custom control by using the UserControl class, perform the following steps:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

In Visual Studio 2005, create a control library project. Specify a name for the project and the location where you want to save the project. In Solution Explorer, rename the UserControl1.vb file or the UserControl1.cs file. The name that you specify for the file will be the name of the custom control. From the Toolbox, add the required controls in the Component Designer. Set the required properties and methods of these controls. Add event handlers for the required events of the controls. Build the control. Create another application. Add a reference to the control library of the custom control. From the Toolbox, add the custom control to the form.

Expose the Properties of Composite Controls Example


This code example creates a composite control by using Visual C#. ctlClock.Designer.cs
namespace ctlClockLib { partial class ctlClock { private System.ComponentModel.IContainer components = null; protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.lblDisplay = new System.Windows.Forms.Label(); this.timer1 = new System.Windows.Forms.Timer(this.components); this.SuspendLayout(); this.lblDisplay.AutoSize = true; this.lblDisplay.Font = new System.Drawing.Font("Microsoft Sans Serif", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblDisplay.Location = new System.Drawing.Point(0, 0); this.lblDisplay.Name = "lblDisplay"; this.lblDisplay.Size = new System.Drawing.Size(0, 24); this.lblDisplay.TabIndex = 0; this.lblDisplay.TextAlign = System.Drawing.ContentAlignment.MiddleCenter this.timer1.Enabled = true; this.timer1.Interval = 1000; this.timer1.Tick += new System.EventHandler(this.timer1_Tick); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font this.Controls.Add(this.lblDisplay); this.Name = "ctlClock"; this.ResumeLayout(false); this.PerformLayout(); } private System.Windows.Forms.Label lblDisplay; private System.Windows.Forms.Timer timer1; } }

ctlClock.cs
using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Drawing; System.Data; System.Text; System.Windows.Forms;

namespace ctlClockLib {

public partial class ctlClock : UserControl { private Color colFColor; private Color colBColor; public Color ClockBackColor { get { return colBColor; } set { colBColor = value; lblDisplay.BackColor = colBColor; } } public Color ClockForeColor { get { return colFColor; } set { colFColor = value; lblDisplay.ForeColor = colFColor; } } public ctlClock() { InitializeComponent(); } protected virtual void timer1_Tick(object sender, System.EventArgs e) { lblDisplay.Text = DateTime.Now.ToLongTimeString(); } } }

Customize a Control to Paint and Render


When you create a custom control that inherits from the Control class, the control cannot paint the foreground on its own. You must write code to implement foreground painting. For example, if you create a ButtonImage control, you can override the OnPaint method so that you can paint your own foreground and background of the control. To paint the ButtonImage control, perform the following steps:
1. 2. Override the OnPaint method to paint the foreground and background. Override the OnPaintBackground method. You should avoid calling the base class implementation because it will paint the background.

Note
The OnPaintBackground method is called by the base control to draw the background. If you do not override this method in the control, it will flicker when re-drawing the control. This flickering occurs because the OnPaintBackground method is called before the OnPaint method. 3. 4. Draw the background in the OnPaint method. Then, draw the foreground, which uses padding to ensure that the text is drawn slightly away from the border. After the painting is completed, dispose the brushes used so that the resources used by these brushes are released.

Customize a Control to Paint and Render


Use the following code example to override the OnPaint Method.

Visual C#
protected override void OnPaint(PaintEventArgs e) { SolidBrush backColorBrush = new SolidBrush(this.BackColor); e.Graphics.FillRectangle(backColorBrush, this.ClientRectangle); Color foregroundColor = ((this.Enabled) ? this.ForeColor : SystemColors.GrayText); SolidBrush foreColorBrush = new SolidBrush(foregroundColor); Rectangle textRectangle = this.ClientRectangle; e.Graphics.DrawString(this.Text, this.Font, foreColorBrush,textRectangle); backColorBrush.Dispose(); foreColorBrush.Dispose(); base.OnPaint(e); } protected override void OnPaintBackground(PaintEventArgs e) { // }

Multithreading and User Interface Considerations

Lesson Introduction

You can use multithreading in a Windows Mobilebased application to run multiple threads for an operation simultaneously. Multithreading helps you keep the user interface free to respond to user input while a resource-intensive computation runs on a background thread.

Lesson Objectives

After completing this lesson, you will be able to:


Explain the purpose of using multithreading in a Windows Mobile user interface. Call a control method across thread boundaries in a multithreaded application.

Update the User Interface Across Thread Boundaries

Controls in Windows Forms are bound to a specific thread and are not thread-safe. A control can be created on any thread, but after you create the control, it cannot switch threads. Therefore, if you are calling a method of a control from a different thread, use the Invoke method or the BeginInvoke method of the control. The Invoke method makes a synchronous call to the method, whereas the BeginInvoke method makes an asynchronous call to the method. When you use the BeginInvoke method to call a method, the EndInvoke method retrieves the return value of the asynchronous operation. If the current control does not have an underlying window handle, the Invoke or the BeginInvoke method searches the control's parent chain for a control or a form that has a window handle. If an appropriate handle is not found, the method throws a NotSupportedException exception. Exceptions raised during the call are propagated back to the caller. The InvokeRequired property of a control retrieves a value that determines whether the Invoke method or the BeginInvoke method must be called. When you call the Invoke method or the BeginInvoke method, the CreateGraphics method creates the graphics for the current control if the control has an underlying window handle. The graphics is valid only for the duration of the current windows message.

Update the User Interface Across Thread Boundaries


To call the myDelegate method of a form, use the Invoke method, as shown in the following code example. Visual C#
this.Invoke(new EventHandler(myDelegate, object[])); public void myDelegate (object sender, EventArgs e) { myTextBox.Text = "Executed the given delegate"; }

To call the myDelegate method of a form from the worker thread, use the BeginIvoke method, as shown in the following code example. Visual C#
myTextBox.BeginInvoke(new InvokeDelegate(myDelegate)); public void myDelegate () { myTextBox.Text = "Executed the given delegate"; }

Managing Device Data by Using Microsoft SQL Server Mobile


Module Introduction

You can create databases for use with your Windows Mobile 5.0based applications by using Microsoft SQL Server 2005 Mobile Edition (SQL Server Mobile). Using SQL Server Mobile, you can create local, single-user databases to store data that can be viewed and updated by your mobile applications. After you have worked with the data on the device, you may need to synchronize this data with the data on a computer running SQL Server. You can also create a SQL Server Mobile database that is integrated and synchronized with Microsoft SQL Server 2005 as part of an enterprise solution.

Module Objectives

After completing this module, you will be able to:


Create a SQL Server Mobile database programmatically and by using tools in Microsoft Visual Studio 2005 and SQL Server 2005. Connect to a SQL Server Mobile database programmatically and by using Server Explorer. Retrieve data from a SQL Server Mobile database. Implement data-bound controls with a SQL Server Mobile database. Perform transactions with a SQL Server Mobile database.

Creating a SQL Server Mobile Database

Lesson Introduction

You can create SQL Server Mobile databases programmatically or by using tools, such as the Data Source Configuration Wizard, that are available in Visual Studio 2005. You can also create SQL Server Mobile databases by using SQL Server Management Studio and SQL Server Mobile Query Analyzer. To ensure high application performance when using SQL Server Mobile, consider factors such as portability, memory, size of databases, and data synchronization.

Lesson Objectives

After completing this lesson, you will be able to:


Describe the features of SQL Server Mobile. Evaluate the considerations for using SQL Server Mobile. Create a SQL Server Mobile database by using the Data Source Configuration Wizard. Create a SQL Server Mobile database by using SQL Server Management Studio. Create a SQL Server Mobile database by using SQL Server Mobile Query Analyzer. Create a SQL Server Mobile database programmatically by using the SqlCeEngine class.

Introduction to SQL Server Mobile


SQL Server Mobile is a mobile database that extends Microsoft enterprise solutions to business and personal information management (PIM) applications on a mobile device. SQL Server Mobile is designed to support smart devices and provides you with a consistent programming model for rapid application development (RAD). SQL Server Mobile is integrated into Visual Studio 2005 and SQL Server 2005. Click to download SQL Server Mobile from the Web. SQL Server Mobile provides the following features:
A compact database engine and a robust query optimizer. Support for multiple concurrent connections to a database. Support for merge replication and remote data access (RDA). A setup and connectivity wizard that help you setup and configure the mobile database. Support for Microsoft .NET Compact Framework Data Provider for SQL Server Mobile (System.Data.SqlServerCe). Support for Microsoft ADO.NET and Microsoft OLE DB Provider. Support for a subset of the SQL syntax.

SQL Server Mobile also provides the SQL Server Mobile Query Analyzer tool that you can use to perform the following tasks:
Create databases. Manage and connect to other databases on a device. Verify RDA and replication applications. Query objects by using the SELECT statement. Compact and repair a database. Insert and delete rows. Modify existing data in a table. Create and modify tables and indexes in a database.

Considerations for Using SQL Server Mobile


SQL Server Mobile databases are portable between various mobile device platforms and computers. But, the space available on the mobile device limits the size of the database that can be stored on the device. Consider the following factors when you use SQL Server Mobile. SQL Server Mobile provides the following portability features:
SQL Server Mobile is typically installed as part of the deployment of a Microsoft .NET Compact Frameworkbased application, but it can also be installed independently on a smart device. You can use RDA and merge replication to transfer and synchronize data between SQL Server databases and Windows Mobile based devices. This data can be manipulated offline and then synchronized with the data on the server.

Consider the following factors related to database size and performance:


The SQL Server Mobile Database Engine occupies approximately 2.2 MB to 2.6 MB of disk space, depending on the processor of the mobile device. The size of the database file (.sdf) on the mobile device can be up to 4 GB. A maximum of 100,000 records can be stored in a table for best performance. The record size and query complexity determine the number of records you can store in a table.

The performance of a database application depends on the speed of the media on which the database is stored. The database on the supported mobile device should be as small as possible. It is a good practice to store only the required data on the device.

SQL Server Mobile provides the following features for data synchronization:
Mobile users often need to work with offline data when connectivity is not available. In these scenarios, you can use SQL Server Mobile to provide a relational store that can be synchronized with SQL Server when a connection is available. Data can be synchronized on any device that can access a server running Microsoft Internet Information Server (IIS). Web Services can be used to synchronize transaction data, but not to synchronize the complete database with SQL Server.

Create a Database by Using the Data Source Configuration Wizard


In Visual Studio 2005, you can create a SQL Server Mobile database from within a project or from outside a project. After you create the database, you can configure it and connect to it. If you need to include a database in a project, create it as a data source within the project by using the Data Source Configuration Wizard. The wizard helps you create and edit data sources in an application. After you run the Data Source Configuration Wizard, the data source is available in the Data Sources window. To view the new database as a dataset in the Data Sources window, on the Data menu, click Show Data Sources.

Create a Database by Using the Data Source Configuration Wizard


To create a database outside a project by using Server Explorer, perform the following steps:
1. 2. 3. On the View menu, click Server Explorer. To open the Choose a Data Source dialog box, right-click Data Connections, and then click Add Connection. To select the data source, in the Choose a Data Source dialog box, select Microsoft SQL Server Mobile Edition, and then click Continue. The Add Connection dialog box is displayed.

Note: To change the data source, in the Add Connection dialog box, click Change.
4. 5. 6. To configure the connection, in the Add Connection dialog box, ensure that My Computer is selected in the Data Source section, and then click Create in the Connection Properties section. To enter the location and name of the new database, in the Create New SQL Server 2005 Mobile Edition Database dialog box, type a fully qualified path and database name (for example, C:\MyDB). To specify the password, in the New Password and Confirm Password boxes, type a strong password as the password for the new database, and then click OK. To ensure that the connection has been made, in the Add Connection dialog box, click Test Connection. A message appears indicating that the test connection succeeded.

7.

Note: SQL Server Mobile does not support opening database files on a network share.
8. 9. To return to the Add Connection dialog box, click OK. To close the Add Connection dialog box, click OK.

Create a Database by Using the Data Source Configuration Wizard


To create a database inside a project by using the Data Source Configuration Wizard, perform the following steps:
1. 2. 3. 4. 5. To open the Data Source Configuration Wizard, open a project. On the Data menu, click Add New Data Source. To select a database, on the Choose a Data Source Type page, ensure that Database is selected, and then click Next. To open the Choose a Data Source dialog box, on the Choose Your Data Connection page, click New Connection. To select the data source, in the Choose a Data Source dialog box, select Microsoft SQL Server Mobile Edition, and then click Continue. The Add Connection dialog box is displayed.

Note:To change the data source, you can click Change in the Add Connection dialog box.
6. 7. 8. 9. To configure the connection, in the Add Connection dialog box, ensure that My Computer is selected in the Data Source section, and then click Create in the Connection Properties section. To enter the location and name of the new database, in the Create New SQL Server 2005 Mobile Edition Database dialog box, type a fully qualified path and database name, such as C:\MyDB. To specify the password, in the New Password and Confirm Password boxes, type a strong password as the password for the new database, and then click OK. To ensure that the connection has been made, in the Add Connection dialog box, click Test Connection. A message appears indicating that the test connection succeeded.

Note:SQL Server Mobile does not support opening database files on a network share.
10. 11. 12. To return to the Add Connection dialog box, click OK. To close the Add Connection dialog box, click OK. To create a database and a dataset inside your project, on the Choose Your Data Connection page, select Yes, include sensitive data in the connection string, and then click Next.

Note:For projects that will be used in real-world applications, exclude sensitive data from the connection string or ensure that the sensitive data is
encrypted. 13. 14. To include your data file in your current project, in the Local database file message box, click Yes. On the Choose Your Database Objects page, select the tables or other objects you want to include in your project, and then click Finish.

Create a Database by Using SQL Server Management Studio


SQL Server Management Studio is an integrated environment used for accessing, configuring, managing, administering, and developing SQL Server components. SQL Server Management Studio is included with SQL Server 2005. You can use SQL Server Management Studio to create and populate a SQL Server Mobile database. To create a SQL Server Mobile database and populate it with data, perform the following steps:
1. 2. 3. 4. 5. Open SQL Server Management Studio. When you are prompted to connect to a server, in the Server Name box, type (local), and then click Connect. In a new query window, write the query for creating a SQL Server Mobile database. Create tables and populate the tables in the new database. To run the query, click Execute.

The following code example creates a database named SQLMobile and a table named MembershipData and populates the table:

USE Master; GO DROP Database SQLMobile; GO CREATE DATABASE SQLMobile; GO USE SQLMobile; GO CREATE TABLE MembershipData (MemberId INTEGER IDENTITY (1,1) CONSTRAINT pkMemberId PRIMARY KEY, MemberName NVarChar (50)); INSERT INTO MembershipData (MemberName) VALUES ('Mr Don Hall');

Create a Database by Using SQL Server Mobile Query Analyzer


You can use Visual Studio 2005 to create a Windows Mobile 5.0based application that uses SQL Server Mobile. When you deploy this application on a device, the SQL Server Mobile Database Engine and SQL Server Mobile Query Analyzer are automatically installed on the device. You can also install SQL Server Mobile Query Analyzer on the device by copying and running the .cab file from the software development kit (SDK) to the device.

Note
SQL Server Mobile Query Analyzer runs only on mobile devices.

After you install SQL Server Mobile Query Analyzer on the smart device, you can use it to create a new database. You can create a database by using the Objects tab of the Query Analyzer window, as shown in the image. On the Objects tab, you can add and drop databases, tables, and indexes. You can also define some of the properties of tables and indexes when you create them. However, for specific table and index definition requirements, you must run the appropriate SQL statements on the SQL tab of the Query Analyzer window.

Steps to create a database by using SQL Server Mobile Query Analyzer.


1. In Query Analyzer, on the Objects tab, select the Databases folder, and then click the connection status button to connect to a database. This button must show a green arrow. If the button shows a red square, a database is connected. You can tap the button to disconnect from the database.

Note:SQL Server Mobile allows only one database connection at a time.


2. 3. 4. 5. 6. In the Connect to SQL Server Mobile dialog box, specify the path and name of the database, and then click New Database. To provide a password for the database, in the Password box, type a password. In the Sort box, select a database collation. The default collation is General. To encrypt the database, select Encrypt. To create the database, click Create.

Create a Database Programmatically


You can create a database during run time by writing the appropriate code. These databases are created on the device and not on the computer running SQL Server 2005. To create a SQL Server Mobile database by using the Engine object, perform the following steps:

1. 2. 3.

Initialize a new Engine object. Set the LocalConnectionString property of the Engine object. This property supports all properties of SqlCeConnection.ConnectionString. To create the database, call the CreateDatabase method of the Engine object.

The following code example creates a file named Test.sdf by using the SqlCeEngine object. Visual C#
string connString = "Data Source='myDatabase.sdf'; LCID=1033; Password=\"s$;2'!dS64\"; " + "Encrypt = TRUE;"; SqlCeEngine engine = new SqlCeEngine(connString);

SqlCeEngine Members
Member SqlCeEngine LocalConnectionString Compact Description An overloaded public constructor that initializes a new instance of the SqlCeEngine class. A public property that gets or sets the connection string to the SQL Server Mobile database. A public method that reclaims wasted space in the SQL Server Mobile database by creating a new database file from the existing file. This method is also used to change the collating order, encryption, or password settings of the database. A public method that creates a new database. A public method that releases all SQL Server Mobile SqlCeEngine resources. An overloaded public method that determines whether two object instances are equal. A public method that serves as a hash function for a particular type. (Inherited from Object.) A public method that gets the Type of the current instance. (Inherited from Object.) A public method that determines whether the specified Object instances are the same instance. (Inherited from Object.) A public method that repairs a corrupted database. A public method that reclaims wasted space in the SQL Server Mobile database by moving empty pages to the end of the file and then truncating the file. A public method that returns a String that represents the current Object. (Inherited from Object.) A public method that recalculates the checksums for each page in the database and compares the new checksums to the expected values. A protected method that allows an Object to attempt to free resources and perform other cleanup operations before the Object is reclaimed by garbage collection. (Inherited from Object.) A protected method that creates a shallow copy of the current Object. (Inherited from Object.)

CreateDatabase Dispose Equals GetHashCode GetType ReferenceEquals Repair Shrink

ToString Verify

Finalize

MemberwiseClone

Connecting to a SQL Server Mobile Database

Lesson Introduction

You can use the .NET Compact Framework to develop applications that use SQL Server Mobile databases. To access and work with data contained within the SQL Server Mobile database, you must connect your application to the database by writing code or by using Server Explorer.

Lesson Objectives

After completing this lesson, you will be able to:


Connect to a SQL Server Mobile database by using Server Explorer. Connect to a SQL Server Mobile database programmatically. Implement exception handling when working with SQL Server Mobile database connections.

Connect to a SQL Server Mobile Database by Using Server Explorer


Server Explorer is a tool that is used to create data connections and to access servers. Server Explorer displays the data connections and the server resources in a tree view. To connect to a SQL Server Mobile database by using Server Explorer, perform the following steps:
1. 2. 3. 4. 5. 6. 7. In Visual Studio 2005, on the View menu, click Server Explorer. In the Server Explorer window, right-click Data Connections, and then click Add Connection. In the Add Connection dialog box, click Change. In the Change Data Source dialog box, in the Data source list box, select Microsoft SQL Server Mobile Edition, as shown in the image. From the Data provider list, select .NET Framework Data Provider for SQL Server Mobile Edition, and then click OK. In the Add Connection Dialog box, in the Connection Properties section, click Browse, browse to the database to which you want to connect, and then click Open. On the Add Connection dialog box, click OK.

Connect to a SQL Server Mobile Database Programmatically


Use the SqlCeConnection class to connect to a SQL Server Mobile database programmatically. Perform the following tasks to connect to the database. Configure a connection by using the SqlCeConnection object. This object represents a unique connection to a data source. When you create an instance of SqlCeConnection, all properties are set to their initial values.

Open a connection to a SQL Server Mobile database by using the Open method of the SqlCeConnection object. The Open method establishes a new connection to the data source. Close a connection to a SQL Server Mobile database by using the Close method of the SqlCeConnection object. The Close method rolls back any pending transactions and ends the connection. If SqlCeConnection goes out of scope, the connection is not closed. You must explicitly close the connection by calling the Close method or the Dispose method.

Connect to a SQL Server Mobile Database Programmatically


The following code example uses the SqlCeConnection object to connect to myDatabase.sdf, insert a row into the Customers table, and then close the connection. Visual C#
SqlCeConnection conn = null; conn = new SqlCeConnection("Data Source = MyDatabase.sdf; Password ='<pwd>'"); conn.Open(); SqlCeCommand cmd = conn.CreateCommand(); cmd.CommandText = "INSERT INTO Customers ([Customer ID], [Company Name]) Values('NWIND', 'Northwind Traders')"; cmd.ExecuteNonQuery(); conn.Close();

Implement SQL Server Mobile Exception Handling


Exception handling helps you trap and handle each error as it occurs in the application. You can handle exceptions in SQL Server Mobile by using the SqlCeException, SqlCeErrorCollection, and SqlCeError classes. When an error occurs, an SqlCeException object is created. This object includes the SqlCeErrorCollection object, which is a collection of SqlCeError objects. An SqlCeError object generates an error message for every error. The object contains a set of error parameters that provides detailed information about each error. The following table provides some scenarios and the corresponding code examples related to exception handling. Connecting to a base file that does not exist This is a type of engine error and is indicated by the error number 25046. This error occurs when you try to connect to a database whose file does not exist. The following code example shows how to implement exception handling for this error. Visual C#

try { //... } catch (SqlCeException e) { if(25046 == e.NativeError) //SSCE_M_FILENOTFOUND MessageBox.Show("The database file cannot " + "be found. Check the path " + "to the database." + e.Message); }

Connecting to a table that does not exist

This is a type of client agent error and is indicated by the error number 28607. This error occurs when you try to access a table that does not exist in the database. The following code example shows how to implement exception handling for this error. Visual C#
try { //... } catch (SqlCeException e) { if(28607 == e.NativeError) //SSCE_M_TABLEDOESNOTEXIST MessageBox.Show("The table does not exist. " + e.Message); }

Modifying the column data type This is another type of client agent error and is indicated by the error number 28608. This error is generated when you try to modify a column data type that does not allow any modification. The following code example shows how to implement exception handling for this error. Visual C#
try { //... } catch (SqlCeException e) { if(28608 == e.NativeError) //SSCE_M_CANTMODIFYCOLUMNTYPE MessageBox.Show("Internal error: " + "Cannot modify the column type. " + e.Message); }

Accessing and invalid column This is a type of query processor error and is indicated by the error number 25503. This error is generated when you try to access an invalid column name. The following code example shows how to implement exception handling for this error. Visual C#
try { //... } catch (SqlCeException e) { if(25503 == e.NativeError) //SSCE_M_QP_BAD_COLNAME MessageBox.Show("The column name is not valid. " + e.Message); }

Entering null values in a column This is a type of engine error and is indicated by the error number 25200. This error occurs when you try to enter null values in a column that does not allow null values. The following code example shows how to implement exception handling for this error. Visual C#
try { //... } catch (SqlCeException e)

{ if(25200 == e.NativeError) //SSCE_WRN_COLUMNNULL MessageBox.Show("The column cannot have " + "NULL values. " + e.Message); }

Implement SQL Server Mobile Exception Handling Example


This Visual C# code example uses the SqlCeError class to detect and display errors that occur when connecting to the database by using the SqlCeConnection object.
using System.Data.SqlServerCe; public void ShowSqlCeException() { string mySelectQuery = "SELECT column1 FROM table1"; SqlCeConnection myConnection = new SqlCeConnection("Data Source=nonExistSource.sdf;"); SqlCeCommand myCommand = new SqlCeCommand(mySelectQuery,myConnection); try { myCommand.Connection.Open(); } catch (SqlCeException e) { ShowErrors(e); } } public static void ShowErrors(SqlCeException e) { SqlCeErrorCollection errorCollection = e.Errors; StringBuilder bld = new StringBuilder(); Exception inner = e.InnerException; if (null != inner) { MessageBox.Show("Inner Exception: " + inner.ToString()); } foreach (SqlCeError err in errorCollection) { bld.Append("\n Error Code: " + err.HResult.ToString("X")); bld.Append("\n Message : " + err.Message); bld.Append("\n Minor Err.: " + err.NativeError); bld.Append("\n Source : " + err.Source); foreach (int numPar in err.NumericErrorParameters) { if (0 != numPar) bld.Append("\n Num. Par. : " + numPar); } foreach (string errPar in err.ErrorParameters) { if (String.Empty != errPar) bld.Append("\n Err. Par. : " + errPar); } MessageBox.Show(bld.ToString()); bld.Remove(0, bld.Length); } }

Retrieving Data from a SQL Server Mobile Database


Lesson Introduction
After connecting to SQL Server Mobile, you can retrieve data from a SQL Server Mobile database and manipulate the data. When developing applications in Visual Studio 2005, you can retrieve data from a SQL Server Mobile database by using a dataset or a resultset.

Lesson Objectives
After completing this lesson, you will be able to:
Identify SQL statements that you can use with SQL Server Mobile. Execute an SQL statement against a SQL Server Mobile data source. Return and update a DataSet by using SqlCeDataAdapter. Retrieve data by using SqlCeDataReader. Retrieve data by using SqlCeResultSet. Retrieve data by using direct table access.

Supported SQL Statements


SQL Server Mobile supports SQL grammar that you can use to query and modify a database or modify data in a database. Querying a SQL Server Mobile database is similar to querying other data sources, but there are some differences. SQL Reference for SQL Server Mobile is a subset of Transact-SQL for SQL Server 2005. Queries that can run on SQL Server Mobile can also run on SQL Server 2005. However, many of the features of Transact-SQL are not supported by SQL Server Mobile. For example, you can execute only a single SQL statement in a command in SQL Server Mobile. SQL Server Mobile supports parameterized queries. In these queries, parameters are delimited with the question mark (?) character. SQL Server Mobile also supports named parameterized queries through ADO.NET. SQL Server Mobile does not support scripting because scripting depends on SQL Management Objects (SMO). The SMO feature is not supported by SQL Server Mobile.

Supported SQL Statements


SQL statements The following SQL statements are supported by SQL Server Mobile:
CREATE DATABASE INSERT SELECT CREATE TABLE UPDATE ALTER TABLE DELETE CREATE INDEX DROP INDEX DROP TABLE

Functions The following functions are supported by SQL Server Mobile:


Aggregate functions

AVGAVG COUNT MAX MIN SUM Date and Time functions DATEADD, DATEDIFF DATENAME, DATEPART GETDATE Mathematical functions ACOS ASIN ATAN ATN2 CEILING COS COT DEGREES EXP FLOOR LOG LOG10 PI POWER RADIANS RAND ROUND SIGN SIN SQRT TAN String functions NCHAR CHARINDEX LEN LOWER LTRIM_lce_ltrim PATINDEX REPLACE REPLICATE RTRIM SPACE_Ice_space STR STUFF SUBSTRING UNICODE UPPER_lce_upper System functions @@IDENTITY COALESCE DATALENGTH

Data types
Bigint image ntext Synonym:nvarchar(n) Binary(n) integer numeric (p, s) tinyint Bit money real uniqueidentifier datetime national character varying(n) ROWGUIDCOL varbinary(n) Float national character(n) smallint IDENTITY [(s, i)] nchar Synonym:nchar(n)

Note:The ntext and image data types are stored in a new data page when the number of bytes exceeds 256 in SQL Server Mobile. This
can affect the extent of compactness in a database, because SQL Server Mobile databases are compacted page-wise and not byte-wise.

Operators
+ (Add), ~ (NOT) !<(Not Less Than) - (Subtract) = (Equals) !>(Not Greater Than) * (Multiply) >(Greater Than) / (Divide) <(Less Than) % (Modulo) >= (Greater Than or Equal To) + (Positive) &(AND) <= (Less Than or Equal To) - (Negative) | (OR) <>(Not Equal To) ^ (Exclusive OR) != (Not Equal To) IN LIKE NOT ALL OR AND SOME, ANY BETWEEN EXISTS

Execute a SQL Statement


You can use the SqlCeCommand object to issue an SQL statement to a data source. This object supports the following methods that can be used to run commands against a data source.

Method ExecuteReader ExecuteNonQuery ExecuteScalar ExecuteResultSet

Description Executes commands that return multiple rows. Executes SQL commands such as INSERT, DELETE, and UPDATE statements. Retrieves a single valuefor example, an aggregate valuefrom a database. Executes commands and returns a result set.

The data provider used by the SqlCeCommand object is Data Provider for SQL Server Mobile. This data provider supports named parameters for passing parameters to an SQL statement. However, it does not support batched queries. You can use an object of the SqlCeCommandBuilder class to automatically generate Transact-SQL statements for single-table updates. You can generate INSERT, UPDATE, or DELETE statements by setting the SelectCommand property. The SelectCommand property must return at least one primary key or unique column; otherwise, an InvalidOperation exception is thrown, and the commands are not generated.

Note
If you change the SelectCommand property after the first database update, you must call the RefreshSchema method.

The following code example uses the SqlCeCommand object to run an SQL statement. Visual C#
string query = "SELECT [Order ID], [Customer] FROM Orders"; string connString = "Data Source = MyDatabase.sdf"; SqlCeConnection conn = new SqlCeConnection(connString); SqlCeCommand cmd = new SqlCeCommand(query, conn); conn.Open(); SqlCeDataReader rdr = cmd.ExecuteReader(); try { while (rdr.Read()) { int val1 = rdr.GetInt32(0); string val2 = rdr.GetString(1); } } catch(SqlCeException exObj) { //Handle SQL exception here } finally { rdr.Close(); conn.Close(); }

The following code example shows how to execute a parameterized query against a data source. Visual C#
SqlCeConnection conn = new SqlCeConnection("Data Source = MyDatabase.sdf;"); conn.Open(); SqlCeCommand command = conn.CreateCommand(); command.CommandText = "INSERT INTO Region (RegionID, RegionDescription) VALUES (@id, @desc)"; SqlCeParameter param = null; param = new SqlCeParameter("@id", SqlDbType.Int); command.Parameters.Add(param); param = new SqlCeParameter("@desc", SqlDbType.NVarChar, 100); command.Parameters.Add(param); command.Parameters["@desc"].Size = 100; command.Prepare(); command.ExecuteNonQuery(); command.Parameters[0].Value = 21; command.Parameters[1].Value = "mySecondRegion"; command.ExecuteNonQuery();

The following code example uses the SqlCeCommandBuilder object to retrieve data from a data source. Visual C#
try { SqlCeDataAdapter adp = new SqlCeDataAdapter(cmd); SqlCeCommandBuilder cb = new SqlCeCommandBuilder(); cb.DataAdapter = adp; } catch (SqlCeException e1) { //Handle SQL Exception here } catch (InvalidOperationException e2) { //Handle Exception here when The SelectCommand does not return at least //one primary key or unique column. }

Return and Update a DataSet by Using SqlCeDataAdapter


The SqlCeDataAdapter class represents a set of data commands and a database connection that is used for retrieving and saving data to the data source. The SqlCeDataAdapter object uses the Fill method to retrieve data from the data source into the DataSet object. The SqlCeDataAdapter object uses the Update method to send changes made in the DataSet object back to the data source. The following table explains how to populate, manipulate, and update a dataset by using a SqlCeDataAdapter object. To populate a dataset from a database, perform the following steps:
1. 2. 3. 4. 5. Create a connection object by using the SqlCeConnection class. Create an SQL statement by using the SqlCeCommand class. Create an instance of SqlCeDataAdapter to specify the SelectCommand property. Create an instance of the DataSet class to store data from the data source. Call the Fill method of the SqlCeDataAdapter class, specifying the DataSet object as the target.

The following code example selects records from a data source and populates a DataSet object with the selected rows.
SqlCeConnection conn = new SqlCeConnection("Data Source = AdventureWorks.sdf"); SqlCeCommand selectCmd = conn.CreateCommand();

selectCmd.CommandText = "SELECT * FROM Employees"; SqlCeDataAdapter adp = new SqlCeDataAdapter(selectCmd); DataSet ds = new DataSet(); adp.Fill(ds);

You can manipulate and update a database by using the SqlCeDataAdapter class and DataSet objects. The SqlCeDataAdapter class supports the following properties that help you manipulate and update data:
SelectCommand. Gets or sets an SQL statement for selecting records in the data source. InsertCommand. Gets or sets an SQL statement for inserting new records into the data source. DeleteCommand. Gets or sets an SQL statement for deleting records from the dataset. UpdateCommand. Gets or sets a command for updating records in the data source. TableMappings. Gets a collection that provides the master mapping between a source table and a DataTable.

The Update method of the SqlCeDataAdapter class calls the respective INSERT, UPDATE, or DELETE statement for each inserted, updated, or deleted row in the DataSet object. The following code example inserts a new row into the data source by using a SqlCeDataAdapter object.
SqlCeCommand cmd = null; SqlCeDataAdapter adp = null; try { adp = new SqlCeDataAdapter(); SqlCeConnection conn = new SqlCeConnection("Data Source = MyDatabase.sdf"); cmd = conn.CreateCommand(); cmd.CommandText = "SELECT [Employee ID], [First Name] FROM Employees"; adp.SelectCommand = cmd; cmd = conn.CreateCommand(); cmd.CommandText = "INSERT INTO Employees ([First Name]) VALUES (@first)"; SqlCeParameter p = null; p = cmd.Parameters.Add("@first", SqlDbType.NVarChar, 10, "First Name"); p.SourceVersion = DataRowVersion.Original; adp.InsertCommand = cmd; cmd = conn.CreateCommand(); cmd.CommandText = "UPDATE Employees SET " + "[First Name] = @first WHERE [Employee ID] = @employeeID"; p = cmd.Parameters.Add("@first", SqlDbType.NVarChar, 10, "First Name"); p.SourceVersion = DataRowVersion.Current; p = cmd.Parameters.Add("@employeeID", SqlDbType.NVarChar, 20, "Employee ID"); p.SourceVersion = DataRowVersion.Original; adp.UpdateCommand = cmd; DataSet ds = new DataSet(); adp.Fill(ds); MessageBox.Show("Number of rows: " + ds.Tables[0].Rows.Count); ds.Tables[0].Rows.Add(new object[] { null, "Nancy"}); ds.Tables[0].Rows[1][1] = "David"; adp.Update(ds.Tables[0]); } catch (Exception e) { MessageBox.Show(e.Message); } finally { if (null != adp.SelectCommand) adp.SelectCommand.Dispose(); if (null != adp.InsertCommand) adp.InsertCommand.Dispose(); }

Retrieve Data by Using SqlCeDataReader


You can use the SqlCeDataReader class to read a forward-only stream of data rows from a data source. However, if you want to retrieve data with indexes, use the Seek method of the SqlCeDataReader class. In addition, if you want to optimize the read operation, restrict the set of rows to be read by using the SetRange method of the SqlCeCommand class along with the Seek method. The following table explains how to retrieve data by using a SqlCeDataReader object and the SqlCeDataReader.Seek method. Use the ExecuteReader method of the SqlCeCommand object to create a SqlCeDataReader object. The following code example retrieves data by using a SqlCeDataReader object.
conn = new SqlCeConnection("Data Source = AdventureWorks.sdf"); conn.Open(); cmd = new SqlCeCommand("SELECT * FROM DimEmployee", conn); rdr = cmd.ExecuteReader(); while (rdr.Read()) { //Read values from Reader } rdr.Close();

The SqlCeDataReader.Seek method retrieves the records with indexed values that match the specified parameters. This method can be used only when the CommandType property is set to the TableDirect value, the CommandText property is set to a valid base table name, and the IndexName property is set to a valid index name on the specified base table. To set the range of rows that you want to retrieve, use the SetRange method of the SqlCeCommand object. The SetRange method retrieves a set of rows based on their index values. However, this method returns only those rows whose index key values match the specified range. The SetRange method takes three parameters. The first parameter specifies the type of options to be used when specifying the range. The second parameter is the starting key value for the range, and the third parameter is the ending key value for the range.

Note
The SqlCeCommand.SetRange method is a faster alternative to a SELECT statement for retrieving a set of rows from a base table.

The following code example retrieves data by using the SqlCeDataReader.Seek method.
try { SqlCeCommand cmd = conn.CreateCommand(); cmd.CommandType = CommandType.TableDirect; cmd.IndexName = "Orders_PK"; cmd.CommandText = "Orders"; cmd.SetRange(DbRangeOptions.Match, new object[] { 10020 }, null); cmd.SetRange(DbRangeOptions.InclusiveStart | DbRangeOptions.InclusiveEnd, new object[] { 10020 }, new object[] { 10050 }); reader = cmd.ExecuteReader(CommandBehavior.Default); bool onRow = reader.Seek(DbSeekOptions.FirstEqual, new object[] { 10045 }); } catch (Exception e) { MessageBox.Show(e.Message); }

Retrieve Data by Using SqlCeResultSet


The DataSet object helps you browse through a set of rows and update them, whereas, the SqlCeDataReader object uses a forward-only, nonupdatable cursor. However, the SqlCeDataReader object provides better performance than a DataSet object. SQL Server Mobile provides support for the SqlCeResultSet object which combines the features of the DataSet object and the enhanced performance of the SqlCeDataReader object. You can change the characteristics of the SqlCeResultSet object by using the following options of the ResultSetOptions enumeration.

Option Insensitive None Scrollable Sensitive Updatable

Description The ResultSet object does not detect changes made to the data source. No ResultSet object options are specified. The ResultSet object can be scrolled both forward and backward. The ResultSet object detects changes made to the data source. The ResultSet object allows updates.

Note
To enable Visual Studio 2005 to generate the code for a ResultSet object, you must set the value of Custom Tool to MSResultSetGenerator.

The following code example uses the SqlCeResultSet object to retrieve data from a data source. Visual C#
SqlCeConnection conn = null; try { //Create database and connection object here and open the same. //create a CREATE statement to create table and then execute the same using ExecuteNonQuery here cmd.CommandText = "SELECT * FROM myTable"; SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable | ResultSetOptions.Scrollable); SqlCeUpdatableRecord rec = rs.CreateRecord(); rec.SetInt32(0, 34); rec.SetDecimal(1, (decimal)44.66); rec.SetString(2, "Sample text"); rs.Insert(rec); } catch (Exception e) { MessageBox.Show(e.Message); } finally { conn.Close(); }

Retrieve Data by Using Direct Table Access


You can use direct table access to bypass the query processor and provide the application with direct access to the underlying table structures. Table structures support base table cursors, which increase the database performance by working directly on the storage engine. Base table cursors can scroll backward or forward and can be updated. These cursors use minimal resources such as memory. Applications that benefit most from direct table access are those that issue a large number of queries against a small set of tables. However, direct table access cannot be used with joined tables. To use

direct table access, set the CommandType property of the SqlCeCommand object to TableDirect. Set the CommandText property of the SqlCeCommand object to the name of the table you want to access. You can use direct table access with a SqlCeDataReader object or with a SqlCeResultSet object. The following code example directly opens the underlying table. It provides the same result as running the Select * from StudentTable query, but without using the query processor.
SqlCeCommand cmd = new SqlCeCommand("StudentTable", conn); cmd.CommandType = CommandType.TableDirect; SqlCeDataReader rdr = cmd.ExecuteReader(); while (rdr.Read()) { // ... }

The following code example creates a new record by using the CreateRecord method, sets values for the record, and then adds the record to the ResultSet object. For optimal performance, the CommandType property is set to TableDirect.
//Create database and connection object here and open the same. //create a CREATE statement to create table and //then execute the same using ExecuteNonQuery here. //For optimal performance use base table access cmd.CommandText = "myTable"; cmd.CommandType = CommandType.TableDirect; SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable | ResultSetOptions.Scrollable); SqlCeUpdatableRecord rec = rs.CreateRecord(); //Insert record rec.SetInt32(0, 35); rec.SetDecimal(1, (decimal)94.25); rec.SetString(2, "Sample text 2"); rs.Insert(rec);

Implementing Data-Bound Controls with a SQL Server Mobile Database

Lesson Introduction

The mechanism of linking the records in a data source to the controls on a form is called data binding. Data binding helps you browse and manipulate the records of the data source. A SQL Server Mobile database provides support for setting data-bound control properties for a SQL Server Mobile data source.

Lesson Objectives

After completing this lesson, you will be able to:


Set data-bound control properties for a SQL Server Mobile data source. Implement data binding for controls connected to a SQL Server Mobile data source.

Set Data-Bound Control Properties


Implementing data-bound controls on a Windows Mobile Form is similar to implementing controls on a Windows Form. You can use the DataSource property of the control or the BindingSource class to bind controls to a data source. The following table explains how to bind the controls to the data source, retrieve data, and update the data source.

The following code example shows how to bind a ListBox control to a data source by setting the DataSource, DisplayedMember, and ValueMember properties.
public class USState { private string myShortName ; private string myLongName ; public USState(string strLongName, string strShortName) { this.myShortName = strShortName; this.myLongName = strLongName; } } ArrayList USStates = new ArrayList(); USStates.Add(new USState("Alabama", "AL")); ListBox1.DataSource = USStates ; ListBox1.DisplayMember = "LongName" ; ListBox1.ValueMember = "ShortName" ;

You can bind the controls to the data source by using the BindingSource class. First, bind the BindingSource object to the data source by using the DataSource property of the BindingSource object. Then, bind the controls to the BindingSource object. In complex binding scenarios, you can set the DataMember property to a specific column of the data source. You can interact with the data source by making calls to the appropriate methods and properties of the BindingSource object. For example, you can use the MoveNext, MoveLast, and Remove methods to browse through and update the database. You can sort and filter the data by using the Sort and Filter properties.

The following code example shows how to bind a ListBox control to a data source by using the BindingSource class.
private BindingSource binding1; binding1 = new BindingSource(); binding1.DataSource = USStates; ListBox1.DataSource = binding1;

You can update the changes in a database by using the SqlCeDataAdapter class with DataSet objects. Use the SelectCommand, InsertCommand, and DeleteCommand properties of the SqlCeDataAdapter class to manipulate the data, and then use the Update method of SqlCeDataAdapter to update the database with the changes. The following code example shows how to use the Update method.
SqlCeCommand cmd = null; SqlCeDataAdapter adp = null; try { adp = new SqlCeDataAdapter(); SqlCeConnection conn = new SqlCeConnection("Data Source = MyDatabase.sdf"); cmd = conn.CreateCommand(); cmd.CommandText = "SELECT [Employee ID], [First Name], [Last Name] FROM Employees"; adp.SelectCommand = cmd; cmd = conn.CreateCommand(); cmd.CommandText = "INSERT INTO Employees ([First Name], " + "[Last Name]) VALUES ('Nancy', 'Smith')"; adp.InsertCommand = cmd; DataSet ds = new DataSet(); adp.Fill(ds); ds.Tables[0].Rows.Add(new object[] { null, "Ellen", "Adams" }); ds.Tables[0].Rows[1][1] = "David"; ds.Tables[0].Rows[1][2] = "Johnson"; adp.Update(ds.Tables[0]); } finally { //dispose the SelectCommand and InsertCommand objects }

Implement Data Binding


Using Visual Studio 2005, you can implement simple data binding and complex data binding in your application. The following table explains the difference between simple and complex data binding. Simple data binding is the ability of a control to bind to a single data element, such as a value in a table column. This type of binding is mostly used for TextBox and Label controls because these controls display a single value. The following code example shows how to implement simple data binding. Visual C#
//Declare a command variable, sCmd, and a string variable, sVal SqlCeResultSet sResSet = sCmd.ExecuteResultSet(ResultSetOptions.Scrollable); while(sResSet.Read()) { sVal = sResSet.GetString(0); // Or sResSet("FullName"); } textBox1.DataBindings.Add("Text", sResSet, "FullName");

Complex data binding is the ability of a control to bind to more than one data element. Complex binding is also known as list-based binding. DataGridView, ListBox, and ComboBox are some controls that support complex binding. The following code example shows how to implement complex data binding. Visual C#
this.customersTableAdapter.Fill(Me.northwindDataSet.Customers); this.customersBindingSource.DataMember = "Customers"; this.customersBindingSource.DataSource = Me.northwindDataSet; this.listBox1.DataSource = Me.customersBindingSource; this.listBox1.DisplayMember = "CompanyName";

Performing Transactions with a SQL Server Mobile Database


Lesson Introduction

SQL Server Mobile supports transactions. Transactions help you group a series of database changes into one logical operation. You can control transactions by specifying the start and end for each transaction. To start and end a transaction, you use SQL statements. In SQL Server Mobile, you start a transaction by using explicit or autocommit transactions.

Lesson Objectives

After completing this lesson, you will be able to:


Explain transaction support in SQL Server Mobile. Start a transaction for a SQL Server Mobile database. Commit or roll back a transaction for a SQL Server Mobile database.

Introduction to Transaction Support for Mobile Devices


Transactions help you group a series of database changes into one logical operation. After you make changes to the database, you can commit or roll back these changes as a single unit by using transactions. Transactions ensure that the properties of atomicity, consistency, isolation, and durability (ACID) are followed so that the data is correctly committed to the database. For example, if two users issue transactions against a database at the same time and if the transactions include more than one data manipulation language (DML) instruction, the integrity of the transactions must be maintained. If the system needs to perform multiple tasks to complete the transaction, all or none of the tasks must be completed and data must remain in a consistent state. If the connection to the database is lost after the transaction commits, all effects of the transaction must remain in the database. SQL Server Mobile Query Analyzer on a device and SQL Server Management Studio on a desktop help you perform transactions by using ADO.NET or OLE DB API functions in the code. SQL Server Mobile implements transactions differently from SQL Server 2005. SQL Server Mobile supports parallel transactions in ADO.NET, but it does not support distributed transactions or nesting of transactions. In SQL Server Mobile, if a cursor is opened within a transaction, the cursor exists within the scope of that transaction, and it ceases to exist when the transaction is aborted. Therefore, create the cursor outside the scope of the transaction. Save points, which enable an application to roll back part of a transaction if a minor error occurs, are not supported by SQL Server Mobile. Therefore, the application must commit or roll back the full transaction when it is completed.

Start a Transaction by Creating a SqlCeTransaction Object


In SQL Server Mobile, you can start transactions in autocommit mode or in explicit mode. By default, SQL Server Mobile works in the autocommit mode. In this mode, a transaction starts when a DML or a data definition language (DDL) statement is issued, and it ends when the operation is completed. An explicit transaction is one in which you explicitly define both the start and end of the transaction. To start a transaction in the explicit mode, create a SqlCeTransaction object by calling BeginTransaction on the SqlCeConnection object. Use the SqlCeTransaction object for all subsequent tasks, such as committing or canceling transactions. The following code example shows how to start a transaction in the explicit mode. Visual C#
SqlCeConnection conn = new SqlCeConnection("Data Source = MyDatabase.sdf; Password ='<pwd>'"); conn.Open(); SqlCeTransaction tx = conn.BeginTransaction();

Commit or Roll Back a Transaction by Using a SqlCeTransaction Object


To update the database with the changes made by a transaction, commit the transaction by using the SqlCeTransaction.Commit method. This method also releases all the resources, such as locks, that are used by the transaction. If an error occurs when the DML statements are run, return the transaction to its previous state by using the SqlCeTransaction.Rollback method. You can also use this method to cancel a transaction. When you try to commit a transaction that is already committed, an InvalidOperationException is thrown. This exception is also thrown when the connection to the database is lost. Visual C#
SqlCeConnection conn = new SqlCeConnection("Data Source = MyDatabase.sdf; Password ='<pwd>'"); conn.Open(); SqlCeTransaction tx = conn.BeginTransaction(); SqlCeCommand cmd1 = conn.CreateCommand(); SqlCeCommand cmd2 = conn.CreateCommand(); cmd1.Transaction = tx; try { cmd1.CommandText = "INSERT INTO Shippers ([Company Name]) VALUES ('Northwind Traders')"; cmd1.ExecuteNonQuery(); cmd2.CommandText = "INSERT INTO Employees ([Last Name], [First Name]) " + "VALUES ('Nancy', 'Smith')"; cmd2.ExecuteNonQuery(); cmd1.CommandText = "DELETE FROM Products WHERE [Product ID] = 1"; cmd1.ExecuteNonQuery(); tx.Commit(); } catch (Exception) { tx.Rollback(); } finally { conn.Close(); }

Managing Enterprise Data by Using Microsoft SQL Server 2005 and SQL Server Mobile
Module Introduction

Microsoft SQL Server 2005 Mobile Edition (SQL Server Mobile) is a database solution that has been designed for developing Microsoft Windows Mobile 5.0based applications. SQL Server Mobile allows users to copy data from a computer running SQL Server 2005 to their mobile device, work on the data on the device, and then synchronize the data with the data on the server. SQL Server Mobile also supports features that help you secure and maintain databases in an enterprise environment. It also supports technologies, such as merge replication and remote data access (RDA), that help you develop robust enterprise applications.

Module Objectives

After completing this module, you will be able to:


Implement SQL Server Mobile database security by using passwords and encryption. Use maintenance techniques to prevent SQL Server Mobile database fragmentation. View and exchange remote SQL Server data from a mobile device by using RDA. Synchronize SQL Server Mobile data with a SQL Server database by using merge replication.

Securing a SQL Server Mobile Database

Lesson Introduction

To avoid unauthorized access to data, you must secure a SQL Server Mobile database before you allow data exchanges with remote SQL Server databases. You can secure a SQL Server Mobile database by using passwords and encryption. You can password-protect or encrypt a database by using SQL Server Management Studio or by writing the appropriate code.

Lesson Objectives

After completing this lesson, you will be able to:


Apply the considerations for password-protecting and encrypting a SQL Server Mobile database. Secure a SQL Server Mobile database by using SQL Server Management Studio. Secure a SQL Server Mobile database programmatically by using passwords and encryption.

Considerations for Password-Protecting and Encrypting a Database


You can secure access to a SQL Server Mobile database by password-protecting the database. To increase data security, you can also apply encryption to the password-protected database. Consider the following factors before you password-protect a SQL Server Mobile database:
You can create a password to access a local SQL Server Mobile database. However, you cannot create a separate password for each user of the database. You can create a password that is up to 40 characters long and contains a combination of letters, symbols, and digits. You cannot modify a password-protected database without providing the correct password. You cannot completely secure the data contained in a password-protected database because it can be viewed in clear text either programmatically or by using a hex editor.

Consider the following factors for encrypting a SQL Server Mobile database:
You can restrict users from accessing the database by programmatically encrypting the database and by using a password for the database. You can access encrypted databases only if you provide the appropriate password. If the password for an encrypted database is lost, the data is unrecoverable. You cannot use the hex editor to view encrypted data because encrypted data is not saved in the clear-text format.

Note
You must encrypt a database when you need to protect sensitive information, such as credit card details. You can password-protect a database when you want to protect non-sensitive information.

Secure a Database by Using SQL Server Management Studio

When you create a SQL Server Mobile database at design time, you can use SQL Server Management Studio to modify the password of the database and encrypt the database. Perform the following steps to secure a SQL Server Mobile database by using SQL Server Management Studio:
1. 2. 3. 4. 5. 6. In SQL Server Management Studio, open Object Explorer. In Object Explorer, in the Connect list, click SQL Server Mobile. In the Connect to Server dialog box, select the SQL Server Mobile database that you want to configure, and then click Connect. In Object Explorer, right-click the SQL Server Mobile database that you just added, and then click Properties. In the Database Properties window, in the Select a page pane, click Set password. To create a new password, in the Old Password box, type the old password, if one exists, and then in the New Password box, type a new password for the database. You can also choose to encrypt the data in the database by selecting the Encrypt check box. However, this option is available only if you set a password for the database. 7. To save the changes, click OK.

Secure a Database Programmatically


You can secure a SQL Server Mobile database by writing the appropriate code to set a password and enable encryption. Use this method if you create the SQL Server Mobile database at run time. The following table describes how you can create a password-protected database or an encrypted database programmatically. You can create a password-protected database by specifying a password for the database when you create the database. Use SQL syntax to create a password-protected database by specifying the password in the CREATE DATABASE statement. The password must follow the DATABASEPASSWORD keyword, as shown in the following syntax.
CREATE DATABASE "<database_name>" DATABASEPASSWORD '<database_password>'

You can create an encrypted database by enabling encryption and specifying a password for the database when you create the database. Use SQL syntax to create an encrypted database by specifying the password and the ENCRYPTION ON option in the CREATE DATABASE statement, as shown in the following syntax.
CREATE DATABASE "<database_name>" DATABASEPASSWORD '<database_password>' ENCRYPTION ON

Note
You can change the password and the encryption settings only when you perform a compact operation on a database.

Accessing password-protected or encrypted databases


You must provide a password to open a password-protected or an encrypted database. To access a password-protected or an encrypted database by using the SqlCeConnection.Open method, specify the password in the connection string, as shown in the following syntax.
"data source=<database_name>; password=<database_password>"

Maintaining a SQL Server Mobile Database


Lesson Introduction

The internal structure of a SQL Server Mobile database might become fragmented over time. Fragmentation can result in wasted disk space and can slow down the performance of the database. You can perform various tasks, such as repairing a corrupted SQL Server Mobile database and emptying a SQL Server Mobile database buffer pool, to avoid fragmentation and maintain your database.

Lesson Objectives

After completing this lesson, you will be able to:


Compact a SQL Server Mobile database. Determine if a SQL Server Mobile database has become corrupt. Repair a corrupted SQL Server Mobile database. Shrink a SQL Server Mobile database. Adjust the size of a SQL Server Mobile database automatically. Empty a SQL Server Mobile database buffer pool.

Compact a Database
SQL Server Mobile database files are divided into logical units that are referred to as pages. When users work with the data, some pages might contain unused space, and some pages might remain unused. These empty spaces can be recovered by using the Compact method. This method reads rows from the source database and writes those rows to the destination database, ensuring that minimum space is wasted on the destination database. You can also use the Compact method to change database settings such as password and locale ID (LCID). The following table describes how you can compact a database programmatically or by using SQL Server Management Studio. To compact a database by using SQL Server Management Studio, perform the following steps:
1. 2. 3. 4. 5. 6. In Management Studio, open Object Explorer. In Object Explorer, click Connect, and then select SQL Server Mobile. In the Connect to Server dialog box, choose the SQL Server Mobile database that you want to compact, and then click Connect. In Object Explorer, right-click the SQL Server Mobile database that you added, and then click Properties. In the Database Properties dialog box, select Perform full database compaction. Under File Options, select the appropriate option depending on whether you need to replace the existing database or create a new database with a new file name after compacting. For example, to overwrite an existing database file, select the Overwrite Existing Database File check box, modify the name and location of the existing database, and then replace it.

To compact a SQL Server Mobile database programmatically using the Compact method of the SqlServerCe.Engine object, perform the following steps:

1.

Create an Engine object and pass in the connection string to the database to be compacted, as shown in the following example. Visual C# SqlCeEngine engine = new SqlCeEngine("Data Source = AdWks.sdf");

2.

Call the Compact method. When you call the Compact method, you can set database properties, such as specifying a password for the database or enabling encryption for the database, as shown in the following example. Visual C# engine.Compact("Data Source=;" + "Password = a@3!7f$dQ;");

Conditions for compacting a database


The following conditions must be met when compacting a database:
The database must be closed. When the Compact method is called, the destination database must not exist. An error will occur if the database specified by DestConnection already exists. To call the Compact method, the device must have free space equal to at least twice the size of the source database.

Effects of compacting a database


The following are the effects of compacting a database:
The database is re-created, and new indexes are created. Table pages are reorganized so that they reside in adjacent database pages. This reorganization improves space allocation by reducing table fragmentation across the database. Unused space created by object and record deletions is reclaimed by rewriting all database data into new data pages. You must compact databases in which objects and records are frequently added, deleted, and updated often. Incrementing identity columns are reset so that the next value allocated will be one step value higher than the highest value in the remaining records. For example, if all records in a database have been deleted, compacting the database sets the value of the identity column of the next record to the seed value. If the highest remaining identity value in the database is 50 and the step value is 5, compacting the database sets the value of the next record to 55. If values are specified for the locale identifier or password in the destination database connection string, these values will be used when creating the destination database.

Verify a Database

When a page is written to a database file, SQL Server Mobile calculates and saves a checksum for that page. If the page is modified or corrupted after being written to the file, it will not match the saved checksum. When SQL Server Mobile reads this page, it returns a native error, SSCE_M_DATABASECORRUPTED (25017). The Verify method of the SqlCeEngine class recalculates the checksums of every page in the database file and then verifies whether the checksums match their expected values. If the database file has not been corrupted, this method returns the value true. If the database file has been corrupted, the Verify method returns the value false. To verify a SQL Server Mobile database programmatically, perform the following steps:

1.

Create an Engine object, as shown in the following code example. Visual C# SqlCeEngine engine = new SqlCeEngine("Data Source = AdWks.sdf");

2.

Call the Verify method to analyze the database for corrupted rows, as shown in the following code example. Visual C# if (false == engine.Verify())

Repair a Database
If a database file is corrupted, try to recover the database file by using the Repair method. This method scans the database and calculates the page checksums to check for corrupted pages. The following table describes how you can repair a database by using SQL Server Management Studio or by writing the appropriate code. To repair a database by using SQL Server Management Studio, perform the following steps:
1. 2. 3. 4. 5. 6. 7. In Management Studio, open Object Explorer. In Object Explorer, click Connect, and then select SQL Server Mobile. In the Connect to Server dialog box, select the SQL Server Mobile database that you want to repair, and then click Connect. In Object Explorer, right-click the SQL Server Mobile database that you added, and then select Properties. In the Database Properties dialog box, select Repair physically corrupted database. To recover the corrupted rows, select the Recover corrupted rows check box. To replace the existing database with the repaired database, in the File Options section, select the Overwrite Existing Database File check box. You can also choose to create a new database with a new file name.

To programmatically repair a database, perform the following steps:


1. 2. Use the Verify method to determine if the database is corrupt. If the database has corrupted rows, call the Repair method to fix the database. You can delete all the corrupted rows by specifying the DeleteCorruptedRows Repair option. You can also attempt to recover the corrupted rows by specifying the RecoverCorruptedRows Repair option, as shown in the following code example. Visual C# engine.Repair(null, RepairOption.RecoverCorruptedRows);

Tip
If the Repair method is invoked with the RepairOption.DeleteCorruptedRows value, all corrupted pages are discarded. Discarding pages might cause a significant data loss if the corrupted pages contain database schema. If the Repair method is invoked with the RepairOption.RecoverCorruptedRows value, the database will attempt to read and recover data from the corrupted pages. However, using this option does not guarantee that the recovered data will be free of logical errors.

Shrink a Database
You can shrink a SQL Server Mobile database to reclaim unused space in the database by using the Shrink method. However, you cannot use this method to change database settings because it does not create a new database file; it only reorganizes existing records and deletes empty records. When you shrink a database, the empty pages are moved to the end of the file, and the file is truncated. The following table describes the methods that you can use to shrink a database. To shrink a database by using SQL Server Management Studio, perform the following steps:
1. 2. In the SQL Server Management Studio window, open Object Explorer. In Object Explorer, click Connect, and then select SQL Server Mobile.

3. 4. 5. 6.

In the Connect to Server dialog box, choose the SQL Server Mobile database that you want to shrink, and then click Connect. In Object Explorer, right-click the SQL Server Mobile database that you added, and then select Properties. In the Database Properties dialog box, from the left pane, select Shrink and Repair. Click Shrink database by deleting free pages, and then click OK.

To shrink a SQL Server Mobile database programmatically, perform the following steps:
1. Create a SqlCeEngine object and set the Data Source property of the Engine object to the database that you want to shrink, as shown in the following code example. Visual C# SqlCeEngine engine = new SqlCeEngine("Data Source = AdWks.sdf"); 2. Call the Shrink method, as shown in the following code example. Visual C# engine.Shrink();

Automatically Adjust the Size of a Database


SQL Server Mobile supports a technique known as autoshrink that helps you automatically adjust the size of a database file. The autoshrink technique moves pages within a database file so that all empty or unallocated pages are contiguously placed at the end of the file. The empty pages are then truncated and made available for the database file system to use. The autoshrink technique uses negligible processor time and memory and is especially suitable for handheld devices and mobile database products. To set autoshrink time intervals for managed code, use the AutoShrink Threshold property of the connection string. This property specifies the percentage of free space in the file before the autoshrink process starts. The default value of the AutoShrink Threshold property is 60.

Important
To disable autoshrink, set the value of the AutoShrink Threshold property to 100.

The following code example shows how you can autoshrink a SQL Server Mobile database named SalesData.sdf. Visual C#
conn.ConnectionString = "Persist Security Info = False; Data Source = 'SalesData.sdf';" + "Password = '<password>'; File Mode = 'shared read'; " + "Max Database Size = 256; Max Buffer Size = 1024; Autoshrink Threshold = 30";

Flush a Database
By default, unwritten or uncommitted changes pending in the buffer pool are written or flushed to the database every ten seconds. To specify the time interval after which the changes must be flushed to the database, set the value of the Flush Interval property of the connection string. This property sets the maximum number of seconds before committed transactions are flushed to disk. For example, to set the Flush Interval property for a database named SalesData.sdf, use the following code

Visual C#
conn.ConnectionString = "Persist Security Info = False; " + "Data Source = 'SalesData.sdf'; Password = '<password>'; " + "flush Interval = 30";

Working with RDA


Lesson Introduction
RDA in SQL Server Mobile allows you to transfer data between a SQL Server table and a local SQL Server Mobile table. You can use the Pull method to access data on a remote SQL Server database table and copy that data into a local SQL Server Mobile database table. Then, you can read and make changes to the data in the local SQL Server Mobile database table. You can use the tracking options provided by SQL Server Mobile to track the updates made in the local table. After making the required changes in the local table, you can use the Push methods to transfer the updates from the local SQL Server Mobile table to the remote SQL Server database table.

Lesson Objectives
After completing this lesson, you will be able to:
Explain how RDA is used to view and exchange data with a remote database from a mobile device. Submit SQL statements to a remote SQL Server database by using the SubmitSQL method. Pull data from a remote SQL Server database to a mobile device. Push data from a mobile device to a remote SQL Server database. Detect and resolve data conflicts when using RDA.

In SQL Server Mobile, transmitting data from a SQL Server database table to a local SQL Server Mobile database table is referred to as pulling data. Transmitting changes that you make in the local SQL Server Mobile database table to the SQL Server database table is referred to as pushing data. For example, if you are running a sales support application on your Pocket PC, you can download or pull a price list from the SQL Server database. You can then capture new orders in the SQL Server Mobile database on the device and upload or push the data back to the SQL Server database. You can also use the application to submit SQL statements directly to the SQL Server database. To implement RDA, you require three components of SQL Server Mobile: the SQL Server Mobile Database Engine, the SQL Server Mobile Client Agent, and the SQL Server Mobile Server Agent. RDA uses Microsoft Internet Information Services (IIS) as the communication mechanism between the SQL Server database on a server and the SQL Server Mobile database on the device. The SQL Server Mobile Database Engine manages the local database on the device. The SQL Server Mobile Client Agent is located on the device and forwards the requests to the SQL Server Mobile Server Agent, which is located on the computer that runs IIS, by using Hypertext Transfer Protocol (HTTP).

The SQL Server Mobile Server Agent handles the HTTP requests made by the SQL Server Mobile Client Agent. The SQL Server Mobile Server Agent uses temporary message files to manage the exchange of data between SQL Server and SQL Server Mobile. During a pull operation, an application sends a request to the SQL Server Mobile Client Agent. The SQL Server Mobile Client Agent then forwards the request to the SQL Server Mobile Server Agent. The SQL Server Mobile Server Agent receives the request, connects to the SQL Server database, and then returns the resulting recordset to the SQL Server Mobile Client Agent. The SQL Server Mobile Client Agent stores this recordset in the SQL Server Mobile database. During a push operation, the SQL Server Mobile Client Agent extracts all the inserted, updated, and deleted records from the SQL Server Mobile database and then sends them to the SQL Server Mobile Server Agent. The SQL Server Mobile Server Agent receives these records, connects to the SQL Server database, and then copies the changes to the SQL Server database.

Submit SQL Statements by Using RDA


You can use the SubmitSql method to submit SQL statements to an instance of SQL Server in the following scenarios:
When an action needs to be performed on the computer running SQL Server during an RDA pull or push operation When you have connected to the computer running SQL Server through HTTP and need to run a stored procedure but do not need any data to be transferred back

Note:When a direct connection to the computer running SQL Server is available, use the SqlClient class to run statements on the server
When an application needs to run SQL statements on a database located on a remote instance of SQL Server.

Use the SqlCeRemoteDataAccess object to submit SQL statements directly to a computer running SQL Server. Perform the following steps to submit an SQL statement:
1. Initialize an SqlCeRemoteDataAccess object and set the properties for the connection, as shown in the following code example. Visual C# SqlCeRemoteDataAccess rda = new SqlCeRemoteDataAccess("http://www.adventure-works.com/sqlmobile/sqlcesa30.dll", "Data Source=MyDatabase.sdf"); 2. Call the SubmitSql method and pass an SQL statement or name of a stored procedure and the connection string to the SQL Server database, as shown in the following code example. Visual C# rda.SubmitSql("sp_ValidateData", strConn);

The following code example uses the SubmitSQL method to run an SQL command on a remote computer running SQL Server. Visual C#
string rdaOleDbConnectString = @"Data Source=MySqlServer; " + "Initial Catalog=AdventureWorks; User Id=username; " + "Password = <password>"; SqlCeRemoteDataAccess rda = null; try { rda = new SqlCeRemoteDataAccess(); rda.InternetLogin = "MyLogin"; rda.InternetPassword = "<password>"; rda.InternetUrl = "http://www.adventure-works.com/sqlmobile/sqlcesa30.dll"; rda.LocalConnectionString = "Data Source=MyDatabase.sdf"; rda.SubmitSql("CREATE TABLE MyRemoteTable (colA int)", rdaOleDbConnectString); }

catch (SqlCeException) { // Handle errors here } finally { rda.Dispose(); }

Pull Data by Using RDA


You can initiate RDA by pulling data from a SQL Server database to a SQL Server Mobile database. You can pull data by using the Pull method. You can then make changes to the pulled table. You can also track the changes made to the pulled table by specifying the appropriate tracking option in the Pull method. The following is the syntax of the Pull method.
Pull(localTableName, sqlSelectString, oleDBConnectionString, trackOption, errorTable)

The parameters used in this syntax are as follows:


localTableName. Specifies the name of the SQL Server Mobile table that receives the extracted SQL Server records sqlSelectString. Specifies a valid Transact-SQL statement that specifies the table, columns, and records to be extracted from the SQL Server database oleDBConnectionString. Specifies the connection string to the local SQL Server Mobile database trackOption. Specifies whether SQL Server Mobile is tracking changes that are made to the pulled table errorTable. Specifies the name of the local error table that is created if an error occurs when the Push method is called to send changes back to the SQL Server database

The trackOption parameter can take the values RdaTrackOption.TrackingOnWithIndexes or RdaTrackOption.TrackingOn. If the RdaTrackOption.TrackingOn value is used, PRIMARY KEY constraints are created on the pulled table. If the RdaTrackOption.TrackingOnWithIndexes value is used, PRIMARY KEY constraints and additional indexes are created on the pulled table.

Note
If you pull a column that has an index, an index is created on the pulled column. Referential integrity constraints are not created on the pulled table because the related tables may not exist in the SQL Server Mobile database. The related tables must be included in the database by writing the appropriate code.

Perform the following steps to pull data from a server:


1. 2. Initialize an SqlCeRemoteDataAccess object and set the properties for the connection. Call the Pull method by specifying the name of the SQL Server table from which to pull data, the SELECT statement to use, and the connection string to the local SQL Server Mobile database. Specify the appropriate tracking option if you want to track the updates made to the local table.

The following code examples show how to pull data from a table named DimEmployee in a SQL Server database and populate a table named Employees in SQL Server Mobile. Visual C#
string rdaOleDbConnectString = @"Provider=SQLOLEDB; "Data Source=MySqlServer; " + "Initial Catalog=AdventureWorks; User Id=username; " + "Password = <password>"; SqlCeRemoteDataAccess rda = null; try {

rda = new SqlCeRemoteDataAccess("http://www.adventure-works.com/sqlmobile/sqlcesa30.dll", "MyLogin", "<password>", "Data Source=MyDatabase.sdf"); rda.Pull("Employees", "SELECT * FROM DimEmployee", rdaOleDbConnectString, RdaTrackOption.TrackingOnWithIndexes, "ErrorTable"); } catch (SqlCeException) { // Handle errors here } finally { rda.Dispose();}

Push Data by Using RDA

When you push data by using the Push method, the changes are copied from a SQL Server Mobile database to a SQL Server database. This method ensures that the updates are fully implemented on the SQL Server database. The following is the syntax of the Push method.
Push(localTableName, oleDBConnectionString, batchOption)

The parameters used in this syntax are as follows:


localTableName. Specifies the name of the SQL Server Mobile table that receives the extracted SQL Server records oleDBConnectionString. Specifies the connection string to the local SQL Server Mobile database batchOption. Specifies whether the changes being sent back to the SQL Server table should be batched together in a single transaction or sent individually

To push data by using RDA, perform the following steps:


1. Initialize an SqlCeRemoteDataAccess object and set the properties for the connection, as shown in the following code example. Visual C# SqlCeRemoteDataAccess rda = new SqlCeRemoteDataAccess( "http:// " + "www.adventure-works.com/sqlmobile/sqlcesa30.dll", "Data Source=MyDatabase.sdf"); 2. Call the Push method, as shown in the following code example. Visual C# rda.Push("MyLocalTable", rdaOleDbConnectString, RdaBatchOption.BatchingOn);

Detect and Resolve Conflicts

In push operations, RDA in SQL Server Mobile provides a limited conflict-reporting mechanism for rows that cannot be updated on the computer running SQL Server. If the changes made to data by different users do not cause errors, they are not considered conflicts. Examples of conflicting rows in RDA are failed insert, update, or delete operations. To capture conflicting rows, SQL Server Mobile provides an error table that you can specify as part of the Pull method. Use the error table to develop applications for managing conflict detection and reporting. RDA performs the following procedures to detect and resolve data conflicts. RDA stores push operation errors in an error table. This table is defined in the Pull method, and it stores the failed row along with the details of the error. RDA inserts all the columns of the failed record from the base table in the server and adds three additional columns. The s_ErrorDate column specifies the date and time when the error occurred. The s_OLEDBErrorNumber column specifies the HResult of the error. The s_OLEDBErrorString column is a string description of the error. Specify the name of the error table in the ErrorTableName property of the Pull method. When users make changes to the SQL Server Mobile database and the changes are pushed to the server, the SQL Server database table is updated to reflect the changes made by the last user. RDA supports only row-level tracking. Therefore, some rows succeed and the others fail, depending on the options that are selected in the Push method. Error tables are automatically deleted if the associated RDA-tracked table in SQL Server Mobile is dropped, even if rows still exist in the error table. Therefore, cache the data in the error table so that it is not lost when you drop the tracked table. You can also pull the data to a table with a name that is different from the name of the original tracked table. After pushing data to the computer running SQL Server, a warning is issued to the application so that you can examine the error table to determine the cause of the errors. Depending on the error, you need to know the current state of the data on the server. RDA supports non-batch and batch transactions. In a non-batch transaction, conflicts are detected at the row level. The conflicting row is stored in a specified error table, and then the row is removed from the original table. To resolve this conflict, you must pull the table again from the server. In a batch transaction, all rows must succeed to process a complete push operation. If one row fails, the transaction fails and no data is updated. In such cases, design the application to allow the user to correct the conflicting data and merge it with the original database.

Synchronizing SQL Server Mobile Data by Using Merge Replication


Lesson Introduction

You can synchronize the data in the SQL Server Mobile database with the data stored in the SQL Server database by using merge replication or RDA. Merge replication is suitable for portable devices because data can be updated independently and autonomously, on both the device and the server. When the device is connected, data can be synchronized by sending changes from the device to the server and by receiving new changes from the server.

Lesson Objectives

After completing this lesson, you will be able to:


Describe how merge replication is used with mobile devices. Differentiate between merge replication and RDA. Subscribe to a SQL Server publication from a mobile device. Synchronize mobile device data with SQL Server data. Reinitialize a subscription to a SQL Server publication from a mobile device. Describe how SQL Server detects and resolves data conflicts when using merge replication.

SQL Server Mobile replication is modeled on SQL Server merge replication. SQL Server merge replication uses a publish-and-subscribe model. In this model, servers are assigned the role of a Publisher, a Subscriber, or a Distributor, depending on the tasks that the servers perform in the replication process. A Publisher is a server that hosts the data that is to be distributed. The data is organized into publications, which consist of small sets of data called articles. A Subscriber is a server that receives copies of publications from a Publisher. The Subscriber subscribes to a particular publication. The subscription specifies a condition under which the Subscriber receives the publication from the Publisher and maps the articles of this publication to the subscription data tables in the Subscriber. A Distributor is a store-and-forward database server that stores the initial snapshots of publications and distributes the snapshots to the Subscribers. Distributors can also store transactions that are required to be sent to the Subscribers. Using merge replication, you can update data on the device and synchronize that data with the data on a SQL Server whenever you connect the device to the server. Using merge replication, you can replicate data from multiple tables at the same time. Merge replication also provides built-in and custom conflict resolution capabilities to detect and resolve data conflicts between the SQL Server database and the SQL Server Mobile database. In addition, merge replication provides data replication options, such as article types and data filtering, to improve the database performance.

Compare Merge Replication with Remote Data Access


You can use either RDA or merge replication for wireless data transfers. When selecting a data connectivity solution for your mobile application, you should evaluate the following features.

Feature Exchange of tracked data changes

Merge replication When tracked data changes are exchanged, changes are replicated in the server and in the client. Merge replication supports column-level tracking to reduce the amount of data sent from the mobile device to the server by transferring only the changed column data. Column-level tracking is supported only in SQL Server 2005. Merge replication supports row-level tracking for transferring complete rows.

RDA When tracked data changes are exchanged, RDA pushes changes only from the client to the server. It supports rowlevel tracking but does not support columnlevel tracking.

Feature Multiple tables support for data propagation

Merge replication Merge replication supports multiple tables during data propagation. The number of tables propagated can be as many as the number of tables defined in the publication. Merge replication also supports the use of different types of tables to propagate data. When a table is added or removed, the publication (server) is replicated automatically without reinitializing the subscription on the client.

RDA RDA supports only one table during data propagation. In addition, RDA does not support the use of different types of tables to propagate data. When a table at the server is added or deleted, the change is not automatically replicated to the client.

Feature Constraints and indexes

Merge replication Referential integrity constraints and indexes are automatically replicated from the server.

RDA Referential integrity constraints are not replicated, but indexes are optionally replicated.

Feature Conflicts

Merge replication During merge replication, conflicts occur when different users modify the same data and when these modified rows are not updated because of an error. The resolution and management of conflicts is reported on the server. Merge replication supports built-in and custom conflict resolvers.

RDA During RDA, conflicts occur when rows are not updated because of an error. These conflicts are not managed but are optionally reported in an error table on the client. RDA does not support conflict resolvers. It also does not detect changes made to the same rows by a different user.

Feature Identity columns

Merge replication Merge replication supports manual and automatic identity-range handling. It also supports BigInt and Int columns.

RDA RDA supports manual identity-range handling. It also supports BigInt and Int columns.

Feature Server invasiveness

Merge replication During merge replication, tables and columns are added to the database on the server to manage replication.

RDA During RDA, no changes are made to the database on the server.

Subscribe to a SQL Server Publication


Before you create a subscription, you must configure SQL Server replication, create the SQL Server publication, and configure IIS. Then, you can create a SQL Server Mobile subscription programmatically or by using SQL Server Management Studio. SQL Server Mobile Subscribers can subscribe to both SQL Server 2000 and SQL Server 2005 publications. A SQL Server Mobile Subscriber is always a client Subscriber that connects to the Publisher by using the HTTP protocol. Use the following methods to create a new subscription. To create a new subscription programmatically, perform the following steps:
1. 2. 3. Initialize an SqlCeReplication object. Set the connection properties. These properties specify the name and location of the Publication to which you are subscribing, the name and location of the local SQL Server Mobile database, and the location of the SQL Server Mobile Server Agent. Call the AddSubscription method to create the subscription. SQL Server Mobilebased applications use the Replication object to create a subscription programmatically and download that subscription to a SQL Server Mobile database on a Windows Mobilebased smart device. The application does this by creating the Replication object, setting the appropriate Replication object properties, and calling the AddSubscription method. 4. Call the Synchronize method to perform data synchronization and populate the local database with the data from the Publication.

To create a new subscription by using SQL Server Management Studio, perform the following steps:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. From within SQL Server Management Studio, connect to an instance of a SQL Server Mobile database. This database can be running on a connected device, or it can be a file on the desktop computer. In Object Explorer, expand the SQL Server Mobile database node, and then expand Replication. To create a new subscription, right-click Subscriptions, and then choose New Subscriptions. On the Introduction page, click Next. On the Choose Publication page, in the Publisher list, click <Find SQL Server Publisher>, select the Publisher, and then click Connect. In the Publications list, select the publication, and then click Next. On the Identify Subscription page, type a name for the subscription. If the publication to which you are subscribing uses dynamic filtering, provide a HOST_NAME value for this database, and then click Next. On the Web Server Authentication page, type the URL to the virtual directory that contains the SQL Server Mobile Server tools, provide the authentication information, and then click Next. On the SQL Server Authentication page, select the type of SQL Server Authentication required to connect to SQL Server, provide the user name and password, if required, and then click Next. On the Complete the Wizard page, select and copy the sample code to use in a Visual C# or Visual Basic application. To create the subscription, click Finish.

Multiple Subscriptions and the AddSubscription Method


SQL Server Mobile supports synchronizing a single database with multiple publications. Therefore, you must consider the effect of multiple subscriptions on the database performance when using the AddSubscription method. You can use the CreateDatabase or ExistingDatabase options when calling the AddSubscription method. When you use the ExistingDatabase option, you must supply values for the Publisher, Publication, and PublisherDatabase properties before calling the AddSubscription method. The following code example shows how to create a SQL Server Mobile subscription.
1. Initialize a SqlCeReplication object by using the following code. Visual C# SqlCeReplication repl = new SqlCeReplication(); 2. Set the connection properties by using the following code. Visual C# repl.InternetUrl = "http://www.adventure-works.com/sqlmobile/sqlcesa30.dll"; repl.InternetLogin = "MyInternetLogin"; repl.InternetPassword = "<password>"; repl.Publisher = "MyPublisher"; repl.PublisherDatabase = "MyPublisherDatabase"; repl.PublisherLogin = "MyPublisherLogin"; repl.PublisherPassword = "<password>"; repl.Publication = "MyPublication"; repl.Subscriber = "MySubscriber"; repl.SubscriberConnectionString = "Data Source=MyDatabase.sdf"; 3. Call the AddSubscription method by using the following code. Visual C# repl.AddSubscription(AddOption.CreateDatabase); 4. Call the Synchronize method by using the following code. Visual C# repl.Synchronize();

Synchronize with SQL Server Data


You must synchronize data to ensure that data in the SQL Server Mobile subscription database matches the data in the corresponding publication. During synchronization, SQL Server merges the changes made to the subscription database with changes to the publication database, resolves any conflicts that occur, and then returns the changes to the SQL Server Mobile subscription.

How data is synchronized


When a SQL Server Mobile subscriber synchronizes with SQL Server, all data changes are retrieved from the publication database. The first time a SQL Server Mobile subscriber is synchronized, it can retrieve data from the Publication database directly or from the snapshot file in the snapshot folder. SQL Server Mobile can exchange data synchronously or asynchronously. When an application exchanges data synchronously, it waits until data is synchronized before continuing with other processes. When an application exchanges data asynchronously, it continues processing other information during the synchronization.

When data is synchronized


Data synchronization occurs whenever an application requests synchronization by calling the Synchronize method of the Replication object. Synchronization occurs automatically if a specific synchronization has a problem. The Publisher sends an automatic resynchronization message when one of the following scenarios occurs:
There is a schema change on the Publisher. Data from the Subscriber cannot be applied at the server when using a Subscriber-always-wins conflict resolver. There is a referential integrity problem when data from the Publisher is applied at the Subscriber. There is a column-level conflict on the Publisher, and the server requests that the Subscriber resend the entire row. Internet Information Services (IIS) restarts during synchronization.

You can use merge replication to synchronize data between SQL Server Mobile and SQL Server. To prepare for merge replication, you need to write code to set the properties of an SqlCeReplication object. When performing a merge replication operation, use the SqlCeReplication.Synchronize method to synchronize data in a SQL Server Mobile database with the data on a host computer running SQL Server.

Reinitialize a Subscription
An application uses the replication object to reinitialize an existing SQL Server subscription. When the subscription is reinitialized, a new snapshot of the data is downloaded from the Publisher. This snapshot data is useful when the SQL Server Mobile subscription contains read-only data that is periodically updated on the Publisher. To reinitialize a subscription in an application, perform the following steps. Initialize an SqlCeReplication object, as shown in the following code. Visual C#
SqlCeReplication repl = new SqlCeReplication();

The following code example shows how to set the connection properties. Visual C#
repl.InternetUrl = "http://www.adventure-works.com/sqlmobile/sqlcesa30.dll"; repl.InternetLogin = "MyInternetLogin"; repl.InternetPassword = "<password>"; repl.Publisher = "MyPublisher"; repl.PublisherDatabase = "MyPublisherDatabase"; repl.PublisherLogin = "MyPublisherLogin"; repl.PublisherPassword = "<password>"; repl.Publication = "MyPublication"; repl.Subscriber = "MySubscriber"; repl.SubscriberConnectionString = "Data Source=MyDatabase.sdf";

Call the ReinitializeSubscription method to mark the subscription for reinitialization. If you set the value of the ReinitializeSubscription method to true, changes on the Subscriber are uploaded to the Publisher before reinitialization occurs. If you set the value of the ReinitializeSubscription method to false, any changes on the Subscriber are discarded during reinitialization. The following code example shows how to mark a subscription for reinitialization. Visual C#
repl.ReinitializeSubscription(true);

To repopulate the subscription, you must call the Synchronize method after calling the ReinitializeSubscription method. The following code example shows how to call the Synchronize method. Visual C#
repl.Synchronize();

The following code example shows how to reinitialize a SQL Server Mobile subscription. In this example, any changes on the Subscriber are first uploaded to the Publisher, the subscription is reinitialized, and then data is synchronized. Visual C#
SqlCeReplication repl = null; try { // Create SqlCeReplication instance // repl = new SqlCeReplication(); repl.InternetUrl = "http://www.adventure-works.com/sqlmobile/sqlcesa30.dll"; repl.InternetLogin = "MyInternetLogin"; repl.InternetPassword = "<password>"; repl.Publisher = "MyPublisher"; repl.PublisherDatabase = "MyPublisherDatabase"; repl.PublisherLogin = "MyPublisherLogin"; repl.PublisherPassword = "<password>"; repl.Publication = "MyPublication"; repl.Subscriber = "MySubscriber"; repl.SubscriberConnectionString = "Data Source=MyDatabase.sdf"; // Mark the subscription for reinitialization with Upload first repl.ReinitializeSubscription(true); // Synchronize to SQL Server to populate the Subscription repl.Synchronize(); } catch (SqlCeException) { // Handle errors here } finally { // Dispose the repl object repl.Dispose(); }

Detect and Resolve Merge Replication Conflicts

If synchronization occurs when a Publisher and a Subscriber are connected, the Merge Agent detects whether there are conflicts. If the Merge Agent detects conflicts, it uses a conflict resolver that determines which data to accept and distribute to other sites. With merge replication, you can use various methods to detect and resolve conflicts. For most applications, the following default methods are appropriate:
If a conflict occurs between a Publisher and a Subscriber, the Publisher change is accepted and the Subscriber change is discarded. If a conflict occurs between two Subscribers using client subscriptions (the default type for pull subscriptions), the change from the first Subscriber to synchronize with the Publisher is accepted. The change from the second Subscriber is discarded. If a conflict occurs between two Subscribers using server subscriptions (the default type for push subscriptions), the change from the Subscriber with the highest priority value is accepted. The change from the second Subscriber is discarded. If the priority values are equal, the change from the first Subscriber to synchronize with the Publisher is accepted.

Developing Connection Capabilities in Microsoft Windows Mobile 5.0Based Applications


Module Introduction

The .NET Compact Framework 2.0 provides built-in support for XML Web services and HTTPbased protocols. The .NET Compact Framework also supports Windows NT LAN Manager (NTLM) and Kerberos authentication. Using these enhanced security features, you can exchange information over different networks without the risk of unauthorized access or modification of data. You can also send and receive messages synchronously or asynchronously on a mobile device by using Message Queuing.

Module Objectives

After completing this module, you will be able to:


Exchange data with a Web page from a mobile application by using HTTP. Call a Web service from a mobile application. Send and receive messages from a mobile device by using Message Queuing. Describe some of the advanced techniques for communicating with mobile devices.

Developing HTTP Connection Capabilities

Lesson Introduction

When developing a Windows Mobile 5.0based application that provides access to data on a Web resource, establish a connection by using the WebRequest class. You can then create a request, authenticate a user, and send data to a Web page.

Lesson Objectives

After completing this lesson, you will be able to:


Connect a Windows Mobilebased application to a Web resource by using the WebRequest class. Connect a Windows Mobilebased application to a Web page by using an HttpWebRequest object. Set authentication credentials for an HttpWebRequest object. Send data to a Web page synchronously, asynchronously, and by using the POST and PUT methods. Handle WebRequest exceptions by using the WebException class. Set and retrieve HTTP headers and cookies by using an HttpWebResponse object.

Connect to a Web Resource by Using WebRequest


The request/response model of the .NET Compact Framework supports the WebRequest class for accessing data from the Internet. The WebRequest class is designed to send a request from the application to a particular Uniform Resource Identifier (URI). You can use the WebRequest class to create a request to a Web resource, such as an HTML Web page or an ASPX Web page. You can then use the WebResponse class to read the response to the request. Perform the following steps to connect a Windows Mobilebased application to an Internet resource:
1. 2. 3. 4. 5. 6. Create an instance of the WebRequest class by using the Create method and specifying the URI of the resource. Set the required properties of the WebRequest object. Send the request to the server by using the GetResponse method. This method returns a WebResponse object. Cast the WebResponse object to an HttpWebResponse object to read protocol-specific properties. Retrieve the stream containing the response data from the server by using the GetResponseStream method of the WebResponse class. After reading the data from the response, close the response stream by using the Stream.Close method, or close the response by using the WebResponse.Close method. It is not necessary to call the Close method on the response stream and the WebResponse object.

The following code example shows how to develop applications by using the WebRequest class and the WebResponse class.

Visual C#
using using using using System; System.IO; System.Net; System.Text;

namespace Examples.System.Net { public class WebRequestGetExample { public static void Main () { // Create a request for the URL. WebRequest request = WebRequest.Create ("http://www.contoso.com/default.html"); // If required by the server, set the credentials. request.Credentials = CredentialCache.DefaultCredentials; // Get the response. HttpWebResponse response = (HttpWebResponse)request.GetResponse (); // Display the status. Console.WriteLine (response.StatusDescription); // Get the stream containing content returned by the server. Stream dataStream = response.GetResponseStream (); // Open the stream using a StreamReader for easy access. StreamReader reader = new StreamReader (dataStream); // Read the content. string responseFromServer = reader.ReadToEnd (); // Display the content. Console.WriteLine (responseFromServer); // Cleanup the streams and the response. reader.Close (); dataStream.Close (); response.Close (); } } }

Connect to a Web Page by Using HttpWebRequest


To connect a Windows Mobilebased application to a Web page, you need to create an HttpWebRequest object to send a request. You can then retrieve an HttpWebResponse object to read the response to the request. You can also use the HttpWebResponse object to prevent the request from being redirected to another Web page. To allow users to access a Web page from a Windows Mobilebased application, you must perform the following tasks. You can create an HttpWebRequest object by using the HttpWebRequest class. This class provides support for methods and properties that are defined in the WebRequest class. The HttpWebRequest class also provides support for additional methods and properties that allow users to interact directly with servers by using HTTP. To initialize a new HttpWebRequest object, use the System.Net.WebRequest.Create method instead of the HttpWebRequest constructor. If the scheme for the URI is http:// or https://, the Create method returns an HttpWebRequest object. The following code example creates an HttpWebRequest object for the URI http://www.contoso.com/.
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/");

To retrieve an HttpWebResponse object, use the HttpWebResponse class. The HttpWebResponse class builds standalone HTTP client applications that send HTTP requests and receive HTTP responses. Do not directly create an instance of the HttpWebResponse class. Use the instance that is returned when you call the HttpWebRequest.GetResponse method.

To close a response and release the connection for reuse, call the Close method of the Stream class or the Close method of the HttpWebResponse class. The following code example uses the HttpWebResponse object that is returned by the HttpWebRequest.GetResponse method.
HttpWebRequest HttpWReq = (HttpWebRequest)WebRequest.Create("http://www.contoso.com"); HttpWebResponse HttpWResp = (HttpWebResponse)HttpWReq.GetResponse(); // Insert code that uses the response object. HttpWResp.Close();

Web pages are often coded to redirect the user to another page. However, you can control the HttpWebResponse object to avoid redirection to another page. The AllowAutoRedirect property of the HttpWebRequest class retrieves or sets a value that specifies whether or not a request must follow redirection responses. If you want the request to automatically follow HTTP redirection headers to the new location of the resource, set the value of the AllowAutoRedirect property to true. This value is the default value. If you set the value of the AllowAutoRedirect property to false, all responses with an HTTP status code from 300 to 399 return to the application. You can also specify the maximum number of redirections by using the MaximumAutomaticRedirections property. The following code example uses the AllowAutoRedirect property to allow the request to follow redirection responses.
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.contoso.com"); myHttpWebRequest.MaximumAutomaticRedirections = 1; myHttpWebRequest.AllowAutoRedirect = true; HttpWebResponse myHttpWebResponse = (HttpWebResponse) myHttpWebRequest.GetResponse();

Set Authentication Credentials


To authenticate a user making a request to resources on the Internet, you must provide details such as the user name and password. Use the NetworkCredential class and the CredentialCache class to set the Credentials property of the WebRequest object. The Credentials property provides the necessary credentials when client authorization for Internet requests is required. The following table describes the functionality of the NetworkCredential class and the CredentialCache class. The NetworkCredential class sets the user credentials when the user requests resources from the Internet. This class encrypts the credentials internally and restricts access to clear-text credentials. Use the constructor of this class to initialize a NetworkCredential object by setting the UserName parameter to userName, the Password parameter to password, and the Domain parameter to domain. The NetworkCredential class sets authentication credentials for a single user. When you develop a Windows Mobilebased application that can access multiple Internet resources, you can use the CredentialCache class to store the credentials for all the resources. A Web server supports authentication methods such as Basic, Digest, and NTLM. You can use any of these authentication methods in your application to validate a user. To store credentials for several different authentication methods, use an instance of the CredentialCache class.

Using the NetworkCredential class


The following code example uses the NetworkCredential class to set authentication credentials. Visual C#
//Get the userName, password and domain name here. //construct the credentials object NetworkCredential credentials = new NetworkCredential(userName, password, domain); //set the credentials on the request request.Credentials = credentials;

Using the CredentialCache class


The following code example uses the CredentialCache class to set authentication credentials. Visual C#
CredentialCache myCache = new CredentialCache(); myCache.Add(new Uri("http://www.contoso.com/"),"Basic",new NetworkCredential(UserName,SecurelyStoredPassword)); myCache.Add(new Uri("http://www.contoso.com/"),"Digest", new NetworkCredential(UserName,SecurelyStoredPassword,Domain)); wReq.Credentials = myCache;

Send Data to a Web Page


When you connect a Windows Mobilebased application to a Web server, a Web page is used to exchange data between the application and the server. You can send data or requests from the application to a Web page synchronously, asynchronously, by using the POST method, or by using the PUT method, as described in the following table. When you create an asynchronous HttpWebRequest object, the Web request is completed in a background thread and, therefore, does not block the user interface. To start an asynchronous request, use the BeginGetResponse method. You need to pass two parameters to the BeginGetResponse methodan asynchronous callback method and the state object of the request. The state object stores the status of the request and the data returned from the server. The asynchronous callback method uses the EndGetResponse method to retrieve the response from the server.

Note
To avoid indefinite processing of a request, the client application needs to implement its own time-out mechanism for errors that can occur in asynchronous requests.

The following code example sends data to a Web page asynchronously.


// Start the asynchronous request. AsyncCallback callback; IAsyncResult result = (IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState); // Create an HttpWebRequest object to the desired Web page. HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.contoso.com"); //Create an instance of the RequestState and assign the request created //above.

//to its request field. RequestState class stores information of status //of request and data returned from server. RequestState myRequestState = new RequestState(); myRequestState.request = myHttpWebRequest; // Start the asynchronous request. IAsyncResult result = (IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState);

When a request is sent synchronously, the main thread of the application is blocked because the request is handled by the main thread. Therefore, the application does not respond to user interaction until it receives a response to the request from the server. Use the GetResponse method of the HttpWebRequest class to send data synchronously. This method returns a WebResponse object that contains the response from the Internet resource. When you make a synchronous request, you need to limit the number of possible redirections, the header length, and other resources used by the request. The following code example sends data to a Web page synchronously.
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.contoso.com"); // Set some reasonable limits on resources used by this request request.MaximumAutomaticRedirections = 4; request.MaximumResponseHeadersLength = 4; // Set credentials to use for this request. HttpWebResponse response = (HttpWebResponse)request.GetResponse (); //Here process the HttpWebResponse object to get the data in the stream //for reading.

When you use the POST method, data is sent to the server by using the HttpWebRequest class. You can use the POST method to submit form data to the URI programmatically by setting appropriate values. The URI handles the data and sends a response to indicate whether it has received the data correctly. To send data by using the POST method, you must set the value of the Method property to POST. You must also set the value of the ContentType property to application/x-www-formurlencoded. The following code example sends data to a Web page by using the POST method.
// Set 'Method' property of 'HttpWebRequest' class to POST. myHttpWebRequest.Method="POST"; ASCIIEncoding encodedData=new ASCIIEncoding(); byte[] byteArray=encodedData.GetBytes(postData);

When you use the PUT method, the HttpWebRequest class is used to send the request. You can use the PUT method to upload a file to a specific URI. To send data by using the PUT method, you must set the value of the Method property to PUT. You must also create a stream of the file by using the GetRequestStream method of the HttpWebRequest class, and write the data to the stream. The following code example sends data to a Web page by using the PUT method.
string fileName = "test.jpg"; Uri uri = new Uri( "http://192.168.2.150/put/")+ fileName;

HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri); req.AllowWriteStreamBuffering = true; req.Method = "PUT"; req.KeepAlive = true; BinaryReader binaryReader = null; FileStream localFile = null; Stream reqStream = null; WebResponse response = null; try { // Allocate buffer for the data, which will be written in blocks. int bufsize = 4096; byte[] buf = new byte[bufsize]; int xcount; localFile = File.Open(path, FileMode.Open); binaryReader = new BinaryReader(localFile); reqStream = req.GetRequestStream(); req.Expect = string.Empty; while ( ( xcount = binaryReader.Read( buf, 0, bufsize ) ) > 0 ) { reqStream.Write( buf, 0, xcount ); } reqStream.Close(); response = req.GetResponse(); success = true; } catch(Exception ex) { //do something } finally { if (null != binaryReader) { binaryReader.Close(); } if (null != response) { response.Close(); } }

Handle WebRequest Exceptions


The WebRequest class and the WebResponse class throw a WebException exception if an error occurs when accessing an Internet resource. The value of the Status property specifies the cause of the error. This property takes a value from the WebExceptionStatus enumeration. Some of the possible values in the WebExceptionStatus enumeration are described in the following table.
Value ConnectFailure ConnectionClosed NameResolutionFailure ProtocolError ReceiveFailure ServerProtocolViolation Success Timeout Description Indicates that the remote service cannot be contacted at the transport level Indicates that the connection was closed prematurely Indicates that the name service cannot resolve the host name Indicates that although a complete response was received from the server, an error occurred at the protocol level Indicates that a complete response was not received from the server Indicates that the server response is not a valid HTTP response Indicates that no error has occurred Indicates that no response was received within the time-out set for the request

The following code example shows how to catch a WebException exception. Visual C#
try { // Create a request instance. WebRequest myRequest = WebRequest.Create("http://www.contoso.com"); // Get the response. WebResponse myResponse = myRequest.GetResponse(); //Get a readable stream from the server. Read from the stream and write any data to the console if required, here. myResponse.Close(); } catch (WebException webExcp) { // If you reach this point, an exception has been caught. Console.WriteLine("A WebException has been caught."); // Write out the WebException message. Console.WriteLine(webExcp.ToString()); // Get the WebException status code. WebExceptionStatus status = webExcp.Status; // If status is WebExceptionStatus.ProtocolError, // there has been a protocol error and a WebResponse // should exist. Display the protocol error. if (status == WebExceptionStatus.ProtocolError) { Console.Write("The server returned protocol error "); // Get HttpWebResponse so that you can check the HTTP status code. HttpWebResponse httpResponse = (HttpWebResponse)webExcp.Response; Console.WriteLine((int)httpResponse.StatusCode + " - " + httpResponse.StatusCode); } } catch (Exception e) { // Code to catch other exceptions goes here. }

Set and Retrieve HTTP Headers and Cookies


HTTP headers are used to transfer all types of information between client and server. You can use cookies for enabling server-side connections, such as CGI scripts, to store and retrieve information on the client side of the connection. The following table describes how to set and retrieve HTTP headers and cookies. The Headers property is a collection of name and value pairs and contains HTTP header values that are returned with a response. Common header information that is returned from the Internet resource is exposed as HttpWebResponse class properties. Some of the properties that represent common headers are ContentEncoding, ContentLength, ContentType, LastModified, and Server. The following code example sets HTTP headers.
protected override System.Net.WebRequest GetWebRequest(Uri uri) { WebRequest wr = base.GetWebRequest(uri); if (this.cookie != null) wr.Headers.Add("Cookie", this.cookie.key + "=" + this.cookie.value); return wr; }

The following code example retrieves HTTP headers.


public HttpCookie(WebResponse response) { string[] values = response.Headers.GetValues("Set-Header"); if (values == null)

throw new NullReferenceException("No Set-Header found."); key = values[0].Split(';')[0].Split('=')[0]; value = values[0].Split(';')[0].Split('=')[1]; }

You can set and retrieve cookies by using the HttpWebRequest class and the HttpWebResponse class. Cookies are stored in the HTTP header. The .NET Compact Framework does not provide any class that you can use to manipulate cookies. However, you can add and remove cookies manually to maintain the session state. The following code example sets cookies.
protected override System.Net.WebRequest GetWebRequest(Uri uri) { WebRequest wr = base.GetWebRequest(uri); if (this.cookie != null) wr.Headers.Add("Cookie", this.cookie.key + "=" + this.cookie.value); return wr; }

The following code example retrieves cookies.


public HttpCookie(WebResponse response) { string[] values = response.Headers.GetValues("Set-Cookie"); if (values == null) throw new NullReferenceException("No Set-Cookie found."); key = values[0].Split(';')[0].Split('=')[0]; value = values[0].Split(';')[0].Split('=')[1]; }

Calling Web Services

Lesson Introduction

The .NET Compact Framework supports the use of Web services in Windows Mobilebased applications. You can design an application to call a Web service synchronously or asynchronously. When the application makes a synchronous call to a Web service, the user must wait for the Web service to respond before interacting with the application. In this case, the application might stop responding if the Web service is unresponsive for a long period of time. However, when the application makes an asynchronous call to a Web service, the user can interact with the application while a call is being made to the Web service.

Lesson Objectives

After completing this lesson, you will be able to:


Add a Web reference to a Windows Mobile project. Make synchronous calls to a Web service from a Windows Mobilebased application. Make asynchronous calls to a Web service from a Windows Mobilebased application. Preauthenticate a Web service call. Maintain the session state in a Web service by using cookies.

Add a Reference to a Web Service


To call a Web service in a Windows Mobile project, you must add a Web reference to your project. When you add a Web reference to your project, Microsoft Visual Studio 2005 automatically generates a proxy class. The proxy class includes methods for accessing the Web service synchronously or asynchronously. These methods serve as a proxy for each method that is exposed by the Web service. By default, the proxy class is not visible in Solution Explorer. To add a Web reference to a project, perform the following steps:
1. 2. 3. 4. 5. In Solution Explorer, select the project that will call the Web service. On the Project menu, click Add Web Reference. In the Add Web Reference dialog box, type the URL for the Web service that you want to call, and then click Go. In the Web reference name box, type a name that you will use in your code to access the selected Web service. To create a reference to the Web service, click Add Reference. The new reference is displayed in Solution Explorer under the Web References node.

Make Synchronous Web Service Calls


When an application makes a call to a Web service, the calling thread is blocked until the Web service returns the result of the method call. This blocking of the calling thread can result in the user interface being unresponsive until the method call is returned. Therefore, you must use synchronous calls for methods that are processed and returned quickly by the Web service.

To make a synchronous call to a Web service, create an instance of the proxy class and then call the methods within the proxy class. The following code example shows how to create an instance of a Web service proxy class and then call the GetItems method to retrieve a list of books. Visual C#
BookCatalog.Service1 bookcatalog = new BookCatalog.Service1(); DataSet ds = bookcatalog.GetItems();

Make Asynchronous Web Service Calls


When an application makes an asynchronous call to a Web service, the call is made on a thread that is different from the thread that is running the user interface. Therefore, the users interaction with the application is not affected while the Web service is being accessed. Each asynchronous method in the proxy class has a corresponding Begin method and End method. Initiate an asynchronous Web service call by calling the Begin method. This method returns a System.Web.Services.Protocol.WebClientAsyncResult object that provides the status information for a pending asynchronous call. To end the Web service call and retrieve the response from the Web service, call the End method. The following code example makes an asynchronous Web service call to the BeginGetItems method and the EndGetItems method. Visual C#
private void button2_Click(object sender, System.EventArgs e) { BookCatalog.Service1 ws = new BookCatalog.Service1(); AsyncCallback cb = new AsyncCallback(ServiceCallback); ws.BeginGetItems(cb,ws); } private void ServiceCallback(IAsyncResult ar) { BookCatalog.Service1 ws = (BookCatalog.Service1)ar.AsyncState; DataSet ds = ws.EndGetItems(ar); }

Preauthenticate a Web Service Call


The procedure for preauthenticating a Web service call is similar to the procedurefor setting authentication credentials for an HttpWebRequest class. To preauthenticate a Web service call, create an instance of the HttpWebRequest class. The PreAuthenticate property of the HttpWebRequest class retrieves or sets a value that indicates whether an authenticate header must be sent with the request. The WWW-authenticate header is sent with each request if the value of the PreAuthenticate property is set to true and the appropriate credentials are provided. The WWW-authenticate header

can be sent only after a client request to a specific URI is successfully authenticated. If the value of the PreAuthenticate property is set to false and the credentials are inaccurate, the request uses standard authentication procedures. Except for the first request, the PreAuthenticate property specifies whether authentication information must be sent with subsequent requests. This information is forwarded to the specific URI without being validated by the server. The following code example shows how to create an instance of the HttpWebRequest class and set the value of the PreAuthenticate property. Visual C#
HttpWebRequest instance; bool value; value = instance.PreAuthenticate; instance.PreAuthenticate = value;

Maintain Session State in a Web Service


Web services are in a stateless form in the .NET Compact Framework. Therefore, you cannot maintain the session state in a Web service call with the autogenerated Web proxy code for the Web service. To maintain the session state, you must manually add code to save the appropriate header information within the application. Then, you must add the saved values to the headers before making the Web service call. In addition, you must pass a token to identify the user with every call to the method. Perform the following steps to maintain the session state manually:
1. 2. 3. Create a new class that inherits from the Web proxy class. This Web proxy class is generated by Visual Studio 2005 when you add a Web reference to your project. Override the GetWebResponse method to get the base WebResponse object, extract the header from the WebResponse object, and save the header. Override the GetWebRequest method to add the local cookie to the request when the Web request is sent back to the application.

4.

5.

The following code example shows how to maintain the session state in a Web service by using Visual C#.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Net; using System.IO; namespace DeviceApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); WS2 ws = new WS2(null); ws.SessionSetValue(2); int i = ws.SessionGetValue(); } } public class WS2 : WS.SessSvc { HttpCookie cookie; public WS2(HttpCookie cookie) { this.cookie = cookie; } protected override WebResponse GetWebResponse(WebRequest request) { //Get the base webresponse WebResponse wr = base.GetWebResponse(request); //Extract the cookie and save it try { this.cookie = new HttpCookie(wr);

} catch (NullReferenceException) { } return wr; } protected override System.Net.WebRequest GetWebRequest(Uri uri) { //Override the GetWebRequest WebRequest wr = base.GetWebRequest(uri); if (this.cookie != null) wr.Headers.Add("Cookie", this.cookie.key + "=" + this.cookie.value); return wr; } } public class HttpCookie { public string key = ""; public string value = ""; public HttpCookie(WebResponse response) { string[] values = response.Headers.GetValues("Set-Cookie"); if (values == null) throw new NullReferenceException("No Set-Cookie found."); key = values[0].Split(';')[0].Split('=')[0]; value = values[0].Split(';')[0].Split('=')[1]; } public HttpCookie(string key, string value) { this.key = key; this.value = value; } } }

Sending and Receiving Messages by Using Message Queuing


Lesson Introduction

Message Queuing is a technology that allows applications running at different times to communicate across heterogeneous networks. Using Message Queuing, you can send messages from a mobile device, such as a Pocket PC, to computers and systems that may be temporarily offline. You can also use Message Queuing to transfer messages between a remote server and a mobile device. Message Queuing supports both synchronous and asynchronous messaging.

Lesson Objectives

After completing this lesson, you will be able to:


Describe how the Message Queuing technology can be used for mobile application development. Perform operations on a message queue. Send messages to a message queue. Retrieve synchronous messages from a message queue. Retrieve asynchronous messages from a message queue.

What is Message Queuing?


The .NET Compact Framework 2.0 supports Microsoft Message Queuing (MSMQ), which is a tool that you can use to create distributed messaging applications in Windows Mobile 5.0. Using MSMQ, mobile device applications can send messages to a message queue. This queue can hold messages for both the sending and receiving applications that are located either on the same network or on different networks. After a mobile device is connected to the network, you can use MSMQ to send a message to the receiving application, even when the receiving application is not running. The receiving application can also check for messages in its local queue at any time. The .NET Compact Framework 2.0 supports the XmlMessageFormatter class that allows you to serialize and de-serialize messages to and from the message queue. Windows Mobile 5.0 supports the SOAP Reliable Messaging Protocol (SRMP) for transmitting messages. System administrators can use MSMQ to efficiently manage large and complex networks of computers and message queues.

Perform Operations on a Message Queue


A message queue is a temporary storage location that stores messages being transmitted between applications across heterogeneous networks. With Message Queuing, users can communicate across networks and computers that may be offline. You can perform the following operations on a message queue. Use the MessageQueue.Create() method to create a new queue at the specified path on a Message Queuing server.

You can use the MessageQueue.Create(path) method to create a nontransactional message queue at the specified path. To create a transactional message queue at the specified path, you can use the MessageQueue.Create(path, transactional) method. In this method, transactional is a Boolean parameter. If you set the value of this parameter to true, the method creates a transactional queue; if you set the value to false, the method creates a nontransactional queue. The following code example creates a message queue if no message queue exists. Visual C#
//Create a queue if it does not exist MessageQueue myNewPublicQueue = MessageQueue.Create(".\\newPublicQueue");

Use the MessageQueue constructor to initialize a new instance of the MessageQueue class. The .NET Compact Framework 2.0 supports the following MessageQueue constructors:
The MessageQueue() constructor, which is the default constructor, initializes a new instance of the MessageQueue class. After the constructor initializes the new instance of the class, you must set the path of the instance before you can use the instance. Use the MessageQueue.Path property to retrieve or set the path of the message queue. When you set the path of the queue, the MessageQueue constructor points to a new queue. The MessageQueue(path) constructor initializes a new instance of the MessageQueue class that references the message queue at the specified path. The MessageQueue(path, sharedModeDenyReceive) constructor initializes a new instance of the MessageQueue class. This instance references the message queue at the specified path with the specified read-access restriction. In this constructor, sharedModeDenyReceive is a Boolean parameter. Set the value of this parameter to true if you want to grant exclusive read access to the first application that references the queue; otherwise, set the value to false.

The following code example opens a message queue. Visual C#


MessageQueue instance= new MessageQueue();

Use the MessageQueue.Close method to free all the resources that are associated with a MessageQueue object, including shared resources, if appropriate. Close a message queue before you delete it on the Message Queuing server; otherwise, messages sent to the queue might throw exceptions. The following code example closes a message queue. Visual C#
// Connect to a queue MessageQueue myQueue = new MessageQueue(".\\myQueue"); // Send a message to the queue myQueue.Send("My message data1."); // Explicitly release resources myQueue.Close();

After you have finished using a message queue, delete all the messages in the queue by using the MessageQueue.Purge method. You cannot recover messages that you purge from a queue.

The following code example deletes all the messages in a message queue. Visual C#
// Connect to a queue MessageQueue queue = new MessageQueue(".\\exampleQueue"); // Delete all messages from the queue queue.Purge();

Use the MessageQueue.Delete method to delete a queue on a Message Queuing server. When you use this method, you must specify the location of the queue to be deleted. The following code example deletes a message queue. Visual C#
if (MessageQueue.Exists(".\\myQueue")) { // Delete the queue MessageQueue.Delete(".\\myQueue"); }

Send Messages to a Message Queue


Using Message Queuing, you can create and send a message to a message queue. You can also compose a response and send it to a response queue. The following table describes how you can perform these tasks. The Message class provides access to properties that you can use to define a message. You can use the Body property of the Message class to specify the message or object that you want to send to a message queue. Alternatively, you can send application-specific data by using the AppSpecific and Extension properties of the Message class. However, you must include message data in the Body property whenever possible, because the content is serialized or encrypted only if it is contained in the Body property. The size of the content in the Body property cannot exceed 4 megabytes (MB). The type of content stored in the Body property is indicated by the Message.BodyType property. You can also set a priority for a message by using the Message.Priority property. After the message is ready, you can use the MessageQueue.Send(message) method to send the message to a nontransactional queue that is referenced by the MessageQueue object.

Note
An object is serialized before it is stored in the Body property.

When you send a message from one application to another application, you can request a response from the receiving application. The responses sent by the receiving application are stored in message queues that are designated as response queues. You can specify any available queue as a response queue for the sending application. The response queue must be a local queue so that the sending application can read the response message locally. You can compose and send a response to a response queue in the same way that you create and send a message to a message queue.

The following code example creates a new message and sends it to a message queue. Visual C#
// Create the queue if it does not exist. MessageQueue myQueue = MessageQueue.Create(".\\myQueue"); //Open a Message queue public MessageQueue () // Create a new message Message myMessage = new Message(); // Set message properties myMessage.Body = messageBody; myMessage.Priority = priority; // Send the message to the queue myQueue.Send(myMessage);

Retrieve Synchronous Messages from a Message Queue


Use the MessageQueue.Peek method and the MessageQueue.Receive method to retrieve synchronous messages from a message queue. These methods, in turn, create a new instance of the Message class and set the properties of this new instance. When you use the MessageQueue.Peek method and the MessageQueue.Receive method, the process thread waits for a specified time interval for a new message to arrive in the queue. The following table explains how to peek into a message, receive a message, enumerate messages, and extract the details of the response queue from a message. The MessageQueue.Peek method reads the first message from the queue. However, it does not remove this message from the queue. Message Queuing orders messages in the queue according to their priority and arrival time. A new message is placed before an older one only if the new message is of a higher priority. Therefore, repeated calls to the MessageQueue.Peek method return the same message until a higher priority message arrives in the queue. The MessageQueue.Peek() method blocks the current process thread until a message becomes available in the message queue. As a result, the application might wait indefinitely for a message and block the thread indefinitely. To avoid this situation, you can specify a time span for which the application will wait for a message to arrive in the queue. The MessageQueue.Peek(TimeSpan) method blocks the current thread until a message becomes available in the message queue or until the specified time-out for a message to arrive in the queue occurs. The following code example shows you how to peek into a message.
// Connect to a queue MessageQueue myQueue = new MessageQueue(".\\myQueue"); // Set Peek to return immediately myQueue.Peek(new TimeSpan(0));

The MessageQueue.Receive method reads and removes the first message from the queue. Therefore, repeated calls to this method return different messages. The MessageQueue.Receive method does not specify a time-out for a message to arrive in the queue. This feature of the method can result in the application waiting indefinitely. Therefore, use the MessageQueue.Receive method only when it is acceptable for the current process thread to be blocked while it waits for a message to arrive in the queue. The following code example shows you how to receive a message from a message queue.

// Create the queue if it does not exist. MessageQueue myQueue = MessageQueue.Create(".\\myQueue"); //Open a Message queue public MessageQueue () // Create a new instance of the class MyNewQueue myNewQueue = new MyNewQueue(); // Send a message to a queue myNewQueue.SendMessage(); // Receive a message from a queue myNewQueue.ReceiveMessage(); public void SendMessage() { // Create a new order and set values. Order sentOrder = new Order(); sentOrder.orderId = 3; sentOrder.orderTime = DateTime.Now; // Connect to a queue on the local computer. MessageQueue myQueue = new MessageQueue(".\\myQueue"); // Send the Order to the queue. myQueue.Send(sentOrder); return; } public void ReceiveMessage() { // Connect to a queue on the local computer. MessageQueue myQueue = new MessageQueue(".\\myQueue"); try { // Receive and format the message. Message myMessage = myQueue.Receive(); Order myOrder = (Order)myMessage.Body; // Display message information. Console.WriteLine("Order ID: " + myOrder.orderId.ToString()); Console.WriteLine("Sent: " + myOrder.orderTime.ToString()); } catch (MessageQueueException) { // Handle Message Queuing exceptions. } return; }

The MessageQueue.GetMessageEnumerator method creates an enumerator object for all the messages in the queue. This method also provides a forward-only cursor to enumerate the messages in the queue. If you make any changes to a message that is placed after the current cursor position in the message queue, the enumeration will reflect those changes. The changes you make to a message that is placed before the current cursor position will not be reflected in the enumeration. However, you can reset the enumeration to move the cursor back to the beginning of the list by calling the MessageEnumerator.Reset method. To delete a message placed at the current cursor position, call the MessageEnumerator.RemoveCurrent method. This method removes the current message from the queue and returns the message to the calling application. The following code example shows you how to enumerate messages in a message queue.
// Connect to a queue MessageQueue myQueue = new MessageQueue(".\\myQueue"); // Get a cursor into the messages in the queue MessageEnumerator myEnumerator = myQueue.GetMessageEnumerator();

The MessageEnumerator.Current property gets the message that the enumerator is pointing to. Use the MessageEnumerator.Current property to retrieve details from a message. For example, you can retrieve the priority of a message or the body of a message. When the enumerator is created, the cursor points to the head of the queue, which is a location before the first message. Therefore, if you use the MessageEnumerator.Current property when the enumerator is created, an error occurs. To avoid this error, you must first call the

MessageEnumerator.MoveNext method to position the cursor at the first message in the queue, and then call the MessageEnumerator.Current property. The following code example shows you how to extract the priority of messages in a queue.
// Connect to a queue MessageQueue myQueue = new MessageQueue(".\\myQueue"); // Get a cursor into the messages in the queue MessageEnumerator myEnumerator = myQueue.GetMessageEnumerator(); // Specify that the priority of the message should be read myQueue.MessageReadPropertyFilter.Priority = true; // Move to the next message and examine its priority while(myEnumerator.MoveNext()) { // Increase the count if the priority is Lowest if(myEnumerator.Current.Priority == MessagePriority.Lowest) numberItems++; }

Retrieve Asynchronous Messages from a Message Queue


You can use the MessageQueue.BeginPeek method and the MessageQueue.BeginReceive method to retrieve asynchronous messages from a message queue. Use these asynchronous methods if you want the application tasks to continue processing on a separate thread until a new message arrives in the queue. The following table explains how to retrieve asynchronous messages from a message queue. Use the MessageQueue.BeginPeek method to initiate an asynchronous peek operation. During the peek operation, when a message becomes available in the queue or the specified time-out occurs, the MessageQueue.PeekCompleted event is raised. When this event is raised, you can call the MessageQueue.EndPeek method to complete the specified asynchronous peek operation by reading the message without removing it from the queue. Perform the following steps to asynchronously peek into a message:
1. Create an event handler and link it to the PeekCompletedEventHandler delegate. When you create a PeekCompletedEventHandler delegate, you must determine which method will handle the event. To associate the event with your event handler, add an instance of the delegate to the event. The event handler is called whenever the event occurs, unless you remove the delegate. 2. 3. Call the MessageQueue.BeginPeek method to initiate an asynchronous peek operation. When a MessageQueue.PeekCompleted event is raised, peek into the message by calling the MessageQueue.EndPeek method.

The following code example shows you how to peek into a message.
// Create an instance of MessageQueue MessageQueue myQueue = new MessageQueue(".\\myQueue"); // Send a message to the queue. myqueue.Send("Example Message"); // Begin the asynchronous peek operation. myqueue.BeginPeek(TimeSpan.FromSeconds(10.0), messageNumber++, new AsyncCallback(MyPeekCompleted)); // Provides an event handler for the PeekCompleted event. private static void MyPeekCompleted(IAsyncResult asyncResult) { // Connect to the queue. MessageQueue myqueue = new MessageQueue(".\\myQueue"); // End the asynchronous peek operation. Message msg = myqueue.EndPeek(asyncResult); // Display the message information on the screen. Console.WriteLine("Message number: {0}", (int)asyncResult.AsyncState); Console.WriteLine("Message body: {0}", (string)msg.Body); // Receive the message. This will remove the message from the queue. msg = myqueue.Receive(TimeSpan.FromSeconds(10.0)); }

msg = myqueue.Receive(TimeSpan.FromSeconds(10.0)); }

Use the MessageQueue.BeginReceive method to initiate an asynchronous receives operation. During the receive operation, when a message becomes available in the queue or the specified timeout occurs, the MessageQueue.ReceiveCompleted event is raised. When this event is raised, you can call the MessageQueue.EndReceive method to complete the specified asynchronous receive operation by reading the message and removing it from the queue. The steps to asynchronously receive a message are similar to the steps to asynchronously peek into a message. The following code example show you how to receive a message from a message queue.
// Create an instance of MessageQueue MessageQueue myQueue = new MessageQueue(".\\myQueue"); // Send a message to the queue. myqueue.Send("Example Message"); // Begin the asynchronous receive operation. myqueue.BeginReceive(TimeSpan.FromSeconds(10.0), messageNumber++, new AsyncCallback(MyReceiveCompleted)); // Provides an event handler for the ReceiveCompleted event. private static void MyReceiveCompleted(IAsyncResult asyncResult) { // Connect to the queue. MessageQueue myqueue = new MessageQueue(".\\myQueue"); // End the asynchronous receive operation. Message msg = myqueue.EndReceive(asyncResult); // Display the message information on the screen. Console.WriteLine("Message number: {0}", (int)asyncResult.AsyncState); Console.WriteLine("Message body: {0}", (string)msg.Body); }

Working with Advanced Communication Techniques for Mobile Devices


Lesson Introduction

Applications can use Transmission Control Protocol (TCP) services to communicate with a remote server by using the TcpClient class and the TcpListener class. These protocol classes are built on the System.Net.Sockets.Socket class and are used for transferring data between client and listener computers. You can use the TcpClient class and various methods in the Sockets class to communicate with a remote server. You can also send and receive data on mobile devices by using various methods of the SerialPort class.

Lesson Objectives

After completing this lesson, you will be able to:


Describe how a TCP client communicates with a remote server. Initiate a TCP connection to a remote server. Write data to a TCP client. Send and receive data by using a serial port.

Communicate with a Remote Server by Using a TCP Client


You can use the TcpClient class to request data from a network resource that uses TCP. The methods and properties of this class help you retrieve the details for creating a socket that uses TCP to request and receive data. The TCP protocol establishes a connection between a mobile device and a remote endpoint. Then, the protocol uses the connection to send and receive data packets. TCP ensures that data packets are sent to the endpoint. TCP also ensures that the data packets are assembled in the correct order when they arrive. The connection to the remote device is represented as a stream of data. Data can be read and written from this stream by using the stream-handling techniques supported by the .NET Compact Framework. To establish a TCP connection, you need to specify the address of the network device hosting the service you require and the TCP port that the service uses to communicate. The TCPClient class uses the synchronous methods of the Socket class to provide access to network services without maintaining state information or requiring the details of setting up protocol-specific sockets. If you need to access features of the Socket class that are not exposed by the TCPClient class, use the Socket class. The Socket class provided by the .NET Compact Framework is a managed-code version of the socket services provided by the Winsock32 API. In most cases, the Socket class methods marshal data into their native Win32 counterparts and handle any necessary security checks. The Socket class supports two basic modes: synchronous and asynchronous. In the synchronous mode, calls to functions that perform network operations wait until an operation completes before returning control to the calling program. In the asynchronous mode, a function call is returned immediately.

Initiate a TCP Connection to a Remote Server


The TcpClient class can connect to and exchange data with a remote server only when a TcpListener or a Socket object that is created with the TcpProtocolType enumeration is listening for incoming connection requests. You can connect to the TcpListener by creating a TcpClient object and calling one of the three available Connect methods. Alternatively, you can create the TcpClient object by using the host name and port number of the remote host. The TcpClient class constructor will automatically attempt a connection. The following table shows you how to initiate a TCP connection to a remote server. You can create a new TCP client by using the TcpClient class. The TcpClient class provides methods for connecting, sending, and receiving stream data over a network in a synchronous blocking mode. You can use the TcpClient class to connect to a remote host synchronously or asynchronously. The TcpClient.Connect method begins a synchronous request for a remote host connection. The TcpClient.BeginConnect method is an overloaded method that begins an asynchronous request for a remote host connection. You can read data from a TCP client by using the following methods:
Use the NetworkStream.Read method to read data from the NetworkStream. This method reads data into the buffer parameter and returns the number of bytes successfully read. If no data is available for reading, the Read method returns a value of 0. The Read operation reads all the available data as specified by the size parameter. Use the NetworkStream.BeginRead method to read data from the NetworkStream asynchronously. Calling the BeginRead method allows you to receive data within a separate execution thread. The BeginRead method reads all the available data as specified by the size parameter. Use the TcpClient.GetStream method to read socket data by using the NetworkStream class. The TcpClient.GetStream method returns a NetworkStream object that you can use to send and receive data.

Write Data to a TCP Client

When writing data to a TCP client, you can send a stream of data over the network by using different methods. Use the following methods to write data synchronously, asynchronously, or as socket data:
Use the NetworkStream.Write method to write data to the NetworkStream object synchronously. The method starts at a specified offset and sends a specified array of byte type from the buffer to the network. The Write method does not write any data until the requested number of bytes is sent or a SocketException is thrown. Use the NetworkStream.BeginWrite method to begin an asynchronous send operation to the remote host. Calling the BeginWrite method allows you to send data within a separate execution thread. You must create a callback method that implements the AsyncCallback delegate, and pass it to the BeginWrite method. In addition, the state parameter must contain the NetworkStream. If your callback method needs more information, create a small class to hold the NetworkStream and the other required information. Use the NetworkStream class to write socket data. Use the TcpClient.GetStream method to return a NetworkStream object that you can use to send and receive data. You must first call the Connect method; otherwise, the GetStream method will throw an InvalidOperation exception. After the NetworkStream is returned, call the Write method to send data to the remote host.

While writing to or reading data from a TCP client, the TcpClient object uses several network resources. To release the network resources, use the following methods to close and release the TCP connection:
Use the TcpClient.Close method to close or dispose a TcpClient instance, without closing the underlying connection. This method labels the instance as disposed, but it does not close the TCP connection or release the NetworkStream that is used to send and receive data. You must use the NetworkStream.Close method to close the stream and the TCP connection.

Use the TcpClient.Dispose method to release unmanaged resources used by the TcpClient class. This method is called by the public Dispose method and the Finalize method. The public Dispose method invokes the TcpClient.Dispose method with the disposing parameter set to true. The Finalize method invokes the TcpClient.Dispose method with the disposing parameter set to false. When the disposing parameter is set to true, the TcpClient.Dispose method releases all the resources held by any managed objects that the specific TcpClient references. The TcpClient.Dispose method releases resources by invoking the Dispose method of each referenced object.

Note
You can use the TcpClient.Dispose method to optionally release managed resources.

Communicate by Using a Serial Port


You can use the SerialPort class to control a serial port file resource. The functionality of this class can be wrapped in an internal Stream object. This object can be accessed through the BaseStream property. The Stream object can also be passed to classes that wrap or use streams. The SerialPort class supports various encoding standards, such as ASCIIEncoding, UTF8Encoding, UnicodeEncoding, and UTF32Encoding. This class also supports any encoding defined in mscorlib.dll. To use alternate encodings, use the ReadByte method or the Write method to perform the encoding manually. The following table describes the methods of the SerialPort class. The SerialPort.Open method, introduced in the .NET Compact Framework 2.0, opens a new serial port connection. Only one open connection can exist per SerialPort object. Before attempting to open a new connection, ensure that the existing open connection has been closed.

Note
An application must wait after calling the Close method before attempting to call the Open method because a port may not close instantly.

The following code example opens a new serial port by using the SerialPort.Open method. Visual C#

SerialPort instance = new SerialPort("COM1") instance.Open

Use the following methods to read data from a serial port:


SerialPort.Read. This is a public method that reads data from the SerialPort input buffer. SerialPort.ReadByte. This is a public method that reads one byte synchronously from the SerialPort input buffer. SerialPort.ReadChar. This is a public method that reads one character synchronously from the SerialPort input buffer. SerialPort.ReadExisting. This is a public method that reads all immediately available bytes in the stream and in the input buffer of the SerialPort object, based on the encoding. SerialPort.ReadLine. This is a public method that reads up to the NewLine value in the input buffer. SerialPort.ReadTo. This is a public method that reads a string up to the specified value in the input buffer.

When a message is received at a serial port, the DataReceived event of the SerialPort object is raised. This event can be raised by any item in the SerialData enumeration.

The DataReceived event is raised on a secondary thread. Therefore, modifying certain elements, such as user interface elements, in the main thread might raise a threading exception. If you need to modify elements in the main Form class or Control class, post change requests back by using the Invoke method that uses the appropriate thread.

Note
The operating system determines whether a serial received event is raised or not, and therefore, all parity errors might not be reported.

The following code example receives serial port notifications by using the SerialDataReceived event. Visual C#
SerialPort instance = new SerialPort("COM1"); instance.DataReceived += new System.EventHandler(this.DataReceived); // Event handler for DataReceived public void DataReceived(object sender, SerialDataReceivedEventArgs e) { // Data is received so can read the data }

Write data to a serial port by using the SerialPort.Write method and the SerialPort.WriteLine method. The SerialPort.Write method is an overloaded method that writes data to the serial port output buffer. Click to view more information about the SerialPort.Write method. The SerialPort.WriteLine method, introduced in the .NET Compact Framework 2.0, writes a specified string and the NewLine value to the output buffer. Click to view more information about the SerialPort.WriteLine method. The SerialPort.Dispose method is an overloaded and overridden method in the SerialPort class. This method releases unmanaged resources used by the SerialPort object. Click to view more information about the SerialPort.Dispose method.

Implementing Interoperability and Platform Features in Windows Mobile 5.0Based Applications


Module Introduction

Windows Mobile 5.0 supports advanced features such as interoperability and IPC on a mobile device. Windows Mobile 5.0 also provides support for monitoring the power status, which is one of the most important considerations for a mobile device user. You can integrate Office Outlook Mobile features into Windows Mobilebased applications. You can also access unmanaged DLL functions and implement IPC by using Win32 and point-to-point message queues in Windows Mobilebased applications.

Module Objectives

After completing this module, you will be able to:


Monitor the system state of a mobile device by using State and Notifications Broker. Integrate Office Outlook Mobile features and data in a Windows Mobilebased application. Call unmanaged DLL functions by using the platform invoke technology. Implement IPC in a Windows Mobilebased application.

Retrieving System State by Using State and Notifications Broker


Lesson Introduction

When performing resource-intensive tasks on a mobile device, you must constantly monitor the state of the software and hardware components of the device. The .NET Compact Framework 2.0 helps you monitor the state of these components by using notifications. The .NET Compact Framework 2.0 supports the State and Notifications Broker API, which acts as a central repository for state information. Using the classes and methods of the State and Notifications Broker API, you can set alerts for system-wide or per-user state changes.

Lesson Objectives

After completing this lesson, you will be able to:


Describe how State and Notifications Broker is used for mobile application development. Identify the available system state values. Query the current system state values by using the Status namespace. Monitor phone radio status by using State and Notifications Broker. Manage power usage on a mobile device by using State and Notifications Broker.

Overview of State and Notifications Broker


The State and Notifications Broker API is a data store that provides a publish-subscribe model for distributing data-change notifications. This API stores state information, monitors changes in state values, and generates notifications about state changes. The State and Notifications Broker API is part of the Windows Mobile 5.0 platform. To develop applications that use the State and Notifications Broker API, you need to install Microsoft Visual Studio 2005 and the Windows Mobile 5.0 SDK for Pocket PC or Smartphone on your desktop computer. Using this API, applications can share information and respond to changes in the state of the device and to the state of other applications. You can implement this API in your applications by using the classes available in the Microsoft.WindowsMobile.Status assembly. The Windows Mobile 5.0 platform supports system-wide state values, such as battery strength, the presence of a camera, or network connectivity. It also supports per-user state values, such as appointments, missed calls, or unread messages. The State and Notifications Broker API uses the registry as the data store. The system-wide state values are stored in the HKEY_LOCAL_MACHINE\System\State registry key, and the per-user state information is stored in the HKEY_CURRENT_USER\System\State registry key.

Available System State Values

Query the Current System State Values


You can query a system state value by using the Microsoft.WindowsMobile.Status namespace. This namespace provides classes and enumerations that you can use to retrieve and set the values of system properties, monitor state changes, and define how to respond to state changes. Perform the following steps to query a system state value by using the Microsoft.WindowsMobile.Status namespace. After you install the Windows Mobile 5.0 SDK, add a reference to the Microsoft.WindowsMobile.Status namespace by selecting it from the Add Reference dialog box in Visual Studio 2005. This namespace provides classes, such as StateBase and SystemState, that expose the State and Notifications Broker API. Using this API, you can access system properties to track state changes. When working with Visual Studio 2005, use Object Browser to select the system state value that you want to monitor. The SystemProperty enumerator in Object Browser provides a list of state value properties, such as PhoneSignalStrength and PhoneRoaming. After you identify the state that you want to monitor, add an instance of the SystemState class to retrieve the current value of the state. You can also use the SystemState class to generate a notification when the state changes.

Note
If the instance of SystemState handles the Changed event of a state, define the instance globally in the class.

After you add an instance of the SystemState class, add a method to handle the SystemState.Changed event. This event is raised when a system state changes. You can add the event handler for the SystemState.Changed event immediately after declaring the instance of the SystemState class. After you add an event handler, you need to write code to respond to the state change. Use the SystemState.GetValue method to retrieve the value of a system state.

Monitor Phone Radio Status


To monitor the radio status of a mobile device, you can add an event handler that enables the application to generate notifications about radio state changes. Alternatively, you can monitor the radio status by querying the system state to retrieve the current state value. The following table provides code examples that show how to monitor the radio status of a mobile device by using an event handler and by querying the system state. The following code example shows how to request notification by using an event handler.
SystemState gprsCoverage; SystemState radioState; private void Trace(string s) { this.gprsCoverage = new SystemState (SystemProperty.PhoneGprsCoverage); gprsCoverage.Changed += new ChangeEventHandler (gprsCoverage_Changed); this.radioState = new SystemState(SystemProperty.PhoneRadioOff); radioState.Changed += new ChangeEventHandler(radioState_Changed); } void radioState_Changed(object sender, ChangeEventArgs args) { //Add your logic here } void gprsCoverage_Changed(object sender, ChangeEventArgs args) { //add your logic here }

The following code example shows how to query the system state and retrieve the current value.
Private Sub GetRadioState If SystemState.PhoneRadioOff Then 'Logic if radio is off Else 'Logic if radio is On End If End Sub

Manage Device Power Usage


Resource-intensive applications affect the battery strength of a mobile device. In addition, running multiple processes simultaneously or leaving the screen of a mobile device active for a long time can also affect battery strength and reduce the standby time of the device. Therefore, you must constantly monitor the battery status of the mobile device and provide information about the battery status to the user. You can use the SystemState.PowerBatteryState property and the SystemState.PowerBatteryStrength property to determine the battery status.

The SystemState.PowerBatteryState Property


The SystemState.PowerBatteryState property indicates the current battery state of the mobile device by using the following values of the BatteryState enumerator. Member name Charging Critical Description Indicates that the battery is being charged Indicates that the battery charge is very low and needs to be charged immediately

Low Normal NotPresent

Indicates that the battery charge is low Indicates that the battery is adequately charged Indicates that there is no charge in the battery

The SystemState.PowerBatteryStrength Property


The SystemState.PowerBatteryStrength property retrieves the remaining battery power level of the mobile device. This property indicates the power level of the battery by using the following values of the BatteryLevel enumerator. Member name VeryHigh High Medium Low VeryLow Description 81100% 6180% 4160% 2140% 020%

Integrating Outlook Mobile Features in a Windows MobileBased Application


Lesson Introduction

When creating a Windows Mobile 5.0based application, you can integrate Office Outlook Mobile features and data into the application by using the Microsoft.WindowsMobile.PocketOutlook namespace. This namespace provides classes that help you create and access appointments, tasks, contacts, e-mail messages, and SMS messages.

Lesson Objectives

After completing this lesson, you will be able to:


Describe the key features of the Microsoft.WindowsMobile.PocketOutlook namespace. Send and intercept SMS messages from a mobile device by using the SmsMessage class. Create and send e-mail messages from a mobile device by using the EmailMessage class. Add, modify, and delete contacts, tasks, and appointments from a mobile device.

Overview of the Microsoft.WindowsMobile.PocketOutlook Namespace


This illustration represents some of the key classes in the Microsoft.WindowsMobile.PocketOutlook namespace.

Send and Intercept SMS Messages


When developing a Windows Mobilebased application, you can integrate both sending and receiving of SMS messages into the application by using the SmsMessage class. This class supports properties and methods that allow you to send and receive SMS messages. The following table describes how to send and intercept SMS messages by using the properties and methods of the SmsMessage class. To send a message, specify the message to be sent by using the SmsMessage.Body property, and then specify the recipient by using the smsMessage.To.Add method. You can also specify that a

delivery report be sent to the sender by setting the value of the SmsMessage.RequestDeliveryReport property to true. After creating the message, use the Send method of the SmsMessage class to send the message. You can use the ChooseContactDialog class to display a dialog box that prompts a user to specify the contact details for sending an SMS message. You can specify the title of the dialog box by using the contactDialog.Title property. You can also specify that a delivery report be sent to the sender by setting the value of the SmsMessage.RequestDeliveryReport property to true. After creating the message, use the Send method of the SmsMessage class to send the message. You can use classes in the Microsoft.WindowsMobile.PocketOutlook.MessageInterception namespace to create applications that can intercept and process SMS messages that are sent to the mobile device. Message interception is a highly configurable mechanism. For example, you can program a mobile device to notify the application about messages based on parameters such as the sender, the receiver, or the message contents. You can also program the interception system to start the application that requested notification if the application is not already running. You can use the following classes to intercept SMS messages:
MessageCondition. Specifies the message condition to be met. MessageInterceptor. Raises an event when an incoming SMS message meets the interception condition. MessageInterceptorEventHandler. A delegate type implemented by classes that have been registered to receive message notification.

The following Visual C# code example shows how to send an SMS message to a mobile device.
SmsMessage smsMessage = new SmsMessage(); smsMessage.Body = "Would you like to meet for lunch?"; smsMessage.To.Add(new Recipient("John Doe", "2065550199")); smsMessage.RequestDeliveryReport = true; smsMessage.Send(); return;

The following Visual C# code example shows how to send an SMS message to a specified contact and then request a return receipt.
using Microsoft.WindowsMobile.PocketOutlook; using Microsoft.WindowsMobile.Forms; // ... ChooseContactDialog contactDialog = new ChooseContactDialog(); contactDialog.Title = "Select user to send message"; if (contactDialog.ShowDialog() == DialogResult.OK) { // Construct message requesting delivery receipt SmsMessage message = new SmsMessage(contactDialog.SelectedContact.MobileTelephoneNumber, "R U Going to the Keynote?"); SmsMessage message.RequestDeliveryReport = true; // Send message message.Send(); }

The following Visual C# code example shows how to intercept an SMS message. In this code example, an object is defined, the MessageCondition object is populated, and then the event handler for the MessageReceived event is added.
using using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Text; System.Windows.Forms; Microsoft.WindowsMobile.PocketOutlook; Microsoft.WindowsMobile.PocketOutlook.MessageInterception;

namespace MsgInterceptorDemo

{ public partial class frmMain : Form { private MessageInterceptor _demoInterceptor = new MessageInterceptor(InterceptionAction.NotifyAndDelete, true); private MessageCondition _demoCondition = new MessageCondition(); public frmMain() { InitializeComponent(); _demoCondition.Property = MessageProperty.Body; _demoCondition.ComparisonType = MessagePropertyComparisonType.StartsWith; _demoCondition.CaseSensitive = true; _demoCondition.ComparisonValue = "MsgDemo"; _demoInterceptor.MessageCondition = _demoCondition; _demoInterceptor.MessageReceived += new MessageInterceptorEventHandler(_demoInterceptor_MessageReceived); } void _demoInterceptor_MessageReceived(object sender, MessageInterceptorEventArgs e) { SmsMessage smsDemo = (SmsMessage)e.Message; MessageBox.Show(smsDemo.Body, "Special SMS Received", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); } private void menuMessage_Click(object sender, EventArgs e) { SmsMessage outboundMsg = new SmsMessage("+14250010001", "MsgDemo - Test Message"); MessagingApplication.DisplayComposeForm(outboundMsg); } } }

Create and Send E-Mail Messages


When developing a Windows Mobilebased application, you can integrate messaging into the application by using classes in the Microsoft.WindowsMobile.PocketOutlook.EmailAccount namespace. This namespace contains the EmailAccount class that provides complete e-mail functionality, including support for attachments. You can create an e-mail message by using the EmailMessage class in the Microsoft.WindowsMobile.PocketOutlook.EmailAccount namespace. After creating the e-mail message, use the Send method of the EmailAccount class to send the e-mail message to a specified e-mail account. The following code example shows how to create an e-mail message, attach a Pocket Word document to it, and then send the message to the selected contact by using the primary e-mail account configured on the device. Visual C#
EmailMessage message = new EmailMessage(); message.To.Add( new Recipient("me@contoso.com")); message.Subject = "Customer Support Email"; message.BodyText = "A new issue has been created by a user." + "Please see the attachment for more details."; message.Attachments.Add(new Attachment(@"\My Documents\issue.doc")); using (OutlookSession session = new OutlookSession()) { session.EmailAccounts[0].Send(message); }

Add, Modify, and Delete Contacts, Tasks, and Appointments


The following table describes how to add, modify, and delete contacts, tasks, and appointments by using classes in the Microsoft.WindowsMobile.PocketOutlook namespace. To add a contact, use the AddNew method of the Contact class. The following code example shows how to add a contact.

Visual C#
public void AddContact(string firstName, string lastName, string title) { OutlookSession os = new OutlookSession(); Contact contact = os.Contacts.Items.AddNew(); contact.FirstName = firstName; contact.LastName = lastName; contact.Title = title; contact.FileAs = contact.LastName + ", " + contact.FirstName; contact.Update(); }

To modify a contact, use the Update method of the Contact class. The following code example shows how to modify a contact. Visual C#
public void EditContact(Contact contact, string firstName, string lastName, string title) { contact.FirstName = firstName; contact.LastName = lastName; contact.Title = title; contact.FileAs = contact.LastName + ", " + contact.FirstName; contact.Update(); }

To delete a contact, use the Delete method of the Contact class. The following code example shows how to delete a contact. Visual C#
public void DeleteContact(Contact contact) { contact.Delete(); }

To add a task, use the AddNew method of the Task class. The following code example shows how to add a new task. Visual C#
public void AddTask(string body, string categories, bool complete, DateTime startDate) { OutlookSession os = new OutlookSession(); Task task = os.Tasks.Items.AddNew(); task.Body = body; task.Categories = categories; task.Complete = complete; task.StartDate = startDate; task.Update(); }

To modify a task, use the Update method of the Task class. The following code example shows how to modify a task. Visual C#

public void EditTask(Task task, string body, string categories, bool complete, DateTime dueDate) { task.Body = body; task.Categories = categories; task.Complete = complete; task.DueDate = dueDate; task.Update(); }

To delete a task, use the Delete method of the Task class. The following code example shows how to delete a task. Visual C#
public void DeleteTask(Task task) { task.Delete(); }

To add an appointment, use the AddNew method of the Appointment class. The following code example shows how to add an appointment. Visual C#
public void AddAppointment(string body, string categories, DateTime startdate) { OutlookSession os = new OutlookSession(); Appointment appointment = os.Appointments.Items.AddNew(); appointment.Body = body; appointment.Categories = categories; appointment.Start = startdate; appointment.Update(); }

To modify an appointment, use the Update method of the Appointment class. The following code example shows how to modify an appointment. Visual C#
public void EditAppointment(Appointment appointment, string body, string categories, DateTime startdate) { appointment.Body = body; appointment.Categories = categories; appointment.Start = startdate; appointment.Update(); }

To delete an appointment, use the Delete method of the Appointment class. The following code example shows how to delete an appointment. Visual C#
public void DeleteAppointment(Appointment appointment) { appointment.Delete(); }

Using Platform Invoke Technology to Call Unmanaged DLL Functions


Lesson Introduction

The .NET Compact Framework supports calling code in unmanaged modules to use DLL functions. Use the platform invoke technology to call these DLL functions. The platform invoke technology is a superset of the managed and unmanaged transitions. This technology provides a rich set of type conversion features to work with the inherent differences between DLL and common language runtime (CLR).

Lesson Objectives

After completing this lesson, you will be able to:


Describe the platform invoke technology. Call an unmanaged DLL function from managed code. Describe how data is marshaled from managed to unmanaged code.

Overview of Platform Invoke Technology


Platform invoke is a technology that allows you to use managed code to call unmanaged functions implemented in DLLs. This technology also allows you to call native assemblies within the .NET Compact Framework. The following are the three different phases of the .NET Compact Framework platform invoke technology:
Design time. As a developer, you must provide a description for the unmanaged function that must be called. The description contains the module name, the entry point name, and the calling convention. Just in time (JIT). CLR extracts information about the unmanaged function being called, locates the DLL containing the specified function, loads the DLL into memory, and then retrieves the address of the function. Run time. CLR marshals the parameters from a managed format to an unmanaged format before the unmanaged function is called. CLR determines how to marshal each parameter depending on how the function has been declared in the managed code.

You can use the methods and properties of the System.Runtime.InteropServices namespace to implement platform invoke services in an application.

Platform Invoke in the .NET Compact Framework


The platform invoke technology functions differently in the .NET Framework environment than it does in the .NET Compact Framework environment. These differences include default encoding, calling conventions, and callback support. While using platform invoke on the .NET Framework, you can set the default character set by using the ANSI, AUTO, or UNICODE clause in the Declare statement. You can also use the CharSet property in the DllImportAttribute attribute to set the default character set. However, the .NET Compact Framework supports only UNICODE encoding by using the CharSet.Unicode and the CharSet.Auto values. This framework does not support any of the clauses of the Declare statement. The .NET Framework also supports three calling conventions using the CallingConvention enumeration in the CallingConvention property of the DllImportAttribute attribute. In the .NET Compact Framework, however, only the default platform calling convention is supported. In addition,

in the .NET Compact Framework, platform invoke does not support callbacks. On the .NET Framework, callbacks are supported through the use of delegates.

Call an Unmanaged DLL Function


To call an unmanaged DLL function, use the DllImportAttribute attribute. This attribute provides the information required to call the function that is exported from an unmanaged DLL. When you use the DllImportAttribute attribute, include the name of the DLL that contains the entry point to an application. The following code example calls the Add method of an unmanaged DLL named math.DLL Visual C#
class ManagedMath { [DLLImport("math.DLL", EntryPoint="Add")] public static extern int Add(int a, int b); }

Platform invoke performs the following steps when an unmanaged function is called:
1. 2. 3. The DLL containing the function is located. The DLL is loaded into memory. The address of the function in memory is located, and its arguments are loaded onto the stack.

Note
The DLL is located and loaded into memory only on the first call that is made to the function. The address of the function in memory is also located only once. 4. The control of the application is transferred to the unmanaged function.

Marshal Data from Managed to Unmanaged Code


Interop marshaling is a run-time activity that is performed by the marshaling service. You can use interop marshaling to determine how data must be passed in method arguments. In addition, interop marshaling ensures that the method returns values between managed and unmanaged memory. Both managed and unmanaged memory contain common representations of data types. The interop marshaler is responsible for handling these data types. However, there are a few data types that may be ambiguous or may not have representations in managed memory. An ambiguous data type can contain multiple unmanaged types mapping to a single managed type. The marshaler provides a default representation for ambiguous types. In case of multiple representations, the marshaler provides alternative representations. You can instruct the marshaler on how to marshal an ambiguous type. The Marshal class provides a collection of methods for converting managed code to unmanaged code. CLR provides two mechanisms for working with unmanaged codeplatform invoke and Component Object Model (COM) interop. You can use the platform invoke mechanism to enable managed code to call functions that are exported from an unmanaged library. Use the COM interop mechanism to enable managed code to interact with COM objects by using interfaces. The platform invoke and COM interop mechanisms use interop marshaling to move method arguments between the caller and the receiver. A platform invoke method call flows from managed to unmanaged code except in callback functions. However, the data can flow in both directions as In or Out parameters. A COM interop method call can flow in both directions.

Implementing Inter-Process Communication


Lesson Introduction

When multiple processes or applications run on a mobile device, these processes or threads may need to communicate with each other. For example, a time-consuming application that is running on the main thread needs to monitor the battery power of the mobile device that is running on another thread. You can implement IPC to help processes or threads communicate with each other. Using IPC, you can send messages between applications or processes that run on the same device or on different computers on the network. You can implement IPC by using Win32 messages.

Lesson Objectives

After completing this lesson, you will be able to:


Describe how IPC is used in mobile application development. Send and receive Win32 messages between two applications.

Why Use Inter-Process Communication?


Inter-process communication (IPC) is a set of methods that can be used to exchange data between multiple threads in one or more processes. These processes may be running on one or more computers connected in a network. You can use IPC methods for message passing, synchronization, managing shared memory, and implementing remote procedure calls (RPC). The methods used for these activities may vary based on the bandwidth and latency of communication between the threads and the type of data being communicated. When developing Windows Mobilebased applications, you can use IPC to send Win32 messages between unmanaged and managed applications. For example, you can use IPC methods in an unmanaged application to monitor the state of a managed application. You can implement IPC in Windows Mobilebased applications by using point-to-point message queues and the MessageWindow class.

Send and Receive Win32 Messages


You can send and receive Win32 messages by using the MessageWindow class. This class creates a Window handle in native code and performs the required platform invoke calls to native Windows functions. To use the MessageWindow class in your application, create a class that is derived from the MessageWindow class and override the default WndProc behavior. You can use the WndProc behavior to examine specific Win32 messages. You can create a Win32 message by using the Create method of the Message class. To send a Win32 message, use the SendMessage method of the MessageWindow class.

You can receive only those messages that you generate by using the MessageWindow class or by using native code. The following Visual C# code example uses the MessageWindow class to send a Win32 message that displays the current x and y coordinates of the mouse on a form. Then the MessageWindow class invokes the callback method on the form to display the coordinates in the title bar.
using System; using System.Windows.Forms; using Microsoft.WindowsCE.Forms; namespace MsgWindow { public class MessageWindowForm : System.Windows.Forms.Form { private System.Windows.Forms.MainMenu mainMenu1; // Create an instance of MsgWindow, a derived MessageWindow class. MsgWindow MsgWin; public MessageWindowForm() { InitializeComponent(); // Create the message window using this form for its constructor. this.MsgWin = new MsgWindow(this); } protected override void Dispose( bool disposing ) { base.Dispose( disposing ); } #region Windows Form Designer generated code private void InitializeComponent() { this.mainMenu1 = new System.Windows.Forms.MainMenu(); this.Menu = this.mainMenu1; this.Text = "Message Window Test"; } #endregion static void Main() { Application.Run(new MessageWindowForm()); } // Process taps to generate messages // with the WParam and LParam parameters // using the X and Y mouse coordinates. protected override void OnMouseMove(MouseEventArgs e) { Message msg = Message.Create(MsgWin.Hwnd, MsgWindow.WM_CUSTOMMSG, (IntPtr)e.X, (IntPtr)e.Y); MessageWindow.SendMessage(ref msg); base.OnMouseMove(e); } // This callback method responds to the Windows-based message. public void RespondToMessage(int x, int y) { this.Text = "X = " + x.ToString() + ", Y= " + y.ToString(); } } // Derive MessageWindow to respond to // Windows messages and to notify the // form when they are received. public class MsgWindow : MessageWindow { // Assign integers to messages. // Note that custom Window messages start at WM_USER = 0x400. public const int WM_CUSTOMMSG = 0x0400; // Create an instance of the form. private MessageWindowForm msgform; // Save a reference to the form so it can // be notified when messages are received. public MsgWindow(MessageWindowForm msgform) {

this.msgform = msgform; } // Override the default WndProc behavior to examine messages. protected override void WndProc(ref Message msg) { switch(msg.Msg) { // If message is of interest, invoke the method on the form that // functions as a callback to perform actions in response to the message. case WM_CUSTOMMSG: this.msgform.RespondToMessage((int)msg.WParam, (int)msg.LParam); break; } // Call the base WndProc method // to process any messages not handled. base.WndProc(ref msg); } } }

Optimizing, Packaging, and Deploying Microsoft Windows Mobile 5.0Based Applications


Module Introduction

Before you deploy a Windows Mobile 5.0based application on a device, you need to optimize system resources and secure the application. Resource-intensive applications may strain the battery or memory of a mobile device. Therefore, you must optimize the mobile devices critical resources, such as memory and power. Applications downloaded from unknown sources can affect the performance of the other applications running on the mobile device and of the device itself. Therefore, you must protect the integrity of the application by implementing security that will prevent users from installing applications from unknown sources. The Microsoft .NET Compact Framework 2.0 provides support for managing memory and power on a mobile device. The .NET Compact Framework 2.0 also provides support for signing an application before packaging and deploying it on a mobile device. After you deploy the application, you can monitor it from a remotely connected workstation by using remote tools. You can also use these remote tools to monitor or update other mobile device components, such as the registry or the file system.

Module Objectives

After completing this module, you will be able to:


Measure and tune the memory usage and system performance of a mobile device. Sign a Windows Mobilebased application by using strong-name signing and certificates. Package and deploy a Windows Mobilebased application. Develop and debug mobile device applications by using the remote tools in Microsoft Visual Studio 2005.

Lesson Introduction

You can improve the performance of your Windows Mobile 5.0based applications by measuring and tuning system resources such as power and memory. Memory management is important for a mobile device because the device has limited physical RAM and no virtual memory paging file. To diagnose and monitor the performance of your Windows Mobilebased applications, implement code tracing and performance counters in your application code. These mechanisms help you optimize device performance and resources.

Lesson Objectives

After completing this lesson, you will be able to:


Apply the guidelines for managing memory and power on a mobile device. Select and implement a technique for managing memory on a mobile device. Select and implement a technique for diagnosing performance on a mobile device. Enable performance counters on a mobile device. Enable trace on a mobile device by using the Trace class.

Measuring and Tuning System Resources


While designing a Windows Mobilebased application, you must consider how your mobile device handles low memory situations and application hibernation. You must also consider how your application allocates memory to manage static and global variables, stacks, and heaps. Apply the following guidelines for managing memory and power on mobile devices.

Guidelines for Managing Memory and Power on Mobile Devices


While designing a Windows Mobilebased application, you must consider how your mobile device handles low memory situations and application hibernation. You must also consider how your application allocates memory to manage static and global variables, stacks, and heaps. Apply the following guidelines for managing memory and power on mobile devices. Windows Mobilebased devices are designed for quick access to applications, and the memory interface of these devices is simplified for users. When an application needs more memory, instead of prompting the user, the shell shuts down inactive applications automatically. The Windows Mobile shell optimizes memory usage for running applications. When the demand for memory is high, idle applications receive a WM_CLOSE message to release memory for an active application. When the application receives this message, it automatically shuts down without a warning. Therefore, to preserve the state of the application from one session to another, you must handle state persistence within your application. Use the GetSystemInfo function, through the SYSTEM_INFO structure, to obtain information about the processor and memory characteristics of the device. Use the GlobalMemoryStatus function to obtain information about the current state of memory on the device through the MEMORYSTATUS structure. The dwTotalPhys and dwAvailPhys members of the structure contain information about the total amount of both the program memory and the memory that is currently available.

Note
Windows Mobile 5.0based devices follow the Windows CE memory architecture. So, available memory is not necessarily memory that is available to the application.

Apply the following guidelines to manage variables and stacks:


Static and global variables. These variables are created when a process starts and cannot be released until the process ends. Therefore, limit the use of static and global variables, especially with large memory allocations and arrays. Stacks. When a process is created on a Windows Mobilebased device, a stack is created for the thread that belongs to that process. Similarly, for each new thread that is created in the process, a new stack is created. The new stack provides usable memory to store the values of parameters passed to functions and the values of variables created in functions. The stack memory that is used by a function is released when the function returns a value.

A Windows Mobilebased device shell uses the WM_HIBERNATE message to instruct applications to release memory. The shell sends this message to one or more applications, beginning with the application that has been inactive for the longest time period. Finally, the shell requests memory from the active application. However, the shell does not send WM_HIBERNATE messages to invisible windows. When an application receives a WM_HIBERNATE message, the application releases any large block of memory that is allocated by the VirtualAlloc function. In addition, the application releases as

many graphics, windowing, and events subsystem objects allocated to memory as possible, including windows, bitmaps, and device contexts.

Techniques for Managing Memory on Mobile Devices


Memory management is important for a device that has limited physical RAM and no virtual memory paging file. Applications for mobile devices must be ready to free memory when they receive WM_HIBERNATE messages. Use the following techniques for managing memory on mobile devices. The GC.Collect method is an overloaded method that forces garbage collection of the common language runtime (CLR) in a mark-and-sweep model. You can use this method to attempt to reclaim inaccessible memory. However, the GC.Collect method does not guarantee that all inaccessible memory is reclaimed. The GC.Collect method is sometimes called to force finalizers to be run for dead objects and to free native code resources or memory. All objects, regardless of how long they have been in memory, are considered for garbage collection. However, objects that are referenced in managed code are not collected. Use the GC.Collect method only if absolutely necessary, because this method freezes all threads while running, which affects the performance of your application. However, if you must call the GC.Collect method in your application, use the method to handle out-of-memory errors (OOMs) by allocating unmanaged resources to trap the errors.

Note
The GC.Collect method does not free all the available memory. This method only frees objects that are not disposable or that have already been finalized. Also, the GC.Collect method does not always free memory back to the system. Therefore, other applications cannot always use memory freed by garbage collection.

The following code example shows how to use the GC.Collect method to manage memory on a mobile device.
using System; namespace GCCollectExample { class MyGCCollectClass { private const int maxGarbage = 1000; static void Main() { // Put some objects in memory. MyGCCollectClass.MakeSomeGarbage(); Console.WriteLine("Memory used before collection: {0}", GC.GetTotalMemory(false)); // Collect all generations of memory. GC.Collect(); Console.WriteLine("Memory used after full collection: {0}", GC.GetTotalMemory(true)); } static void MakeSomeGarbage() { Version vt; for(int i = 0; i < maxGarbage; i++) { // Create objects and release them to fill up memory // with unused objects. vt = new Version(); } } } }

To properly dispose unmanaged resources, implement a public Dispose method or a Close method that runs the necessary cleanup code for an object. The IDisposable interface provides the Dispose method. Resource classes that implement this interface can use the Dispose method. Because the Dispose method is public, users of your application can directly call this method to free memory that is used by unmanaged resources. The Dispose method calls the GC.SuppressFinalize method when it disposes an object. If the object is currently in the finalization queue, the GC.SuppressFinalize method prevents the Finalize method for the object from being called. Executing a Finalize method affects application performance. If your Dispose method has already cleaned up the object, it is not necessary for the garbage collector to call the object's Finalize method.

Note
You can also use the Using statement to dispose objects. This statement defines a scope outside which an object or objects will be disposed.

The following code example shows how to use the Dispose method to manage memory on a mobile device.
public class BaseResource: IDisposable { private IntPtr handle; private Component Components; private bool disposed = false; public BaseResource() { } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if(!this.disposed) { if(disposing) { Components.Dispose(); } CloseHandle(handle); handle = IntPtr.Zero; } disposed = true; } ~BaseResource() { Dispose(false); } public void DoSomething() { if(this.disposed) { throw new ObjectDisposedException(); } } }

Techniques for Diagnosing Performance on Mobile Devices


Instrumentation allows you to monitor or measure the level of product performance and to diagnose errors. In programming, instrumentation is the ability of an application to implement code tracing, debugging, and performance counters. Use the following techniques to implement instrumentation while diagnosing performance issues on mobile devices. A performance counter collects performance data about a computers resources and other processes. The counter information includes the category or object for which the counter records the performance. A computer's categories include physical components such as processors, disks, and memory. There are also system categories, such as processes and threads. Each category is related to a functional element within the computer and has a set of standard counters assigned to it. You can use counter data to determine the number of system resources that are being utilized by an application on your mobile device. You can also use a performance counter to diagnose the slow performance of an application on your mobile device. For example, the counter can monitor the number of garbage collection operations being performed. This will determine whether garbage collection is affecting application performance. You can monitor the performance of your application by tracing your application code. You can use this technique during development or after deployment. By using the Trace class, you can record information about errors and application performance to logs, text files, or other devices for analysis. In the case of a distributed application, you can add instrumentation to the application by using Trace statements at strategic locations in your code.

Note
You can also trace code execution in an installed application by using the Trace class. By using trace switches in your code, you can control whether tracing occurs and whether the process is extensive.

You can use the System.Diagnostics namespace to debug your application. This namespace provides classes, such as the Trace class and the Debug class, that allow you to interact with system processes, event logs, and performance counters. During development, you can use the output methods of the Debug class to display messages in the Output window of the Visual Studio Integrated Development Environment (IDE). By using the Debug.Write method in the Output window, you can trace, debug, and optimize application performance based on the results from the test environment. Debug your application in a debug build by enabling the Debug conditional attribute to receive all debugging output. When your application is ready for release, compile your release build without enabling the Debug conditional attribute so that the compiler does not include your debugging code in the final executable file.

Enable Performance Counters on a Mobile Device


The .NET Compact Framework does not support PerformanceCounter objects, but it does contain a set of predefined performance counters. These performance counters can be used to analyze the types of load an application places on the resources of the mobile device.

Performance counters in the .NET Compact Framework

On a mobile device, performance counters are useful for determining the impact of garbage collection (GC) and just-in-time (JIT) compilation on the performance of the application. The following categories of performance counters are supported by the .NET Compact Framework. Category Loader Generic Locks, Threads, and Timers GC Memory JIT Exceptions Interop Networking Windows Forms Description Counters that pertain to the operation of the CLR Counters that pertain to generic methods Counters that pertain to locks, threading, thread pools, and timers Counters that pertain to garbage collection operations Counters that pertain to the memory heaps managed by the garbage collector Counters that pertain to JIT compiler operations Counters that pertain to exceptions Counters that pertain to interoperability with native code Counters that pertain to network send and receive operations Counters that pertain to the System.Windows.Forms namespace

Monitor performance at run time


You can monitor application performance at run time by using the Remote Performance Monitor, which is a debugging and performance-tuning tool in the .NET Compact Framework 2.0 SP1. This tool provides a user interface that allows you to view performance data in real time. When you start your application from Remote Performance Monitor, the tool reads statistical data for performance counters directly from the CLR. You can provide additional diagnostic support by allowing users to view the .NET Compact Framework performance data by using Perfmon.exe, which is a standard Windows performance-monitoring tool. Using the Remote Performance Monitor tool, you can perform the following tasks:
View performance counter data while an application is running. View performance counter data in a graphical format in Perfmon.exe while an application is running. Enable the generation of .stat files to duplicate behavior that is supported in earlier versions of the .NET Compact Framework. When you use this feature, all .stat files are written to the disk when the application is closed. View previously generated .stat files created in the .NET Compact Framework 2.0. Enable and disable logging.

Generate performance statistics


You can use the performance counters in the .NET Compact Framework to create statistical reports about the performance of your application. To obtain performance statistics, perform the following steps:
1. 2. Browse to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETCompactFramework. Set the PerfMonitor registry subkey value to 1.

3. 4. 5.

Run the application that you want to examine for performance. Do not run any other .NET Compact Framework applications at the same time. Examine the statistics file generated on the root drive of your device. The file has the same name as the .NET Compact Framework application that has a .stat extension and that is currently running. To turn off the performance counters, set the PerfMonitor registry subkey value to 0.

Log file information


Log files contain diagnostic information about interoperability, loading the program, and networking. You can enable logging for your application by setting the registry keys. First, set a registry key to enable general logging, and then set the appropriate registry keys for the required logging components and options. When you enable interoperability logging, the log file records all COM Interop calls and provides information about Platform Invoke calls and marshaling. When you enable program loader logging, the log file includes information about trust levels assigned to modules as they are loaded. This information can include failure to resolve methods, successful assembly loading, and failure to detect functions within the Platform Invoke dynamic-link library (DLL).

Enable Performance Counters on a Mobile Device


To run an application from Remote Performance Monitor, perform the following steps:
1. 2. 3. 4. 5. 6. To start Remote Performance Monitor, browse to Program Files\Microsoft.NET\SDK\CompactFramework\v2.0\bin, and then click NetCFrpm.exe. In the Device box, select the device. If you are using a Microsoft ActiveSync connection, select the name of the device from the list. If you are using an Ethernet connection, type the IP address and port number in the Device box. In the Application box, type the full path to the application. In the Parameters box, type a command-line argument for the application. Verify that the application is not running on the device. Click Connect. Remote Performance Monitor starts the application and displays performance data.

To use Perfmon.exe with Remote Performance Monitor, perform the following steps:
1. 2. 3. 4. Run an application from Remote Performance Monitor. Browse to \Windows\System32 and launch Perfmon.exe. In Perfmon.exe, select the category of counter that you want to graph. The names of the categories correspond to the categories that are displayed when you view statistical data in Remote Performance Monitor. Click Add.

Enable Loggin on a Mobile Device


To enable logging, perform the following steps:
1. 2. Go to HKLM\Software\Microsoft\.NETCompactFramework\Diagnostics\Logging\Enabled. Set the Enabled key value to 1.

You must set the Enabled key value to enable any type of logging. Create the subkeys under logging because the keys do not exist by default. You can turn off all logging by setting the logging value to 0. To enable Interop logging, perform the following steps:
1. 2. Go to HKLM\Software\Microsoft\.NETCompactFramework\Diagnostics\Logging\Interop\Enabled. Set the Enabled key value to 1.

To enable Loader logging, perform the following steps:


1. 2. 3. Go to HKLM\Software\Microsoft\.NETCompactFramework\Diagnostics\Logging\Loader\Enabled. To enable Loader logging, set the Enabled key value to 1. To enable Loader and GACrelated logging, set the Enabled key value to 2.

Enable Trace on a Mobile Device


You can use the properties and methods of the Trace class to add instrumentation to release builds. This class provides methods to display an Assert method dialog box and to return an assertion that always uses the Fail method. To customize the target of the tracing output, you can add or remove TraceListener instances from the Listeners collection. By default, the trace output is emitted by using the DefaultTraceListener class. The Trace class provides properties to get or set the level of indent and the IndentSize. This class also provides properties to perform an AutoFlush operation after each write operation. In addition, the BooleanSwitch and TraceSwitch classes provide the means to dynamically control the tracing output. You can modify the values of these switches without compiling your application again.

Note
The Trace and Debug classes are functionally identical. However, the procedures and functions of the Trace class are compiled into release builds by default, whereas procedures and functions of the Debug class are not compiled into release builds.

Optimizing, Packaging, and Deploying Microsoft Windows Mobile 5.0 Based Applications
Lesson Introduction

You can protect the integrity of a Windows Mobilebased smart device by implementing security that will prevent users from installing applications from unknown sources. You can implement security in an application by using the security models for smart devices that are supported by Windows Mobile 5.0. For example, you can sign an assembly with a certificate.

Lesson Objectives

After completing this lesson, you will be able to:


Describe the application security model for Windows Mobilebased applications. Sign a Windows Mobilebased application assembly by using strong-name signing. Sign a Windows Mobilebased application by using a trusted privilege or un-privilege certificate.

Introduction to the Application Security Model


The application security model for Windows Mobile-based devices is based on digital code signing. This illustration represents some of the tools in the application security model.

Sign the Application Assembly


Strong-name signing (or strong-naming) gives an application or component a unique identity. Other applications can use this unique identity to refer explicitly to the application or component. You can use a strong name to guarantee that component dependencies and configuration statements map exactly to the correct component and component version. Strong-name signing allows you to specify the servicing version to be used for a shared component. Strong-name signing also allows different applications to specify different versions of the referenced assembly without affecting other

applications. You can use the strong name of a component as security evidence to establish a trust relationship between two components. You can use strong names for .NET Compact Framework assemblies such as application assemblies (.exe) and shared component assemblies (.dll). If you want to install the assemblies to the Global Assembly Cache (GAC), you must sign the assemblies before installation. However, you must avoid using strong-name signing for application EXE assemblies. An application or component that is strong-named cannot reference a weak-named component. Therefore, using strong-name signing for an EXE prevents the EXE from referencing weak-named DLLs that are deployed with the application. A strong name includes information about the assembly's identity, such as its simple text name, version number, and culture information. A strong name also includes a public key token and a digital signature. To sign an assembly in a Visual Basic or Visual C# device project, perform the following steps:
1. 2. 3. 4. In Solution Explorer, right-click the Visual Basic or Visual C# project, and then on the shortcut menu, click Properties. To open the Signing page, on the project name page, click Signing. On the Signing page, select the Sign the assembly check box. To use a strong name key file that already exists, in the Choose a strong name key file list, click Browse, and then in the Select File dialog box, select the file you want to use.

Note
To create a new strong name key file, in the Choose a strong name key file list, click New, and then in the Create Strong Name Key dialog box, create a strong name key for the assembly.

Sign the Application by Using a Trusted Privilege or Un-Privilege Certificate

The Smartphone Application Security model is designed to be flexible to meet the requirements of different types of mobile operator networks. This security model categorizes applications into privileged and unprivileged applications, based on the level of access allowed by the application to the device features and the application programming interfaces (APIs) on the device. Privileged trust applications have full access to the computer system and the APIs. An application signed with a certificate in the privileged certificate store runs in the privileged execution mode. Unprivileged trust applications have limited access to the system and the APIs. An application signed with a certificate in the unprivileged certificate store runs in the unprivileged execution mode.

To sign a Visual Basic or a Visual C# device project, perform the following steps:
1. 2. 3. 4. 5. In Solution Explorer, right-click the Visual Basic or Visual C# project, and then on the shortcut menu, click Properties. To open the Devices page, on the project name page, click Devices. On the Devices page, in the Authenticode Signing section, select the Sign the project output with this certificate check box. To open the Select Certificate dialog box, click Select Certificate. In the Select Certificate dialog box, from the list of certificates, select the certificate you want and then click OK.

Note
If the certificate you want does not appear in the list, click Manage Certificates. After you receive the certificate, in the Select Certificate dialog box, click OK. The certificate details appear in the Authenticode Signing box on the Devices page.

Packaging and Deploying Windows MobileBased Applications

Lesson Introduction

Deployment is the process of transferring an application to the target device. Before deployment, you must package the application by creating a CAB file. This file is a type of executable archive file that can contain your application, dependency files, resources, and Help files. After creating the CAB file, you must choose a deployment option.

Lesson Objectives

After completing this lesson, you will be able to:


Create a CAB file for a mobile device project. Customize a CAB file for a mobile device project. Select a deployment option for Windows Mobilebased applications.

Create a Mobile Device CAB Project


When you create a CAB file, Visual Studio 2005 generates an INF file. The INF file contains details about the folders into which the files will be installed, the required Windows Mobile version, and the uninstall permissions of the application. To create a CAB file, you must first add a CAB project and then populate this project. To add a CAB project, perform the following steps:
1. 2. 3. 4. 5. 6. To open an existing smart device project, on the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, select a smart device project, and then click Open. To add a CAB project, on the File menu, point to Add, and then click New Project. In the Add New Project dialog box, in the Project types pane, expand Other Project Types, and then click Setup and Deployment. In the Templates pane, select Smart Device CAB Project. In the Name box, type CABProject, and then click OK.

To populate the CAB project, perform the following steps:


1. To ensure that the files you select later in the process are installed into the Application folder on the target device, in the left pane of the File System Editor, select the Application Folder node. If the File System Editor is not visible, access Solution Explorer, right-click the CAB project name, point to View, and then click File System.

2. 3.

In Visual Studio 2005, on the Action menu, point to Add, and then click Project Output. In the Add Project Output Group dialog box, from the Project list, select your smart device project.

From the list of output options, select Primary output, and then click OK.

Customize the CAB Project


You can customize a CAB file by changing the product name and specifying a location for the output file. You can also add dependency files, create a shortcut to the primary output, and modify a registry entry. The following table describes the possible customizations for a CAB file. To change the product name, perform the following steps:
1. 2. 3. In Solution Explorer, select the CAB project. On the View menu, click Properties Window. In the ProductName field of the Property window, type the new product name.

Note
You can also use the Properties window to change the name of the manufacturer and to specify allowed versions of the operating system.

To specify the placement of an output file, in this case the Program Files folder, perform the following steps:
1. 2. 3. 4. In Solution Explorer, select the CAB project. On the View menu, point to Editor, and then click File System. Right-click Primary Output, and then click Properties Window. In the Properties window, change the Folder property to Program Files Folder.

To add dependency files, perform the following steps:


1. 2. 3. In Solution Explorer, select the CAB project. On the Project menu, point to Add, and then click File. In the Add Files dialog box, browse to the file that you want to add, and then click Open.

To create a shortcut to the application, perform the following steps:


1. 2. 3. 4. 5. In the right pane of the File System Editor, select Primary output from<your application project name>. On the Action menu, select Create Shortcut to Primary output from<your application project name>. Right-click Shortcut to Primary output from<your application project name>. On the shortcut menu, click Rename. Type a name for the shortcut.

To edit a registry entry, perform the following steps:


1. 2. 3. 4. 5. 6. 7. 8. In Solution Explorer, select the CAB project. On the View menu, point to Editor, and then click Registry. On the Registry<your project name> tab, under the Registry on Target Machine node, right-click HKEY_CURRENT_USER. On the shortcut menu, click New Key. Type a name for the new key and then right-click the new key. On the shortcut menu, point to New, and then click Key. Type a name for the key and then right-click the key. On the shortcut menu, click Properties Window.

Deployment Options for Windows MobileBased Applications


There are various deployment options that you can use, depending on the application that you want to deploy. The following table describes the deployment options that you can use for a Windows Mobile based application. ActiveSync is a synchronization software that allows you to copy the application CAB files to a mobile device. The user can then manually run the CAB file on the device to install the application. ActiveSync includes a tool named Application Manager that provides a mechanism to install and remove applications from a connected device. If you use HTTP, users are directed to a Uniform Resource Locator (URL) on which the CAB files are located. When the users access the URL from their Windows Mobilebased device, they can download and install the application. You can use a storage card to deploy applications on disconnected devices. Windows Mobile detects the storage card each time the card is inserted into the smart device. When the device reads the storage card, the Windows directory stores the autorun.exe file, which automatically starts the installation of CAB files. Autorun.exe also enables Windows Mobile software to detect the removal of the storage card. Autorun.exe then instructs the application to perform a cleanup operation and to remove itself from the active memory.

Working with Remote Tools for Visual Studio 2005


Lesson Introduction

You can use remote tools to connect to a Windows Mobilebased device from a development workstation. You can use these tools to manage file and registry information and to monitor the performance of threads or processes on a Windows Mobilebased device. In addition, you can test and debug applications on a device from a remotely connected computer.

Lesson Objectives

After completing this lesson, you will be able to:


Describe the remote tools for developing and debugging Windows Mobilebased applications in Visual Studio 2005. Locate and run the remote tools in Visual Studio 2005. View the file system on a mobile device by using Remote File Viewer. View the registry on a mobile device by using Remote Registry Editor. View processes that are running on a mobile device by using Remote Process Viewer.

Remote Tools for Visual Studio 2005


This illustration represents some of the remote tools that you can use to perform programming tasks on a Windows Mobile 5.0based target device.

Run the Remote Tools for Visual Studio 2005


The Visual Studio IDE does not include the remote tools by default. To use these tools in the Visual Studio environment, click Start, point to All Programs, point to Microsoft Visual Studio 2005, and then click Visual Studio Remote Tools. You can add these remote tools to the Tools menu of Visual Studio 2005, by performing the following steps:
1. 2. 3. 4. In Visual Studio 2005, click Tools, and then click External Tools. In the External Tools dialog box, click Add. In the Add dialog box, browse to \Program Files\CE Remote Tools\5.01\Bin. From the list of remote tools, select the tools that you want to add to the Tools menu.

View the File System by Using the Remote File Viewer


You can use the Remote File Viewer tool on a computer for a hierarchical view of the file system. This tool is similar to the Windows Explorer tool for viewing files and folders in Microsoft Windows. You can access the Remote File Viewer from the Tools menu in the Visual Studio development environment. This tool allows you to transfer files between a remotely connected computer and a mobile device. You can also modify files or folders on a device from a remotely connected computer. You can perform the following actions to transfer or modify files by using the Remote File Viewer. To export a file to a device, perform the following steps:
1. 2. 3. 4. On the target device, select the folder to which you want to export the file. On the computer, in Visual Studio 2005, on the File menu, click Export File. Browse to the directory in which you have stored the file that you want to export. Select the file, and then click Open.

To import a file from a device, perform the following steps:


1. 2. 3. 4. On the target device, select the file you want to import. On the File menu, click Import File. On the computer, browse to the directory in which you want to save the file. Click Save.

To display file or folder properties, perform the following steps:


1. 2. On the device, select the file or folder whose properties you want to view. On the File menu, click Properties.

To rename a file or folder, perform the following steps:


1. 2. 3. On the device, select the file or folder that you want to rename. On the File menu, click Rename. In the Rename dialog box, type a name for the file or folder.

To delete a file or folder on a device, perform the following steps:


1. 2. 3. On the device, select the file or folder that you want to delete. On the File menu, click Delete. Click Yes to confirm the deletion.

View the Registry by Using the Remote Registry Editor


You can use the Remote Registry Editor to manage the registry on a device from the development workstation. You can perform the following tasks by using the Remote Registry Editor. To add a key or entry into the registry of the device, perform the following steps:
1. 2. 3. 4. 5. In the registry of the device, select a location for the key or entry. On the Edit menu, click New. To add a key, click Key. Alternatively, click String Value, Multi String Value, Binary Value, or DWORD Value. For a key, in the text box, type a name for the registry key. For an entry, in the Name box, type a name for the entry, and then in the Value box, type a value for the entry. To confirm the process, click OK.

To modify registry values on a device, perform the following steps:


1. 2. Double-click the registry entry that contains the value that you want to change. In the Value box, type the new registry value, and then click OK.

View Running Processes by Using the Remote Process Viewer


The Remote Process Viewer tool displays information about each process that is running on a target device. You can use this tool from the Visual Studio development environment or from Platform Builder. The Remote Process Viewer displays information about threads and processes in the following panes. Pane Process pane Thread Description This is the top pane in the Remote Process Viewer window. The Process pane displays information about each process that is running on a target device. This is the center pane in the Remote Process Viewer window. The Thread

pane Module pane

pane displays information about each thread corresponding to the selected process in the Process pane. This is the bottom pane in the Remote Process Viewer window. The Module pane displays information about each module corresponding to the selected process in the Process pane.

Displaying information about processes that are running on a target device


To display information about a process that is running on a target device, perform the following steps:
1. 2. In Visual Studio 2005, on the Tools menu, click Remote Process Viewer. In the Process pane of the Remote Process Viewer window, select a process that is running on the target device.

Potrebbero piacerti anche