All posts by GavinS

Escaping Generics with T4 Templates

Originally posted on: http://geekswithblogs.net/gavin/archive/2010/03/13/138501.aspx

I’ve been doing some work with T4 templates lately and ran into an issue which I couldn’t find an answer to anywhere.  I finally figured it out, so I thought I’d share the solution.

I was trying to generate a code class with a T4 template which used generics

The end result a method like:

public IEnumerator GetEnumerator()
            {
                return new TableEnumerator<Table>(_page);
            }

the related section of the T4 template looks like this:

 public IEnumerator GetEnumerator()
            {
                return new TableEnumerator<#=renderClass.Name#>(_page);
            }

But this of course is missing the Generic Syntax for < > which T4 complains about because < > are reserved.

using syntax like <#<#><#=renderClass.Name#><#=<#> won’t work becasue the TextTransformation engine chokes on them.  resulting in : Error 2 The number of opening brackets (‘<#’) does not match the number of closing brackets (‘#>’) 

even trying to escape the characters won’t work: <#\<#><#=renderClass.Name#><#\<#> this results in:

Error 4 A Statement cannot appear after the first class feature in the template. Only boilerplate, expressions and other class features are allowed after the first class feature block. 

The final solution delcares a few strings to represent the literals like this:

<#+
   void RenderCollectionEnumerator(RenderCollection renderClass)
 {  
  string open = “<“;
  string close =”>”;
#>
   public partial class <#=renderClass.Name#> : IEnumerable
        {
            private readonly PageBase _page;
            public <#=renderClass.Name#>(PageBase page)
            {
                _page = page;
            }

            public IEnumerator GetEnumerator()
            {
                return new TableEnumerator<#=open#><#=renderClass.Name#><#=close#>(_page);
            }
        }
<#+
 } 
#>

This works, and everyone is happy, resulting in an automatically generated class enumerator, complete with generics!

Hopefully this will save someone some time 🙂

Custom XSLT for TRX Test Results

Originally posted on: http://geekswithblogs.net/gavin/archive/2009/08/25/134311.aspx

VS 2008 requires you have VS 2008 Test Edition to see the results of a Generic Test, this wasn’t sufficient with out current project as a lot of developers don’t use test edition.  I put together this custom xslt transform to convert the .trx test result file to an html report anyone can view, complete with collapsable sections…

Here is a link to the latest version of the XSLT:

http://yourcomputer.com/TRX2HTML.xslt

Here is the TrxConverter.cs file I use to Generate the html.

http://yourcomputer.com/TrxConverter.txt

Rename it to .cs

 

 

Time to Upgrade the certs..

Originally posted on: http://geekswithblogs.net/gavin/archive/2009/05/12/132066.aspx

Well, I was recently laid off from my Job of 5 years at Sage Software..  Sage has gone through 2 or 3 rounds of layoffs so far, the latest letting go of 500 employees in North America..

…”To help us better bring our costs in line with revenues, we are reducing staff by about 500 positions across the company, which includes employees as well as open positions that are being closed permanently. “

So, I’ve decided to take the opportunity to upgrade my Microsoft Certifications to the latest and greatest..  The last tests I took were in 2004, duting the .net 1.1 release..  Hard to believe it’s been so long..

Here is my current certs:

Microsoft Certification Status

  Credential Certification / Version   Date Achieved
 
  Microsoft Certified Application Developer   May 07, 2004
  For Microsoft .NET   May 07, 2004
  Microsoft Certified Solution Developer   Jun 11, 2001
  For Microsoft .NET   Sep 01, 2004
  Microsoft Visual Studio 6.0   Jun 11, 2001
  Microsoft Certified Professional   Apr 10, 2000

So, I’m going to take:

http://www.microsoft.com/learning/en/us/exams/70-553.mspx

http://www.microsoft.com/learning/en/us/exams/70-554.mspx

These 2 tests will allow me to upgrade my existing MCSD/MCAD to the new MCPD..  After taking these 2 tests I will have to take a few more to upgrade to .NET 3.0-3.5 certs, the MCTS..  I’m not sure right now if I’ll go that far, but maybe I should since I’m doing it.  I’ll have plenty of time if I’m unemployed..

These are all very difficult tests, I work fulltime as a contract developer and have for the last 15 years, but there are so many subjects you get tested on that you just don’t use everyday..  Hence, it will take alot of studying to get upto speed and feel like I can pass them.  Studying is hard, but you are forced to learn stuff that you should probbly know.  I’ve scheduled the above 2 tests for June 3rd, June 4th respectively.

I have yet to fail a Microsoft test, I guess I’ve studied hard enough in the past to make sure I can pass them.  We’ll see how it goes, I’m starting to study now, studying everyday during my lunch hour..

On a side note, If anyone knows of any contract positions available, please let me know.  I live in Phoenix, Arizona, so something local would be preferable, or something I can do remote word work also.  Thanks!

06/30/09 Update – Passed the 70-553, tough test…  Going to take the 70-554 next month..

Writing a UAC compliant Application

Originally posted on: http://geekswithblogs.net/gavin/archive/2008/08/01/124187.aspx

I’ve seen a lot of developers clueless when it comes to UAC in Vista.  The whole point to UAC is give your application the minimum amount of privileges required for it to run.  If you wrote your application, you should have a pretty good idea of what system resources your application needs to access. 

The solution here is not to require your users to “turn off UAC”, or to set your application to run in compatibility mode.  This is the biggest reason UAC has gotten such a bad reputation.. its our fault! Most apps shouldn’t require full privilege to run (with exceptions of course, depending on the app) Don’t claim your application is “Vista-Compliant” because it works if you run it as administrator.  Microsoft is doing a good thing by working to control the privilege an application can have.

This is a good video done by Chris Corio (Windows Security Team) this will give you a good understanding of UAC.

http://www.microsoft.com/emea/msdn/spotlight/sessionh.aspx?videoid=326

The best advice I have is “Run your app as a standard user” see if everything works as standard.  If it doesn’t, why?  What resources are you trying to access that a standard user can’t have?  Are you storing things on the file system, outside of the users App Data Context?  Are you writing to the registry?  If your creating WCF endpoints you will have to run as an admin.

Microsoft has a good tool for seeing how an app runs and what it accesses under different privilege levels, the Vista Application Compatibility Toolkit this app acts as a startup wrapper around your app to run it in different security modes and find warnings, errors, etc.  It can help you find the parts of your application that are requiring a higher level privilege and help you fix them if necessary.

Take it upon yourself to learn more about UAC, Code Access Security and Vista security.  Vista is a great operating system if people would stop complaining and take a minute to learn why security had to change.  The plague of spyware, malware, adware and the like is being cured… way to go Microsoft!

Should I upgrade my Microsoft Certifications ?

Originally posted on: http://geekswithblogs.net/gavin/archive/2008/07/30/124131.aspx

I’ve been debating lately if it’s worth the effort to upgrade my Microsoft Certifications to the latest and greatest.

Microsoft Certification Status

  Credential Certification / Version   Date Achieved
 
  Microsoft Certified Application Developer   May 07, 2004
  For Microsoft .NET   May 07, 2004
  Microsoft Certified Solution Developer   Jun 11, 2001
  For Microsoft .NET   Sep 01, 2004
  Microsoft Visual Studio 6.0   Jun 11, 2001
  Microsoft Certified Professional   Apr 10, 2000

Interestingly, my Microsoft Partner link shows:

  • MCPS
  • MCSD
  • MCAD
  • MCNPS

Not sure where the MCNPS came from… So, yeah… it’s been awhile since I took any tests… I’m certified on .NET 1.1, while 2.0, 3.0 and 3.5 are now out.  To Upgrade:

Developers who use the Microsoft .NET Framework 2.0 and Microsoft Visual Studio 2005 should consider the following two credentials:

These credentials give developers a simpler and more targeted framework to showcase their technical and on-the-job skills.

I have to take 2 exams to upgrade to VS2005:  Exam 70–554 and Exam 70–553  While I do have the experience, I used VS2005 for several years, I’m now using VS 2008 which I would then need:

MCPD: Enterprise Application Development 3.5 and MCTS: .NET Framework 3.5, Windows Forms Applications and MCTS: .NET Framework 3.5, ASP.NET Applications and MCTS: .NET Framework 3.5, Windows Communication Foundation Applications and MCTS: .NET Framework 3.5, ADO.NET Applications

Is it worth it? 

XMLSerializer and Unable to cast type to type

Originally posted on: http://geekswithblogs.net/gavin/archive/2007/07/31/114312.aspx

I recently had a strange problem with XMLSerialization throwing the error: There was an error creating the XML Document.  Unable to cast type Configuration to type Configuration

Here was the simple configuration class:

Serializable]public class Configuration

{

public bool Active;

public string lastPSM = “”;

 }

and the Save method:

public

{

XmlSerializer serial = new XmlSerializer(typeof(Configuration));

TextWriter writer = new StringWriter();

serial.Serialize(writer, config);

Console.WriteLine(writer.ToString());

writer.Close();

}

cant get much easier than that, but everytime i called Serialize I would get the error, so I changed the code to this:

public

{

XmlSerializer serial = new XmlSerializer(config.GetType());

TextWriter writer = new StringWriter();

serial.Serialize(writer, config);

Console.WriteLine(writer.ToString());

writer.Close();

}

Low and behold that fixed it, and now, funny enough, changing the code back to the way it was before works fine now…  Anyone care to share why things like this would happen?  I even tried closing, re-opening studio to make sure something hadn’t gotten whacked…  strange I can’t make it break now while before I couldnt make it work…

Ahhh the joys of development….

.NET State Management, AppDomain, Thread Context

Originally posted on: http://geekswithblogs.net/gavin/archive/2007/07/27/114228.aspx

Maybe I need to re-subscribe to MSDN magazine or something, it seems there are soooo many things you can learn about programming, there is never enough time..  If you spend all your time programming, you never have time to learn about  new stuff.  And even if you learn a ton, things seem to slip by…  It seems everything most of us developers know is because we had to do something at sometime in the past and had to find a way to do it.  If the ways and means we do things are the correct way, who knows..  If it works, great!!!

When you first start programming you start to run into state management and storage issues. You always run into a problem that requires that you store something that something else can make use of.  Say for example you have a list of Cities that you read from a file on disk. So, you can create a new city object, and make a Collection of Cities in your application somewhere to load them into.  As a beginner programmer, I would always start a windows app with some “Control” class which would be my “everything class” something like this:

Public class control
{

private collection cities
private frmForm1 form1
private frmForm1 form2

private void loadcities(){load the file, store the values in the collection}

public void GO()
{
 loadcities();
 form1 = new frmForm1(cities);
 form1.showdialog(); 

 form2 = new frmForm2(cities, form1.SelectedCity);
 form2.showdialog();

}

}

While I agree this is pretty bad…  for a beginner long ago, it served its purpose.  I was able to load the city list once and query state on one form from another without having to read/write anything else to the disk, Or store anything anywhere else for that matter.  I found that by creating this “control” class I had a global place that I could store things and something that would know about both forms.

This type of design leads to a very strictly coupled application.  Nothing can ever change on either form, or in my control class without bad consequences.  Plus you can’t develop object oriented, interface based stuff this way…

Web Developers have been lucky since the asp days as they have a global “state bag”, ie “session”  they can stick things in while navigating from page to page.  But, as far as I knew there was nothing like this for a windows developer, I would always store state in a scenario like the above example, or stick things in a database or the registry for storage.

Enter the AppDomain and the Thread.

While I was always aware these objects existed, they didn’t seem to be something you mess with that often. I had no idea that you could store things in them and provide a global, or thread specific “state bag”.  I can load my cities list and stick it on the Thread Context.

Saving Data to the Thread:

Thread.AllocateNamedDataSlot(“CitiesList”);

LocalDataStoreSlot myData;
myData=Thread.GetNamedDataSlot(“CitiesList”);
Thread.SetData(myData, cities);

Getting it back out:

LocalDataStoreSlot myData;
myData=Thread.GetNamedDataSlot(“CitiesList”);
Collection cities=(Collection)Thread.GetData(myData);

Finally, we need to free the data slot that we allocated in the beginning of our application.

Thread.FreeNamedDataSlot(“CitiesList”);

This allows you to take an object and stick it in the Current thread’s local storage.  You can also do the same thing with the AppDomain, if you need to access your data with mutiple threads of execution.  Just make sure you lock, unlock the objects when your thread is accessing them so you don’t mess up your data by having mutiple thread try to change the values at the same time.

from MSDN:
 // appdomain setup information
        AppDomain currentDomain = AppDomain.CurrentDomain;

        //set predefined system variable application name
        String dataName = “APP_NAME”;
        String setappname = “MyApplication”;
        currentDomain.SetData(dataName, setappname);

        //Create a new value pair for the appdomain
        String dataValue = “ADVALUE”;
        Int32 advalue = 6;
        currentDomain.SetData(dataValue, advalue);

        //get the value specified in the setdata method
        Console.WriteLine(” ADVALUE is: ” + currentDomain.GetData(“ADVALUE”));

        //get system value specified at appdomainsetup
        Console.WriteLine(“System value for application name:” + currentDomain.GetData(“APP_NAME”));

There are some samples and better descriptions than I can give here:

http://msdn2.microsoft.com/en-us/library/system.threading.thread.setdata.aspx
http://msdn2.microsoft.com/en-us/library/system.appdomain.setdata(vs.71).aspx

I’m sure alot of you guys know about this stuff, but maybe someone can learn something… 

If any of you more seasoned guys have some best practices for doing this stuff, please feel free to share.

Cheers!

Dynamic Help Configuration in CAB – Custom Builder Strategy

Originally posted on: http://geekswithblogs.net/gavin/archive/2007/06/05/113008.aspx

Well, I just finished up some work in our CAB app to dynamically associate help with specific CAB smartparts.  I thought it was pretty cool in the end to be able to do this with a Builder Strategy and not have to hardcode all of the help references in each component.

So, there are a few parts to make this work.

The HelpComponent is a serializable type we defined to store help info.

The Help Provider Service will be used to load our stored HelpConfiguration file.

The Help Provider Strategy hooks up the help to the smartparts as they are created.

We also need an interface for the HelpProvider Service:

public interface IHelpProviderService
    {
        Dictionary<string, HelpComponent> HelpComponents { get;}
        void InsertItem(string key, HelpComponent item);
        bool Contains(HelpComponent item);
        bool Contains(string key);
    }
Now we define the serializable type:
    public enum HelpNavigator
    {
        AssociateIndex, Find, Index, KeywordIndex, TableOfContents, Topic, TopicId
    }
    [Serializable]
    public class HelpComponent
    {
        private HelpNavigator _navigationType;
        [XmlAttribute]
        public HelpNavigator NavigationType
        {
            get { return _navigationType; }
            set { _navigationType = value; }
        }
        private String _helpNamespace;
        [XmlAttribute]
        public String HelpNamespace
        {
            get { return _helpNamespace; }
            set { _helpNamespace = value; }
        }
        private String _helpKey;
        [XmlAttribute]
        public String HelpKey
        {
            get { return _helpKey; }
            set { _helpKey = value; }
        }
        private String _componentName;
        [XmlAttribute]
        public String ComponentName
        {
            get { return _componentName; }
            set { _componentName = value; }           
        }
      
        public override string ToString()
        {
            if (String.IsNullOrEmpty(_componentName))
            {
                if (base.ParseType() == null)
                    return this.GetType().ToString();
                else
                    return base.ParseType().AssemblyQualifiedName;
            }
            else
            {
                if (this.ParseType() != null)
                    return _componentName + "::" + this.ParseType().AssemblyQualifiedName;
                else
                    return _componentName;
            }
        }
    }
Ok, so this defines the Serializable type, so we can make an XML file like this:
<HelpConfiguration>
    <HelpComponent TypeName="AdminModule.Editors.NewRelationship, AdminModule"
                 NavigationType="TopicId"
                 HelpKey="722412"
                 HelpNamespace="Help\EntityExplorer.chm"/>
    <HelpComponent TypeName="AdminModule.Editors.NewBusinessRuleStep, AdminModule"
                 NavigationType="TopicId"
                 HelpKey="72248"
                 HelpNamespace="Help\EntityExplorer.chm"/>
</HelpConfiguration>
So, we build the Help Provider Service to Load the saved HelpConfiguration Data into a Dictionary
using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
    public class HelpProviderService : IHelpProviderService
    {
        private Dictionary<string, HelpComponent> helpComponents;
        public Dictionary<string, HelpComponent> HelpComponents
        {
            get { return helpComponents; }
            set {  }
        }
        public void InsertItem(string key, HelpComponent item)
        {
            HelpComponents.Add(key, item);
        }
        public bool Contains(HelpComponent item)
        {
            foreach (KeyValuePair<string, HelpComponent> comp in HelpComponents)
            {
                if (comp.Value == item)
                    return true;
            }
            return false;
        }
        public bool Contains(string key)
        {
            foreach (KeyValuePair<string, HelpComponent> comp in HelpComponents)
            {
                if (comp.Key == key)
                    return true;
            }
            return false;
        }
        public HelpProviderService()
        {
            helpComponents = new Dictionary<string, HelpComponent>();
        }
    }

 Now, when smartparts are created in the normal CAB manner:

 _propertyGrid = ModuleWorkItem.SmartParts.AddNew<PropertyGridToolWindow>();

The Builder Strategy will pick up the creation and dynamically hook-up the help

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.Practices.ObjectBuilder;

    public class HelpProviderStrategy:BuilderStrategy
    {
        private bool _canConfig;
       
        public HelpProviderStrategy()
        {
        }
        public override object BuildUp(IBuilderContext context, Type typeToBuild, object existing, string idToBuild)
        {
            WorkItem wi = context.Locator.Get<WorkItem>(new DependencyResolutionLocatorKey(typeof(WorkItem), null));
            IHelpProviderService _helpProvider = wi.Services.Get<IHelpProviderService>(false);
            if (_helpProvider != null)
            {
                if (_helpProvider.HelpComponents.Count > _helpcomponents.Count)
                { LoadHelpConfiguration(_helpProvider); }
                Control control = existing as Control;
                if (control != null)
                {
                    AddHelpSupport(control);
                }
            }
            return base.BuildUp(context, typeToBuild, existing, idToBuild);
        }
        private void AddHelpSupport(Control c)
        {
            HelpComponent help = _helpcomponents.Find(
                delegate(HelpComponent searchComponent)
                {
                    return searchComponent.ComponentName == c.Name &&
                        c.GetType().Equals(searchComponent.ParseType());
                });
          
            if (help == null)
            {
                help = _helpcomponents.Find(
                    delegate(HelpComponent searchComponent)
                    {
                        return c.GetType().Equals(searchComponent.ParseType());
                    });
            }
            //Assign Help Provider
            if (help != null)
            {
                HelpProvider provider = _providers[help.HelpNamespace];
                provider.SetHelpKeyword(c, help.HelpKey);
                provider.SetHelpNavigator(c, (System.Windows.Forms.HelpNavigator)Enum.Parse(typeof(System.Windows.Forms.HelpNavigator), help.NavigationType.ToString()));
            }
        }
}
}
Don't forget to add the Builder Strategy to you root workitem: 
        protected override void InitializeCommonStrategies(Builder builder)
         {
             base.InitializeCommonStrategies(builder);
......
             builder.Strategies.AddNew<HelpProviderStrategy>(BuilderStage.Initialization);
        }

You may not be able to just copy/paste all the code here and make it work, but if you can follow the example you should get a pretty good idea of how to implement this dynamic help configuration strategy in CAB.

Gavin