Thursday, November 17, 2011

My Play

In this week’s This Developers Life, they discussed Play. Not to be out done, I thought I would write about my own play patterns. It was fun to hear about the race car driver and the home manufacturer, I want to hear more. To promote dialog, I am presenting my story.

Improv

Almost 2 years ago, I started taking Improv classes at the Blue Door Theatre in Spokane because I heard about some consultancy in New York City that provided Improv classes to all their consultants. The local NPR station announced the class on their arts calendar and I just said what the F# and I took the class. At that point I had never even seen live Improv.

Like many programmers, I have an Aspergers personality. This serves me well when I am actually doing my core job; for the rest of my life, not so much. Improv gives me a chance to play at being in the world where everyone else lives. It gives me the opportunity to playing at being an extrovert.

Through something we call “Yes, And”, I am learning to accepting the current situation and adapting to the current situation. And I am learning to do it quickly. As a programmer, I like to work carefully and look for the perfect solution; in Improv I just don’t have the time. (The programmer in me is telling me that this blog post isn’t good enough; if it wins, no one else will ever read this.)

Am I taking Improv to become a great actor and become famous? No. My chances of ever performing Improv in public: about 50/50 (based on the fact that most of us underestimate our own talents). Do I really care? Do you take Kung Fu to fight? If memory serves me right, Cane was able to avoid fighting as much as he fought. I have presented at Code Camps 5 times since I started Improv.

Technology

My work project is frozen to the technology that existed when it was started. I like to play with the new stuff. I have Windows 8 installed on my laptop. I am slowing working my way through WPF 4 Unleashed. I am looking into writing for the Android Tablet. No, this is an extension of work.

Music

I have a guitar, a bass and a keyboard that I attempt to use to make sounds with. In the past I found that the guitar to be a great stress reliever. On second thought I haven’t really even touched these things since I started Improv. Since classes don’t start up again until next year, I would take out an instrument and …

Christine

I have a 1982 Supra that I have tried to keep alive for the last dozen or so years. Due to some poor financial decisions on my part, I haven’t done much with her for the past couple of years. My dream is to restore her on YouTube. Yes, her name is a reference to the Stephen King book.

Wednesday, November 09, 2011

Tablets and Open Source Voting Software

Yesterday on NPR, they had a short piece on iPad Voting. I don't like modern voting machines because of the closed nature of their software; very few people know what is going on inside those things.

If I had my way, the voting software would be written as an open source project. The voting machines would be common hardware that could be used in schools after election season. On Election Day morning, representatives from all interested parties would download the source from the project's site, build, run unit tests, install the software and generally verify that the software is correct.

The hardware would probably be tablet computers. Right now the market would be iPad, Android and, coming soon, Windows Metro. I would imagine that each vendor would sponsor voting machine projects that use their hardware. When the local community center would buy tablet computers of some after school program, the quality of its open source voting software may affect the buying decision. You wouldn’t need to buy new hardware every election cycle, schools could go without the iPad for the first week of November (“Hey kids, this is a ‘yellow pad’, we used these in the 20th century”).

Monday, October 31, 2011

Windows 8 and Fear of Change

For Halloween, I will discuss Windows 8 and Metro. I hear lots of fear and loathing in regard to Microsoft’s strategy regarding Windows 8 and the tablet.

I’ve heard horror stories about how we will be forced to throw away all we’ve learned the last 10 years and learn to write apps in HTML5 and JavaScript. Tales that Silverlight is doomed to the bone yard and so on … In short, the technology world changing and all our skills will be null and void. In our next job, we will need to rehearse the phrase: “Do you want fries with that?”

Come on, part of being a developer is dealing with change and uncertainty. In the mid 1990s, we went from DOS and character based computers to the GUI Land of Windows 95. In the early 2000s it was .NET for everyone in Windows Land. And now there are rumors of doom about what Microsoft is up to with Windows 8.

Part of the bargain of working in this business is change; we get to work on the cool new things and we have to work on the cool new things. We spend more time keeping up, learning things we need to be up to date. By choosing what to learn, we are also placing bets on winners and losers. If I study Window 8, I am betting for Microsoft and against Google and Apple. Of course, I could hedge my bet by studying both Window 8 and Android (that would reduce my potential reward.

Windows 8 etc.

Windows 8 (WinRT, Metro, etc.) represents to response to iOS and Android tablets. I don’t know if Windows 8 will preserve the market share that Microsoft has enjoyed with Windows for the past generation. I don’t know if Windows 8 will be a second Vista. It is even possible that this is the beginning of the end of Windows or even Microsoft.

I can’t say that Microsoft is late to the Tablet game. There was the PocketPC that was a small tablet that used a “pen” and there was a tablet version of Windows XP (also used a “pen”). These are pen tablets, the cool new tablets are touch tablets.

Microsoft is taking a different approach than Apple. Apple has two Operating Systems: iOS for tablets and devices and OSX for full blown computers. Microsoft is going with One OS to Rule Them All: Windows 8 will be on desktop and little tablet devices. I suppose WP8 will be Windows 8.

There are as many changes in the other platforms. Change defines our industry. Every change represents risks to all participants. Not changing also represents risks. This is just part of the job.

Sunday, September 25, 2011

Filtering files by Date Range

In this For Work post I am wrote a function that will return a list of files (FileInfo objects actually) for a given search string and date range.

The Problem

My internal customer wants archive files in a given directory for a given date range. Right now I am working on the part where I get the files; the rest of the problem is beyond the scope of this post.

My Solution

I am using FileInfo.GetFiles() to get a list of FileInfo objects for a given filename filter and then use Linq to filter that list for the date range.

So here’s my function:

/// <summary>
/// Returns a List of FileInfo for a given serch pattern and date range.
/// </summary>
/// <param name="searchPath">
/// The path + the search string
/// </param>
/// <param name="startDt">
/// The beginning date for the search (as of midnight)
/// </param>
/// <param name="endDt">
/// The end date of the search (as of midnight;
/// use DateTime(y, m, d 23, 59, 59) to get the whole day)
/// </param>
/// <param name="searchOp">
/// Specifies whether to search the current directory, or the current directory
/// and all subdirectories.        
/// </param>
/// <returns>
/// A List of FileInfo
/// </returns>
public static List<FileInfo> SearchFiles(string searchPath, DateTime? startDt, 
    DateTime? endDt, SearchOption searchOp)
{
    // Break searchPath into parts
    string directory = Path.GetDirectoryName(searchPath);
    string pattern = Path.GetFileName(searchPath);

    // DirectoryInfo exposes GetFiles used below
    var dinfo = new DirectoryInfo(directory);
    // Get all of the files that meet the criteria
    var finfol = new List<FileInfo>(dinfo.GetFiles(pattern, searchOp));

    // Throw out the files that are out of the date range
    // Here is where I would add aditional filters
    return new List<FileInfo>(
        from f in finfol
        where (f.LastWriteTime >= (startDt ?? DateTime.MinValue)) &&
              (f.LastWriteTime <= (endDt ?? DateTime.MaxValue))
        select f);
}

Thursday, August 18, 2011

Creating Simple Form Item Template for VS 2008

In this For Work blog entry, I am going to create a Visual Studio Item Template for a Windows Form. We have several patterns of forms that we need to create over and over again. I want to be able to create my own Form with all my setting set by default, include some standard controls and derive from my base class, etc.

I am not using Export Template because I want to see all the working parts.

The Process

Create a Starter Form

Create a form that has everything I want in my template in a WinForm project. In this case I will pretend that we created a WinForm called MyForm.cs.

Gather the Template Files together

I created a directory somewhere on the file system and copy the form’s source files into that directory. Add to those files an ico file and a new text files with a .vstemplate extension. So for my template, I would put the following files”

MyForm.cs The Form’s code file. Not yet changed, will replace class name and namespace later.
MyForm.Designer.cs The Form’s designer code files. Will also need replace class name and namespace.
MyForm.resx (Optional) Form’s resources, In this example, I use this to set a different icon.
BICYCLE.ICO The Icon file that appears in the Add New Item dialog
MyFormCS.vstemplate Empty file. Will be the Template metadata file.

Add/Replace Template Parameters in Source files

In the process Template Parameters are substituted with values created by the New Item Wizard when the new item is created. They are declared in the form of $parameter$

In my demo, I use the following Template Parameters:

rootnamespace The full namespace of the item; “root” namespace suggests something different
safeitemrootname The name of the item (or class) being created.

So given the following code:

using System; using System.Windows.Forms; namespace ItemTemplatePlayGround { public partial class MyForm : Form { public MyForm() { InitializeComponent(); } …

I change the code to read:

using System; using System.Windows.Forms; namespace $rootnamespace$ { public partial class $safeitemrootname$ : Form { public $safeitemrootname$() { InitializeComponent(); }  

Fill out the .vstemplate file

The .vstemplate file contains most the metadata that Visual Studio needs use my template. Things like the name and description of the template, the icon that is displayed in the new New Item dialog, the project type, etc. It also contains a list of all the files that make up the templates and instructions on how to handle them. (NOTE: the physical location of the template file determines the Template’s “Language” and “Category”, so I can’t claim that it contains all the metadata).

Notice that Template Parameters appear in the .vstemplate file.

<VSTemplate Type="Item" Version="2.0.0" 
            xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <TemplateData>
    <Name>My Lame Form</Name>
    <Description>An empty Form</Description>
    <DefaultName>MyForm.cs</DefaultName>
    <ProjectType>CSharp</ProjectType>
    <Icon>BICYCLE.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <ProjectItem TargetFileName="$fileinputname$.cs"  
                 ReplaceParameters="true" 
                 SubType="Form">MyForm.cs</ProjectItem>
    <ProjectItem TargetFileName="$fileinputname$.Designer.cs"  
                 ReplaceParameters="true">MyForm.Designer.cs</ProjectItem>
    <ProjectItem TargetFileName="$fileinputname$.Designer.resx"
                 ReplaceParameters="true">MyForm.Designer.resx</ProjectItem>
  </TemplateContent>
</VSTemplate>

I have chosen not to go over every detail of the .vstemplate file. There are denser articles on the web that cover them in painful detail.

The TempateData section gives data about the template as a whole. Name and Description are what you think they are. DefaultName is used to propose a name in the Add New Item dialog. ProjectType is the language of the item; either CSharp or VisualBasic. Icon refers to the icon (.ico) file that provides the icon next to the project type name in the New Item dialog.

The TemplateContent contains ProjectItem elements for each of the files in the template (except the icon file and the .vstemplate itself). If your project contains 5 files total, there should be 3 ProjectItem elements.

Within the ProjectItem element, the TargetFileName attribute is the name of the new file created by the template. ReplaceParameters determines if Template Parameters in this file are replaced. SubType determines the Visual Studio Editor used to design this file; you only need this attribute if this file uses a designer. The Element’s inner text represents the name of the file within the template itself. The element value is the before file name and the TargetFileName is the after.

Where are my template files?

The default your item template files are located in My Documents\Visual Studio 2008\Templates\ItemTemplates\Language. On my system, Visual Studio 2008 was looking in C:\Users\jacks\Documents\Visual Studio 2005\Templates\ItemTemplates. So, it is a good idea to make sure that Visual Studio is looking in the right place.

To check/change the template location: Tools => Options, select the Projects and Solutions group and the General tab.

Links

Finished Template

Saturday, July 23, 2011

Generate several files from one template with the T4 Toolbox

I have been playing with using T4Toolbox to generate more than one file from a single template within Visual Studio.

T4Toolbox.Template

The Template class is the T4Toolbox’s version of TextTransformation that has a very special method called RenderToFile(); this method writes the text to be generated to a file. So, If I wanted to generate a file for each item in a list (say a list of database tables), I could use a foreach loop to create a new instance of my Template class and call Its RenderToFile method with different file names.

<#@ template language="C#v3.5" hostSpecific="true" #>
<#@ output extension="txt" #>
<#@ include file="T4Toolbox.tt" #>
<#
    Write("This file (minimum.txt) is also generated");
    for (int i = 7; i <= 11; ++i)
    {
        string fileName = string.Format("file{0:00}.lam", i);
        var lt = new LameFileTemplate(fileName);
        lt.RenderToFile(fileName);
    }
#>
<#+
private class LameFileTemplate : Template
{
    public LameFileTemplate(string fileName)
    {
        this.FileName = fileName;
    }
    private string FileName {get; set;}
    public override string TransformText()
    {
        #><#=this.FileName#><#+
        return this.GenerationEnvironment.ToString();
    }
}
#>

When I save this file, Visual Studio runs the template and creates several files. Notice that creates a file that matches the file name of the template; this can’t be helped. Since the default output extension is “cs”, it is important to set this to something else.

image
My template and generated files

NOTE: In a failed demo that I gave at the Portland Code camp this spring I wrote a template that would create a SELECT stored procedure for each table in a given database (each in its own file). The demonstration was too complicated and hard to follow. It used the Generator class SMO and a bunch of other stuff.

Thursday, June 23, 2011

The GAX Property Directive

One of the things that really bother me about T4 templates is the lack of direct parameter support (at least in the Visual Studio 2008/.NET 3 timeframe).

In an earlier post, I passed parameter by writing the parameter data to a file outside of the template and reading the data from within. I used a common assembly linked to both sides of the divide. This works for me, but it is really hacky.

GAX Template Host

During my preparation for my Portland Code Camp presentation, I came across Guidance Automation Toolkit for Visual Studio 2008. It has its own TemplateHost that includes a Dictionary of parameters.

Parameters are exposed to the Template through a custom directive. On the template, the parameter is declared using a directive like this:

<#@ property processor="PropertyProcessor" name="MyName" type="String" #>
The directive contains the following parts:
processor Should be "PropertyProcessor" (there may be a way to write your own processor, I haven’t gone down that rat hole yet).
name The Variable name that can appear in your code. It works just like a variable, however, tangable T4 Editor doesn’t provide Intenesence (I wouldn’t have expected it).
type Any .NET Type that the template knows about. You should use the .NET type name (as opposed to C# or VB.NET type).
In C# the parameters are created like this:
var arguments = new Dictionary();
arguments.Add("MyProperty", new PropertyData("String", typeof(string)));
To pass parameters from your code you need to create a Dictionary<string, PropertyData>, add your parameters and pass them as the second argument into the TemplateHost constructor (the first can be any string as far as I can tell).

Simple Sample

The Template

<#@ template language="C#" debug="True" #>
<#@ output extension="txt" #>
<#@ assembly name="System.dll" #>
<#@ import namespace="System" #>
<#@ property processor="PropertyProcessor" name="MyProperty" type="Nullable<Int32>"#>
<#@ property processor="PropertyProcessor" name="MyName" type="String"#>
My Property Test
<# if (MyProperty.HasValue) {#>
Property Value: <#= MyProperty.Value #>!
<#}#>
Name: <#= MyName #>

C# code

static void Main(string[] args)
{
    // Prepare template parameters
    var arguments = new Dictionary<string, PropertyData>();
    arguments.Add("MyProperty", new PropertyData(42, typeof(int?)));
    arguments.Add("MyName", new PropertyData("Jack Stephens", typeof(string)));

    // Initialize GAX template host
    // The Template Host is from GAX, not the default host
    var host = new TemplateHost("Random String", arguments);
    host.TemplateFile = Path.Combine(Directory.GetCurrentDirectory(), 
        "PropertyTest.tt");

    // Transform template
    string template = File.ReadAllText(host.TemplateFile);

    ITextTemplatingEngine engine = new Engine();
    string output = engine.ProcessTemplate(template, host);

    Console.Write(output);
    Console.ReadKey();
}

References