Topics:

  • Building Managed Code as part of the OS (Part 3): Debugging
  • Windows 8.1 Update
  • $0 Windows Licesninsing and Open Source

NEWS

Windows 8.1 Update

Now available on MSDN, dated 3rd April 2014. It comes in three downloads.

See my Blog on HowTo install and the the new beaut subtle features.( Click Here)

$0  Windows Licensing and Open Source

At Build 2014 Microsoft announced that it would provide Windows 8 and Windows RT for free to OEMs (original equipment manufacturers) for devices with screens smaller than 9 inches. There is much hype and discussion about what this really means. What does it apply to? The conditions as I understand it are:

  • It will apply to device manufacturers only (OEMs)
  • Commodity items only
  • Screen size < 9 inches
    • So its targeting phablets and phone
  • I think there was some kind of 12 month limit to the license.

I suspect that Windows Embedded Compact/CE won’t go to $0 licensing, especially given the required 10 year support. It just wouldn’t make sense. The main target I think is trying to get phone manufacturer to support the multi-boot feature available with phone 8.1. (Multi-boot Windows Phone-Windroid). Microsoft has been aggressively pursuing HTC on that front. The big question for Windows embedded developers is where does Compact/CE fit in Microsoft's new vision? Is it going to have a substantive role or will it be largely ignored. Will it part of Microsoft's new mantra One Windows?

Also, it is noticeable that .Net Microframework got a mention at Build with respect to Open Sourcing of .NET. Could the Compact Framework follow?


Building Managed Code as part of the OS (Part 3): Debugging

The Story so far

In the previous two blogs in this topic a acse was mounted for building Managed Code with teh OS like Native Code. We saw how it is possible insert a C# Managed Code project into a Windows Embedded Compact OS project as a Subproject such that it is built with and

included with the OS. The first method required a content only Subproject (like those generated by CEComponentWiz (on Codeplex here). It uses prelink.bat to build an existing SDK project and to use postlink.bat to add built contents to the OS. The second method introduced the new tool WECSharpWiz (available on Codeplex here). It is a tool for generating a new Managed Code Subproject that "looks and feels" like a Native Code Subproject, except that the project is C#. WECSharpWiz (watch for a renaming to CEESharpWiz soon, please excuse the pun!), can generate a new C# console or WinForms app and additional items ca be added to the project (source files and resources) as well as additional references; all as part of the wizard. Existing source files can be imported to the project. It is intended that a later version will allow for the complete import of an existing project, whether Desktop .NET, Compact Framework 2, 3.5 (Compact7) or 3.9. There are some limitations though:

  1. here is no capability to debug these apps apart from a brute force writeline approach.
  2. Whilst the forms page comes with its designer page , generated forms page can't be viewed in a the Visual Editor this making GUI design a bit harder. This also means that the creation of UI component event handlers have to be coded manually.
  3. Whilst resource files can be added, resource compilation is not currently supported.
  4. Whilst there is an ability to add additional files to a project, there are only two file templates, a blank class and a blank form (with its designer).
    • Subsequent versions will add more templates.
  5. Compilation errors in the Output Windows when double clicked don't take you to the source code.

The main focus of this blog article is (1), debugging. Lets look at some partial workarounds for (2) and (3) first. (4) is coming in later versions and no solution to (5) is yet to be offered.

2. The Visual Designer

Normally one opens a form using the Visual Designer, adds UI controls and creates a suitable layout for the form's user interface (UI). One then double clicks on each control to generate an event handler stub for a control, or uses the property pages to create the stubs for all required event handlers. Without the use of Visual Designer, this is much harder.

Project File .(csproj)
  1. <ItemGroup>
  2.   <Compile Include="Class1.cs" />
  3.   <Compile Include="Form1.cs">
  4.     <SubType>Form</SubType>
  5.   </Compile>
  6.   <Compile Include="Form1.Designer.cs">
  7.     <DependentUpon>Form1.cs</DependentUpon>
  8.   </Compile>
  9.   <Compile Include="Program.cs" />
  10.   ...
  11.   ...
  12.   ...
  13. </ItemGroup>
 

..you can see that the form is tagged as a form for the compiler and its designer is linked to it The project that is generated by WECSharpWiz is a sources project so we need someway of passing the above metadata to the compiler in the sources file. Any ideas??  Also, right-clicking on the file in Solution Explorer doesn't give you an opening options.

A workaround is to just create the form in a full OS SDK project with its GUI designed and event handlers created. Then import it into the sources project when generating that Managed Code project (Menu-Project-Import Existing..) .. but then you do end up needing an SDK! Or just manually code the UI and event handler stubs .. er!!

3. Resources

Resources such as images are often used directly by controls as part of the UI configuration and are so configured during the design phase of the form. For example, when a PictureBox cintrol has it image set during design time, that image is bound into the project code as a resource. At runtime it is sourced for the relevant control (in the "Windows Form Designer generated code" in the form's Designer.cs code) from the embedded resources. Because of the lack of a Visual Design Editor (to take you through this resourcing) and the lack of resource embedded with WECSharpWiz (ie no .resx file is generated), an alternative is needed.

  • The suggested workaraound is to
  • Add the resource (eg image) to the project resources using Menu-Project-Add Existing Resource.
    • This will collect the resource files in the subproject directory when the project is generated, and see that it is included in the OS image if the apps is included, or downloaded with the app if running via Target Control (Yes you can).
  • Add startup code after the InitalizeComponent() call in the form constructor to load the resource.

For example the following code will add an image to PictureBox1. Note that loading images to the PictureBox with the Compact Framework is a bit more cumbersome than for the Desktop .NET:

Code for if image was loaded in designer using an embedded resource (Not possible in this scenario): [This code has been updated]

In form.dDesigner.cs:
  1. this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("Image1.png")));

Instead call from the Form Constructor:

In form constructor:
  1. InitializeComponent();
  2. string image = "\\AboutBoxImage.jpg";
  3. string appName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
  4. string appPath = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
  5. appPath = appPath.Replace (appName+ ".exe" ,"");
  6. image = appPath + image;
  7. LoadImage(image, this.logoPictureBox);

The Compact Framework code to dynamically load an image into a PictureBox:

LoadImage()
  1. private void LoadImage(string filePath , PictureBox pictureBox1)
  2. {
  3.     if (File.Exists(filePath))
  4.     {
  5.         using (FileStream reader = new FileStream(filePath, FileMode.Open))
  6.         {
  7.             byte data = new byte[reader.Length];
  8.             reader.Read(data, 0, (int)reader.Length);
  9.            using (MemoryStream memory = new MemoryStream(data))
  10.            {
  11.                pictureBox1.Image = new Bitmap(memory);
  12.                pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
  13.             }
  14.         }
  15.     }
  16. }

Better version (found the one above "flakey"!):

LoadImage() V2
  1. private void LoadImage(string filePath, PictureBox pictureBox)
  2. {
  3.     if (File.Exists(filePath))
  4.     {
  5.         pictureBox.Image = new Bitmap(filePath);
  6.     }
  7.     else
  8.     {
  9.         MessageBox.Show("AboutBox Image file not found:" + filePath, "About Box");
  10.     }
  11. }

Also need a reference:
using System.IO;

Caveat:
This resource won't embellish the control during design time but will be there at runtime. You could "hack" the "Windows Form Designer generated code" in the form's Designer.cs code to show it at design time as well but that is fraught danger. (I have actually done it successfully.  Ask me if you want a further blog on how to do it.)


Debugging OS Managed Code Subprojects

Debugging an application typically requires breakpoints to be inserted into the lines of code (conditionally or unconditionally) so that the values of various entities, at that point, can be inspected. Also break points are useful for checking that a line in the code is actually reached, or when it is reach (eg. how many loops). Tracing is also another feature of debugging where values are output at certain lines of the code to be sent to a debug window without the program breaking at that point. There are other things such as threads, performance etc. that re important, especially in an embedded context,but lets focus upon just getting the functionality of an app correct.

When running an OS with KITL enabled, Native Code Subprojects can be debugged using a breakpoints, Debug Macros, etc.  The Windows Embedded Compact/CE Debug Macros have been largely unchanged through the various versions of the OS.  When running a Managed Code Subproject, the breakpoints don't work. The problem is the attached debugger with KITL is at an OS API-Native Code level, whereas Managed Code requires a Managed Code debugger to be attached. Managed Code, at least conceptual, is "interpreted" by the .NET Common Language interpreter (CLI) Virtual Machine. So you may well be debugging the CLI rather than the C# source when trying to debug such code as Subprojects over KITL. This is not to be confused with running a separate instance of Visual Studio to build, deploy and debug an SDK project over CoreCon which does invoke and attach the CLI debugger. We are launching Subprojects, albeit Managed Code, using KITL and attaching to the OS debugger.One approach is to to simply use C# print statements inserted in the C# code to print messages and where required or invoke a C# MessageBox to effect a break in code. Lets examine this.

CE/Compact Debug Macros

The CE/Compact Message Macros are (ignoring the DebugZone ones):

DEBUGMSG (cond, printf_exp)

Conditionally outputs a formatted debugging message to NKDbgPrintfW.

This macro is only present in Debug and Checked builds; it does nothing on Retail and ship builds.

RETAILMSG (cond,printf_exp)

Conditionally outputs a formatted debugging message to NKDbgPrintfW.

This macro is only present in Debug, Checked, and Retail builds; it does nothing on ship builds.

ERRORMSG (cond,printf_exp)

Conditionally outputs a formatted error message to NKDbgPrintfW, adding the file name and line number where the error occurred.

This macro is only present in Debug, Checked, and Retail builds; it does nothing on ship builds.

DEBUGCHK (exp)

Asserts an expression and produces a DebugBreak if the expression is FALSE.

This assertion is only present in Debug and Checked builds; it does nothing on Retail and Ship builds.

This macro assumes that a global variable dpCurSettings has already been defined, where dpCurSettings must be a DBGPARAM structure.

ASSERT (exp)

Asserts an expression and produces a DebugBreak if the expression is FALSE.

This assertion does not assume dpCurSettings is present. The assertion is only present in Debug and Checked builds; it does nothing on Retail and Ship builds.

ASSERTMSG (msg, cond)

Asserts an expression, and if the expression is FALSE, produces an error message to NKDbgPrintfWand a DebugBreak.

This macro is only present in Debug and Checked builds; it does nothing on Retail and Ship builds.

DEBUGLED (cond, parms)

Conditionally outputs a pattern to WriteDebugLED.

This macro is only present in Debug and Checked builds; it does nothing on Retail and Ship builds.

RETAILLED (cond, parms)

Conditionally outputs a pattern to WriteDebugLED.

This macro is only present in Debug, Checked, and Retail builds; it does nothing on Ship builds.

Typically, Managed Code development would be done with a RETAIL Release of the OS and so the only two macros of use are highlighted in blue, RETAILMSG and RETAILLED. RETAILMSG can implement a form of writeline debugging. To use the macros in Managed Code, you would need to invoke them in a native code DLL then PInvoke them.. You can't PInvoke a macro! Hence some of the macros would only return information about where they are located in the native code DLL. A Codeplex project was created to explore this. It has the native DLL and its managed code wrapper. Give it a try if you wish. Its located at https://cedebugcf.codeplex.com/

Current Debugging Workaround:

  • The simplest way to insert debug messages,  is to insert Debug.WriteLine statements.
    • These appear in the Debug window of the development system, in the same manner that RETAILMSGs do.
    • There are some conditional versions of this. See System.Diagnostics.Debug (here)
    • A using System.Diagnostics reference will need to be added.
  • Breakpoints can be inserted by inserting MessageBox  statements displaying the data of interest,

More thoughts on debugging later. Your thoughts as feedback are most welcome.


WECSharpWiz: Conclusion

WECSharpWiz is quite useful for creating C# applications that build with the OS. UI development and debugging are difficult though. Once the project  import feature is implemented it will be a productive tool for including SDK C# apps directly into the OS build. It will also simplify the upgrading of C# from previous Compact Framework versions to CF 3.9. This import feature will be in the next version, which will be called CEESharpWiz on Codeplex. Watch for that or monitor this blog. Note though that you can import an existing project manually with the current version of WECSharpWiz by creating a new project and importing existing code and resources.

Open-mouthed smileEnjoy


Managed Code Blog Series