ADDED Setup/deployAndTestCe.eagle
Index: Setup/deployAndTestCe.eagle
==================================================================
--- /dev/null
+++ Setup/deployAndTestCe.eagle
@@ -0,0 +1,354 @@
+###############################################################################
+#
+# deployAndTestCe.eagle -- Windows CE Deployment & Testing Tool
+#
+# Written by Joe Mistachkin.
+# Released to the public domain, use at your own risk!
+#
+###############################################################################
+
+package require Eagle
+
+proc usage { error } {
+ if {[string length $error] > 0} then {puts stdout $error}
+
+ puts stdout "usage:\
+[file tail [info nameofexecutable]]\
+[file tail [info script]] \[year\] \[platform\] \[configuration\]\
+\[culture\] \[platformId\] \[deviceId\] \[quiet\]"
+
+ #
+ # NOTE: Indicate to the caller, if any, that we have failed.
+ #
+ exit 1
+}
+
+#
+# NOTE: This procedure will output a diagnostic message, typically to the
+# standard output channel, using the [puts] command unless the global
+# variable "quiet" is non-zero.
+#
+proc qputs { args } {
+ if {!$::quiet} then {
+ eval puts $args; flush stdout
+ }
+}
+
+#
+# NOTE: This procedure looks up and returns the target device based on the
+# locale, platform Id, and device Id.
+#
+proc getDevice { cultureInfo platformId deviceId } {
+ set datastoreManager [object create -alias \
+ Microsoft.SmartDevice.Connectivity.DatastoreManager \
+ [$cultureInfo LCID]]
+
+ set platform [$datastoreManager -alias GetPlatform [object create \
+ Microsoft.SmartDevice.Connectivity.ObjectId $platformId]]
+
+ if {[string length $deviceId] == 0} then {
+ set deviceId [$platform GetDefaultDeviceId]
+ }
+
+ set device [$platform -alias GetDevice $deviceId]
+
+ qputs stdout [appendArgs \
+ "returning device \"" [$device Name] "\" of platform \"" \
+ [$device Platform.ToString] "\" with Id \"" [$device Id.ToString] \
+ \"...]
+
+ return $device
+}
+
+#
+# NOTE: This procedure starts a process on the target device and optionally
+# waits for it to complete.
+#
+proc startRemoteProcess { device fileName arguments {wait true} } {
+ set remoteProcess [$device -alias GetRemoteProcess]
+
+ if {![$remoteProcess Start $fileName $arguments]} then {
+ error [appendArgs "could not start remote process \"" $fileName \"]
+ }
+
+ if {$wait} then {
+ qputs stdout [appendArgs \
+ "waiting for remote process " [$remoteProcess GetId] ...]
+
+ while {![$remoteProcess HasExited]} {
+ qputs -nonewline stdout .
+ after 1000
+ }
+
+ qputs stdout ""
+ return [$remoteProcess GetExitCode]
+ }
+
+ return -1
+}
+
+set argc [llength $argv]
+
+if {$argc >= 0 && $argc <= 7} then {
+ #
+ # NOTE: Setup the default values for all command line options.
+ #
+ array set default {
+ year 2008
+ platform {Pocket PC 2003 (ARMV4)}
+ configuration Release
+ culture en-US
+ platformId 3c41c503-53ef-4c2a-8dd4-a8217cad115e
+ deviceId {}
+ quiet false
+ }
+
+ #
+ # NOTE: Process all the command line options. If a command line option
+ # is not present, use the default value.
+ #
+ set names [list \
+ year platform configuration culture platformId deviceId quiet]
+
+ for {set index 0} {$index < [llength $names]} {incr index} {
+ set name [lindex $names $index]; set value ""
+
+ if {$argc > $index} then {
+ set value [string trim [lindex $argv $index]]
+ }
+
+ if {[string length $value] > 0} then {
+ set $name $value
+ } else {
+ set $name $default($name)
+ }
+ }
+
+ #
+ # NOTE: Grab the culture instance based on the configured culture name.
+ #
+ set cultureInfo [object invoke -alias System.Globalization.CultureInfo \
+ GetCultureInfo $culture]
+
+ #
+ # NOTE: Build the list of .NET Compact Framework packages that need to be
+ # deployed to the target device.
+ #
+ if {![info exists packages]} then {
+ #
+ # NOTE: The two letter ISO language name is needed when building the
+ # default list of .NET Compact Framework packages because one of
+ # them is a localized resource package.
+ #
+ set language [string toupper [$cultureInfo TwoLetterISOLanguageName]]
+
+ #
+ # NOTE: The default list of .NET Compact Framework packages contains the
+ # .NET Compact Framework 3.5 installation CAB file for ARMV4 on the
+ # Pocket PC and its associated resource installation CAB file.
+ #
+ set packages [list abd785f0-cda7-41c5-8375-2451a7cbff37 \
+ \\windows\\NETCFv35.ppc.armv4.cab c0ccf48e-4bfb-4d84-827c-981a595e40c5 \
+ [appendArgs \\windows\\NETCFv35.Messages. $language .cab]]
+ }
+
+ #
+ # NOTE: Save the path where this script is running from.
+ #
+ set path [file dirname [info script]]
+
+ #
+ # NOTE: The base path should be the project root directory, which should
+ # be one level above the one containing this script.
+ #
+ set base_path [file dirname $path]
+
+ #
+ # NOTE: The managed binaries to be deployed to the target device should
+ # be located in the "\bin\\Compact\bin"
+ # directory.
+ #
+ set managed_directory [file join \
+ $base_path bin $year [appendArgs $configuration Compact] bin]
+
+ #
+ # NOTE: The native binaries to be deployed to the target device should
+ # be located in the "\bin\\\"
+ # directory.
+ #
+ set native_directory [file join \
+ $base_path bin $year $platform $configuration]
+
+ #
+ # NOTE: Build the list of all application files that need to be deployed to
+ # the target device, including all the native and managed binaries.
+ #
+ if {![info exists fileNames]} then {
+ #
+ # NOTE: Grab the assembly name instance based on the primary managed
+ # assembly file name. This is needed because the build portion of
+ # the assembly version is used when building the default list of
+ # application files to be deployed to the target device.
+ #
+ set assemblyName [object invoke -alias System.Reflection.AssemblyName \
+ GetAssemblyName [file join $managed_directory System.Data.SQLite.dll]]
+
+ #
+ # NOTE: The default list of application files includes the test application
+ # itself, the System.Data.SQLite managed assembly, the SQLite interop
+ # assembly, and the test application configuration file.
+ #
+ set fileNames [list [file join $managed_directory testce.exe] [file \
+ join $managed_directory System.Data.SQLite.dll] [file join \
+ $native_directory [appendArgs SQLite.Interop. [format %03d \
+ [$assemblyName Version.Build]] .dll]] [file join $managed_directory \
+ test.cfg]]
+ }
+
+ #
+ # NOTE: Setup the directory on the target device where the application files
+ # should be deployed to.
+ #
+ if {![info exists device_directory]} then {
+ set device_directory "\\Program Files\\testce\\"
+ }
+
+ #
+ # NOTE: Load the managed assembly that allows us to communicate with the
+ # target device. If this fails, the necessary SDK components are
+ # probably not available on this system.
+ #
+ object load Microsoft.Smartdevice.Connectivity
+
+ #
+ # NOTE: Lookup the necessary device based on the platform and device Ids.
+ #
+ set device [getDevice $cultureInfo $platformId $deviceId]
+
+ #
+ # NOTE: Attempt to connect to the target device, which may be an emulator.
+ # By default, we attempt to connect to the "Pocket PC 2003 SE Emulator"
+ # device of the "Pocket PC 2003" platform (English). If this fails,
+ # the target device is probably unavailable, either because it is not
+ # connected or some SDK components are missing.
+ #
+ $device Connect
+
+ #
+ # NOTE: Grab the file deployer instance for the target device. This will
+ # be used to download packages and send files to the target device.
+ #
+ set fileDeployer [$device -alias GetFileDeployer]
+
+ #
+ # NOTE: Process each entry in the list of packages to be downloaded to the
+ # target device. The package list must contain the package Id and the
+ # file name (relative to the target device), in that order, for each
+ # package to be downloaded to the target device.
+ #
+ foreach {packageId packageFileName} $packages {
+ qputs stdout [appendArgs \
+ "downloading package \"" $packageId "\" to device..."]
+
+ $fileDeployer DownloadPackage [object create \
+ Microsoft.SmartDevice.Connectivity.ObjectId $packageId]
+
+ qputs stdout [appendArgs \
+ "installing package file \"" $packageFileName "\" on device..."]
+
+ startRemoteProcess $device wceload.exe [appendArgs "/noui " \
+ $packageFileName]
+ }
+
+ #
+ # NOTE: Process each application file to be sent to the target device.
+ #
+ foreach fileName $fileNames {
+ qputs stdout [appendArgs \
+ "sending file \"" $fileName "\" to device..."]
+
+ #
+ # NOTE: All the application files are sent to the same directory on the
+ # target device and the SendFile method requires a fully qualified
+ # file name; therefore, grab the file name only from the source file
+ # name and append that to the directory name on the target device.
+ # Using [file join] and/or [file normalize] should be avoided here
+ # because the directory name on the target device is not necessarily
+ # valid a file name on this system and vice versa.
+ #
+ $fileDeployer SendFile $fileName [appendArgs $device_directory \
+ [file tail $fileName]] true false
+ }
+
+ #
+ # NOTE: Run the test application on the target device in "automatic" mode
+ # (i.e. no user interaction is required) and capture the exit code.
+ # The exit code will be zero upon success (i.e. all tests passed) or
+ # non-zero otherwise.
+ #
+ set testFileName [file nativename [file join $device_directory testce.exe]]
+ set exitCode [startRemoteProcess $device $testFileName true]
+
+ #
+ # NOTE: Is the target device actually an emulator running on this system?
+ #
+ set isEmulator [$device IsEmulator]
+
+ #
+ # NOTE: We no longer need to be connected to the target device.
+ #
+ $device Disconnect
+
+ #
+ # NOTE: Also, if the device is an emulator, attempt to shutdown the process
+ # containing it now (since we probably caused it to start).
+ #
+ if {$isEmulator} then {
+ #
+ # NOTE: Try to find the top-level window for the device emulator process
+ # based on the "LCDDisplay" window class name. Using this method
+ # of finding the target window is somewhat fragile and may not work
+ # reliably in the future.
+ #
+ set hWnd [lindex [lindex [info windows LCDDisplay] 0] 0]; # FIXME: ???
+
+ #
+ # NOTE: Make sure we found it before trying to lookup the parent process.
+ #
+ if {[string is integer -strict $hWnd] && $hWnd != 0} then {
+ #
+ # NOTE: Attempt to lookup the parent process for the target window.
+ #
+ qputs stdout [appendArgs "found device emulator window handle " $hWnd \
+ ", looking up the process Id..."]
+
+ set processId 0; set threadId 0; set error null
+
+ if {[object invoke -flags +NonPublic \
+ Eagle._Components.Private.WindowOps GetWindowThreadProcessId \
+ [object create IntPtr $hWnd] processId threadId error] eq "Ok" && \
+ [string is integer -strict $processId] && $processId != 0} then {
+ #
+ # NOTE: This is not ideal; however, if we simply try to close the
+ # target window, it will prompt to save state changes and that
+ # requires user interaction. We never want to save the state;
+ # therefore, just forcibly kill the process containing the
+ # emulator.
+ #
+ qputs stdout [appendArgs "found device emulator process Id " \
+ $processId ", killing..."]
+
+ kill -force $processId
+ }
+ }
+ }
+
+ #
+ # NOTE: Print the overall result of running the test application and exit
+ # using the exit code from the test application on the target device.
+ #
+ qputs stdout [expr {$exitCode == 0 ? "SUCCESS" : "FAILURE"}]
+ exit $exitCode
+} else {
+ usage ""
+}
Index: Setup/verify.lst
==================================================================
--- Setup/verify.lst
+++ Setup/verify.lst
@@ -505,12 +505,12 @@
# NOTE: This is the list of interop and other files that should be present in
# the standard "PocketPC" binary archives (i.e. for the .NET Compact
# Framework).
#
set sds_manifests(binaryCompact) {
- "SQLite.Interop.[format %03d $build].dll"
- "SQLite.Interop.[format %03d $build].pdb"
+ [appendArgs SQLite.Interop. [format %03d $build] .dll]
+ [appendArgs SQLite.Interop. [format %03d $build] .pdb]
test.cfg
testce.exe
testce.pdb
}
Index: testce/TestCases.cs
==================================================================
--- testce/TestCases.cs
+++ testce/TestCases.cs
@@ -69,15 +69,16 @@
}
}
internal class TestCases
{
- private bool autoClose;
internal Form1 frm;
- internal int total;
- internal int passed;
- internal int failed;
+
+ private bool autoClose;
+ private int total;
+ private int passed;
+ private int failed;
internal TestCases(bool autoExit)
{
this.autoClose = autoExit;
}