Prism Application Core Scenario Broken In Visual Studio 2013 XAML Designer

October 29, 2013

Since the beginning of October 2013 I’ve been doing a lot of spiking using Visual Studio 2013 and have discovered this is a great product and also has some differences between Visual Studio 2010.

Anyone following this blog knows that I love WPF and patterns & practices Prism Library. Not only the library but the documentation (guidance) for creating composite applications.

As I was converting VS 2010 solutions at work to VS 2013 I started running into problems with my Prism applications and the module views not loading in the XAML Designer and the XAML Editor displaying errors that were not in VS 2010.

I have reported my findings to the XAML Tools Team.

I have a logged a connect bug here:  https://connect.microsoft.com/VisualStudio/feedback/details/806969/prism-application-core-scenario-broken-in-visual-studio-2013-xaml-designer

After a few days I found a workaround for the problem and will share it at the bottom of this post.

Working Prism Core Scenario Visual Studio 2010

See Source Control section below.  The WorkingCoreScenario.zip file should be unzipped and opened using Visual Studio 2010 w/SP1.

A core design practice of composite applications is to break the application into discrete modules (assemblies).  The main application executable will discover the modules at runtime and load them.  The main executable does not have any references to its modules. This very loose coupling of the application and its modules is a core design principle of Prism and composite applications. See Modular Application Development chapter.

The below image shows the pieces of the scenario. Notice that the WorkingCoreScenario assembly does not have a reference to the NotReferencedFormsLibrary. This forms library represents a Prism module that would have all the views and viewmodels for a module.

PrismCoreScenarioSolution

The above App.xaml file contents are shown below.  (NOTE:  I’ve had to break the Source line below because the text is too long to fit.)

Below I’m merging a resource dictionary from the Control Library. This allows the main executable and all modules to reference resources in that compiled assembly.  I typically put images and common resources in a compiled assembly so that the XAML Designer parser does not have to keep parsing the resource dictionary each time it loads a XAML file.

<Application 
    x:Class="WorkingCoreScenario.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary 
                    Source="pack://application:,,,/ControlLibrary;component/Resources/
                            ControlLibraryResourceDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
            <SolidColorBrush x:Key="redBrush" Color="Red" />
            <SolidColorBrush x:Key="yellowBrush" Color="Yellow" />
        </ResourceDictionary>
    </Application.Resources>
</Application>

If you open NotReferencedFormsLibrary UserControl1.xaml in the XAML Designer you’ll see:

WorkingCoreScenarioVS2010Designer

If you open NotReferencedFormsLibrary UserControl1.xaml in the XAML Editor you’ll see:

WorkingCoreScenarioVS2010XAMLEditor

Broken Prism Core Scenario Visual Studio 2013

See Source Control section below.  The BrokenCoreScenario.zip file should be unzipped and opened using Visual Studio 2013 RTM.

If you open NotReferencedFormsLibrary UserControl1.xaml in the XAML Designer you’ll see that neither of the resources App.xaml are available in the XAML Designer.

BrokenCoreScenarioVS2013Designer

If you open NotReferencedFormsLibrary UserControl1.xaml in the XAML Editor you’ll see that none of the resources in App.xaml are available.

BrokenCoreScenarioVS2013XAMLEditor

Discussion and Workaround for Visual Studio 2013

The differences between VS 2010 and VS 2013 have broken a core Prism application scenario. I really like the Prism guidance for creating modules that are not referenced by any other assembly. This very loose coupling promotes well structured and designed applications that are not brittle and will stand the test of time and change.

For now, the only workaround I’ve got to work is to have the main assembly reference each of the modules.  Adding the reference then allows the modules to have access to resources in App.xaml including merged resources.

Source Code

The two above scenarios are in separate zip files on my Oceanware GitHub account.

https://github.com/Oceanware/BrokenPrismCoreScenario

The above repro contains:

  • The BrokenCoreScenario.zip file should be unzipped and opened using Visual Studio 2013 RTM.
  • The WorkingCoreScenario.zip file should be unzipped and opened using Visual Studio 2010 w/SP1.

To create the BrokenCoreScenario solution I simply copied the WorkCoreScenario solution to a machine with VS 2013 and opened it.  No other changes were made.

NOTE:  Prism is not required to open these demo solutions.

Close

Hopes this helps someone and have a great day,

Just a grain of sand on the worlds beaches.


System Process is Locking .exe Files that Visual Studio Builds

October 23, 2013

This has been happening for a while not and I decided to get to the bottom of this very annoying problem.

Problem

I build a solution in Visual Studio, then I rebuild that same solution and get the very familiar error message:

Error 1 Unable to copy file “obj\x86\Debug\MainApplication.exe” to “..\bin\MainApplication.exe”. Access to the path ‘..\bin\MainApplication.exe’ is denied. MainApplication

Root Cause

After many, many of these dumb messages I wanted to see what process would be so aggressive as to want to lock my newly compiled file.

So I fired up Process Explorer (procexp.exe).

First thing you must do is Show Details for All Processes. This action is on the File menu.

The use the Find menu, select Find Handle or DLL…. 

In the Process Explorer Search, enter the full name (no path) of the .exe reported in your above Visual Studio build error message. 

Why Is This Happening

So my questions is, why is the System process PID:4, locking my .exe file?

Currently I have to wait several minutes until the file is no longer locked.  I have noticed that if I have an instance of Windows Explorer open in the build output folder that files get locked more often.

Hint:  Don’t kill System PID:4, your computer will lock up. 

SystemLockingBuiltFiles

Solution

I started thinking about what could be doing this:  Virus, Search Indexer?  Bingo!

I searched for how to throttle the search indexer.  Turns out someone already figure this out.

http://www.sevenforums.com/tutorials/194374-indexer-backoff-enable-disable-windows-7-a.html

One last step may be required.  After performing the above steps, you may need to reboot your computer. 

(Windows team, please provide a setting on the Indexer UI to set throttling, needing a registry entry is not a good solution to this problem.)

So far, this has solved my problem by enabling Indexer Backoff as explained in the above tutorial.

Close

Hopes this helps someone and have a great day,

Just a grain of sand on the worlds beaches.


Visual Studio 2010 Tooltip Assassin

March 29, 2013

I don’t know about you, but the Visual Studio 2010 XAML and C# editor tooltips don’t provide much value.  When presenting they are a distraction. When I collapse a region of XAML and the mouse wonders over the collapsed region I get this enormous tooltip painted over the XAML I’m looking at.

I finally decided to put a stop to this and code tooltip free.

I found this elegant solution provided by Noah Richards that he posted on github:  DisableQuickInfo.

I made one modification to his code by adding a second ContentType attribute to include XAML.

You can download the vsix file below and install or simply use this code to build the project yourself.  If you have Visual Studio 2012 you’ll need to build it yourself.

After installing you view the extensions information in Visual Studio’s Extension Manager.

NoTooltips

Source

namespace QuickInfoAssassin {
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Utilities;

    //Many thanks to Noah Richards and his DisableQuickInfo extension
    // https://github.com/NoahRic/Random/blob/master/DisableQuickInfo.cs

    [Export(typeof(IQuickInfoSourceProvider))]
    [Name("Quick Info Assassin")]
    [Order(Before = "Default Quick Info Presenter")]
    [ContentType("csharp")]
    [ContentType("XAML")]
    internal class QuickInfoAssassinProvider : IQuickInfoSourceProvider {
        public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) {
            return new CancelingQuickInfoSource();
        }
    }

    internal class CancelingQuickInfoSource : IQuickInfoSource {
        Boolean _isDisposed;

        public void AugmentQuickInfoSession(
            IQuickInfoSession session, IList<Object> quickInfoContent,
            out ITrackingSpan applicableToSpan) {
            
            // Dismiss the session immediately.
            session.Dismiss();
            applicableToSpan = null;
        }

        public void Dispose() {
            if (!_isDisposed) {
                GC.SuppressFinalize(this);
                _isDisposed = true;
            }
        }
    }
}

If you are not familiar with creating Visual Studio Editor Extensions MSDN provides a number of walkthroughs to get you going.  I used this one: Walkthrough: Displaying QuickInfo Tooltips.

You’ll need the Visual Studio SP1 SDK to create the project that can be found here.

Download

After downloading change the extension from .vsix.DOC to .vsix. This is a requirement of WordPress. You will also need to Unblock the file using the file properties dialog in Windows Explorer.

Download (QuickInfoAssassin.vsix (40 KB))

Have a great tooltip free day,

Just a grain of sand on the worlds beaches.


Change and Deleted Item Tracking within the Infragistics DataGrid

July 2, 2012

Now that I’m back developing production Line of Business (LOB) applications again, I wanted to share some techniques and challenges that I’ve overcome in our WPF UI.

Our company uses the Infragistics NetAdvantage for WPF product for our WPF UI. We have been very happy with the product, support response and updates. Currently we use the XamRibbon, and XamOutlookBar in our Prism shell; the XamDataChart in our Dashboard; and XamDataGrid in our data entry forms. Our application is in its infancy and as new requirements, features and capabilities are added we will be using more of the controls in the NetAdvantage for WPF full featured suite.

Introduction

For my first post, I thought I would cover an aspect of using the XamDataGrid (all data grids really) that is foundational to LOB applications.

What I’m referring to is tracking the users edits (inserts, updates and deletes) while working in a data grid and then providing the capability to utilize the same database connection to perform the updates, and optionally perform the updates as an atomic transaction.

There are use cases when a user changes data in a data grid, that those changes are immediately reflected back to the database.

Our scenario is one where the design requires that the user be able to make their edits and then commit all the changes all at once. An example of this would be a master-detail use case, when child rows are associated with a master record, e.g. customers, orders, order detail.

In this example, all other development concerns such as data validation, concurrency, actually reading from or writing to a database are not part of the example code; this enables the reader to focus on one technique for tracking inserts, updates, and deletes.

XamDataGrid Requirement

The Infragistics XamDataGrid requires that the data source implement IBindingList in order for the data grid to support adding rows.

Yes, there are techniques for dynamically adding data to your data source without having to do this, but I wanted to allow the data grid to perform its work in a natural way so our data source is derives from BindingList<T>.

Tracking Inserts, Updates and Deletes

When the user deletes a row in the XamDataGrid, the row is removed from the collection and is not longer visible in the UI.

This is where the below ChangeTrackingBindingList<T> comes into play. This class keeps track of the deleted rows by adding a deleted row to an internal collection and then exposing a method (GetDeletedItems) to return those deleted rows when required. If you look below, you’ll see I’ve overridden the RemoveItem method; the implementation adds the deleted row to the internal collection of deleted rows.

It also exposes a method (GetChangedItems) to return only those non-deleted rows that have been inserted or updated.

namespace GridEditing.Infrastructure {
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;

    /// <summary>
    /// Represents the ChangeTrackingBindingList that tracks changes and deleted items.
    /// </summary>
    /// <typeparam name="T">
    /// T: The type of object to provide change tracking binding list services for.
    /// </typeparam>
    public class ChangeTrackingBindingList<T> : BindingList<T> where T : ITrackDirtyEntity {

        IList<T> _deletedItems = new List<T>();

        /// <summary>
        /// Initializes a new instance of the <see cref="ChangeTrackingBindingList{T}"/> class.
        /// </summary>
        public ChangeTrackingBindingList() {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ChangeTrackingBindingList{T}"/> class.
        /// </summary>
        /// <param name="list">The list.</param>
        public ChangeTrackingBindingList(IList<T> list)
            : base(list) {
        }

        /// <summary>
        /// Gets all items in the collection.
        /// </summary>
        /// <returns>
        ///   <see cref="IEnumerable{T}"/> that contains all items from this collection; 
        ///   includes deleted and non-deleted items.
        /// </returns>
        public IEnumerable<T> GetAllItems() {
            return this.Union(_deletedItems).ToList();
        }

        /// <summary>
        /// Gets items that have been changed in the collection.
        /// </summary>
        /// <returns>
        ///   <see cref="IEnumerable{T}"/> that contains items that have been changed; 
        ///   does not include deleted items.
        /// </returns>
        public IEnumerable<T> GetChangedItems() {
            return this.Where(i => i.IsDirty).ToList();
        }

        /// <summary>
        /// Gets the deleted items.
        /// </summary>
        /// <returns>
        ///   <see cref="IEnumerable{T}"/> that contains all items deleted from this collection.
        /// </returns>
        public IEnumerable<T> GetDeletedItems() {
            return _deletedItems;
        }

        /// <summary>
        /// Clears the items.
        /// </summary>
        protected override void ClearItems() {
            base.ClearItems();
            _deletedItems = new List<T>();
        }

        /// <summary>
        /// Sets the item's MarkedAsDeleted property to <c>true</c>. 
        /// Adds the item to the DeletedItems collection. Removes item from list.
        /// </summary>
        /// <param name="index">The index.</param>
        protected override void RemoveItem(Int32 index) {
            var item = this[index];
            _deletedItems.Add(item);
            base.RemoveItem(index);
        }
    }
}

Consuming the ChangeTrackingBindingList<T>

The below MainWindowViewModel exposes the Customers collection. The collection is initialized and customers inserted in the constructor. (please do not populate your collections in your constructors, this is demo-only code)

You’ll notice that after loading the customers, I loop through the collection and set the IsDirty property to false. Your base class for your entity objects should handle this for you, so that when an object is populated from a database, the object is returned from the service layer in a non-dirty state to provide accurate tracking in the UI layer. The below example is over simplified on purpose to show how the view model will process the data once the user saves their changes.

The most important method below is the SaveExecute method that is invoked when the user clicks the Save button. The CanSaveExecute method determines if the collection has been changed or not. Any change to the collection will cause the Save button to be enabled.

Please Note: the code in the SaveExecute method would 99.9999% of the time actually be executing in a service layer. The service layer method would receive the ChangeTrackBindingList<T> as an argument and would use a data layer to process the changes.

Within the SaveExecute method we can see the workflow:

  • Deleted items are removed from the database.
  • Then the inserted or updated items are committed to the database.
  • The view model would then reload the inserted and changed data into the data grid. This reloading refreshing the timestamps that play the role in concurrency and identity columns are populated after an item is inserted and reloaded from the database.
namespace GridEditing {
  using System;
  using System.Diagnostics;
  using System.Linq;
  using System.Windows.Input;
  using GridEditing.Infrastructure;
  using GridEditing.Model;

  public class MainWindowViewModel : ObservableObject {
    ChangeTrackingBindingList<Customer> _customers;
    ICommand _saveCommand;
    Boolean _customersDirty;

    public ChangeTrackingBindingList<Customer> Customers {
      get { return _customers; }
      set {
        _customers = value;
        RaisePropertyChanged("Customers");
      }
    }

    public ICommand SaveCommand {
      get { return _saveCommand ?? (_saveCommand = new RelayCommand(SaveExecute, CanSaveExecute)); }
    }

    public MainWindowViewModel() {
      // load from the service layer
      var list = new ChangeTrackingBindingList<Customer>();
      list.Add(new Customer { FirstName = "Josh", LastName = "Smith", Id = 1 });
      list.Add(new Customer { FirstName = "Sacha", LastName = "Barber", Id = 2 });
      list.Add(new Customer { FirstName = "Brian", LastName = "Lagunas", Id = 3 });
      list.Add(new Customer { FirstName = "Karl", LastName = "Shifflett", Id = 4 });
      foreach (var customer in list) {
        customer.IsDirty = false;
      }
      this.Customers = list;
      this.Customers.ListChanged += (s, e) => _customersDirty = true;
    }

    Boolean CanSaveExecute() {
      return _customersDirty;
    }

    void SaveExecute() {
      // call the service layer, passing the DeleteMarkingBindingList<Customer>
      // the service layer will loop through each item, and either insert it, update it, delete it, 
      // or discard.
      // this is demo code only, but demonstrates the workflow

      foreach (var customer in this.Customers.GetDeletedItems()) {
        // if the Id property is zero then the service layer does not have to do anything
        // if the Id property is greater than zero, the service layer will delete the item.
        // simulate removing from the data base
        Debug.WriteLine(
          String.Format("Customer deleted: {0} {1}", customer.FirstName, customer.LastName));
      }

      foreach (var customer in this.Customers.GetChangedItems()) {
        if (customer.Id == 0) {
          // perform insert in service layer
          customer.Id = this.Customers.Max(c => c.Id) + 1;
          // simulate inserting into the data base
          Debug.WriteLine(
            String.Format("Customer inserted: {0} {1}", customer.FirstName, customer.LastName));
        } else {
          // perform update in service layer
          // simulate updating the data base
          Debug.WriteLine(
            String.Format("Customer updated: {0} {1}", customer.FirstName, customer.LastName));
        }
      }

      // reload the updated records from the database
      // simulate getting all records from the database

      _customersDirty = false;
    }
  }
}

Running the Application

When the application is initially spun up, the Save button will be disabled since no inserts, updates or deletes have taken place.

DisabledButton

After a row has been inserted, the Save button is enabled.

EnabledButton

To the initial data, the following changes have been made.

ChangesMade

When the Save button is clicked, notice the Debug output window. Each of the requested operations are performed; these operations are easily driven by the ChangeTrackingBindingList<T>.

DebugOutputWindow

After the Save is completed, the UI will be updated as below, the Id field has been populated and the Save button is disabled again.

UpdatedRecords

UI XAML – XamDataGrid Tips

The Infragistics XamDataGrid really makes it easy for developers to deliver a full-featured data grid editing experience. This example does not even scratch the surface of the many capabilities of the data grid. In future posts I’ll demonstrate some real-world scenarios with respect to the XamDataGrid’s UI capabilities, for now, let’s stick with tracking the users edits and updating the database.

Tips

1.  By default the XamDataGrid will set string properties to null if the user enters a blank or empty string in the data grid. This is not the behavior I want, instead I need an empty string. This is accomplished using a no-op converter.

Infragistics has made applying the no-op converter a snap by setting ValueToTextConverter property on the XamTextEditor using a style as I’ve done below. In the XamDataGridNullStringPreventionConverter’s Convert and ConvertBack methods I simply return value. The causes the XamDataGrid to set string properties to an empty string instead of the null value.

2.  Take a look down at the XamDataGrid.FieldSettings, you’ll notice CellClickAction has been set to EnterEditModeIfAllowed. The user no longer has to double click a cell to get into edit mode, simply clicking the cell, will put the cell in edit mode.

3.  Making an Id field read-only is straightforward. Have a look at the Id field in the XamDataGrid’s FieldLayout. By setting Id columns FieldSettings.AllowEdit to false, the cells are read-only.

<Window 
    xmlns:local="clr-namespace:GridEditing"
    xmlns:infrastructure="clr-namespace:GridEditing.Infrastructure"
    x:Class="GridEditing.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Data Grid Editing and Deleting" 
    Height="341" 
    Width="608" 
    ResizeMode="NoResize"
    xmlns:igDP="http://infragistics.com/DataPresenter" 
    xmlns:igEditors="http://infragistics.com/Editors">
  <Window.DataContext>
    <local:MainWindowViewModel />
  </Window.DataContext>
  <Window.Resources>
    <infrastructure:XamDataGridNullStringPreventionConverter 
      x:Key="XamDataGridNullStringPreventionConverter" />
  </Window.Resources>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <TextBlock Text="Infragistics Data Grid Editing and Deleting" Margin="11" FontSize="18" />
    <igDP:XamDataGrid 
      Grid.Row="1" Margin="11" 
      DataSource="{Binding Path=Customers}" IsNestedDataDisplayEnabled="False">
      <igDP:XamDataGrid.Resources>
        <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}" >
          <Setter Property="Margin" Value="0" />
        </Style>
        <!--this style is required to prevent null strings from being sent to the model-->
        <Style TargetType="{x:Type igEditors:XamTextEditor}" >
          <Setter 
            Property="ValueToTextConverter" 
            Value="{StaticResource XamDataGridNullStringPreventionConverter}" />
        </Style>
      </igDP:XamDataGrid.Resources>
      <igDP:XamDataGrid.FieldSettings>
        <igDP:FieldSettings CellClickAction="EnterEditModeIfAllowed" />
      </igDP:XamDataGrid.FieldSettings>
      <igDP:XamDataGrid.FieldLayoutSettings>
        <igDP:FieldLayoutSettings 
                    SupportDataErrorInfo="None"
                    DataErrorDisplayMode="None" 
                    AutoGenerateFields="False"
                    AddNewRecordLocation="OnBottom" 
                    AllowAddNew="True" 
                    AllowClipboardOperations="All" 
                    AllowDelete="True" 
                    ExpansionIndicatorDisplayMode="Never" />
      </igDP:XamDataGrid.FieldLayoutSettings>
      <igDP:XamDataGrid.FieldLayouts>
        <igDP:FieldLayout>
          <igDP:FieldLayout.SortedFields>
            <igDP:FieldSortDescription FieldName="Id" Direction="Ascending" />
          </igDP:FieldLayout.SortedFields>
          <igDP:Field Name="Id">
            <igDP:Field.Settings>
              <igDP:FieldSettings AllowEdit="False" />
            </igDP:Field.Settings>
          </igDP:Field>
          <igDP:Field Name="FirstName" Width="200" />
          <igDP:Field Name="LastName" Width="200" />
        </igDP:FieldLayout>
      </igDP:XamDataGrid.FieldLayouts>
    </igDP:XamDataGrid>

    <Button 
      Width="65" Margin="7" Grid.Row="2" Content="Save" 
      Command="{Binding Path=SaveCommand}" HorizontalAlignment="Right"/>

  </Grid>
</Window>

Download

After downloading change the extension from .zip.DOC to .zip. This is a requirement of WordPress.

Download Demo Application (25K)

Requirements

To run the demo application, you’ll need to get the Infragistics NetAdvantage for WPF. A demo version is available here.

Close

There are business frameworks like CSLA that have trackable objects and handle the above scenarios I’ve shown. Currently, I prefer to the simplest solution possible and use the above for tracking user changes within the XamDataGrid.

You can see the amount of very simple code to enable this scenario is small, easy to understand and implement.

Have a great day,

Just a grain of sand on the worlds beaches.


Insidious ByRef Legacy Code Issue

April 24, 2012

The ByRef in the title should give you a hint that this is about legacy VB.NET code.

One of my duties at my new job is to maintain our legacy VB.NET codebase until we deploy our WPF software. When I use the term legacy it should not be taken in a negative manner. Our legacy code runs our company everyday and does it very well.

If you don’t know, VB.NET has a powerful but insidious property on Microsoft.VisualBasic.DateAndTime module called Today. Well, this little beast is a read-write property to the system date.

Yesterday I got a report of an exception that we have never seen before, System.Security.SecurityException; user does not have permission to change the system date.

Over the last few weeks we have been moving from Windows XP to Windows 7 with UAC set at the Default level (as it should be.) We are running in a different, more secure computing environment. The user that reported the issue was upgraded yesterday morning.

After researching the problem it turns out that we had several method calls within our legacy application that were passing Today ByRef. Yes, you guessed it; this caused a call to update the system date each time these methods were executed and returned. In reality no real damage was done; however under Windows 7 with UAC turned on, it caused the above security exception.

Solution

I found every instance of Today in the code and changed it to, Date.Today which is the read-only syntax.  You can also use Today.Date.

If you are maintaining legacy code that you didn’t write and have an unexplained issue, looking at method calls that are passed ByRef might help. 

If you have Today in your VB.NET code, take a look and make sure it’s not being passed ByRef and make sure you code is not mutating it.

Have a great day,

Just a grain of sand on the worlds beaches.


Coding Signing Internal Applications and a Gotcha

April 16, 2012

This blog post explains one way to code sign your internal applications along with their installers. Code signing your applications and installers provide a UAC friendly user experience during installation, uninstall, and when your legacy applications may need to run with administrative privileges (more about admin privileges below).

UAC Friendly Installation Experience

The below image pictures a user friendly UAC dialog, complete with Program name, Verified publisher. If you internal applications are not code signed, the user will get a warning dialog, with a bizarre program name, and Verified publisher set to unknown.

I don’t know about you, but I would rather condition my users to see UAC friendly dialogs, rather than the warning dialog. Next thing you know, they have “accidently” approved a UAC warning that could cause you a big problem.

InstallationUAC

If you are signing applications that are not internal to your organization, the content surrounding certificates and the guidance surrounding signtool.exe may violate your organizations code signing rules or procedures.

This blog post is about code signing internal applications that will be used within your organization.

Code Signing Certificate

The first order of business is to get a code signing certificate installed on machines that will build your internal applications. You can see from the below image, that my certificate server gmcx-Security-CA has issued a code signing certificate and that I have imported that certificate into the “Personal” Store under the “Certificates” folder.

To be honest, creating a code signing certificate that did not have my name on it, instead had our organization’s name is was bit of a PIA and required creating a certificate template on the certificate server that allowed me to do this. I found this TechNet article very helpful:

http://technet.microsoft.com/en-us/library/cc731705(v=ws.10).aspx

Certificate Manager

After you create the certificate, export it and import it on all machines under the users “Personal” store as above.

For example, I have this certificate installed on our two developer machines and on the build server.

Configuring the Solution (executable projects)

There are several ways to configure actions that take place during MSBuilds. I have chosen the “batch file” method because it is very easy to implement and debug. You could leverage one of two out-of-the-box build Tasks or create your own build task, but I chose “batch files” for the above reasons.

Notice that I have checked these batch files into source control. This ensures that all machines can build the solution correctly.

ProjectBatchFiles

AfterBuildTasksDebug.bat

If your scenario requires code signing the debug build, the below batch file uses the signtool.exe program to code sign the .exe program. You “could” also pass in command line parameters to the batch file that would include the folder name of the target along with the target name.  I’ve kept this simple to make it easier to understand all the pieces.

Notice that I didn’t have to specify a certificate, password, etc.  This is because I only have one code signing certificate installed on my machine.  The “/a” switch instructs signtool to automatically pick the code signing certificate from my “Personal” store.

@echo on

call “C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat”

call signtool sign /a “C:\Projects\GMC\Src\GMC\bin\Debug\GMC.exe”

AfterBuildTasksRelease.bat and the Gotcha

Now time for a nasty gotcha. This little beast cost me about 2 hours trying to figure out why, every time I did a Release build using the Setup project to build and create the install package that the .exe the installer installed was not longer signed.

Read this thread on the Windows Dev Center for full details:

Setup project strips digital signature from exe target

Now that you have read the above thread, you’ll fully understand why when creating a release build, you must code sign the .exe under the \obj and \bin folders.

The signtool… commands sign my .exe. Let me call out one additional signtool switch you need to mind when signing your .exe.

You should also specify the “/t” switch. This will time stamp your .exe so the user knows when the .exe was built.

@echo on

call “C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat”

call signtool sign /a /t http://timestamp.comodoca.com/authenticode
   “C:\Projects\GMC\Src\GMC\obj\Release\GMC.exe”

call signtool sign /a /t http://timestamp.comodoca.com/authenticode
   “C:\Projects\GMC\Src\GMC\bin\Release\GMC.exe”


Configuring Visual Studio 2010 to Use the above Batch Files During a Build

BuildEvents

  • Open the Build Events dialog from the .exe project’s properties tab.
  • Change the “Run the post-build event” option to “When the build updates the project output.”
  • Enter the above text in the “Post-build event command line” text box.

This will run one of the two batch files based on the configuration, Debug or Release.

Building the Solution

Like many of you, I don’t build my Release builds within Visual Studio.  Some use a build server, others build them from the command line to allow other tasks to be accomplished.

Below is a fragment of a batch file that I use when building a release build.  The devenv… command rebuilds my solution. Notice the “/rebuild” switch instead of the “/build” switch.

The signtool… command signs my .msi installer that the Setup project built. Let me call out two additional signtool switches you need to mind.

It is important that you specify the “/d” switch for your .msi installers. If you scroll back up to the top of this blog post and view the UAC image, you’ll notice the Program name matches the text in the below “/d” switch. If you don’t specify this, your user will see some bizarre text.

You should also specify the “/t” switch. This will time stamp your installer so the user knows when the installer was built.

@echo on

call “C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat”

devenv /rebuild Release /project GMC_Setup C:\Projects\GMC\Gmc.sln

echo .
echo .
pause

signtool sign /a /d “GMC for Office 2010 Setup” /t http://timestamp.comodoca.com/authenticode
   C:\Projects\GMC\Src\GMC_Setup\Release\GMCForOffice2010_Setup.msi

… additional tasks

Legacy Applications Running on Windows 7 and Above

My company has a legacy Windows Forms application that was written during the days of Windows XP.  My company like many other enterprises never installed Windows Vista.  Recently we installed Windows 7 on our enterprise desktops.

Well the legacy enterprise applications I’ve inherited do things are are not UAC friendly.  For example, writing to the \Program Files folder and other tasks that are now under Windows 7 considered taboo.

Being a good Enterprise Administrator and Developer, I want all my clients running Windows 7 with UAC set to the Default setting and for my users to learn about the UAC feature and its benefits; this will provide them a safer computing environment here at work and at home.

Microsoft has documented UAC here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa511445.aspx  

Microsoft and bloggers have documented a number of strategies for dealing with UAC and legacy applications.  Turning UAC off or limiting its capabilities should not be considered a good option.

I was not willing to take on the risk of modifying our legacy applications, so I run my few enterprise applications with an embedded application manifest that tells the operating system this application requires administrator privileges to execute. All of our users are administrators on their local computer.

Example Application Manifest

Notice the the below application manifest that the “requestExecutionLevel” is “requireAdministrator.”

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>
  <assemblyIdentity version=”1.0.0.0″ processorArchitecture=”X86″ name=”GMC” type=”win32″/>
  <trustInfo xmlns=”urn:schemas-microsoft-com:asm.v3″>
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level=”requireAdministrator”/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

To embed the above application manifest you need to use the mt.exe program. I placed the below command at the top of my two batch files, AfterBuildTasksDebug.bat and AfterBuildTasksRelease.bat.

You’ll need to edit the paths and .exe name as well as the manifest name.

call “C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\mt.exe” -manifest
   “C:\Projects\GMC\Src\GMC\GMC.exe.manifest”
   -outputresource:”C:\Projects\GMC\Src\GMC\bin\Debug\GMC.exe;#1″

Close

For those of you that have the need or desire to code sign your internal enterprise applications, I hope this blog post will help you avoid the long learning curve.

Have a great day,

Just a grain of sand on the worlds beaches.


Boise Code Camp Prism, Ocean 3 Session

March 24, 2012

The links to the code presented at the Boise Code Camp is in the below Downloads section.

This links include Ocean 3 and a modified Prism 4 library that has two new features.

The Ocean 3 solution includes a Prism Ocean Demo application that shows off Ocean working with Prism. In a later release, I’ll add database demonstration code as well that uses the new and improved Service<T> and Repository<T>.

The demo application shows off:

  • WPF Ribbon being populated by a Prism Region; when forms are navigated to, their respective ribbon tabs are automatically rendered.
  • Automatic view/view model wiring up by the Unity container. No view or view model navigation registrations required.
  • Automatic setting of the correct IRegionManager on all view models; this region adapter does not draw the IRegionManager out of the IoC container, instead it uses the one assigned to the view. This technique prevents the incorrect IRegionManager being assigned in cases of child windows or scoped regions.
  • Demonstration of a child window hosting a form; that same form can be shown within the shell or child window requiring no form or view model modifications to function correctly; i.e. no “if in popup then do this code.”
  • When views are navigated away from, the currently focused control is cached; when that same instance of that form is navigated back to, focus will automatically be set to the correct control.
  • Queued dialog service for forms.
  • The view modal dialogs are asynchronous, by not blocking the UI thread, a form that has a dialog displayed, can be navigated away from and navigated back to.
  • When a view has a view modal dialog displayed, the views ribbon tabs are automatically disabled.
  • Ocean FormControl that provides many services for LOB forms.
  • Ocean FormNotificationControl that shows the form status from a validation perspective.
  • Ocean provides a comprehensive validation stack.
  • In addition, many small features are also shown.

I’ll release a new version of BBQShack soon, PrismBBQShack. This is a complete end-to-end store application that will show off all features of Ocean 3 (like the data stack) and will have a Win8, WinRT XAML touch-enabled point of sale application.

Downloads

After downloading, you MUST read the READ ME NOW.txt file in the Acme.Example solution.

After downloading, you must rename the to downloads from .zip.doc to .zip.  This is a requirement of Word Press.

Ocean 3

Modified Prism 4

To use the modified Prism 4 download, after unzipping, go to the \Prism\Prism4\ folder and run these two batch files:

  • Run Update Prism Binaries.bat
  • RegisterPrismBinaries.bat

They will rebuild the supplied modified Prism 4 and will register this version of Prism in the registry so that you can use the Add References dialog. This modified version of Prism will work with any current Prism application as no API’s were removed or changed, only added.

Have a great day,

Just a grain of sand on the worlds beaches.


Follow

Get every new post delivered to your Inbox.

Join 245 other followers