Unable to load DLL 'sqlceme35.dll': The specified module could not be found

by 3. October 2009 00:49

If you are running x64 then you'll need to install the following:

Microsoft SQL Server Compact 3.5 Service Pack 1 and Synchronization Services for ADO.NET version 1.0 Service Pack 1 for Windows Desktop

This threw me for a loop because my form would simply load without any data.  As a result I would be stepping through code (stepping over my data layer) and my form would activate with nothing in it.   Drilling down deeper I discovered the view would activate on line 228 below:

  222 public DataBindingList<T> ExecuteList<T>(string sqlCommand, ListDelegate<T> listDelegate)
  223 {
  224     try
  225     {
  226         DataBindingList<T> dataList = new DataBindingList<T>();
  227 
  228         using (SqlCeConnection conn = new SqlCeConnection(ConnString))
  229         {

This had me scratching my head wondering if some of the Async processes were messing with my debugger.   Since it worked on the 32-bit development box (which I don't currently have with me) I had no reason to suspect foul play on my x64 development box - this misconception resullted in much head-banging time.   

I should have payed attention to this error earlier, as it would reveal itself, but more towards the end of the debugging session and not on line 228 above; it would reveal itself as a messagebox not attached to any particular line of code.  I wrongly had suspected corrupt dlls as I am dabbling in a multi-targeting application (code shared between mobile and winforms).   It wasn't until I placed the try/catch (shown above) that the error revealed itself within the scope of the process.

Hopefully you'll hit this blog before the others because Head-banging occurred longer than it needed as I ended up chasing rouge blogs on this topic that had me going in circles until I figured out they were dead-ends. In the end the fix was quite simple - simply install SP1 and everything started working. 

Mobile Framework for Mobile 5.0 - Managing Control State with ControlContainer

by 21. March 2009 00:42

Preceived performance is more significant then actual performance.  If a user clicks a Login button and nothing happens within the first few second they'll click it again thinking perhaps it didn't register.  If a few more seconds pass they may wonder if it locked up.  

If however the button text changes immediately showing that it is checking their credentials (against a backend database) and then a second later changes again letting the user know that it is loading data, which may be from multiple data sources (in the case of the example below Facility, Level of Care and Patient data) the perceived performance will be high.  
See video clip (no audio) 

The following ObjectContainer class allows us to easily manage a Button's state (Text and Enabled properties) by taking advantage of the IDisposable interface:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
 
namespace Library.Mobile.Interface.Containers
{
    /// <summary>
    /// Manages object state, i.e., if T is Button then the button
    /// will be disabled and the button text will be stored.  When
    /// the control disposes the text will be restored and the button
    /// reenabled.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ObjectContainer<T> : IDisposable
    {
        public T Data { get; set; }
        public string Text { get; set; }
 
        /// <summary>
        /// Constructor - sets up T so that it can be restored on dispose
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="text">The text.</param>
        public ObjectContainer(T control, string text)
        {
            Data = control;
 
            // Cast T to object so we can work withit
            object data = Data;
 
            if (control is Button)
            {
                Text = ((Button)data).Text;     // Store button text
                ((Button)data).Enabled = false; // Disable button
                ((Button)data).Text = text;     // Set new button text
            }
            Application.DoEvents();
        }
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing,
        /// or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            // Cast T to object so we can work withit
            object data = Data;
 
            if (Data is Button)
            {
                ((Button)data).Text = Text;     // Restore button text
                ((Button)data).Enabled = true// Enable button
            }
            Application.DoEvents();
        }
    }
}

Below we'll modify the button text, as business logic dictates, and when we're done the original state will be automagically restored:

Note that on the breakpoint for line 56 that we still have our standard "Login" text for our login button. 

On the very next instruction (line 61) we see that we've changed our button text to "Verifying Login.."; reference arrows below:

With a successful login we change our button text again, on Line 73, to show that we are logged in and loading Tom's patient data:

At this point we raise the OnLoginSuccess event which is subscribed to in the main view (we are inside of a Login UserControl).   Below we show the new modal form that is loaded.  We haven't hit line 79 yet; as far is the Login control is concerned we are still on line 74.

Once OnLoginSuccess is exited (line 74 below) and we exit the scope of the using statement (Line 61 thru 78) our ObjectContainer.Dispose event will fire.  So when we hit line 79 the ObjectContainer's Dispose event will have effectively restored the button state. 

See video clip (no audio)  In this video clip you saw the button text being changed beyond the scope of what was being shown above.  Each user control (usrFacility, usrLevelOfCare and usrPatient) on the Main view is passed a PatientDataEventArgs during it's OnViewReady() event where it gets a reference to the usrLogin control and updates the login view's button text.   Below is the typical user control presenter:

Mobile Framework for Mobile 5.0 - Resolving unmapped Interface returns null

by 20. March 2009 06:11

Error Subclassing controls - workaround HERE

UPDATE: Mobile 6 Framework has an excellent DI container!   As of this writing you have to download it from the Source Code tab (it isn't in the release) but in the download they provlde performance test and the Mobile container out performs all others to include Unity.

http://mobile5framework.codeplex.com/  <= Mobile 5 Framework source code
http://www.codeplex.com/compactcontainer  <= Dependency Injection for Compact Framework 

Side note: one thing I really love about VSS, that we can't easily do in VSTS, is share projects between solutions.  For example, my production application (Electronic Patient Record Medical System) uses the same libraries as my Mobile 5 Framework (Codeplex) project.  So as I update/fix my framework it is immediately available for my codeplex project.  Even though my development environment is managed by VSS the interesting (cool/strange) thing is my Codeplex project is a VSTS solution that includes my shared VSS projects - and it doesn't complain - it works in both environments :)  

On to the real information:   I updated the CompactContainer today to return null if an interface is not Type Mapped, i.e., there is not an entry in the configuration file to support the type being resolved.

The alternative would be to throw an exception like other DI containers, which I trust a lot of thought went into.  I opted to return null for reasons demonstrated by the following code, e.g., if on line 37 my ILogger cannot be resolved (as it won't because it wasn't configured) line 38 will still result in a logger.

Why?  The Logger setter on line 24 set it to the value null, returned by Container.Resolve<ILogger>(), however line 20 sees the null which results in DefaultLogger() being instantiated and then returned on line 22. 

So the lazy instantiation of Logger ensures there will always be a logger HOWEVER if I did configure ILogger in my configuration file then it will be used.   Throwing Exceptions involve a performance hit which we really want to avoid in the Compact Framework.

NOTE:  I used .NET 3.5 extensions to substitute Resolve (on line 37 above) for the actual CompactContainer syntax shown on line 369 below.

My goal is to leave existing functionality of the CompactContainer intact, for backwards compatibility, while adding new features.   The image following this one shows the result(s) of unit test against the CompactContainer's original code.

The following shows the unit test using CompactContainer35 running against the original objects provided in the TestDI demo application (using it's config.xml and config2.xml contents):

Then of course we have our unit test for our new Interface injection: 

/// <summary>
/// Determines whether this instance [can inject interface with 
/// configured immplmentation].
/// </summary>
[TestMethod]
public void CanInjectInterfaceWithConfiguredImmplmentation()
{
    // ConfigFilename is pulled from the baseclass - it is
    // identical to the CompactContainer CONFIG.XML with used
    // with TestDI with exception of Filename and appended Properties
    CompactContainer.CompactConstructor.DefaultConstructor
        .AddDefinitions(ConfigFilename);
 
    // Resolve interface based on the following ObjectDefinition
    // in the configuration file (in AppBaseTest)
    //----------------------------------------------------------------------
    // <ObjectDefinition Name='TypeMappings'>
    //   <Property 
    //      Name='IMockDIObject' 
    //      SetWithNewType='CompactContainer.Tests.MockObjects.MockDIObject' 
    //      FileName='CompactContainer.Tests.dll'/>
    // </ObjectDefinition>
    //----------------------------------------------------------------------
    IMockDIObject mockObj = Container.Resolve<IMockDIObject>();
 
    // Assert that we successfully resolved our interface
    List<MockUser> userList = mockObj.GetUserList(this, EventArgs.Empty);
    Assert.AreEqual(2, userList.Count, "There should be two Mock Users");
    Assert.AreEqual("Bill", userList[0].FirstName);
    Assert.AreEqual("Diane", userList[1].FirstName);
 
}

Mobile Framework for Mobile 5.0 with a Compact (DI) Container

by 18. March 2009 15:21

Note: In this blog I show how to deserialize XML into an object that has child objects. 

Although the core requirements for this phase of my current project will result in a Mobile/PDA application being completed by next week, I struggle having to work without a DI container (been real spoiled by Unity on the Web and Desktop side of the house).    

Preliminary research led me to an excellent (beta) DI container on codeplex (http://www.codeplex.com/compactcontainer/) by Mariano Julio Vicario.  Although it doesn't yet have constructor injection it provides setter injection which means I can inject my business logic layer as well as other reusable services.  Important since I've created a very dynamic framework.

I ran into two snags... the first was that it doesn't support .NET 3.5 - the serialization crashes and burns when I plugged it into a prototype application (source attached) that utilizes my framework.  I should clarify that Mariano's TestDI demo does run on the .NET 3.5 framework "as is" however it uses the .NET 2.0 assemblies.  When you create a new project and attempt to utilize the CompactContainer is where you will run into problems. 

The second was that the P&P folks released a new Mobile framework late Feb which replaced the CAB with a DI container.  Naturally I jumped on that, even at risk of scraping my framework, but was dismayed to see that it only supports Mobile 6.1 - so I ordered my new HP IPAQ 211 w/1gig ram but it won't be here until next week (about the time my application will be completed).   I'm chomping at the bit to play with the new Mobile framework....

So Mariano's DI container it is it for my current framework but I still had to get past the first snag - this blog has the details :)

I opted to go with LINQ to SQL and replaced the deserialization process with it.  Below is the line of code I changed to make the switch.

The magic is done with the new Extension class which is referenced at the top of the file as follows:

using CompactContainer.Tools;
using System.Xml.Linq;
 
// BillKrat.2009.03.18 - provide LINQ to XML extensions
using CompactContainer.Extensions;


The following Unit Test shows it in action:

using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml.Linq;
using CompactContainer.ConfigurationObjects;
using CompactContainer.Extensions;
 
namespace CompactContainer.Tests
{ 
    /// <summary>
    /// Summary description for UnitTest1
    /// </summary>
    [TestClass]
    public class CompactContainerFixture
    {
        public CompactContainerFixture() {  }
 
        private XElement config = XElement.Parse (
            @"<?xml version='1.0' encoding='utf-8' ?>
            <CompactContainer xmlns='http://tempuri.org/ConfigurationSchema.xsd'>
              <Context Name='default'>
                <ObjectDefinition Name='Demo' 
                                  Type='PasswordManager.Login.LoginViewPresenter' 
                                  Singleton='false' 
                                  FileName='PasswordManager.exe'>
                    <Property Name='Str' 
                              Set='Hi Set of String' />
                    <Property Name='Inte' 
                              Set='28' />
                    <Property Name='Something' 
                              SetWithNewType='TestDI.BehaviourISomething' 
                              FileName='PasswordManager.exe' />
                    <Property Name ='Obj2' 
                              SetWithObjectDefinition='Object2'/>
                </ObjectDefinition>
                <ObjectDefinition Name='Object2' 
                                  Type='PasswordManager.Main.MainViewPresenter' 
                                  Singleton='true' 
                                  FileName='PasswordManager.exe'>
                  <Property Name='Inte2' Set='98' />
                </ObjectDefinition>
              </Context>
            </CompactContainer> ");
 
        /// <summary>
        /// Determines whether this instance [can read configuration file].
        /// </summary>
        [TestMethod]
        public void CanReadConfigurationFile()
        {
            CContainer container = new CContainer();
 
            // Uses new CompactContainerExtensions
            container.Items = config.GetContext();
 
 
            Assert.AreEqual(1, container.Items.Length, 
                "There should only be one context");
            Assert.AreEqual(2, container.Items[0].ObjectDefinitions.Length, 
                "There should be two Object Definitions");
 
            ObjectDefinition demo = container.Items[0].ObjectDefinitions[0];
            ObjectDefinition object2 = container.Items[0].ObjectDefinitions[1];
 
            Assert.AreEqual("default", container.Items[0].Name,
                "The context name should be 'default'");
 
            Assert.AreEqual("Demo", demo.Name);
            Assert.AreEqual("PasswordManager.Login.LoginViewPresenter", demo.Type);
            Assert.IsFalse(demo.Singleton);
            Assert.AreEqual("PasswordManager.exe", demo.FileName);
            Assert.IsNotNull(demo.Properties.First<Property>(
                p => p.Set.Contains("Hi Set of String")));
            Assert.IsNotNull(demo.Properties.First<Property>(
                p => p.Set.Contains("28")));
            Assert.IsNotNull(demo.Properties.First<Property>(
                p => p.SetWithNewType.Contains("TestDI.BehaviourISomething")));
            Assert.IsNotNull(demo.Properties.First<Property>(
                p => p.FileName.Contains("PasswordManager.exe")));
            Assert.IsNotNull(demo.Properties.First<Property>(
                p => p.SetWithObjectDefinition.Contains("Object2")));
 
            Assert.AreEqual("Object2", object2.Name);
            Assert.AreEqual("PasswordManager.Main.MainViewPresenter", object2.Type);
            Assert.IsTrue(object2.Singleton);
            Assert.AreEqual("PasswordManager.exe", object2.FileName);
            Assert.IsNotNull(object2.Properties.First<Property>(
                p => p.Name.Contains("Inte2") && p.Set.Contains("98")));
        }
    }
 
 
}

The new Extension class follows:

using System.Collections.Generic;
using CompactContainer.ConfigurationObjects;
using System.Xml.Linq;
 
namespace CompactContainer.Extensions
{
    /// <summary>
    /// 
    /// </summary>
    public static class XElementExtensions
    {
        /// <summary>
        /// Attrs the STR.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="fieldName">Name of the field.</param>
        /// <returns></returns>
        public static string AttrStr(this XElement element, string fieldName)
        {
            object data = element.Attribute(fieldName);
            return data == null ? "" : element.Attribute(fieldName).Value;
        }
 
        /// <summary>
        /// Attrs the bool.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="fieldName">Name of the field.</param>
        /// <returns></returns>
        public static bool AttrBool(this XElement element, string fieldName)
        {
            object value = element.Attribute(fieldName);
            return value == null ? false :
                "true".Contains(element.Attribute(fieldName).Value.ToLower());
        }
 
        /// <summary>
        /// Gets the properties.
        /// </summary>
        /// <param name="prop">The prop.</param>
        /// <returns></returns>
        public static Property[] GetProperties(this XElement prop)
        {
            List<Property> propList = new List<Property>();
            foreach (XElement pr in prop.Elements())
                propList.Add(new Property
                {
                    FileName = pr.AttrStr("FileName"),
                    KeyType = pr.AttrStr("KeyType"),
                    ListType = pr.AttrStr("ListType"),
                    Name = pr.AttrStr("Name"),
                    Set = pr.AttrStr("Set"),
                    SetDictionary = pr.AttrStr("SetDictionary"),
                    SetList = pr.AttrStr("SetList"),
                    SetWithNewType = pr.AttrStr("SetWithNewType"),
                    SetWithObjectDefinition = pr.AttrStr("SetWithObjectDefinition"),
                    ValueType = pr.AttrStr("ValueType")
                });
            return propList.ToArray();
        }
 
        /// <summary>
        /// Gets the object definitions.
        /// </summary>
        /// <param name="objDef">The obj def.</param>
        /// <returns></returns>
        public static ObjectDefinition[] GetObjectDefinitions(this XElement objDef)
        {
            List<ObjectDefinition> odList = new List<ObjectDefinition>();
            foreach (XElement od in objDef.Elements())
                odList.Add(new ObjectDefinition
                {
                    FileName = od.AttrStr("FileName"),
                    Name = od.AttrStr("Name"),
                    Properties = od.GetProperties(),
                    Singleton = od.AttrBool("Singleton"),
                    Type = od.AttrStr("Type")
                });
            return odList.ToArray();
        }
 
        /// <summary>
        /// Gets the context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public static Context[] GetContext(this XElement context)
        {
            List<Context> contextList = new List<Context>();
            foreach (XElement child in context.Elements())
                contextList.Add(new Context
                {
                    Name = child.AttrStr("Name"),
                    ObjectDefinitions = child.GetObjectDefinitions()
                });
            return contextList.ToArray();
        }
    }
}

The following is a short screencast (no audio) that shows the framework in action (the virtual methods in PresenterBase provide hooks into events that are not normally available, i.e., OnLoad for user controls) :
http://global-webnet.net/Webcast/PasswordManager.htm 

http://mobile5framework.codeplex.com/ <= Source code

MobileFlow.txt (5.97 kb)  <= Shows the flow of events for Views and their User Controls (best viewed in notepad with Arial 10 font - alignment)

 

Visual Studio 2008 can't deploy to Emulator - Stops responding

by 14. March 2009 07:40

Ran into a situation when deploying to the Emulator with Visual Studio 2008, Windows 7 and the compact framework.  Everytime I attempted to deploy the emulator would have the spinning circle (center of image below)



Visual Studio would stop responding and generate an error message. 

 

I had reset my computer and received the same results. 

Everything had been working without issue so I undid prior code changes, rebuilt and still my Visual Studio would lock up and my Emulator would stay with the spinning circle.

Since the emulator was still running I treated it like a Device and stopped the running program and tried again.  Still locking up Visual Studio.  I then did a Hard Reset on the emulator and walla!  I was back in business - Visual Studio 2008 was happy again.

Mobile / Compact Framework UserControl DesignMode null in constructor

by 14. March 2009 04:12

Mobile Development has proven to be quite the chore.  Nothing like getting all of your code in place after hours of work to find your designer is broken and there isn't a clue as to why.  Countless hours lost because you can't get the designer to show your Mobile Form, and YOU HAVE TO BE ABLE TO UPDATE IT, with your only option to "undo checkout" (source control) and start over.   I learned to try "all" my views/forms regularly before I go too far...

If you are like me and this is costing you days of development and you are starting to think you can't use UserControls or derive from base classes because the Visual Studio Designer (I'm using VS2008) is too fragile, there is a solution!  It follows on line 10 below:

    1         /// <summary>

    2         /// Constructor

    3         /// </summary>

    4         public usrPatients()

    5         {

    6             InitializeComponent();

    7 

    8             // The ParentChanged += that follows will crash the

    9             // designer (Mobile designer is fragile)

   10             if (DesignMode.IsTrue)

   11                 return;

   12 

   13             // So our UserControl can have an OnLoad event - this

   14             // event fires when the parent form adds the user control

   15             ParentChanged += (sender, e) => { OnLoad(sender, e); };

   16         }

Note: before you run off and try to type in the code above please know DesignMode is a class I wrote with a static property IsTrue (keep reading..) 

So you google the problem CLICK HERE and the first link on the list gives you a clue that you are in trouble - emphasis on "There is no LicenseManager in Compact Framework", you also learn that this.DesignMode doesn't work in UserControls, you learn Site.DesignMode is always null in constructors, you learn the directives don't work - the most important thing you learn is you need to return after InitializeComponent() yet Visual Studio doesn't support a way to do this in a VS2008 UserControl constructor. 

I think I actually chuckled when I saw the above because that is where I was living, I was quickly falling behind the power curve and was tired of rewriting code over and over.  The following was my form with three user controls (top three containing dropdown with buttons).

The pattern I have been following the last couple of weeks follows: I'd do simple infrastructure work on my user control, would have everything working during runtime, and then would have to stop to do my dreaded Form/View check (clicking on every single control) and wouldn't you know it - I'd get to a form that uses my control and I'd get the following error:

I was locked out of my form AGAIN!!!   This was becoming a critical issue - I was dead in the water again and it was time to find out why and fix it.

Are you where I was?  Rest assured - I have your answer :)  Keep reading...

This was a critical error because unlike some of the other errors I've encountered, where they give you a clue and you can go to the offending line of code in the control and fix it - the above tells you nothing.

So to recap... after much research I came to the conclusion that user controls *have* to return immediately after InitializeComponent() or the successive commands could threaten parent forms from being able to build themselves in the designer.   The problem is no available solutions work - especially for the Compact Framework with code in the constructor.

For example,  I have an MVP infrastructure (Model-View-Presenter) in place where my Presenter's baseclass wires up the MVP.   To make this happen (automagically) I have to have a Load() event in my user control - which doesn't exists - so I created one tapping into the ParentChanged event on line 15 below.

 

    1         /// <summary>

    2         /// Constructor

    3         /// </summary>

    4         public usrPatients()

    5         {

    6             InitializeComponent();

    7 

    8             // The ParentChanged += that follows will crash the

    9             // designer (Mobile designer is fragile)

   10             if (DesignMode.IsTrue)

   11                 return;

   12 

   13             // So our UserControl can have an OnLoad event - this

   14             // event fires when the parent form adds the user control

   15             ParentChanged += (sender, e) => { OnLoad(sender, e); };

   16         }

This works now and I'm allowed to use my infrastructure without breaking my Form in the designer!  The usrPatientsPresenter(this, args) statement on line 39 completely wires up my View, Presenter and Model ensuring the Parent form will be notified (w/data) when an event in the user control happens: 

   20         private usrPatientsPresenter _presenter;

   21         public IPresenterBase Presenter

   22         {

   23             get { return _presenter; }

   24             set { _presenter = (usrPatientsPresenter) value; }

   25         }

   26 

   27         /// <summary>

   28         /// Overridden so we have hook into something we can use

   29         /// as a load event

   30         /// </summary>

   31         /// <param name="e"></param>

   32         protected void OnLoad(object sender, EventArgs e)

   33         {

   34             // Instantiate and configure presenter

   35             PatientDataEventArgs args = new PatientDataEventArgs {

   36                 CurrentProviderData =

   37                     ((IViewBase)Parent).Presenter.CurrentProvider

   38             };

   39             _presenter = new usrPatientsPresenter(this, args);

   40             _presenter.cboPatient = this.cboPatient;

   41 

   42             // Subscribe to presenter's event and bubble to form

   43             _presenter.OnNewPatient += (sender1, e1) =>

   44                 { if (OnNewPatient != null)

   45                     OnNewPatient(sender1, e1); };

   46 

   47             // Subscribe to presenter's event and bubble to form

   48             _presenter.OnPatientChanged += (sender1, e1) =>

   49                 { if (OnPatientChanged != null)

   50                     OnPatientChanged(sender1, e1); };

   51         }

Below is the interface that shows what my Form AND UserControl (view) presenters will consistently have available, i.e., OnViewLoad and more importantly OnViewActivated - since user controls load before the main form does:

    7 namespace Library.Mobile.Interface.Interfaces.Base

    8 {

    9     public interface IPresenterBase

   10     {

   11         event EventHandler<EventArgs> OnPresenterActivated;

   12         ProviderData CurrentProvider { get; set; }

   13 

   14         void OnViewReady(object sender, EventArgs e);

   15         void OnViewSet(object sender, EventArgs e);

   16         void OnViewLoad(object sender, EventArgs e);

   17         void OnViewActivated(object sender, EventArgs e);

   18     }

   19 }

Now for the answer we've been searching for (drum roll):

    1 using System;

    2 using System.Linq;

    3 using System.Collections.Generic;

    4 using System.Text;

    5 

    6 namespace Library.Mobile.Interface.Base

    7 {

    8     public sealed class DesignMode

    9     {

   10         public static bool IsTrue

   11         {

   12             get { return AppDomain.CurrentDomain

   13                 .FriendlyName.Contains("DefaultDomain"); }

   14         }

   15     }

   16 }

Please post a link to this Blog if this has cost you countless days of work (as it did me) so we can perhaps save someone else the headaches....

 

Notice

Blog videos and references to CodePlex projects are no longer valid