I got it wrong, let me tell you. After finishing the CEDB .NET code, I started to write the Pocket Access layer for .NET CF and realized how some of my early assumptions were simply wrong.
The CEDB code implements a record containing a collection of properties. Each property maps to a CEPROPVAL structure directly, meaning that the contained value is accessed through bit conversion methods. This is pretty stupid. My early reasoning was that this would make it so much easier to read and write the binary info to and from the database.
When I tried to fill a DataTable object using this approach, I was surprised with the poor speed. At first I blamed the DataGrid but realised that, although it is a slow loader, the bulk of the time was being spent loading the DataTable. I turned my attention to the DataTable and applied all the tricks of the trade to make it load faster. Nah... no way.
But wait! Could it be...? Was it in my code to load the records? Like Michael Abrash used to say: "Assume nothing: Test everything".
Bingo! As any Scorpio worth his salt, I rewrote the whole thing. Upon loading, the record now converts all its properties to boxed values or string references (blobs are just byte arrays, but references as well). These are all packed into an object array which makes it a breeze to load into a DataRow. Buffers are reused to avoid heap fragmentation and the undesirable visit of our friend the garbage collector.
The Suppliers table of the converted Northwind database now gets loaded into a brand-new DataTable object in under 200 ticks on my iPAQ 3850 (I cannot get enough of this machine...), down from almost 600 ticks using the old code. Impressive, huh?
Optimization rocks!
Monday, May 30, 2005
Tuesday, May 24, 2005
SqlCeSpy .NET
I'm starting to publish the full source code for SqlCeSpy, a SQL CE 2.0 database viewer / editor based on the FastSqlCe assembly and the fssce.dll DLL. All managed code is being published for review but not the C++ code. The project file can be found here (Zip 352KB). By opening and using this code, you acknowledge that this code was written by me and that I am the only one to blame for any errors that you may find there (hehehe).
Before you deploy the project to the device, make sure that the fssce.dll file is copied to either the target project folder or to the \Windows folder.
Functionality is now limited to browsing the database structure and to renaming tables, something that seems to be deprecated on SQL Mobile. By the way - what does "deprecated" mean? I'm feeling linguistically challenged here: does it mean that the feature is not supported or that it is supported but should not be used? Comments are welcome.
Before you deploy the project to the device, make sure that the fssce.dll file is copied to either the target project folder or to the \Windows folder.
Functionality is now limited to browsing the database structure and to renaming tables, something that seems to be deprecated on SQL Mobile. By the way - what does "deprecated" mean? I'm feeling linguistically challenged here: does it mean that the feature is not supported or that it is supported but should not be used? Comments are welcome.
Monday, May 23, 2005
Debugging over WiFi in VS2005
After all, it seems like we will be able to debug Windows CE 5.0 applications over WiFi in VS 2005. This workaround takes ActiveSync 4.0 out of the way and enables true WiFi debugging. Great news!
Friday, May 20, 2005
Installing a MAPI filter
I recently came across the challenge of writing an application that processed SMS messages. The MAPIRULE sample of the Pocket PC 2003 was duly studied, successfully modified and used. The real challenge came when I needed to cleanly install it and uninstall it. Installing is simple: you just copy the DLL to the \Windows folder, register it (the setup can do this for you) and then you have to soft-reset the device (a setup DLL is required for this). This is quite simple and a sample of soft-reset code can be found here.
Uninstalling calls for a different approach. First, you have to make sure that the DLL is not being used by the SMS-handling process. My answer to this is to shut down the tmail.exe process. Here is some code:
After killing the process, you have to unregister the DLL (sample code here) and finally soft-reset the device.
A sample setup dll project is available on demand.
Uninstalling calls for a different approach. First, you have to make sure that the DLL is not being used by the SMS-handling process. My answer to this is to shut down the tmail.exe process. Here is some code:
BOOL KillProcess(LPCTSTR pszProcName)
{
HANDLE hSnapshot;
BOOL bRet = FALSE;
hSnapshot = CreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS, 0);
if((int)hSnapshot != -1)
{
BOOL bOk;
PROCESSENTRY32 pe;
DWORD dwID = 0;
HANDLE hProcess;
pe.dwSize = sizeof(PROCESSENTRY32);
for(bOk = Process32First(hSnapshot, &pe);
bOk;
bOk = Process32Next(hSnapshot, &pe))
{
if(!wcsicmp(pe.szExeFile, pszProcName))
dwID = pe.th32ProcessID;
}
CloseToolhelp32Snapshot(hSnapshot);
if(dwID != 0)
{
// Kill the process
hProcess = OpenProcess(0, FALSE, dwID);
if(hProcess != INVALID_HANDLE_VALUE)
{
bRet = TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
}
}
}
return bRet;
}
After killing the process, you have to unregister the DLL (sample code here) and finally soft-reset the device.
A sample setup dll project is available on demand.
Tuesday, May 17, 2005
The New Emulator
The Microsoft Device Emulator 1.0 Community Preview is now available for download (just follow the link). Yes, this is the much expected ARM native emulator. You can actually install retail products on the emulator, run them and even better, develop against it using eVC4 SP4. How cool can this get?
Monday, May 16, 2005
Native is Faster
I couldn't help linking this in:
A .NET Loss
What is strange is presumably they had tried out .NET 2 which would seem to have a more compelling story than .NET 1, but found that lacking as well.
I wonder why...
A .NET Loss
What is strange is presumably they had tried out .NET 2 which would seem to have a more compelling story than .NET 1, but found that lacking as well.
I wonder why...
Data Port ActiveX
I finally managed to write an ActiveX component for the Data Port Component. Instead of using a rocket-science C++ approach, I turned to the venerable Visual Basic 6 to do the job for me. The result of this work is now available online and is made out of two parts. First, you need to download the newest version of dplib.dll (Zip 1.45 MB). You get both the release and debug versions as well as the debug symbols and the map file. Second, you need to download the Vb6DataPort project (Zip 293 KB) that includes both the ActiveX project (DataPortX) and the consuming application with the same name as the Zip file.
This project shows how the Data Port Component must be used from VB6 and uses new code (the dplib.dll is now on version 1.1.25) that is not yet compatible with the published C# wrapper. The C# wrapper will be updated to comply with the changes and will also be published with the source code (it's a very thin wrapper, really).
To make things work reliably, you should put the dplib.dll in the search path or you risk getting a run-time error from VB...
This project shows how the Data Port Component must be used from VB6 and uses new code (the dplib.dll is now on version 1.1.25) that is not yet compatible with the published C# wrapper. The C# wrapper will be updated to comply with the changes and will also be published with the source code (it's a very thin wrapper, really).
To make things work reliably, you should put the dplib.dll in the search path or you risk getting a run-time error from VB...
Sunday, May 15, 2005
Windows Mobile Platform Migration FAQ for Developers
The new version of the Windows Mobile Platform Migration FAQ for Developers is now online (just follow the link).
Check out the "Recent Updates" list next to the May 2005 entry: they're about Windows Mobile 5.
Check out the "Recent Updates" list next to the May 2005 entry: they're about Windows Mobile 5.
Saturday, May 14, 2005
CeDbgView32
Here is an interesting tool from Laurent Docquir to help us in debugging Windows CE processes: CeDbgView32. Cool stuff!
Friday, May 13, 2005
Robert Burdick's Blog
I've just added Robert Burdick's Blog to my list of links. His latest post teaches you how to programmatically turn on or off the Pocket PC WLAN adapter in a device-independent fashion. Great stuff!
Wednesday, May 11, 2005
News for us, Native Fellas
Nishan Jebanasam just posted an article on MSDN on What's New in Visual Studio 2005 for Native Developers. Although some image links are still broken as I write this, it is definitely an interesting read.
There is also another one, also by Nisham, on Migrating Microsoft eMbedded Visual C++ Projects to Visual Studio 2005 where he discusses the Upgrade Wizard and other issues.
There is also another one, also by Nisham, on Migrating Microsoft eMbedded Visual C++ Projects to Visual Studio 2005 where he discusses the Upgrade Wizard and other issues.
Data Port and VB6
I finally managed to make VB6 work with the Data Port Component (or the other way around). Why VB6? Although Microsoft killed it, a lot of people out there is still using it and will continue to do so in the foreseeable future. Interestingly, I recieved a lot of requests to develop a Component wrapper in VB6 from the UK. Being an almost complete ignorant, I shied away from this until one of my customers actually started the project.
At first it seemed quite straightforward. First, I had to change all __cdecl exported functions to __stdcall. The need for the second change was very hard to detect. The supporting DLL was designed to either be P/Invoked from .NET or to be directly consumed by a C++ application. This meant shielding all database-related functions with COM initialization code. This also meant exit exceptions when the DLL was consumed by VB6, either on the IDE or on the standalone runtime. After discovering this, there was the threading issue. Apparently one cannot safely call back into VB6 from an external thread, something that is safe in C++ and even on the .NET framework (that is how the C# sample works). The final solution is to start a timer to poll the import or export progress data. A kludge, but it works.
The nice thing about the whole process is that I had to instrument the whole code just to make sure there were no memory leaks or invalid pointers. A typical case of spring cleaning...
At first it seemed quite straightforward. First, I had to change all __cdecl exported functions to __stdcall. The need for the second change was very hard to detect. The supporting DLL was designed to either be P/Invoked from .NET or to be directly consumed by a C++ application. This meant shielding all database-related functions with COM initialization code. This also meant exit exceptions when the DLL was consumed by VB6, either on the IDE or on the standalone runtime. After discovering this, there was the threading issue. Apparently one cannot safely call back into VB6 from an external thread, something that is safe in C++ and even on the .NET framework (that is how the C# sample works). The final solution is to start a timer to poll the import or export progress data. A kludge, but it works.
The nice thing about the whole process is that I had to instrument the whole code just to make sure there were no memory leaks or invalid pointers. A typical case of spring cleaning...
Monday, May 09, 2005
MEDC UK
I finally made up my mind and registered for the MEDC UK event. I'm starting off with the "What's New for Native Code Developers in Windows Mobile" session. Now, I wonder why did I chose this one? I also chose the SQL Mobile session to finish the morning. In the afternoon, I will attend the "New Managed Messaging, State, and Notification APIs in Windows Mobile" session and the "Developing High Performance Applications with the .NET Compact Framework". Let's see how much P/Invoke we still have to do to get these things running... Native is faster, let me tell you!
Friday, May 06, 2005
Vibrating a Pocket PC
Vibrating a Pocket PC is a simple matter of turning a led on or off. As a matter of fact, the vibrating device when present is operated through the led API. The only problem you will have to sort out is the corresponding led number as this is device-dependent. On the HTC Pocket PC Phone Edition devices, this is led number 1.
To use this functionality in your applications, use the following code:
Simple, right?
To use this functionality in your applications, use the following code:
extern "C"
{
BOOL NLedGetDeviceInfo(INT nID, PVOID pOutput);
BOOL NLedSetDevice(INT nID, PVOID pOutput);
};
void SetLedStatus(int wLed, int wStatus)
{
NLED_SETTINGS_INFO nsi;
nsi.LedNum = (INT) wLed;
nsi.OffOnBlink = (INT) wStatus;
NLedSetDevice(NLED_SETTINGS_INFO_ID, &nsi);
}
Simple, right?
Wednesday, May 04, 2005
First Customers
After nine months selling software on the internet, only today did I manage to sell a product to a Portuguese company. Hum...
Now you know why I write in English.
Now you know why I write in English.
Sunday, May 01, 2005
New Projects
While I have a lot of code that needs further development, I cannot seem to decide what is going to be the next project on the list. There is the FastSqlCe code that needs to be further developed (schema is done, now data is waiting). Before that, I have DesktopSqlCe that is still waiting for command parameters and base table seeks. Now I'm thinking about adding a data synchronization feature to Data Port Wizard and also to produce an RDA-like feature for Jet databases. Hum...
Meanwhile, I published a small QA on Pocket PC Developer Network based on a year-old piece of code that shows you how to turn on the WiFi radio on a Dell Axim X30. There was some detective work involved in writing this one, especially using Remote Spy++. Fun stuff!
Meanwhile, I published a small QA on Pocket PC Developer Network based on a year-old piece of code that shows you how to turn on the WiFi radio on a Dell Axim X30. There was some detective work involved in writing this one, especially using Remote Spy++. Fun stuff!
Subscribe to:
Posts (Atom)