Wednesday, December 20, 2006

Alpha Blending on SmartPhone

I created a quick test app to experiment with the performance of the P/Invoke AlphaBlend calls as discussed in this blog post by Chris Lorton. The AlphaBlend native call does not support per-pixel alpha blending so the alpha value is specified for the entire image. The "incr" label in these two videos is the step value for the alpha channel used in the animation. The frame rates were better than expected, right around 17-20fps.

The tool I am using to record the video is called CoolCapture (I'm using the trial version here). It's very cool. It's essentially a fully featured screen capture tool for Windows Mobile 5 devices. You can generate both videos or pictures. I was fairly impressed with the performance as well; capturing these two videos below only resulted in about a ~6 fps reduction in my animation (thus the blending doesn't look as smooth as it actually is). The trial version limits the recording interval to ~10 seconds (though the webpage says 5 seconds).

Note that the capture resolution was 240x320 (the device resolution); however, this was automatically changed to 640x480 when I uploaded the video to YouTube. This is why the videos have that stretched out look.

Wednesday, December 13, 2006

2125 ActiveSync Internet Pass Through

I was trying to use ActiveSync as a pass through to my laptop's internet connection so that I could debug a HttpWebRequest problem while tethered to VS2005. However, I couldn't even get PIE (Pocket IE) to use the ActiveSync connection much less my app--well, now I'm at least half way there. I can browse the web using PocketIE and ActiveSync as my internet connection.

1) Open ActiveSync on your computer, select File->Connection Settings. In the ComboBox below "This computer is connected to:" make sure "The Internet" is selected.

2) In PIE, select Tools->Options->Connections. Then, select "The Internet" as your network.

Now, I'm going to see if my own app can do this.

Tuesday, December 12, 2006

Link to Files in VS2005

David Kline posted about sharing code between multiple projects (where a common assembly is not appropriate):

I would prefer to not create a duplicate of this file as maintaining changes between the two copies can be time consuming and error prone. Fortunately, Visual Studio 2005 has a great feature to allow for file sharing between projects -- you can add an existing file as a link. Here's how:

1. In the project where you wish to add the file, right click the project name in the Solution Explorer
2. Select Add and then Existing Item...
3. In the Add Existing Item dialog, navigate to the desired file
4. Click the downward pointing arrow next to the Add button and select Add As Link.
Once added to a project, linked files are easy to identify by the small arrow in the lower-left corner of the file icon in the Solution Explorer.

Sunday, November 19, 2006

Measuring CPU Load

I am looking for an API call or library I can download that provides access to CPU load information. I am willing to pay for third-party commercial applications. I have scoured the internet and it doesn't appear like anything exists out there. I experimented with the .NET CF Remote Performance Monitor today but that does not include any CPU statistics.

Note, it appears that the pps tool from http://www.xs4all.nl/~itsme/projects/xda/tools.html might do the trick. Further investigation is needed.

Monday, November 13, 2006

Cannot Create Native C++ Projects

If you try to create a native C++ Smart Device project, you would have repeatedly try to finish the ‘New Project’ dialog but wouldn’t have been able to get it to work.

This problem is due to the New Project dialog not playing nice with the changes in Internet Explorer 7 (the New Project dialog for native projects is actually a glorified web browser control).

The workaround is simple - Open the registry entry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Ext\PreApproved
Add a new entry and name it
{D245F352-3F45-4516-B1E6-04608DA126CC}

Again this is something we have fixed for Visual Studio 2005 SP1.


(link)

Update 11/13/2006 2:50PM: Note: this did not work for me. I am currently installing the Visual Studio 2005 SP1 Beta release; hopefully this fixes the problem as well.

Update 11/13/2006 6:50PM: VS2005 SP1 Beta works!

Tuesday, November 07, 2006

SQL Server Everywhere Renamed

SQL Server Everywhere has been renamed to SQL Server Compact Edition. I guess there was a lot of confusion about what SQL Server Everywhere was--particularly, disambiguating it with SQL Server Express.

(link)

Thursday, September 28, 2006

Platforms for .NET CF 2.0

As a corrollary to my last post, what does .NET CF 2.0 run on? According to Jim Wilson's post:
  1. PocketPC 2003 & PocketPC 2003 SE
  2. PocketPC 2005 (or 5.0)
  3. SmartPhone 2005 (or 5.0)
  4. WindowsCE 5.0

WindowsCE vs. Windows Mobile

What is the difference between Windows CE and Windows Mobile-based Smartphone and Pocket PC software?

Windows CE is a customizable, embedded operating system for a variety of small-footprint devices. OEMs can use Windows CE to design platforms and customize applications to maximize the user experience for devices such as handhelds, thin clients, logic controllers, and advanced consumer electronics.

Windows Mobile is a complete software platform built on Windows CE. Unlike Windows CE, the Windows Mobile Smartphone and Pocket PC operating systems are specifically designed for devices that require a specialized hardware configuration. The software includes standardized interfaces and applications that ensure compatibility across hardware designs. For more information, visit the Windows Mobile Web site.

(link)

Mike Hall adds his two cents here with regards to the above as well as Windows XP Embedded.

Thursday, September 14, 2006

Installing a Windows Mobile Application from Desktop

Jim Wilson talks about how to create a Windows Mobile device application installer that works from from the Windows Desktop. (link)

Tuesday, August 29, 2006

Appointment ListChanged Event

It appears as though the ListChanged event in PocketOutlook for the AppointmentCollection does not work correctly--at least I couldn't get it to work. Not too much on the web about this but I found a related post on the microsoft.public.dotnet.framework.compactframework newsgroup:

Has anyone been able to receive an event when you've registered to receive events from ListChanged?

Here is the code I'm using (I'm using VS 2005 RC1 with CF 1.0):

OutlookSession outlook = new OutlookSession();
outlook.Appointments.Items.ListChanged += new
ListChangedEventHandler(Items_ListChanged);

This code runs just fine, but changing the calendar doesn't fire this event in my application. I've searched the net, but haven't found anyone who appears to have used it.


Peter Foot, from InTheHand fame, then responded:

I haven't checked, but it's possible that the events in Microsoft.WindowsMobile.PocketOutlook only fire when the changes are made through these APIs not when changed from another application...

The original poster, however, corrected Peter with information from the MSDN docs:

Here's what the docs say:

"Occurs when either the collection changes, or when an individual PIM item in the collection changes."

Additionally, the MSDN article "What's New for Developers in Windows Mobile 5.0" says that you can track changes made to Pocket Outlook folders using managed code and gives an example, so it sounds like it should show changes made by other applications. As far as I can tell, that's the whole idea, in fact.

But I can't get it to trigger any events.

SystemState CalendarAppointment Events Seem Very Broken

I posted the following to microsoft.public.dotnet.framework.compactframework about the CalendarAppointment related system states (direct link):

For the most part, I've had good experiences with the new Microsoft.WindowsMobile.Status.SystemState infrastructure in .NET CF 2.0. However, recently I've run up against numerous issues with the CalendarAppointment* and CalendarNextAppointment* events. Incidentally, I've tested this on the I-Mate KJAM Pocket PC Phone as well as the Cingular 2125, T-Mobile SDA, and the I-Mate SP5m SmartPhones. It shouldn't be too hard to repo what I'm describing on your own device.

I will describe the problems in descending importance:

1. The SystemState calendar related events do not properly notify subscribers when the calendar appointment state changes. My impression of these system states is that an event will be fired throughout the day as a user's calendar appointments occur. I would say that in more than 90% of the cases, no event is triggered. I haven't been able to diagnose exactly why this is. The problem I'm describing here seems relevant for all calendar related events. For example,

private SystemState _stateCalendarAppointmentBusyStatus;

private void Init()
{
_stateCalendarAppointmentBusyStatus = new
SystemState(SystemProperty.CalendarAppointmentBusyStatus, true);
_stateCalendarAppointmentBusyStatus.Changed += new
ChangeEventHandler(OnStateCalendarAppointmentBusyStatusChanged);

}

private void OnStateCalendarAppointmentBusyStatusChanged(object sender,
ChangeEventArgs args)
{
AppendText(SystemProperty.CalendarAppointmentBusyStatus,
(BusyStatus)args.NewValue);
}

private void AppendText(SystemProperty systemProperty, object newValue)
{
_textBox.Text += systemProperty + ": " + newValue + "\r\n";
}

Just to add a little more feedback on this (at the risk of muddling my point). I do actually tend to see events fire if I go in and modify the _current_ calendar entry. For example, if it's 4:15PM and I change my current calendar appointment (which occurs from 4-5:00PM) from "Busy" to "Out of Office", a calendar related event (e.g., CalendarAppointment or CalendarAppointmentBusyStatus) will fire. However, if it's 3:59PM and my current calendar entry says that I am "Free" then at 4:00PM, when you would expect my 4 o'clock appointment event to trigger an event, nothing happens :(

2. At this point, I thought perhaps I misunderstood what the current calendar appointment events did particularly because I seemed to get events when I would go into the calendar and modify the current appointment. However, this isn't the issue. I setup a polling sensor that would, instead of relying on the events, constantly poll the calendar related system states. You can do this because calling SystemState.CalendarAppointment, for example, returns the current value of that system state. However, what I found through polling was that this system state was not actually changing. To test this out, setup a "refresh" button in your GUI or run a windows Timer object to spit out the current state of the CalendarAppointment* system states. Then, add 5 or 6 test appointments to your calendar that will occur over the course of the next 10 minutes. You'll note that the states don't actually change with the calendar appointments. I've found that the CalendarAppointment* and CalendarNextAppointment* seem to be particularly troublesome while CalendarHomeScreenAppointment* stuff works a little more frequently (though these events are much less useful to us).

3. Going back to using the system state events. Interestingly, the following code will sometimes throw a NullReferenceException because the args object passed in is null. Perhaps this makes sense--if the current appointment is deleted the BusyStatus switches from a known state to a null state--however, this is underdocumented. An unsavvy programmer could easily fail to null check the ChangeEventArgs argument.

private void OnStateCalendarAppointmentBusyStatusChanged(object sender,
ChangeEventArgs args)
{
AppendText(SystemProperty.CalendarAppointmentBusyStatus,
(BusyStatus)args.NewValue);

}

Hopefully someone at MS has the patience to read through this whole post and respond. If you made it this far, thanks!

UPDATE 09/11/2007: I received word from Microsoft today that this is indeed a bug in WM 5.0. Direct quote from the Microsoft employee, "I’ve confirmed the bug on WM 5.0, but it seems to be fixed in WM 6.0. That is, that the Notification Broker (and associated registry settings) don’t update properly when the calendar changes."

Friday, August 25, 2006

Issues with SystemState.Date

The SystemState functionality on Windows Mobile 5.0 phones provides a straightforward facility for tracking certain device states and events (e.g., power, signal strength, sms and phone calls). See this link for a listing of all (144?) individual system states that one can easily track with the .NET event model. However, we've identified a few problems with this framework in my lab.

The first relates to SystemProperty.Date. Subscribing to the SystemProperty.Date results in a ChangedEventArgs object with the wrong value type, or, at least a value type that is inconsistent with documentation. Even the SystemState.Date type (which is of type System.DateTime) would leave you to believe that the ChangedEventArgs.NewValue object would be of type DateTime. In this case, however, it's actually a byte array of length 8. We believe this represents milliseconds in UTC time (8 bytes in C# is a long type). See this Date and Time article at MSDN for more on working with date and time. This typing issue results in a InvalidCastException in the following code.


private SystemState _stateDate;

cstr(){
_stateDate = new SystemState(SystemProperty.Date);
stateDate.Changed += new ChangeEventHandler(OnStateDateChanged);
}

private void OnStateDateChanged(object sender, ChangeEventArgs args){
//The code below will throw an exception as the args.NewValue type is actually
//a byte array of size 8! This is undocumented and unexplained.
DateTime date = ((DateTime)args.NewValue);
}

I have not comprehensively explored this issue. Other than the fact that the arg.NewValue is a byte array of length 8, I cannot elaborate. It is only conjecture that args.NewValue here is a timestamp in milliseconds at UTC. Regardless, it seems to contradict documentation and go against the paradigm established by other SystemState functions.

One final note about this state. The SystemState.Date docs say:

Gets the current date. This Date/Time value changes once per day. Monitor this property to perform actions on a daily basis. Do not use Date to get an accurate clock time; instead, use Time.

The documentation does not explicitly point out the strategy or time of day that SystemState.Date changes, only that it changes daily. I had hoped that it would change at midnight each and every day; however, what we found was that SystemState.Date appeared to change at midnight GMT (or 5PM PST). So, even if you were to schedule a daily routine with this property, it wouldn't necessarily be at the beginning of the day. Given this limitation, we decided to roll our own SystemState.Date event class that fires at midnight each day.

If I get a chance this weekend, I'd like to follow up this post with the problems we've experienced at my lab with the SystemState.CalendarAppointment* properties. They don't appear to change at all no matter what the calendar/appointment structure is like on the phone.

Update February 9th, 3:15AM: My suspicions about the 8-byte array were somewhat correct. It is a representation of DateTime. This is how you properly convert the byte array to a DateTime object:

byte[] rawValue = SystemState.GetValue (SystemProperty.Time) as byte[];
long
value = BitConverter.ToInt64 (rawValue, 0);
DateTime time = DateTime.FromFileTime (value);

Tuesday, August 22, 2006

Size Limit of SQL Server 2005 Mobile Database

Size limit of SQL Server 2005 Mobile database: 4 Gigabytes.
Size limit of SQL Server Everywhere Edition database: 4 Gigabytes.

(link)

Monday, August 21, 2006

SqlCeParameter Bug?

I made the following post to microsoft.public.sqlserver.ce on August 17th.

The following SqlCeCommand throws an exception. Is this a bug or am I doing something wrong?

SqlCeCommand sqlCmd = sqlConn.CreateCommand();
sqlCmd.CommandText = String.Format("INSERT INTO {0} (UserId, VersionId, {1}, PropertyName, PropertyValue, PropertyValueType) VALUES (@userid, @versionid, @headercolumnval, @propertyname, @propertyvalue, @propertyvaluetype)", strTable, headerName);
String strValue = p.Value.ToString();
sqlCmd.Parameters.Add("@userid", SqlDbType.NVarChar, 255, "UserId").Value = Globals.UserId;
sqlCmd.Parameters.Add("@versionid", SqlDbType.BigInt, 8, "VersionId").Value = Globals.VersionId;
sqlCmd.Parameters.Add("@headercolumnval", SqlDbType.NVarChar, 255, headerName).Value = headerColumnValue;
sqlCmd.Parameters.Add("@propertyname", SqlDbType.NVarChar, 255, "PropertyName").Value = p.Key;
sqlCmd.Parameters.Add("@propertyvalue", SqlDbType.NVarChar, 4000, "PropertyValue").Value = strValue;
sqlCmd.Parameters.Add("@propertyvaluetype", SqlDbType.NVarChar, 255, "PropertyValueType").Value = p.Type.FullName;
sqlCmd.Transaction = sqlTransact;
sqlCmd.Prepare();
sqlCmd.ExecuteNonQuery();
sqlCmd.Dispose();

Throws the following exception at the sqlCmd.ExecuteNonQuery() line:

System.InvalidOperationException was unhandled
Message="@propertyvalue : String truncation: max=255, len=463, value="(removed for posting clarity)"."
StackTrace:
at System.Data.SqlServerCe.SqlCeCommand.FillParameterDataBindings()
at System.Data.SqlServerCe.SqlCeCommand.ExecuteCommandText()
at System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand()
at System.Data.SqlServerCe.SqlCeCommand.ExecuteNonQuery()
at MyExperience.IO.DatabasePopulator.InsertProperty()
at MyExperience.IO.DatabasePopulator.ParseTriggers()
at MyExperience.IO.DatabasePopulator.Populate()
at MyExperience.MyExperienceFramework.Initialize()
at MyExperience.Application.MainForm.OnLoad()
at System.Windows.Forms.Form._SetVisibleNotify()
at System.Windows.Forms.Control.set_Visible()
at OpenNETCF.Windows.Forms.Application2.RunMessageLoop()
at OpenNETCF.Windows.Forms.Application2.Run()
at MyExperience.Application.Program.Main()

However, if I change the line:

sqlCmd.Parameters.Add("@propertyvalue", SqlDbType.NVarChar, 4000, "PropertyValue").Value = strValue;

to

sqlCmd.Parameters.Add("@propertyvalue", SqlDbType.NVarChar).Value = strValue;

no exception is thrown and, better yet, the full amount of data actually makes it into the database. That is, the value is not truncated to the 255 length that Sql somehow thinks exists as a constraint.

Note that my schema for this table looks like:

TableName:
TriggerProperties

Columns:
UserId (PK, nvarchar(255), not null)
VersionId (PK, nvarchar(255), not null)
TriggerName (PK, nvarchar(255), not null)
PropertyName (PK, nvarchar(255), not null)
PropertyValue (nvarchar(4000), not null)
PropertyValueType (nvarchar(255), not null)

I followed this post up with this one on August 18th:

Ah, it looks like SqlCeParameter forces the Size property to 255. That's strange given the fact that the docs say, as previously mentioned, that the nvarchar data type can range from 1 to 4000 characters.

However, bear in mind, that by simply avoiding setting the Size property (either via the constructor or the property itself) allows one to INSERT nvarchar data much larger than 255. In other words, it looks like this "bug" is at the parameter level and not database level.

This is the test code:

for (int i = 0; i <= 500; i+=100){ SqlCeParameter param = new SqlCeParameter("@Test", SqlDbType.NVarChar, i); Debug.WriteLine(i + ": " + param.Size);

//Just in case the property acts differently, set it and print again
param.Size = i;
Debug.WriteLine(i + ": " + param.Size);

}


prints:

0: 0
0: 0
100: 100
100: 100
200: 200
200: 200
300: 255
300: 255
400: 255
400: 255
500: 255
500: 255

Any input from MS (or MVPs) on this? I'm far from being a seasoned C# SQL developer so maybe I'm doing something wrong.

Unfortunately I haven't heard any substantive comments back on usenet from MS or otherwise. Anyone in the blogosphere have an idea?

Update 8/25/2006 @ 11:08PM: On August 21st, I e-mailed the SQL Server Everywhere team via their contact page about this issue. Here's what I said:

Not sure how appropriate it is to contact you about problems I'm experiencing with Sql Mobile 2005, but I thought I'd give this a shot. If this is the wrong venue of communication, just ignore this plead for help.

I'm having issues with the SqlCeParameter class, particularly with regards to how it handles setting the Size property. I can't seem to set the size to anything larger than 255 for the nvarchar datatype.

Please see my usenet post for more details (unfortunately no one with any expertise in this area has responded yet): direct link here


I received a response on August 24th:

Yes Jon you are right that there seems to be some problem with larger than 255 chars. I just tried and could repro it.

I shall come back to you on this after some more digging around to see if there is any work around.


To which I responded:

Thank you so much for the response. I was really hoping I'd hear back from someone at Microsoft to help me with this.

The work around that I've come up with is to simply leave out specifying the length parameter in the SqlCeParameter object. So, for my SQL data columns that are of type nvarchar and length > 255 I do this:

SqlCeParameter param = new SqlCeParameter("@custid", SqlDbType.NVarChar);


Rather than explicitly including a length and column:

SqlCeParameter param = new SqlCeParameter("@custid", SqlDbType.NVarChar, 2000, “CustomerID”);


You’ll note that in the former case your data can be of length > 255 and, critically, it will still make it into the database. In the latter case, however, you incur an exception.

Perhaps my workaround will shed some light on the underlying problem.


On August 25th I received another response:

I found the work around you used works perfectly and some of the internal apps also use it the same way as you mentioned. However, while digging I found that you can not use parameterized query when you have image/ntext columns (Large Object Datatype). Will update you more once I get some clarity.

To which I responded:

Hmm, I also use image data types in my SQL Mobile 2005 database and it appears to be working. In fact, a parameterized query, I believe, is the only way to get binary data into the database. What was the issue you ran into here?

Saturday, August 19, 2006

Nullable Types

I have yet to work extensively with nullable types, a new addition to C# 2.0. A nullable type can represent the normal range of values for its underlying value type, plus an additional null value. This is somewhat similar to how SQL allows you to create an int datatype column that allows a null value. To declare a nullable type, you use the '?' operator. For example, int? num = null;

More on the C# 2.0 Nullable Types
Jon Skeet's Blog : Elegant comparisons with the null coalescing operator
Jon Skeet's Blog : Nullable types and the null coalescing operator
MSDN Reference : ?? Operator (C# Reference)
MSDN Reference : Nullable Types (C# Programming Guide)

Friday, August 18, 2006

Recently Published Mobile Device Downloads

Direct link to the Microsoft Download Center for Mobile Devices (sorted by release date).

Hard Reset T-Mobile SDA

Had tip: (nino and here)

Update 08/26/2007: I couldn't get this to work on my Cingular 2125 device. I finally figured out what I was doing wrong; I held down the power button too long. You do not need to hold the power button down until you see the boot screen... simply press it for 0.5-1 seconds. Also, Mike Poulson points out there are two ways to reset the HTC Torando/Faraday-based SmartPhone.

The first way requires you to be able to boot the phone and get to the start menu. The second is if you cannot do this (i.e., forgot PIN or will not boot all the way).

First way: Start -> Accessories -> Clear Storage

Second way:

1. Remove Battery

2. Replace battery
3. Hold down right and left soft keys
4. Press Power button for ~1.45 seconds then release Power button only
5. Confirm prompt to reset

Monday, August 14, 2006

Usage of SqlCeCommand.Parameters

I posted the following to microsoft.public.sqlserver.ce:

I'm curious about the Parameters property in SqlCeCommand. Is this the preferred/best usage of the SqlCeCommand object? I suppose one benefit of using Parameters is the ability to set binary/image data (as those are byte arrays) for insertions/updates. Are there other benefits? I tend to format all of my command statements like the following:

SqlCeCommand cmd = sqlConn.CreateCommand();
cmd.CommandText = String.Format("INSERT INTO {0} (ActionName,
ActionType) VALUES ('{1}', '{2}')", "Actions", actionName, actionType);
cmd.Transaction = sqlTransact;
cmd.ExecuteNonQuery();

instead of

SqlCeCommand cmd = sqlConn.CreateCommand();
cmd.CommandText = "INSERT INTO @tablename (ActionName, ActionType)
VALUES (@actionname, @actiontype)";
cmd.Parameters["@tablename"].Value = "Actions";
cmd.Parameters["@actionname"].Value = actionName;
cmd.Parameters["@actiontype"].Value = actionType;
cmd.Transaction = sqlTransact;
cmd.ExecuteNonQuery();

What's the "best practice?"

Ilya Tumanov, a member of the .NET Compact Framework Team, responded with:

Yes, parameterized query is a preferred way. Benefits are:
  • No need to create bunch of string objects all the time (in your code).
  • No need to convert parameters from binaries to strings (in your code).
  • No need to parse strings to get binaries back (in SQL CE).
  • No locale/format specific issues as binary is format less and locale independent.
  • No need to redo each command from scratch, prepared execution plan can be used with just different parameters.
  • Works for all data types including binary/image.
Performance benefits from using parameters range from significant to really huge.

(link)

Update 08/16/2006 12:57AM: I followed up the above post with:

Thanks so much for this thorough response--it clarified much for me. One follow-up question, what do you mean by "No need to redo each command from scratch, prepared execution plan can be used with just different parameters?" This is most certainly my naivete here with respect to SQL; a short elaboration would probably suffice.

Illya once again responded:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sqlc...

Preparing Commands
To be able to execute a query, the database engine must first parse, compile, and optimize the SQL statement. Often, this work can be done once if the command is to be executed multiple times, potentially saving time. If clients expect to run a query more than once, it is recommended that the command be prepared once, then call Execute multiple times. This should maximize performance by avoiding query recompilation. Commands can be prepared prior to execution by calling ICommandPrepare::Prepare. This is equivalent to compiling the command.

Real life equivalent would be a move to another apartment. Would you rather move your stuff item by item or pack it and move it all at once?



Friday, August 11, 2006

Reduce Size of .NET Executables

Found an article in the Journal of Object Technology entitled "Using Reflection to Reduce the Size of .NET Executables" by Vasian Cepa (link). One relevant section pertains to how .NET CF devices use compression by default for storing programs:

The technique we used for compressing .NET applications does not work with .NET Compact Framework (CF) [17]. The .NET CF does not implement the methods of the Assembly and AppDomain classes that make this technique possible. However, the devices that run .NET CF use compression by default for storing programs and data in the non-volatile device memory ([17] reports up to 2:1 compression ratio). This means that this technique may not be directly needed in .NET CF devices9.


[17] P. Yao and D. Durant. .NET Compact Framework Programming with C#. Addison Wesley, 2004.

Monday, July 31, 2006

SQL Mobile Size Limit

Ginny Caughey, a Device Application Development MVP, wrote about SQL Mobile size limitations in the microsoft.public.sqlserver.ce newsgroup (direct link here):

The limit for a SQL Mobile database is 4 gb, so unless my math is wrong, you shouldn't have any problems at all with 80,000 records of that size assuming you enough space on the device. I have a production app that handles 65,000 records and on a mobile device seeking to a unique key using the table's index is almost instantaneous. One thing I have found with big databases is that sometimes queries get very slow because the query processor apparently wants more memory for its own work than I have available. I've been able to reduce a 30-minute query to well under a second by switching from using SQL syntax to TableDirect in situations like that.

One other point with large amounts of data - don't try to load all that data into a DataSet. Use SqlCeResultSet and only load the data you need at any given point in your app.

VS2005 Debugging Problem, Breakpoints AutoDisabling Themselves

I posted today to microsoft.public.dotnet.languages.csharp about a VS2005 debugging problem that my colleague is experiencing (direct link).

My colleague is having problems debugging in VS2005. When he sets
breakpoints in his code and launches his application via Debug->Start
New Instance, the breakpoints autodisable themselves and the
"breakpoint icon" switches from being filled in to outlined with a
warning glyph on the bottom right hand corner. When moused-over, the
icon reads "The breakpoint will not currently be hit. The specified
module is not being loaded." I checked the loaded modules list via the
Debug->Windows->Modules interface and the specified module was, indeed
loaded, with a pointer to a valid pdb (as far as I can tell).

I even started a brand new Form application from scratch and ran it in
debug mode without adding any new code. I set a breakpoint at the first
line in Program.cs but this too was autodisabled with the same "module
is not being loaded" warning.

I Googled around the newsgroups/web for a while but did not find
anything that directly related.

I should note also that: setting a breakpoint via
System.Diagnostics.Debugger.Breakpoint() works as does Debug->Step Into
new instance.

Thursday, July 27, 2006

Benchmarking StringBuilder vs. String

A recent CodeProject post compares StringBuilder vs. String across varying degrees of usage.

In the following article I will show you the numbers for StringBuilder vs String which I did measure with .NET 2.0 a P4 3.0 GHz and 1 GB RAM. Every test was performed 5 million times to get a stable value.
(link)

I wonder if the same performance would be observed on Windows Mobile Devices.

Wednesday, July 26, 2006

MSDN Library Free Download

According to some msdn blogs (e.g., Rob Caron), MSDN June 2006 is a free download. Get it here.

Saturday, July 15, 2006

TextBox OnPaint in .NET CF 2.0

Is it possible to override the OnPaint and/or OnPaintBackground methods in the System.Windows.Forms.TextBox class in .NET CF 2.0?

Sadly, no. See here and here.

SqlServer Mobile Edition, In-Proc Database

I just posted the following to microsoft.public.sqlserver.ce:

On Sriram Krishnan's blog he writes, "Sql Mobile is a super-lightweight, in-proc database that runs on devices. The key phrase for me personally is 'in-proc'. This means that there is no IPC involved and as a result, performance is blindingly fast."

This is really the only discussion I could find about in-proc databases via a quick Google search. Can anyone provide me with any more information on what an "in-proc database" is and how it differs from an "out-of-proc?" database. The implication of Sriram's post is that SqlMobile is efficient because it doesn't use interprocess communcation (assuming that's what IPC stands for). Do most databases use IPC?

(direct link)

(Update: 07/16/2006 1:37PM) I received the following response from Ginny Caughey, a Device Application Development MVP.

Some databases such as SQL Server run as services in their own process space, often on a different machine from the apps that consume those services. Others such as SQL Server Everywhere/SQL Mobile are DLLs that run in the same process space as the application that uses them. Not only does this imply that there is no process boundary to impact perforamance, but also when the hosting application ends, so does the database engine so there is no service running to serve as a potential security threat. There are advantages to client/server databases such as SQL Server, but for stand-alone and mobile apps, there are also advantages for an in-process database such as SQL Mobile/Everywhere.

(direct link)

Thursday, July 06, 2006

Purchased OpenNetCF SDF 2.0

I finally went ahead and purchased the SDF 2.0 Extensions for Visual Studio 2005 from OpenNetCF.org. It's only fifty bucks and you get the source code, which, for me, is mostly useful for educational purposes. I'm always wondering if my coding style, design, etc. are up to par. You can also use the free version of the SDF 2.0, which isn't crippled but doesn't include the source here. I used it for quite a while before deciding that I should support the OpenNetCF team.

Oh and by the way, the installer for the purchased version of SDF 2.0 takes about 15 minutes on my 3Ghz HT 1.5GB RAM Pentium 4 machine to complete. I was almost going to e-mail support that their installation package was broken but then I discovered the h2reg process, which is started by the installer, was just taking forever. I believe this is because of some of the integrated VS2005 stuff they've done in SDF 2.0. Note that the free version installs rather quickly.

Tuesday, July 04, 2006

ActiveSync, A Lesson Learned

At the risk of jumping the gun here, it appears that my ActiveSync woes were not due to Microsoft's negligence or poor programming (though, I suppose, they really should have had the ActiveSync troubleshooter page much earlier, circa 4.0 or even 3.X). In fact, it was my own fault for not noticing that my IT department at work packaged BlackICE (a firewall program) with our VPN software. So, simply by installing our VPN (a rather innocuous gesture), I created a firewall that prevented TCP traffic over port 990.

Now, I'm not 100% confident that this will solve all of my ActiveSync issues but it appears that, at the moment, I've figured out the connection problem.

Sunday, July 02, 2006

ActiveSync Connection Problems Continue

I finally decided to post to the ActiveSync newsgroup about my ActiveSync issues (here). Here's a copy of the post:

My laptop will not connect to any of my WM 5.0 devices (including the i-mate KJAM, the Cingular 2125, and the T-MOBILE SDA). Though I've experienced this problem in the past, I've been able to uinstall and reinstall ActiveSync 4.2 and restart my computer to solve the problem.
I've been blogging about my problematic encounters with ActiveSync for a while now but have never sought the expertise of this newsgroup. I'll provide a quick summary of my ActiveSync issues here. You can visit my blog for more details: http://csharponphone.blogspot.com/2006/05/activesync-41-sit-spin.html

Basically, I plug-in my WM 5.0 device, the little networking animation starts up in the taskbar (and says acquiring network address, etc.). This icon dissapears and then the ActiveSync icon in the taskbar turns green and starts to spin. This continues until a timeout is reached at which point I'm given a choice of visiting Microsoft's troubleshooter webpage (it then forwards me on to the "If ActiveSync Cannot Receive Data Through Port 990" page). I've tried following all of the previous advice posted here and on the web, but to no avail. My laptop is running Windows Firewall and McAfee VirusScan Enterprise 8.0.0.

Any help from MVPs, Microsoft employees, or anyone with a clue into what might be happening would be much appreciated.

NETSTAT RETURNS:
Active Connections

Proto Local Address Foreign Address State
TCP 127.0.0.1:1150 127.0.0.1:1151 ESTABLISHED
TCP 127.0.0.1:1151 127.0.0.1:1150 ESTABLISHED
TCP 192.168.2.76:1038 64.233.167.125:5222 ESTABLISHED

IP-CONFIG RETURNS:
Ethernet adapter Local Area Connection 16:

Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Windows Mobile-based Device #14
Physical Address. . . . . . . . . : 80-00-60-0F-E8-00
Dhcp Enabled. . . . . . . . . . . : Yes
Autoconfiguration Enabled . . . . : No
IP Address. . . . . . . . . . . . : 169.254.2.2
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . :
DHCP Server . . . . . . . . . . . : 169.254.2.1
Lease Obtained. . . . . . . . . . : Sunday, July 02, 2006 1:53:41 PM
Lease Expires . . . . . . . . . . : Tuesday, August 01, 2006 1:53:41 PM

Update: 07/04/2006 11AM: Here's my follow-up to the post above:

I'm ashamed to admit this, but it never occurred to me to check my
process list to see if there was any networking software running on my
computers that I did not know about. Imagine my surprise when I saw
blackd.exe (part of the BlackICE firewall package). As soon as I
noticed this, I figured this might be the root of my problem. It seems
the company that I work for includes a custom install of the BlackICE
installation with their VPN software. I force closed the process in
Task Manager, plugged in my WM 5.0 device and, what do you know,
ActiveSync turns green immediately and says connected.

I probably would have thought of this earlier on, but ActiveSync would
occassionally work--it wasn't a consistent problem. This maybe more an
issue with BlackICE however.
Unfortunately, the install of BlackICE that I have does not include a
frontend, so I must manually edit their configuration file to open the
ActiveSync related ports (despite warnings in the file itself against
it).

So, in the end, it appears my frustration was misdirected at Microsoft.
It really should have been at my IT department for not disclosing that
BlackICE was packaged with our VPN.

Hopefully now my ActiveSync problems are solved.

Two Inch View

Just added an RSS feed to a new blog called "The Two Inch View," which is dedicated to "Windows Mobile media and entertainment." The site design is crisp and very readable and the author has a long history with WindowsCE/Mobile (a former MVP). The site is actually sponsored by Windows Mobile, which hopefully implies a strong foundation and dedication to frequent updates. It currently has some posts on the Windows Mobile Device Center, which looks like a new skin on top of ActiveSync (and, hopefully, includes some bug fixes to ActiveSync as well).

Friday, June 30, 2006

Microsoft Bluetooth Stack

Peter Foot, who developed 32feet.net, has a list of Windows Mobile devices that use the Microsoft Bluetooth Stack (as opposed to, say, some 3rd party stack like the Widcomm stack whose SDK is cost prohibitive for most developers--and certainly most graduate students like myself).

Friday, June 23, 2006

.NET CF 2.0 SP1 Released

"Microsoft .NET Compact Framework version 2.0 SP1 release has been completed and is in the process of being released. This service pack was driven customer feedback including improvements in stability, adds new debugging features, extended platform support, and new developer functionality." (from .NET CF Team Blog)

Download it here.

Thursday, June 22, 2006

Sql Server 2005 Mobile

Astonishing as it now seems to me, I had not used SQL before integrating Sql Server 2005 mobile into my current project. That said, I occassionally run into these problems that could only happen to a SQL neophyte. For example, I've found out the hard way that naming your table columns either Trigger, Default or Option is a bad thing and confuses the hell out of SQL (and your development team members). Trigger, Default and Option, as I'm sure most of you know, are reserved words in Sql.

Tuesday, June 13, 2006

More ActiveSync Woes

I've had trouble with "cradling the emulator" in ActiveSync ever since I found out about this feature. In VS2005, open Tools->Device Emulator Manager. In the Emulator Manager, right click on a device and select "connect." Once the specified emulator has launched and loaded, you can right click on that device (again in the Emulator Manager) and select "cradle." This should cradle the emulator to ActiveSync so you can, for example, explore the emulator file system. However, this feature rarely works for me. Typically what happens is that after I select "cradle", the icon immediately changes (signifying that the device is indeed cradled) but ActiveSync does not respond. This seems independent of the "sit and spin" issue though as the ActiveSync icon does not change to green, nor does it animate at all. It simply stays gray.

Ah, ActiveSync, how you destroy my workday efficiency.

Update (07/12/2006 11:00AM): OK, thanks to Sriram's feedback (see Comments), I figured this out. Here are the steps (click on the images to see full size screenshots).

Step 1: Open Device Emulator Manager in VS2005 (Tools->Device Emulator Manager)
Step 2: Right click on your device of interest, start it.
Step 3: After the device has started, right click on the device again and select 'Cradle.' See Figure 1 below.
Step 4: The icon should change to represent that the device has been cradled. However, this does not necessarily mean that ActiveSync has actually connected to the device. See Figure 2 below.
Step 5: If ActiveSync has not actually connected to the device, yet the cradled icon is shown, open up ActiveSync, select File->Connection Settings. This will open up a Connection Settings Dialog. From there, click the Connect button. See Figure 3 below. This should find and connect your emulator device to ActiveSync.

Figure 1: Cradle the emulator

Figure 2: Emulator supposedly cradled

Figure 3: Open ActiveSync, click on File->Connection Settings. In the Connection Settings Dialog, click on the Connect... button. This should find your cradled emulator device.

Tuesday, June 06, 2006

Installation Error, Support Info: 4

I had problems deploying and running .NET CF 2.0 applications on my i-mate K-JAM (running Windows Mobile 5.0--OS 5.1.70). I posted this message to Google Groups:

I've been unable to successfully load a small test app I've written in VS2005 and .NET CF 2.0 (C#) for the i-mate K-Jam PocketPC Phone Edition.

The error that pops up on the K-JAM when deploying and debugging from VS2005, "Installation error. Stop all applications and processes and maximize available storage space, and run installation again. Support info: 4."

If I attempt to run the app by clicking on it in the file explorer on the K-JAM, I get the error, "This application (TestPocket.exe) requires a newer version of the Microsoft .NET Compact Framework than the version installed on this device." When I click details, I get:

TestPocket.exe
InvalidProgramException

I've tried this with the target device selected as both "Windows Mobile 5.0 Pocket PC Device" and "Windows Mobile 5.0 SmartPhone Device." I receive the same error in both cases.

Has anyone run into this before? I can successfully deploy my test app to the PocketPC and SmartPhone emulators as well as to the Cingular 2125 SmartPhones.

Mark Prentice replied with a pointer to a working solution at his blog:

I’m happy to report the workaround for the system failure, which will be included in SP1, has now also been slipstreamed into the current download. If .NET Compact Framework v2 CAB installation on a Windows Mobile 5.0 device fails with error #4 then this fix is for you. Just re-download the NETCFv2 package and re-install!

Here's a link to the .NET CF 2.0 download.

Sunday, June 04, 2006

.NET CF Menu Item Size

I'm developing an application that will be used by those with impaired vision and reduced motor control. Unfortunately, .NET CF makes it quite difficult to change font sizes for menus and menu items. In fact, MenuItem classes do not expose the Font property. In many instances, I avoid this problem because I run my application full screen--however, some messageboxes are run in "normal mode" with the menubars exposed.

Daniel Moth talks about a work around which involves modifying registry settings:

Menus (MainMenu, ContextMenu and MenuItem) are resized according to their Font. However, they do not expose a Font property, so you are stuck with whatever the default Font is for the platform. You can change that through the registry:

HKLM\Menu\BarFnt
DWORD "Ht" for height , DWORD "Wt" for boldness: 700 or 400

HKLM\Menu\PopFnt
same as above, but this applies to menu items rather than the menu bar

Friday, June 02, 2006

Params Keyword

The params keyword lets you specify a method parameter that takes an argument where the number of arguments is variable.

For example,

static void Main()
{
TestArgsMethod("Hello", " goodbye ", " hello");
TestArgsMethod("Numbers", 1, 2, 3, 4);
}

static void TestArgsMethod(String text, params Object[] args)
{
StringBuilder sb = new StringBuilder();
sb.Append(text);
foreach(Object o in args)
{
sb.Append(o.ToString());
}
Debug.WriteLine(sb.ToString());
}

Thursday, June 01, 2006

XmlReader and LineNumber

I made this post to microsoft.public.dotnet.languages.csharp but no one has responded, so I thought I'd repost it here. If you know the answer, please either leave a comment or respond in the newsgroup.

"According to the MSDN documentation within the XmlTextReader class for
.NET 2.0, the recommended practice to create XmlReader instances is
using the XmlReaderSettings class and the XmlReader.Create() method.
However, the problem is, the XmlReader class does not expose certain
properties that I need, e.g., LineNumber, LinePosition, etc. I would
like to follow Microsoft's recommended practices, but I'm not sure how
I can get XmlTextReader functionality out of XmlReader.

Should I instantiate a XmlTextReader object and pass this to the
XmlReader.Create() method and then access this underlying text reader
to obtain the info I need? Or is there some way to get the
XmlReader.Create() method to return a XmlTextReader object? Or should I
ignore there suggestion and simply create an XmlTextReader object
manually and not use the XmlReader.Create() method at all.

Thanks!"

Update 07/12/2006 @ 1:03PM: Zafar Abbas responded with a solution,

The reader obtained via XmlReader.Create supports the IXmlLinfInfo interface
from which you can access the line properties:

reader = XmlReader.Create (...)

IXmlLineInfo info = reader as IXmlLineInfo;
Console.WriteLine(info.LineNumber);
Console.WriteLine(info.LinePosition);

this should print your line numbers of the current node.

Monday, May 29, 2006

Windows CE != Windows Mobile

"Windows Mobile is not Windows CE (and vice-versa), Windows Mobile has Windows CE as its core – WM 2003 was based on WinCE 4.x, WM 5.0 is based on WinCE version 5 – plus a standard shell, applications and APIs." (link and a follow up here)

Wednesday, May 24, 2006

Alpha Blending

Since my last post was on drawing transparency color keys in .NET CF, I thought I should explore alpha blending as well. It is possible to do alpha blending .NET CF, but not without some effort (i.e., venturing into p/invoke). Here, at the .NET CF UI and More blog, the author writes:

Briefly, there are two ways to do alpha blending in WM5: the AlphaBlend() function and with the Image COM object in the Imaging API.

He then goes on to explain how to implement these two methods. (direct link). The happy alternative is offered through OpenNetCF (who else) in their SDF 2.0 library. See Alex Feinman's post here.

Transparency

This morning I googled around for "standard transparency colors" in hopes that I would find a color key that is typically used to represent transparency in images. In .NET CF, the only way to make part of an image transparent is through the following code:

ImageAttributes attr = new ImageAttributes();
attr.SetColorKey(Color.White, Color.White);
Rectangle rDest = new Rectangle(xImage, yImage, Image.Width, Image.Height);
g.DrawImage(Image, rDest, 0, 0, Image.Width, Image.Height, GraphicsUnit.Pixel, attr);


In this case, the color "white" would be made transparent in the given Image. Note that although SetColorKey allows the developer to specify a transparency color range, I believe that this range is limited to one color on .NET CF. During my search, I found that the standard chroma key is "bright pink." However, it's also convention to automatically select the chroma key based on the upper-left hand corner pixel of the image, in hopes that this is representative of the "background" pixels. Here's a post by Ed Kaim (MSFT) that really explains this well imo.

"However, the issue you're raising is why Microsoft recommends the usage of ImageAttributes in order to draw transparency, and why the top left pixel is called out as a prime source. First of all, ImageAttributes is the only feasible way to draw transparency in managed code on the .NET Compact Framework. Otherwise you'd have to go pixel by pixel and only draw the nontransparent ones, which would be slow and painful. The reason the top left pixel is offered is because it's often transparent in images with transparency. Sure, it's not *always* transparent, but it's usually transparent, due to its location in the image and the fact that most pictures on buttons don't go all the way to the top left border. However, you can decide that your standard chroma key color is bright pink (as many do) and hardcode your ImageAttributes object to use that color for all images, provided you do the work in the art to make sure the same exact color is used on the transparent spots in your files, whatever format they may be."

Monday, May 22, 2006

Retrieving an Assembly's PublicKeyToken

The short of it is, use the sn -T blah.dll command (see link). Here's the step-by-step for finding the PublicKeyToken of the System.Data.SqlServerCe.dll:

1. Open up the Visual Studio 2005 Command Prompt from the Start Menu. That should set the environment for using VS2005 commands.
2. C:\>cd "C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\SQL Server\Mobile\v3.0\"
3. Type "sn -T System.Data.SqlServerCe.dll"

The sn utility will return something like: Public key token is 3be235df1c8d2ad3

Note: if you do not include a capital T (but instead a lowercase, -t), you will receive the following error: "Failed to convert key to token -- The public key for assembly '(null)' was invalid."

ActiveSync 4.1, Sit & Spin

As a .NET CF developer, I'm getting quite tired of dealing with the obvious failings of ActiveSync. It is, without a doubt, one of the most frustrating programs I've been forced to deal with. I'm currently struggling with the problem where you plug-in a Windows Mobile 5.0 device to a desktop machine running ActiveSync 4.1 and ActiveSync just sits there and continuously spins the green icon while displaying "Connecting." It will literally do this for hours (if I let it). See screen below:


I've scoured the net for a solution and have found none. This has been happening off and on since I started working on Windows Mobile 5.0 devices. Unfortunately, I have not been able to diagnose the cause. Restarting the device does not solve the problem. Restarting the desktop (which I hate doing) does not solve the problem. Sometimes, moving the USB cable from one port to another works, but not always. I can waste a full hour or so simply trying to get my activesync connection up so I can debug my program. :(

Oh and the online KB has a few reported issues with regards to ActiveSync 4.1:
http://support.microsoft.com/kb/911422/en-us
http://support.microsoft.com/kb/912240/en-us

and, perhaps most relevant,

http://support.microsoft.com/kb/911423/en-us

Sadly, however, none of these quite get at the issue I am experiencing. This last link is closest but simply blames the problem on Windows Firewall (which I've disabled to see if it has any effect, it does not).

Update (05/22/2006 11:42AM): It appears that the ActiveSync 4.2 Beta Preview is now available and it comes with a USB troubleshooter. I'm going to try it now. See these two blog posts by Jason Langridge (here and here).

Update (05/24/2006 5:27PM): So far ActiveSync 4.2 has worked perfectly for me--I have not run into the "sit and spin" problem (or any problem) since upgrading.

Update (05/26/2006 1:59PM): Despite upgrading to ActiveSync 4.2 on my laptop, I still have the "sit & spin" problem when connecting to my Windows Mobile 5.0 devices. The horribly ironic thing is that the "USB troubleshooter" promised in ActiveSync 4.2 is actually just a webpage and not, say, a tool. This is so frustrating. I really can't imagine being the only one with this problem as its occurred on my desktop machines (both work, school and home) and laptop with a variety of WM 5.0 devices. I am not running any firewall except the Windows XP built-in firewall (and even when I disable it, ActiveSync still just sits there spinning).

Update (06/02/2006 9:07PM): I got my laptop to work again with ActiveSync. I uinstalled ActiveSync 4.2, restarted, and then reinstalled 4.2. Now things seem to be working for the moment. Incidentally, after this reinstall, I actually got the SmartPhone emulator to cradle via the Device Manager which has never worked for me properly. Note that my work desktop machine, which had a behaving install of ActiveSync 4.2 just stopped working today. However, like with my laptop, a full reinstall of 4.2 seemed to fix the problem.

Update (06/13/2006 10:21AM): Both my advisor and my mentor at work have run into the "sit & spin" problem. The solution of upgrading to 4.2 beta and restarting seems to solve the problem, but only temporarily. My advisor also tried to manually unblock all the ActiveSync ports in Windows Firewall; however, this did not seem to make a difference. As I've noted in the past, I've completely disabled Windows Firewall to try and debug the "sit & spin" problem and it's not made a difference, so his experiences are not surprising.

Update (06/13/2006 11:00AM): I want to reemphasize how I often solve the "sit & spin" problem as strange as it might sound. I have four USB ports on the back of my computer. If I encounter the feared continuously spinning green ActiveSync icon, I unplug my USB cord from the back of the computer and move it to another port while my WM 5.0 device is still connected to the other end. ActiveSync then appears to do some initialization (e.g., my tray shows off another icon that's animated) and then immediately connects properly. This only works for those ports in the back of my computer that have not yet had ActiveSync connections. Once I move the cord to all four ports, I must uninstall ActiveSync and start the process all over.

Update (07/02/2006 1PM): I spent a large amount of my Sunday morning and early afternoon determined once and for all to get to the bottom of the ActiveSync sit & spin problem. My laptop (Dell 710m) has Windows Firewall installed as well as McAfee VirusScan 8 and two USB ports. I tested both USB ports with two different USB cords and three different WM 5.0 devices (the i-Mate K-JAM, the Cingular 2125, and the T-Mobile SDA), all of which would not connect to my laptop, despite all efforts (see the sit & spin problem above). Once the green ActiveSync taskbar icon spins for a certain amount of time, a dialog (new to ActiveSync 4.2) asks me if I'd like to be forwarded to a troubleshooter webpage. If I select OK, I am forwarded to a page entitled "If ActiveSync Cannot Receive Data Through Port 990" (here) . The first three steps are trivial and meant to ensure that you have USB connections enabled both on the desktop and device (and yes I double and triple checked, everything looks fine in this regard). The last point (point 4), states that if I have an internet firewall, make sure its enabled to accept ActiveSync connections. Well, as previously stated, I only run Microsoft's Firewall program and upon examination, they do specifically allow connections from all ActiveSync related .exes. Just to ensure the firewall wasn't my problem, I turned it off but ran into the same problem. Finally, I uninstalled ActiveSync 4.2 and reinstalled it as directed by the USB troubleshooter here (step 9). Unfortunately, though this has worked for me in the past, uninstalling ActiveSync and rebooting my devices and desktop did not solve the problem. So, now I'm stuck. No ActiveSync and no solution. I did find a set of relatively helpful links though for ActiveSync troubleshooting (the fact that there is a community formed around this problem should say something to Microsoft, no?). Here are the links:

1. ActiveSync 4.X Troubleshooting Guide - Connection Flow - provides a very thorough look at ActiveSync issues with respect to establishing a connection (by Chris De Herrera)
2. ActiveySync 4.X Troubleshooting Guide - Firewall, VPN, Proxy Issues (also by Chris De Herrera)
3. Bev Howard's Solving ActiveSync Issues
4. TCP ports required by ActiveSync (I found this the first day I experienced the sit & spin problem, but since tweaking these ports in Windows Firewall never solved anything I never linked to it. I do so for thoroughness now).
5. ActiveSync 4.0/4.1 TroubleShooter Guide
6. The ActiveSync Troubleshooter (which 4.2 dynamically links to when a problem is encountered)

I have not seen an outpouring of complaints on the newsgroups about this problem, though this post is one of the most actively visited on my website so presumably others are encountering it as well. By a rough estimate, I figure the Microsoft ActiveSync development team owes me about 20 hours of my time (perhaps more) based on this problem alone. Others at my research lab have also spent countless hours trying to get their WM 5.0 devices to connect to ActiveSync. Now, as computer scientists we are used to tooling around and debugging programs as well as fault-prone systems. We typically can navigate around these problems. However, if ActiveSync 4.X is broken (and, imo, it is very f*ing broken) it have dramatic implications for the userbase of our WM 5.0 product. If our users can't sync their devices, then they can't (#1) install our application and (#2) use the desktop side of our application.

Update (07/02/2006 8PM): I made a post to the microsoft.public.pocketpc.activesync newsgroup about this problem (here). I also copied the post to my blog here.

Update (07/04/2006 11AM): It appears that my ActiveSync Sit & Spin issue has been resolved and in bit of probably all too common misplaced blame, it was not the fault of Microsoft as I suspected. See here and here.

Wednesday, May 17, 2006

.NET Micro Framework

See Daniel Moth's posting here. Also, the "official" webpage here.

Tuesday, May 16, 2006

Simkin# (or SimkinCS if you will)

Out of a desire to have a scripting language for the .NET Compact Framework, I've recently ported Simkin from Java to C#. Simkin is a "high-level lightweight embeddable scripting language for Java or C++ and XML" originally written by Simon Whiteside. This page has an online demo in Java (warning, might not play nice in all browsers).

Here's a screenshot of SimkinCS running in .NET in a demo app. Click on the picture for a larger view. You can download this proof-of-concept application here.

(left: before execution, right: after execution)

Update (May 17th, 2006 @ 2:02PM): You need the .NET 2.0 runtime environment to run this application. You can download the .NET 2.0 redistributable package here. This is the reason why the application fails to run and returns the error "The application failed to initialize properly (0xc0000135)" on some systems. My guess is, though, if you read this blog you likely have .NET 2.0 installed on your machine.

Tuesday, April 25, 2006

Buggers, Scripting Support in .NET CF 2.0

Scripting support in .NET CF 2.0 is just as absent as in .NET CF 1.0 :(

Hopefully someone will get around to answering this post.

Monday, April 24, 2006

Cingular 2125 Developer Locked

Solution to Windows Mobile 5.0 hardware being developer (application) locked by default can be found here.

Genius!

Tuesday, April 11, 2006

Primary Key Efficiency

Not sure if this is relevant to SQL Server Mobile or SQL Server 2005, but still interesting nonetheless. The key takeaway seems to be that the primary key should be single column if possible and an int datatype (link).

Also, from link, "A primary key is an attribute (or combination of attributes) that uniquely identify each instance of an entity. A primary key cannot be null and the value assigned to a primary key should not change over time. A primary key also needs to be efficient. For example, a primary key that is associated with an INTEGER datatype will be more efficient than one that is associated with a CHAR datatype. Primary keys should also be non-intelligent; that is, their values should be assigned arbitrarily without any hidden meaning. Sometimes none of the attributes of an entity are sufficient to meet the criteria of an effective primary key. In this case the database designer is best served by creating an "artificial" primary key."

Monday, April 10, 2006

Multiple Columns as Primary Key?

I was questioning whether my database design was a good one. This is my first project using SQL (or any database for that matter) and I wondered whether using multiple columns as a primary key was "good design" or, alternatively, if I should just create a dummy column in my tables and use the IDENTITY property (so that they are auto-numbered and guaranteed unique). I guess this is a hotly debated issue. I found quite a few discussions on the web about it--with people arguing adamently in both directions.

Here are a few links.

1. "Primary Key" (Google Groups).
2. "Design: multiple columns for primary key" (Google Groups)
3. "SQL Server Performance Questions & Answers" (in favor of IDENTITY columns)

Adding Foreign Keys to .SDF via VS2005

From msdn forums:

"You can't add a foreign key to a SQL Mobile database from within VS2005 - you cannot do it graphically nor by using the query designer (where it would be tempting to enter an ALTER TABLE .. ADD FOREIGN KEY statement).
In the absence of SQL Server 2005 Management Studio in your situation, you will need to run the ALTER TABLE command either from your program code or inside of Query Analyzer 3.0 on device."

(link)

Sunday, April 09, 2006

SqlCeConnection Keep Connection Open?

Consensus seems to point to keeping one instance of SqlCeConnection open for the duration of executation for performance reasons.
  1. SqlCeConnection guidelines (MSDN Forums)
  2. Performance with SqlCeConnection (Usenet)
  3. Data Architecture & Pooling (Usenet) <- this is for SqlServerCe 2003
Marcus Perry in his MSDN blog notes:
Creating and destroying SQL Mobile database connections is an expensive task and so the SqlCeConnection is designed to be a long lived, shared instance across the lifetime of the application. For a complex app, ideally the SqlCeConnection instance would be placed in a singleton wrapper class that manages access to the database.

Though this information comes from a Microsoft employee, it still seems contentious. Dave Hayden, a MS MVP, said in this MSDN forum post:
For 99% of all applications, the best practice is to open and dispose of database connections right when you need them and not to leave them open for the duration of the application. Open the database connection as late as possible and close/dispose of it as soon as possible.

Nicholas Paldino (a .NET/C# MVP) seems to agree with Dave:

You shouldn't keep a connection open and lying around. The SqlConnection class uses a connection pool in the background, and keeping your connection open is actually going to degrade your performance. You will want to create a new connection, open it, use it, and then close it for every operation that you do (or group of operations). You shouldn't be holding the connection open across operations. You will also notice MUCH better performance when you do this. The same thing holds with the command object. Don't use the same one. Use new ones. If you want to use a command object over and over again, you can, but use it for the same parameterized command. Don't keep changing the command string.

Both Dave and Nicholas are basing their advice on SQL Server's behavior (not SQL Server Mobile). SQL Server supports connection pooling, SQL Server Mobile does not. Again, from MS Employee Marcus Perry (link),
There is no connection pool used for local database access for SQL Mobile.

If only one SqlCeConnection is used, note that it is not thread safe. Thus, a multithread application must provide mechanisms to safely access the SQL database from multiple threads. There seem to be two approaches: one is to make the singleton wrapper class (mentioned above) thread safe and the other is to give each thread access to its own SqlCeConnection object. See these MSDN forum posts (here and here). Microsoft has yet to endorse a specific approach as a "best practice" (a discussion about this can be found here).

Tuesday, February 14, 2006

Application Verifier Tool for Windows Mobile 5.0

The Application Verifier tool assesses the stability of an application and detects common programming mistakes. The tool can detect and pinpoint memory leaks, handle leaks, and leaks in graphics device interface (GDI) objects. The tool can also detect some forms of heap corruption.

(link)

Thursday, February 09, 2006

Lock on this?

When writing attempting to write threadsafe code in C#, I'm always debating whether to lock on 'this' or some Object in existence purely for synchronization. Here are a few links contributing to this debate:

1. .NET Safe Thread Synchronization
2. Lock Choice