softwaregreenhouses.com Blog http://softwaregreenhouses.com/blog nuturing the growth of living abstractions... Mon, 11 Feb 2008 00:09:01 +0000 http://wordpress.org/?v=2.8.6 en hourly 1 Handling .NET Assembly Licenses (.licx, .license) Dynamically at Runtime http://softwaregreenhouses.com/blog/2008/02/01/handling-net-assembly-licenses-dynamically-at-runtime/ http://softwaregreenhouses.com/blog/2008/02/01/handling-net-assembly-licenses-dynamically-at-runtime/#comments Fri, 01 Feb 2008 22:30:45 +0000 Marty Nelson http://softwaregreenhouses.com/blog/2008/02/01/handling-net-assembly-licenses-dynamically-at-runtime/ One of the frustrating things about the .NET licensing system is that although you can embed the licenses into a non-executable assembly, they will not be loaded and recognized at runtime.  The must also be embedded into the running executable.

This can be a real hassle if you are loading types dynamically from dll’s that may contained valid licensed third-party components.

After experimenting a bit, deugging through the LicenseManager, LicenseContext, and other .NET classes using the new nifty VS2008 source files, here is a simple solution that works.  And we didn’t even need to use Reflection :) .

It turns out that when you call GetSavedLicenseKey() on the statically scoped CurrentContext LicenseContext class, it actually reads the embedded licenses keys from the supplied resource assembly and stores them.

Assembly assembly = Assembly.LoadFrom(@”C:\Your\assembly\path”);

LicenseManager.CurrentContext.GetSavedLicenseKey(typeof(string), assembly);

Notice that the type doesn’t matter, it just needs to be a non-null value.  Of course if you have the type, you may end up writing something more like:

Type type = Type.GetType(typeName);

LicenseManager.CurrentContext.GetSavedLicenseKey(type, type.Assembly);

//This will not throw a licensing exception:

object instance = Activator.CreateInstance(typeName);

Enjoy…

]]>
http://softwaregreenhouses.com/blog/2008/02/01/handling-net-assembly-licenses-dynamically-at-runtime/feed/ 1
Part II – Windows Controls Extensibility with .NET 3.5 CLR Add-Ins using WPF and Crossbow http://softwaregreenhouses.com/blog/2008/01/13/part-ii-windows-controls-extensibility-with-net-35-clr-add-ins-using-wpf-and-crossbow/ http://softwaregreenhouses.com/blog/2008/01/13/part-ii-windows-controls-extensibility-with-net-35-clr-add-ins-using-wpf-and-crossbow/#comments Sun, 13 Jan 2008 20:59:03 +0000 Marty Nelson http://softwaregreenhouses.com/blog/2008/01/13/part-ii-windows-controls-extensibility-with-net-35-clr-add-ins-using-wpf-and-crossbow/ In an earlier post, I described a method of hosting windows controls that relied on a hidden form on the add-in side that hosted the add-in control, but appeared in a designated area of the host form.

There has been continued interest in using CLR Add-Ins with Windows Form, see the CLR Team’s post Support for Windows Forms in Hosts and Add-Ins.

While it work well graphically, some of the more detailed integration of ALT+ and CTRL+ keys, tab order, etc. did not work entirely well.

Following the advice of the Jesse Kaplan at the Microsoft CLR Add-In team, I have created a new sample using WPF and Crossbow to handle the pseudo-marshalling of the windows control.

This example uses VS2005 and, other than the add-in pipeline itself, it is, from the perspective of the host and add-in developer, a *pure* Windows Forms experience.

>>Download Solution Here

With the built in adapters for WPF in System.AddIn.Pipeline, in addition to WPF/Windows interop available via Crossbow (or the should I say the project formally know as Crossbow?), the code becomes almost trivial.

Here’s a quick run down of the pipeline:

The Add-In View

[AddInBase]

public interface IAddInControl

{

    Control GetControl();

}

The Add-In Side Adapter

[AddInAdapter]

public class AddInControlVca : ContractBase, IAddInControlContract

{

    private readonly IAddInControl addInControl_;

 

    public AddInControlVca(IAddInControl addInControl)

    {

        addInControl_ = addInControl;

    }

 

    #region IAddInControlContract Members

 

    public INativeHandleContract GetControl()

    {

        WindowsFormsHost host = new WindowsFormsHost();

        host.Child = addInControl_.GetControl();

        return FrameworkElementAdapters.ViewToContractAdapter(host);

    }

 

    #endregion

}

The Contract

[AddInContract]

public interface IAddInControlContract : IContract

{

    INativeHandleContract GetControl();

}

The Host Side Adapter

[HostAdapter]

public class AddInControlCva : ElementHost

{

    private readonly ContractHandle contractHandle_;

 

    public AddInControlCva(IAddInControlContract contract)

    {

        Child = FrameworkElementAdapters.ContractToViewAdapter(contract.GetControl());

        contractHandle_ = new ContractHandle(contract);

    }

}

Consuming The Add-In

Collection<AddInToken> tokens = GetAddInTokens();

foreach (AddInToken token in tokens)

{

    TabPage page = new TabPage(token.AddInFullName);

    tabControl1.TabPages.Add(page);

    Control addInControl = token.Activate<Control>(

        AddInSecurityLevel.FullTrust,

        string.Format(“AddInControlDomain{0}”,

            tabControl1.TabPages.IndexOf(page)));

    addInControl.Dock = DockStyle.Fill;

    page.Controls.Add(addInControl);

}

 

]]>
http://softwaregreenhouses.com/blog/2008/01/13/part-ii-windows-controls-extensibility-with-net-35-clr-add-ins-using-wpf-and-crossbow/feed/ 11
Integrating Testers into the Agile Environment (James Shore @ XP PDX) http://softwaregreenhouses.com/blog/2007/11/10/integrating-testers-into-the-agile-environment-jim-shore-xp-pdx/ http://softwaregreenhouses.com/blog/2007/11/10/integrating-testers-into-the-agile-environment-jim-shore-xp-pdx/#comments Sat, 10 Nov 2007 18:24:23 +0000 Marty Nelson http://softwaregreenhouses.com/blog/2007/11/10/integrating-testers-into-the-agile-environment-jim-shore-xp-pdx/ On October 24th, James Shore gave a presentation to the XP PDX group on testing in the agile environment.  This was part of a series of events Jim is giving in anticipation of his new book co-authored with Shane Warden, The Art of Agile Development.

By using XP practices as a defect prevention measure, defects are much lower than in traditional development environments and fewer tester resources are required.  Jim is seeing in projects that are using this type of agile defect prevention that:

  • Defects have been reduced to “a couple a month.”
  • The ratio of testers to programmers is 1:4, significantly lower than the 2:1 or 1.5:1 ratio seen in large development organizations.

Why It Works

XP agile engineering practices are a way to produce quality code by preventing defects as part of the software development process.  Jim sited two studies to support this position:   

  • The first raised the somewhat paradoxically issue of “More Testing, Worse Quality.”  Essential by increasing the amount of testing resources in an after the fact “find and fix” mode, developers take less responsibility for the quality of their code.
  • The second was a straight-up study of average developers using XP practices and the resulting defect rates were ridiculously lower than industry averages.

Jim then showed how specific XP practices fit into specific categories of defects.

Defects of Intent

These are defects where the code does not work as intended by the programmer.  For example, I write if(foo.IsBar), when I meant to write if(!foo.IsBar).  The XP practices that address these defects are:

  • Test-Driven Development (specifically test-first development)
  • Pair Programming
  • Sustainable Pace
  • Continuous Integration
  • Shared Coding Standards

Defects of Design

The idea here is that areas of design problems or difficulty are the source of most of the defects, “20% of the modules cause 80% of problems.”  These are addressed by:

  • Relentless Refactoring
  • Collective Code Ownership
  • Common System Metaphor
  • Simple Design

Defects of Requirement

This is when what was produced is the wrong thing (even though it may have been done it very well!).  Code works great, but it’s not what was wanted or needed. To make sure the right thing is done well, practice:

  • Sitting with the Customer
  • Iterative (Small) Releases
  • Example Driven Requirements/Customer Acceptance Tests

Role of the Tester in the Agile Environment

Given that the developers are now preventing defects in the first place, what is the role of the Tester?  Jim suggests three primary areas:

  • Finding requirement gaps.
  • Technical investigation (performance, stability, etc.)
  • Exploratory testing.

For the last item, the expectation is that nothing is going to be found.  When defects are found, the team meets to do root cause analysis on why the defect occurred.  What about the process allowed the defect to happen?  Is there a design issue that needs to be addressed?  Is the customer accessible and sitting with the team?  Exploratory testing is intended provide an overall indicator of the health of the quality in the software development process.

 

 

]]>
http://softwaregreenhouses.com/blog/2007/11/10/integrating-testers-into-the-agile-environment-jim-shore-xp-pdx/feed/ 0
Windows Controls Extensibility with .NET 3.5 CLR Add-Ins Using a “Leased-Space” Model http://softwaregreenhouses.com/blog/2007/10/20/windows-controls-extensibility-with-net-35-clr-add-ins-using-a-leased-space-model/ http://softwaregreenhouses.com/blog/2007/10/20/windows-controls-extensibility-with-net-35-clr-add-ins-using-a-leased-space-model/#comments Sat, 20 Oct 2007 15:52:31 +0000 Marty Nelson http://softwaregreenhouses.com/blog/2007/10/20/windows-controls-extensibility-with-net-35-clr-add-ins-using-a-leased-space-model/ Please Read

I wrote this initial example before Jesse Kaplan suggested using WPF and Crossbow to implement Windows Control Add-in integration.  My newer post here describes this technique.  The approach below may still be valid if seen as a *lightweight* technique if the overhead of loading WPF is too great and Hot Key integration is not important.

UI Integration for Add-Ins 

With the release of .NET 3.5 Beta 2, Jack Gudenkauf touted the inclusion of the highly requested UI integration feature for System.AddIns, for WPF only.  While from a .NET 3.5 perspective it looks attractive to leave Windows Forms behind, the reality is that:

  1. Microsoft has done an excellent job making new .NET Framework versions additive and pseudo-backwards compatible, thus it has become easier to use the best of the new without needing to fully migrate to the bleeding edge.
  2. Windows Forms has been around a long time.  There’s plenty of legacy code, and perhaps more importantly, legacy developer skills.

Even with an eventually migration to WPF in the near-term future, I needed a Windows Form extensibility story now.  

Initially, I had conceived of creating a shadow control on the host-side of the add-in boundary, forwarding calls and events to the “real” add-in control and visa-versa.  I quickly became overwhelmed with the number of Control methods, properties, events and had doubts about the threading feasibility of this approach. 

Leased-Space Model

Then I realized that for add-in UI stories, I wasn’t really looking for control level integration.  UI add-ins are more feature based, serving as small components of functionality with often clearly defined input/output contract expectations.  The host-form doesn’t really care how the add-in goes about its control business, as long as it does it in the right place.  A designated control on the host form becomes the marker for the leased space, and any changes to its size and position are tracked. 

Here’s the critical code in the host side adapter:

public void Activate(Control leasedSpace, Form hostForm)

{

    leasedSpace_ = leasedSpace;

 

    //some of these events may be redundant…

    leasedSpace_.Move += LeasedSpaceChanged;

    leasedSpace_.Resize += LeasedSpaceChanged;

    leasedSpace_.SizeChanged += LeasedSpaceChanged;

    leasedSpace_.VisibleChanged += LeasedSpaceChanged;

    leasedSpace_.Parent.Move += LeasedSpaceChanged;

    if (!leasedSpace_.Parent.Equals(leasedSpace_.TopLevelControl))

    {

        leasedSpace_.TopLevelControl.Move += LeasedSpaceChanged;

    }

 

    addInFormHandle_ = addInControl_.Activate(GetPanelRectangle(), new HostFormVca(hostForm));

 

    leasedSpace_.Invalidate();

 

    leasedSpace_.GotFocus += LeasedSpaceFocused;

}

 

private void LeasedSpaceChanged(object sender, EventArgs e)

{

    Rectangle rectangle = GetPanelRectangle();

    if (rectangle != lastUpdate_)

    {

        addInControl_.UpdateLocation(rectangle);

    }

    lastUpdate_ = rectangle;

}

 

private Rectangle GetPanelRectangle()

{

    return leasedSpace_.RectangleToScreen(leasedSpace_.ClientRectangle);

}

 

private void LeasedSpaceFocused(object sender, EventArgs e)

{

    addInControl_.Focus();

}

Dealing with a Rectangle and contract representing the needed information from the host form (more on this later) are easy enough to pass across the add-in boundary:

[AddInContract]

public interface IAddInControlContract : IContract

{

    IntPtr Activate(Rectangle rectangle, IHostFormContract hostForm);

    void UpdateLocation(Rectangle rectangle);

    void Focus();

}

The add-in side adapter creates an independent host form for the control, with all the form borders and trimmings turned off.

public IntPtr Activate(Rectangle rectangle, IHostFormContract hostFormContract)

{

    Application.EnableVisualStyles();

 

    HostFormCva hostForm = new HostFormCva(hostFormContract);

 

    form_ = new AddInControlHostingForm(hostForm);

    form_.FormBorderStyle = FormBorderStyle.None;

    form_.ShowInTaskbar = false;

    form_.Controls.Add(control_);

    control_.Anchor = AnchorStyles.Bottom | AnchorStyles.Left |

        AnchorStyles.Right | AnchorStyles.Top;

 

    form_.Size = rectangle.Size;

    form_.Location = rectangle.Location;

 

    form_.Show(hostForm);

 

    return form_.Handle;

}

 

public void UpdateLocation(Rectangle rectangle)

{

    form_.Size = rectangle.Size;

    form_.Location = rectangle.Location;

}

Simple enough.  Hook up the pipeline, create a test control and away we go.  The add-in form dutifully adheres to the size and location of its associated host control.

Fixing the Bugs

Well, not quite.  There are four UI inconsistencies.  Two of which won’t be relevant until we add menus and toolbars.  The other two are:

  1. Focus.  The title bar on the host form loses focus whenever the add-in’s form is active.  It doesn’t look like a single integrated form.
  2. Layering.  The host form covers the add-in’s form once it regains the focus.  A quick hack is to set the addInForm.TopMost = true.  Nice for a proof-of-concept demo, but not a workable solution.

We’re going to need to deal with WndPrc to sort this mess out.  And there’s an architectural impact:  the host form is going to be customized, meaning we won’t be able to use any Form as our host view.  It will need to be used as the replacement base class for any form that we want to make add-in capable.  At this point, this limitation seems acceptable.

Help From the Internet

While I did spend a few days looking at Console.WriteLine(m) in WndPrc, it was mostly to know enough to know what question to ask to find the right answers.  The maturity of Winows Forms means someone else has mostly likely already been there.  James Brown’s post on creating Docking Toolbars provided the answer to both the focus and layering issue.  It is also the reason that the form handles are passed in both directions.  In the host form, we ignore any deactivation messages if one of the hosted add-in’s form is being activated:

protected override void WndProc(ref Message m)

{

    if (IsDeactivateMessage(ref m) && AddInWindowBeingActivated(ref m))

    {

        m.Result = new IntPtr(1);

    }

    else

    {

        base.WndProc(ref m);

    }

}

So far, there hasn’t been then need to broadcast an activation message to the add-ins’ forms, as they don’t have a displayed title bar.  The add-in’s form merely needs the owner form handle in the show method, and Windows takes care of all the layering issues.  The add-in side adapater for the host form essentially acts as a wrapper to expose IWin32Window.

Menus and Toolbars

MenuStrip and ToolStrip add two more issues to resolve:  click-through (it takes two clicks on a menu or toolbar if the form does not have the active focus) and command keys.  Rick Brewster had already tackled the first issue for Paint.NET (another Toolbar, multi-form environment).  The solution introduces two more derivative classes that must be used on any host form instead of the “normal” .NET controls.

Not Yet Done: Command Keys

Ideally we would have a communication mechanism from the add-in’s form to report Command Keys (Alt, Ctl, etc. combinations) back to the host form for processing.  There’s also some preventative code needed to prevent shenanigans like using ALT+F4 on the add-in’s form.

For some reason, ProcessCmdKey does not fire in the add-in form. Paint.NET has a command key registration implementation that I am looking at.  The pipeline is in place through the HostFormCva class to pass any needed information back to the host form.

One of the reasons I wanted to post this solution is to see if anyone else already had the Windows knowledge to help solve this last problem.

Also, please let me know if you come up with any other UI scenario that need to be mitigated.  I’m curious to know if there are certain controls or hosting situations that break the appearance of a single integrated UI form.

And a Caveat…

If you try and launch the AddIn in a separate process, it hangs when you call Activate().  It does work cross AppDomain, which is the big win for the .NET assembly versioning and unload stories.

Also, the solution is for VS2005, with .NET 3.5 installed of course.

In the code, the sample host form implementation manages the add-in AppDomains and handles AddInToken finding and activation.  The main base class (AddInCapableForm) just takes the leased-space control and an IAddInControl.  It will be up to your process to figure out the best way to collocate or segregate add-ins into AppDomains (a topic worthy of its own blog entry).

Download solution

]]>
http://softwaregreenhouses.com/blog/2007/10/20/windows-controls-extensibility-with-net-35-clr-add-ins-using-a-leased-space-model/feed/ 2