GPS Programming Tips for Windows Mobile - Part 1
NETCF: Memory leak... now what??
Supporting Kiosk-Applications on Windows Mobile (Technically achievable vs. supported)
Wireless Programming on Windows Mobile: supported or not supported?
Establishing GPRS Connection on Windows CE and Windows Mobile: Sample Codes
Disable WebBrowser's Context-Menu in NETCF applications
MAPI on Windows Mobile 6: Programmatically retrieve mail BODY (sample code)
Microsoft released a HotFix for NETCF v3.5 on Windows Mobile 6.1.4 onwards, to address basic functionalities of WebBrowser control
The right approach to get a Contact’s last communication (IItem’s PIMPR_SMARTPROP)
Remote Desktop Mobile (RDP Client) disconnects after 10 minutes of inactivity
Support Boundaries for Windows Mobile Programming (Developing Drivers, for example... Or even WiFi Programming)
Miei post in italiano sul team-blog del Supporto Tecnico agli Sviluppatori
WOW!!! Being linked by one of the most followed blogs about .NET Troubleshooting is really a honor!! And by the way, if you are interested on ASP.NET, Debugging and similar, you MUST know Tess Ferrandez' blog! Thanks Tess!!
Really many mobile developers have often various issues related to memory. This is obviously mainly related to the restrictions Windows CE has (till version 5.0) about memory-management, basically what Doug Boling called "Living within the box" here. Remember that Windows Mobile, even 6.1, still relies on Windows CE 5.0 components, therefore it still "suffers" the 32MB-limitation per process.
I've been involved in cases about memory so many times that I started blogging… see my very first post "NETCF: Memory leak... now what??". And I’m glad to say that all the hints I’ve written in that post must have helped many developers, because since then I worked rarely on cases related to memory…
In any case, before saying that "the problem is with memory", you should consider having a solid understanding of how that works on Windows CE (till v5.0). There are many authoritative places where you can look at over the web and books; and many others that are specific to .NET Compact Framework. So I won’t repeat them here (unless you want so).
Apart from the bloat of info you can find in my old post, some other things you should know:
- In the past Motorola\Symbol did an excellent job on troubleshooting memory issues, and they developed a tool that is part of their Private SDK and that work on Motorola devices. So, if you’re specifically targeting Motorola\Symbol devices, if you think the problem is with memory then you must use it. Its name is "Remote Memory Viewer", but sincerely I don’t know if it’s still available. Consult with Motorola to check if this is the case.
- Remember that Remote Performance Monitor (RPM) offers not only the ability to compare the GC Heap at different times, but also to export data that can be seen on the PC’s Performance Monitor (Start\Run… "perfmon").
- In some very rare cases, especially on devices with additional hardware features (barcode, etc), a problem with the memory is something that can’t be resolved without modifying the architecture of the application: in some cases the application hits a limitation of the platform and a limit of your abilities as ISV Application Developers (compared to what an OEM can do with their platform, especially if "many" drivers have to be loaded by DEVICE.EXE). In general, for applications that may require so much memory, an architectural design is to split it into at least 2 applications: a shell that act as a guardian and kills background applications, and a main application doing the job.
- To emulate user’s interaction with UI and verify if disposing a form in a managed application actually marks the object as ready to be collected, an approach that you may use is to see what happens if, after showing and disposing a form "many" times and after "some" Garbage Collections, all the memory is really cleaned up. This way we'll know if the leak is due to something internal to that particular form for example. I'm simply talking about something similar to the following:
int N = 1000;
for (int i = 1; i <= N; i++)
if (i % 200 == 0) MessageBox.Show(i.ToString()); //simply to know it’s going
//for example at this point you can click on RPM's "GC Heap"
frmTest frm = new frmTest(/*...*/);
MessageBox.Show("Over. Done. Finito.");
After running the loop for N times, looking at RPM you should make sure that "some" Garbage Collections occurred and then you can look if in the GC Heap there are still frmTest objects alive.
- If the problem is with a v2.0 application, even SP2, make sure you're not hitting a bug, by verifying if running on the v3.5 addresses the issue (click here for details). However, this is a suggestion valid in general, and indeed I've already written as point 2 of a previous post.
Crashes happen when the application closes unexpectedly. On Desktops you can leverage on many tools, starting with ADPlus + WinDbg. But this is not the case for us "tiny" programmers… some hints:
1. Start by reading "How the Windows Mobile 5.0 Shell Handles Low Memory Situations": note that the OS doesn't send WM_HIBERNATE nor WM_CLOSE to the foreground application: is your application the one with the focus?
2. How many processes are running at the time of the process' exit? If your process requires so much memory, then you should free the virtual memory associated to the DLLs loaded by other processes (which places the DLL Load Point down in the 32MB), by killing undesired processes and if possible by not starting the drivers you don't need (this last thing is not supported for ISVs however there are some known ways over the web to achieve the result, which may be OEM-specific).
3. If the application is managed: in general, the .NET CF CLR does not close applications without an unhandled exception dialog box. If you are seeing your application disappear in low memory conditions, it is more likely either the OS closing the application because of general low memory or because some native code within the application’s process experienced an unhandled exception.
4. It may be that the exception is raised by the application and not caught by anyone. Global Exception Handling is a concept for example discussed by Daniel Moth here.
5. In order to trap whatever interesting information, you may use BugTrap. This is the device-side executable of the "Windows Mobile Developer Power Toy" named "RAPI Debug". It might be useful in some cases because it can trap exceptions that aren’t caught by the application or are (or should be) smoothly handled by the OS. For any exception type problem, BugTrap will capture the exception details without the need for an ActiveSync\WMDC connection. But with such it gets even better since DEBUGMSG and RETAILMSG info will be available on the attached PC screen (or redirect to a file). You can run the application after starting RAPI_Debug on your development PC (it requires an ActiveSync connection with the device), and you can use it more than once, to see if the caught exception, if any, is always the same. If you have problems on running it, it may be that it's because RAPI Security Policy on the device (chosen by the manufacturer) prevents it to run: in such a case, you may simply start bugtrap.exe on the device BEFORE launching your application."
6. If you enable "Error Reporting", in case of a crash a mini-dump will be automatically generated. A .kdmp file is then available and you can for example look at it through the Windows CE Dump Viewer. Unfortunately, when working with RETAIL devices very rarely this approach leads to something interesting, because a RETAIL image by definition has no Debug Symbols and you may simply end up by knowing that the function at address X failed to access parameter at address Y. So this approach is for OEMs or for In-ROM ISVs\IHVs, not really for ISV Application Developers. Also because without control on the platform, you can’t even control how DrWatson creates the dumps for you.
The principle you should follow is the one used by Dr House in his movies: explore all the paths in order to discard a possible conclusion. It’s an attitude more than a process. And after some years you start dealing this way with everything… So, when facing a problem with an application you're writing for Windows Mobile, ask yourself the following questions.
1- Make sure the problem is not OEM-specific. Remember that, as I’ve written here, you should contact that OEM's Technical Support in order to troubleshoot the issue, as only the OEM knows in detail what they included in their OS based on the Windows CE\Mobile platform. So, having been able to reproduce it on different devices from different makers, or even better on the Device Emulator, is one of the first steps. If you don’t know precisely how the interaction between Microsoft and the OEMs work, you may for example read my answer #4 on my friend Chris’ blog here.
2- Before wasting huge amount of time on whatever type of troubleshooting, make sure you’re using the state-of-the-art technologies. For example, if you have a weird problem with a managed application running against v2.0, even if SP2, then you can check if v3.5 included a fix precisely to address the issue you’re experiencing. You don’t need to recompile via VS2008, as I’ve discussed about this here. Or, another example is SQL Compact 3.5: SP1 was recently released – if your issue is somehow related to SSCE3.5 then you should make sure if it was addressed in 3.5 SP1. Finally, when talking about state-of-the-art, I’m also referring to possible ROM Upgrades and Updates published by OEMs so that you can verify if the issue was raised by a older version of a OS' or OEM's component.
3- A problem is not something random. It’s random until we discover its pattern, and when we do it, we have a “deterministic problem”. So, a hint is: invest some time on trying to understand if the problem doesn’t happen under certain circumstances. In really very rare cases I had to do with real random problems, due to random failures of the CPU… but this was fixed by the CPU-manufacturer some years ago.
4- Remember that the goal of this phase is to exclude possible problem’s causes… so what about 3RD party libraries? I’m talking about the controls and libraries that the application depends on, and which you don’t own the source of. Many times you simply have to make sure that you’re using them correctly (Is this library the right version for this device? Was the control meant to work for NETCF v3.5? …).
5- Once you exclude all the possible external problems, it’s time to dig into it. But… we can’t work on the whole solutions, plenty of projects! You need to separate the “offending” portion. How do you know that? A possible approach, if the problem is reproduced on the Device Emulator, is to instrument your code, for example by adding calls to the OutputDebugString function in critical parts of your code and configure Device Emulator to bring up a serial debug output console. To do so go to the "File", "Configure..." menu item, switch to the "Peripherals" property sheet and check the "Create text console window for serial port 1" option. To make this option permanent, you can use Visual Studio menu Tools\Options\Devices, select the emulator and then you’ll have the same dialog.
6- Last but not least, EQATEC recently came out with a gift to all Mobile Programmers: a new tool called EQATEC Tracer that may be tremendously useful when troubleshooting.
Now come with me: follow the line of my thoughts and tell me if I’m correct. This is a blog written by a member of the Microsoft Technical Support (sorry, it’s “Customer Service Support”), right? What’s a Support Engineer good for? (Feel free to add any comment, but I’ll ban out the ones I don’t like… ) Can you ask a Support Engineer about beta technologies that will be released in 1-2 years time? Well, yes – but purely because he may have spent some spare time on this. This is indeed the job of an Evangelist. Can you ask a Support Engineer to architect a solution based on the “Mobile Accelerator” that suits your exact scenario? Well, yes – but actually he usually works on solutions that have already been architect-ed and it may be that his knowledge-bag misses some guidelines that instead Consultants must surely have.
What’s in my opinion a Support Engineer is really good at is “Troubleshooting”. Developers ask for our intervention when they don’t know how to continue debugging a nasty problem, or if they think that the problem may be related to a bug, or to know if they’re coding the right way, and so on. The blogosphere is so full of really cool and interesting blogs written by “Mobile Programmers” that share their smart code, I can’t compete with them.. In conclusion, what I can probably offer to the Developer Community is some hints and suggestions about how to face a problem when you have it.
This is basically what some of my co-workers already do, see for example Carlo’s blog. “Ahh..”, you may say, “that’s Web Development: for that you have plenty of troubleshooting tools and techniques, this is not the same in our tiny niche.”. Above all, we’re no longer a niche.. see MEDC: it’s now part of the “main-stream” TechEd. And see also how many blogs & web-sites about Mobile Programming recently proliferated. But you’re right about the other aspect: unfortunately we don’t have many tools that desktop programmers take for granted.
So my intention is to share some techniques that might guide you to the solution when facing a problem during mobile development. Hope it'll be useful, and sorry if I'll write something that may appear obvious to many (but not to all).