2013年10月30日 星期三

如何自动cradle wince模拟器

http://m.blog.csdn.net/blog/chief1985/5429861#

wince的模拟器有个Device Emulator Manager,这里面可以对模拟器进行cradle,之后Device Emulator Manager会是activesync和模拟器建立连接(DMA方式),之后wince的一些工具就可以用了。例如cecopy.exe,cedir.exe等,下面是一个列表:
cecopy.exe:拷贝文件到wince设备或模拟器(反过来也可以)
cedel.exe:删除wince设备或模拟器上的文件
cedir.exe:列举文件
ceexec.exe:执行程序
cegetinfo.exe:获取剩余空间信息
cemkdir.exe:创建目录
cereg.exe:注册表操作
这些工具的意义看名字就知道了,可以在http://www.microsoft.com/downloads/details.aspx?familyid=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en下载,这里面还有一些别的工具。
cradle一般的做法是Device Emulator Manager右键来选择。对于喜欢命令行一键搞定的程序员来说,cradle是一个比较麻烦的事,有没有可以在命令行里面cradle的方法呢?
答案是肯定的。在msdn里面,微软提供了一个对Device Emulator Manager编程的方法(http://msdn.microsoft.com/en-us/library/bb887543.aspx)。大家可以从http://download.microsoft.com/download/3/6/1/361517d0-2054-4d41-af95-36d18e141df5/DEMAutomationSetup.msi下载这个例子,然后进行编译,编译一般会报错,说找不到DEMComInterface.tlb,这就需要更改一些工程的Include目录。例子的作者将Device Emulator装在d盘,我们只需要将这个目录改为自己的Device Emulator安装地方就可以了。DEMAutomation支持如下命令,其中就有cradle 。Device Emulator Manager提供的API可以参考http://msdn.microsoft.com/en-us/library/bb531169.aspx
List :列举模拟器
bringtofront [VMID|Name] :窗口置顶
connect [VMID|Name] :连接
cradle [VMID|Name]
clearsavestate [VMID|Name]
getconfiguration [VMID|Name] [existing device configuration file]
reset [VMID|Name]
uncradle [VMID|Name]
setconfiguration [VMID|Name] [device configuration file to create]
shutdown [VMID|Name]

参考网址:
http://msdn.microsoft.com/en-us/library/bb887543.aspx
http://msdn.microsoft.com/en-us/library/bb531169.aspx
http://social.msdn.microsoft.com/Forums/en-US/microsoftdeviceemu/thread/84fb02dc-2510-46b4-98e9-541297d555c4

2013年10月28日 星期一

Windows Mobile App Development

Windows Mobile App Development 

Additional resources and references

WMTF - UIAL Overview

WMTF - UIAL Overview

UIAL Overview

The UI Abstraction Layer (UIAL) is a collection of C# classes that model globalized access to an applications user interface. The Device Automation Toolkit (DATK) provides C# classes for generic controls, whereas the UIAL exposes every individual instance of these controls for easy programmatic access. The UIAL hides details about each control, such as control ID or parent window, from the tests that need to use these controls. In this way test cases are isolated from changes in the UI - changes to details in UI controls only require changes in the corresponding UIAL, not in the hundreds of test cases that may require access to that control.

UIAL Components

Every application has its own set of UIAL projects - one for each supported device. Within each UIAL project you will have 4 important components:

Dialog Classes

Every dialog in an application is exposed in a Dialog class.
  • Derives from MobilityToolKit.MobilityDialog
  • Contains details about the dialog itself such as control ID and parent window.
  • Exposes a DATK object for every control contained within the dialog. The DATK objects are exposed as properties of the dialog class.
  • Contains a VerifyAllControls() method that checks to see that each non-optional control in the dialog can be found.
  • Exposes a static instance of the IdnHolder class for the dialog to provide access to localized strings found in the dialog.
  • Recently updated versions expose a DATK ControlBinding object for every control which gives you access to the WindowFinder used to bind to a control.
  • Example: %_WMTFROOT%\CalViewSample\AbstractionLayer\SmartPhone\CalViewMain.cs

Application Class

Each application has one application class to hold all the dialog classes. This is the starting point for locating any single UI element.
  • Contains a Launch() method used to start the application using the UI.
  • Contains a static property for each of the Dialog classes within the app.
  • Example: %_WMTFROOT%\CalViewSample\AbstractionLayer\SmartPhone\Microsoft.MobileDevices.AbstractionLayer.CalView.SmartPhone.cs

IdnHolder Classes

Each dialog in an application has an associated IdnHolder class to hold localized resources for the dialog.
  • Contains static IdnString instances for various string resources found in the dialog.
  • Example: CalViewSample\AbstractionLayer\SmartPhone\IdnHolders.cs

UIAL self-test

Each UIAL contains a self-test suite that walks through the UI to validate itself.

  • Contains Begin() and End() methods for test setup and cleanup.
  • Contains AbstractionLayerBVT() method which walks through the UI to call VerifyAllControls() on every dialog in the application. 
  • Verification is very simple - the test passes if AbstractionLayerBVT() completes without throwing an exception.
  • Example: %_WMTFROOT%\CalViewSample\AbstractionLayer\SmartPhone\Microsoft.MobileDevices.AbstractionLayer.CalView.SmartPhone.cs  

How a UIAL is used

The UIAL for an application is used primarily by the Area Library for the application. Briefly, the Area Library is a collection methods that accomplish common UI tasks. For instance, the Inbox Area Library might contain a method that configures a messaging account, while the Contacts Area Library might contain a method to create a new contact. In order to accomplish these tasks the Area Library has to interact with a large number of controls on the device. Rather than specify the details of each control itself the Area Library simply gets the DATK object for UI element that it is interested in from the UIAL and then interacts with that object. For example, in order to select an item in the sample CalView application, you would use:
CalViewUIAL.CalViewMainDialog.MainListView.SetItemSelected(index, true); The Area Library uses the UIAL to locate specific controls by narrowing down the location from the app, to the dialog, to the control itself. The Area Library only cares where the control is, not what properties it has, which provides a level of isolation from changes in the UI.

Creating a UIAL

To a large extent the UIAL consists of generated code, but area owner expertise is needed to finish the process. The following are the general steps that are used to generate a UIAL. The work items below are needed to complete the UIAL. Remember, when working with the UIAL, that most of the classes representing dialogs will be automatically regenerated, so making changes to these files is wasted work. For this reason when changes are needed in these dialog classes you need to either add tags to the associated RCML files, or you need to extend the class that needs changes and make the changes in the inherited class. This is not the case with the classes representing applications.

Generate RCML files for dialogs and windows.

Use RcmlSnap to take a snapshot for every window in your application. This could take a few minutes per dialog.

Rename Controls in RCML to be Semantically Correct.

See the section on Editing the RCML to find out how to do this. This could take about 15 - 30 minutes per file.

Generate your UIAL project.

  • Run RCtoCS to generate the cs files for your application windows, and include them in your project.
  • Run UIALAppGen to generate the code for the application and main dialog classes.

Expose IdnStrings.

  • IdnStrings are a way to globalize strings found in the product, so that test automation can be easily globalized.
  • Use CeStrip to extract the resource strings and IDs from each module in your application.
  • RCTOCS will produce a skeleton file to hold your IDN strings called IdnHolders.cs along with the other classes for the UIAL. In this file you will find a class for each of the dialogs in your UIAL. Assuming that globalization of your test automation is important, the task here is to populate these classes with IdnString objects for strings that are exposed from your dialogs.
  • Each class contains an example that will help you see how to create the IdnString object. Depending on the size of your area and the number of strings this could take a couple hours.

UIAL Self-Test.


Every UIAL project has an auto generated self-test to smoke test the UIAL. A self-test is a convenient way of ensuring a minimal level of correct functionality of the UIAL. To implement this, you need to modify the test to open every dialog before calling the validation method on that dialog. This will take a couple hours at least.

Maintaining a UIAL

When UI or resource changes are made in the product the UIAL must be updated to reflect these changes.

Re-run RcmlSnap to update the RCML files

  • Run RcmlSnap on a new or updated window. With updated windows, make sure that RcmlSnap has access to the existing .rcml file, so that it can round-trip changes you've made to it previously.

Re-run RCTOCS to update the UIAL files

  • See RCtoCS for information on running the tool.

Re-run CeStrip to get an updated list of resource strings.

  • See CeStrip for information on running the tool.
  • Look at the IdnHolders.cs file for your UIAL project, a new class will be added for every new RCML file.
  • Add any new resource strings to the corresponding dialog classes in IdnHolders.cs.

Make sure the UIAL self-test passes


  • Build and the UIAL using Visual Studio.
  • Run the UIAL self-test by deploying the UIAL project with the Tux.Net project as the startup project. 

Tools used to work with a UIAL

These are the tools used when working with a UIAL:
  • RCtoCS: Tool generates UIAL Dialog classes based on RCML files that have been decorated with specific tags.
  • RcmlSnap: Tool generates RCML based on the top-level window currently displayed on a device. 
  • GenFinder: Tool determines Datk.WindowFinder object that should be used to locate a specific control on a device.
  • CeStrip: Tool which extracts resource strings in name=value pairs from a Windows CE binary.
  • UIALAppGen: Tool generates a UIAL Application class based on a number of UIAL Dialog class files. 

How to decorate RCML files for use by RCTOCS

In order to auto-generate abstraction layer code for your application, you must first mark up the .RCML files that correspond to each dialog in the application.
RCML is XML, and the tool that reads it and converts it to C# code is looking for a specific set of attributes that need to be added to the existing tags. What follows is a list of the tags you want to change, the attributes you want to add to each tag, and an example of each attribute. Attributes are case-sensitive.
  • <PAGE>
    • APPNAME="appName": This is the name of your app to be appended to your project namespace when the C# code is generated.
    • FRIENDLYNAME="FindReplace": This will be the name of the parent class containing all the child controls. Don't add "Dialog" as part of the text, since that will be appended to your FRIENDLYNAME by the codegen tools.
    • NAMESPACE="Microsoft.MobileDevices.AbstractionLayer.pOffice": This is the parent namespace onto which APPNAME will be appended. Do not put the value inside the APPNAME attribute into your NAMESPACE value. If you have a parent app namespace, like pOffice or pOutlook, this is the right place to add it.
    • PROJECT="PocketPC": Choices are PocketPC and Smartphone.
    • DIRECTORY="\abstractionlayer\<appName>\<sub-appName>\<project>": This is a relative path where the generated files will be copied.
    • CSHELP="The FindReplace dialog": This is a place to put text that will be added to comments in the generated code.
    • PROCESSNAME="yourapp.exe" - (OPTIONAL): This attribute will add a property to the dialog window finder that tells it to match this dialog only if it is owned by the provided process name. This can be helpful if the wrong dialog is being found when you try to initialize a specific UIAL object.
    • SCOPE="private" - (OPTIONAL): This attribute will cause a base and a derived UIAL class to be generated by rctocs. The derived class can safely be hand-edited. Include this attribute if you need to override any of the UIAL defaults. If you don't need to do this, leave this attribute off.
    • BASECLASS="ClassName:(parameterString)" - (OPTIONAL): This attribute specifies that the UIAL class generated for this dialog should be derived from base class "ClassName" and that the constructor should pass "paramaterString" to the base constructor.  The base class needs to derive from MobilityToolKit.MobilityDialog.
    • OBSCURED="true" - (OPTIONAL): This attribute will force the .Visible property of the mainFinder object to be set to false. This worked around a bug in the DATK that caused exceptions when a UIAL object is initialized with the .Visible property set to true.  This should no longer be necessary.
    • IGNORETEXT="true" - (OPTIONAL): This attribute will prevent rctocs from initializing the .Text property of the mainFinder object. This is useful under circumstances where the main dialog's titlebar text changes at runtime, or the auto-generated IDN value corresponding to the window title is wrong, for whatever reason. NOTE: including this attribute will cause any value inside the IDNTEXT attribute to not be generated.
    • IDNTEXT="YourDialogIdns.mainWindowTitle" - (OPTIONAL): If present, the contents of this attribute will be used as the value of the .Text property of the mainFinder object, in place of an auto-generated IDN value. We recommend that the value you use here is a reference to a member variable contained within the IdnHolder class that belongs to this dialog. An instance of this class is already provided by rctocs, for your convenience, and looks something like this:
      /// <summary>
      /// IdnHolder object holding all the owner-maintained strings for AlignDialog./// </summary>

      public readonly AlignDialogIdnHolder AlignDialogIdns = new AlignDialogIdnHolder();
  • <BUTTON>, <CHECKBOX>, <COMBOBOX>, <LABEL>, <LISTBOX>, <SPINNER>, <EDIT> (the following attributes apply to all of these tags)
    • FRIENDLYNAME="ShowFormattingCheckBox": This will be the name of the control in the generated code. You should append the control type to 1 or 2 words describing the control.
    • CSHELP="Check this box to toggle formatting display": This is a place to put text that will be added to comments in the generated code.
    • OBSCURED="true" - (OPTIONAL): This attribute will force the .Visible property of the control's WindowFinder object to be set to false. This worked around a bug in the DATK that caused exceptions when a UIAL object is initialized with the .Visible property set to true.  This should no longer be necessary.
    • OPTIONAL="true" - (OPTIONAL): This attribute will prevent the control from being added to the dialog's VerifyAllControls() method. This is useful for controls that are present and visible only under specific circumstances at run-time.
    • MODIFIER="override" - (OPTIONAL): Use this to specify a modifier for the control (override, virtual, public, private, etc.) where public is the default if not specified.
    • IDNTEXT="YourDialogIdns.mainWindowTitle" - (OPTIONAL): If present, the contents of this attribute will be used as the value of the .Text property of the control's WindowFinder object. This is useful under circumstances where identification by control ID alone is insufficient or error-prone. We recommend that the value you use here is a reference to a member variable contained within the IdnHolder class that belongs to this dialog. An instance of this class is already provided by rctocs, for your convenience, and looks something like this:
      /// <summary>
      /// IdnHolder object holding all the owner-maintained strings for AlignDialog./// </summary>
      public readonly AlignDialogIdnHolder AlignDialogIdns = new AlignDialogIdnHolder();
As you choose friendly names for your controls you want to postfix the DATK Control type to the end of the variable name. For example, if you have a combo box that sets the Type of a search you could name it SearchTypeComboBox. Or, if you have a textbox that accepts a name you could name it NameTextBox. Here is the list of DATK control names that should be used:
  • Button
  • CheckBox
  • ColumnHeader
  • ComboBox
  • ContextMenu
  • Control
  • HtmlControl
  • HtmlLink
  • HtmlLinks
  • Label
  • LabelEditControl
  • ListBox
  • ListView
  • ListViewItem
  • MainMenu
  • Menu
  • MenuItem
  • RadioButton
  •  RichEditBox
  • SBTextBox
  • SIPFloater
  • SIPWindow
  • SliderControl
  • Softkeys
  • TabControl
  • TabPage
  • TextBox
  • ToolBar
  • ToolBarButton
  • VirtualListView
After your changes have been made, drag each file into Internet Explorer to confirm that it parses correctly.

2013年10月27日 星期日

Something relating to Windows CE/ Mobile


.NET Compact Framework

Microsoft .NET Compact Framework 是 Windows Mobile 和 Windows Embedded CE 裝置上不可或缺的元件,它可讓您建置和執行 Managed 應用程式以及使用 Web 服務。.NET Compact Framework 包含經最佳化的 Common Language Runtime (CLR) 和 .NET Framework 類別庫 (Class Library) 子集,後者支援如 Windows Communication Foundation (WCF) 和 Windows Form 等功能。此外,其中也包含專為 .NET Compact Framework 設計的類別。

.NET Compact Framework 可支援 Visual Basic 和 Visual C# 開發。目前它並不支援 C++ 開發。

.NET Compact Framework 繼承 Common Language Runtime 的完整 .NET Framework 架構,可用於執行 Managed 程式碼,還提供與 Windows CE 作業系統裝置的互通性 (Interoperability),使您可以存取原生 (Native) 的函式,並將您最喜歡的原生元件整合到應用程式中。

下列圖例摘要說明 .NET Compact Framework 平台架構。

.NET Compact Framework 架構圖形



.NETCF and Window Phone 7

Windows Phone 7 Series Application development platform is based on Microsoft Silverlight and XNA Framework – that are underneath powered by .NET Compact Framework (.NETCF). .NETCF provides the managed runtime environment for both Silverlight and XNA applications targeting Windows Phone 7.



Windows Mobile 5.0 - Emulators: copying files and ActiveSync

Shared Folder

The emulators allow you create a shared folder - a folder on your desktop PC, that appears as a Storage Card on the emulated device. Open up the Emulator's properties from "File / Configure.." and then select a Shared Folder from the textbox.

ActiveSync

Now this is really cool. The new emulators can actually connect to the copy of ActiveSync running on your desktop, and they behave like a real, physical device. This means you can select Explore, and wander through their file system copying and pasting files. This is by far the simplest way to copy your support files to your emulator. You can even copy CAB files, and test your new installers (something I'll cover in another blog entry very soon).

To get ActiveSync working, first configure ActiveSync itself (you'll need the very latest version), by opening "Connection Settings", and changing the pull-down under "Allow connections to one of the following" to "DMA". DMA is "Direct Memory Access", and allows the emulator to create a direct connection with ActiveSync without any extra wires.

Next, from within Visual Studio, open the Tools menu and select "Device Emulator Manger". From within this dialog, find the current emulator you are using, right click, and select "Cradle".

Then on the emulated device itself, open the ActiveSync tool, and select "Connect via DMA..." from the menu option.

And that's it! You should see ActiveSync starting as if the emulator was a real device. Now if you click Explore on the ActiveSync dialog, you can drill down to whatever location you need to copy and paste files.


Step by Step: Using Microsoft Device Emulator In-Depth in Your Application Development Experienc



Getting Started with Building Windows Mobile Solutions with Visual Studio and Windows Mobile 6 SDK


Windows 7 - Using the Windows Mobile Emulator

Windows Mobile Test Framework Overview

Windows Mobile Test Framework Overview

Framework Layers

This document will give a high level overview of the pieces that make up the Windows Mobile Test Framework. This framework is made primarily of .Net class libraries which are used to automate interaction with the device UI.
These class libraries are broken out into separate layers with differing purposes. The layers are shown in the diagram below, which illustrates how the different pieces are built on top of one another. Tux.Net, not shown here, simply executes code from the test suites, but is built primarily on Logging and Utils.Net components.



Logging

The Logging library contains classes associated with logging test data and test result management. The Logging library is generic enough that it can be used by any tool, not just .Net test automation, and it can even be used by desktop tools. The main interfaces into the Logging library for .Net Automation are GlobalLogger and GlobalLogResultManager.
GlobalLogger is used for logging text and comments to log files during testing. It is used by Mtk, UIAL, Area Library, and Test components. It frees you from worrying about where and how to log data - it will make sure your data gets in the right file, where the "right" file is defined by whatever file the GlobalLogger has been configured to deliver to. GlobalLogger also has the notion of logging levels so that you can assign varying importance to different comments. For instance, UIAL comments may be logged at debug level and only turned on during debugging, whereas comments at the test level would always be logged. GlobalLogResultManager is used for keeping track of the result of your test - Pass or Fail - as you perform multiple steps in each test case. It is used almost exclusively in the Test and Area Library layers.

Utils.Net

Utils.Net is a toolbox of common device oriented code that can be reused in any automation component including MTK, UIAL, Area Libraries, and Tests. The .Net Framework provides a very rich library of code for desktop tools to reuse, but the .Net Compact Framework contains only a subset of this library. Utils.Net includes many things missing from the .Net Compact Framework that we need on a regular basis to work with and test our devices. As we have need of these missing library components we crate and add them to Utils.Net.

Utils.Net holds code that isn't just useful to .Net Automation, but potentially for anyone who is working with the .Net Compact Framework. In addition, Utils.Net builds for the desktop to facilitate sharing code between device and desktop.

Device Automation Toolkit

The Device Automation ToolKit (DATK) is primarily a C# library of classes that mirror controls on our devices. Most classes in DATK map to a control found in our devices, such as edit boxes, list views, and buttons. In addition to these control classes there is the WindowFinder class, which is the key to working with DATK. It allows you to specify the characteristics (such as type, text, and owning process) of the control you are looking for on the device, and bind that control to a DATK control object. Using the DATK control object you can get information about the control on the device such as the text, selected/unselected status, focused/unfocused status, and more. Even more importantly you can use the DATK control object to interact with the control on the device. In this way we can use DATK to automate the use of UI on the device.

The DATK does not currently depend on the Logging or Utils.Net components.

Mobility Toolkit

The Mobility ToolKit (MTK) is simply an Windows Mobile specific extension to the DATK class library. Because DATK is dedicated to all graphical Windows CE platforms, it has been kept it free of classes representing controls that are not provided as part of the Windows CE operating system. For instance, Softkeys are a very important component in Mobile devices but do not exist in Windows CE itself. We have placed Windows Mobile specific DATK controls into their own library, the MTK. In addition, MTK holds some other classes which are useful to automation. ApplicationManager is the most obvious example of this, which we use to launch applications on Windows Mobile devices.

The MTK has many classes that derive from DATK classes, and it also depends heavily on Logging and Utils.Net.

Abstraction Layer

DATK provides classes for most of the UI elements found on our devices. However, in order to initialize one of these objects to an actual UI element at the Datk layer, you need to use the Datk WindowFinder class. A WndowFinder is provided search criteria such as class name, title, label, control ID, etc and then asked to find the control that matches the criteria it was given. The search criteria are especially sensitive to design and implementation change of the UI, and so this warrants a mode of abstraction to help protect test automation from these changes.
The UI Abstraction Layer, or UIAL, is meant to encapsulate all controls on every form of an application so that the automation developer does not have to determine the properties of every control he uses or use WindowFinder to get that control. It is a C# library that provides a 1:1 mapping between particular controls on the device and DATK control objects. There should be a UIAL for every application, and there should be a property in each UIAL that maps to every control found in that application. This centralizes the work of characterizing each control so that when elements of the UI change only the UIAL needs to change, not all of the code that automates that element.
An application developer must create a UIAL component in order to make their application testable. Anyone can do this for most applications, actually, but only the application developer can reliably ensure that the UIAL adheres to a contract between the automation and the application as the application changes.

The UIAL depends heavily on DATK, MTK, Utils.Net, and Logging. It is used almost exclusively by the Area Libraries. The UIAL is largely tool-generated code, not hand-written code.

Area Libraries

The UIAL is used to hide the complexity of finding controls in DATK, but it does not combine the use of these controls into common usage scenarios. This is what the Area Libraries are for - providing a library of routines that act out common UI scenarios on the device.
The goal of the libraries is to make test script writing as straightforward as typing in descriptions of manual test case steps. The code is very generally comparable to the aggregate steps taken in manual testing. For instance, the first step in a test case for Microsoft Word would be open Word.exe, which corresponds to a series of UI based commands: click Start, click Programs File, Scroll Down, Click Word. "Open Word" might be implemented in the Area Library, so that the test case doesn't need to deal with the specifics of what it takes to open Microsoft Word. The Area Library also abstracts away the notions of a Windows Mobile SKU (Professional, Classic, Standard) to provide functions that act appropriately depending on which version is being used.


Test Cases

In our .Net Automation Framework test suites are simply C# classes that inherit from a class called TestSuite. Tests are simply C# methods in these classes decorated with an attribute that designates them as test cases. Tests are generally organized into test suites by feature. Tests rely almost solely on the area library for functionality, and consist of not much more than a series of calls into the area library, to string together common UI scenarios into a single test scenario. Tests do not call into the UIAL unless the test is specific to a particular kind of Windows Mobile device, which should be fairly rare, depending on the application being tested.
A Test developer should create a test assembly to host test cases for their application.

The Tests depend heavily on Area Libraries, for scenario and object creational patterns, and Logging. They occasionally (rarely in theory) need to use UIAL, MTK, or DATK.

Tux.Net

Tux.Net is a C# program, specifically a test harness, used to run tests on devices. When run from a device with command line or a configuration file it will locate the specified test suites and tests inside managed assemblies and execute them. It has many options for specifying what tests or suites will be run, and how they should be run (for instance, should they be shuffled or repeated). Tux.Net looks for classes inheriting the TestSuite class and methods with the TestCase attribute to know what it can run, and it can run any assembly meeting these requirements.

Tux.Net executes Tests, but it is built primarily with the Logging library and Utils.Net.

Source: WMTF Document