Monday, November 05, 2007

It is, if I am not mistaken, the year 2007.  Why is it that my fancy-pantz hotel room in downtown Atlanta does not just come with Internet access?  Why, further, do they outsource to these companies who's systems seem unerringly to not work the first time?  I don't travel a lot, but I have yet to have Internet access work in a room without calling the front desk or "iBahn" or whatever.  Business travelers flying business class staying in business hotels asking for the corporate rate are highly likely to expect to plug their laptops into the wall and have it work.

Monday, November 05, 2007 9:24:30 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Thursday, November 01, 2007

There are various little gotchas writing software for Vista.  I've posted before about ridiculous things like logging not working.  You must use the Admin token to write to the Program Files directory so in some cases your program will silently fail and create no logs.  I've also been looking for a way to elevate a single action from .NET: an application that can run without elevation but has a button with the cute shield icon that invokes an action that requests elevation from the user.  At any rate, I just switched to Enterprise Library from log4net and had to get it to produce log files in a User location rather than \program files\myprogdir and the configuration (though the tools are nice) do not support this.  Luckily Enterprise Library 3.1 comes with the source so I dug around and found what to do.  To save you the trouble.

I'm using RollingFlatFileTraceListener.  This class only has one constructor:

public class UserScopeRollingFileListener : Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener
{
public UserScopeRollingFileListener(string fileName, string header, string footer, ILogFormatter formatter, int rollSizeKB, string timeStampPattern, RollFileExistsBehavior rollFileExistsBehavior, RollInterval rollInterval)
: base(GetUserScopedFilePath(fileName), header, footer, formatter, rollSizeKB, timeStampPattern, rollFileExistsBehavior, rollInterval)
{
}

protected static string GetUserScopedFilePath(string logFileName)
{
string path = logFileName;
if (Environment.OSVersion.Version.Major > 5)
{
string homeDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
path = System.IO.Path.Combine(homeDir, logFileName);
}

return path;
}
}

So, in the constructor call the GetUserScopedFilePath().  If the OS is Vista, it takes the log file name from the app.config file and maps it into My Documents.  It could just as easily be Local Application Data or something else.  The Logging configuration uses a "Data" class associated with each listener to build to the listener class.  This seems odd since this Data class explicitly invokes the constructor of the Listener even though the configuration requires the Type of the listener to be present in the app.config.


/// <summary>
/// Represents the configuration data for a <see cref="RollingFlatFileTraceListenerData"/>.
/// </summary>    
[Assembler(typeof(UserScopedRollingTraceListenerAssembler))]
public class UserScopedRollingTraceListenerData : Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData
{
public UserScopedRollingTraceListenerData()
{
}
}

/// <summary>
/// This type supports the Enterprise Library infrastructure and is not intended to be used directly from your code.
/// Represents the process to build a <see cref="RollingFlatFileTraceListener"/> described by a <see cref="RollingFlatFileTraceListenerData"/> configuration object.
/// </summary>
/// <remarks>This type is linked to the <see cref="RollingFlatFileTraceListenerData"/> type and it is used by the Custom Factory
/// to build the specific <see cref="TraceListener"/> object represented by the configuration object.
/// </remarks>
public class UserScopedRollingTraceListenerAssembler : RollingTraceListenerAssembler
{
public UserScopedRollingTraceListenerAssembler()
{
}

/// <summary>
/// This method supports the Enterprise Library infrastructure and is not intended to be used directly from your code.
/// Builds a <see cref="FlatFileTraceListener"/> based on an instance of <see cref="FlatFileTraceListenerData"/>.
/// </summary>
/// <seealso cref="TraceListenerCustomFactory"/>
/// <param name="context">The <see cref="IBuilderContext"/> that represents the current building process.</param>
/// <param name="objectConfiguration">The configuration object that describes the object to build. Must be an instance of <see cref="FlatFileTraceListenerData"/>.</param>
/// <param name="configurationSource">The source for configuration objects.</param>
/// <param name="reflectionCache">The cache to use retrieving reflection information.</param>
/// <returns>A fully initialized instance of <see cref="FlatFileTraceListener"/>.</returns>
public override TraceListener Assemble(IBuilderContext context, TraceListenerData objectConfiguration, IConfigurationSource configurationSource, ConfigurationReflectionCache reflectionCache)
{
UserScopedRollingTraceListenerData castObjectConfiguration
= (UserScopedRollingTraceListenerData)objectConfiguration;

ILogFormatter formatter = GetFormatter(context, castObjectConfiguration.Formatter, configurationSource, reflectionCache);

UserScopeRollingFileListener createdObject
= new UserScopeRollingFileListener(
castObjectConfiguration.FileName,
castObjectConfiguration.Header,
castObjectConfiguration.Footer,
formatter,
castObjectConfiguration.RollSizeKB,
castObjectConfiguration.TimeStampPattern,
castObjectConfiguration.RollFileExistsBehavior,
castObjectConfiguration.RollInterval
);

return createdObject;
}
}

Now, if you used the Enterprise Library configuration tool to create the RollingFlatFileListener configuration, you need to make two changes:

<listeners>

<add fileName="MyLogFileName.log" rollSizeKB="0" timeStampPattern="yyyy-MM-dd"

rollFileExistsBehavior="Overwrite" rollInterval="None" formatter="Text Formatter"

header="" footer=""

listenerDataType="MyNS.MyNS.UserScopedRollingTraceListenerData, MyAssembly.Name"

traceOutputOptions="None"

type="MyNS.MyNS.UserScopeRollingFileListener, MyAssembly.Name"

name="Rolling Flat File Trace Listener" />

</listeners>

One other thing I wanted to change about the logging, is that I like the log4net syntax for different log levels.  You would get an ILog implementation and call log.Debug(message) or log.Error(message) or log.Fatal(message).  With the joy of Extension Methods you can create your own on-the-fly facade with the compiler doing most of the work:

    public static class LogExtensions

    {

        static void Debug(this LogWriter l, string message)

        {

            LogEntry entry = new LogEntry();

            entry.Message = message;

            entry.Severity = System.Diagnostics.TraceEventType.Verbose;

            l.Write(entry);

        }

 

        static void Error(this LogWriter l, string message)

        {

            LogEntry entry = new LogEntry();

            entry.Message = message;

            entry.Severity = System.Diagnostics.TraceEventType.Error;

            l.Write(entry);

        }

    }

So extension methods now allow me to say Logger.Writer.Error("An error has occurred: value was null").  I am now happy with the Logging application block.

Thursday, November 01, 2007 8:36:15 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [3]  |  Trackback

I'm enjoying Enterprise Library right now, especially the unexciting yet very useful Logging and Caching application blocks.  In the past I have used things like log4net, but the configuration tool that comes with Enterprise Library 3.1 is enough reason to use EL by itself. 

Thursday, November 01, 2007 3:55:06 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, October 31, 2007

One of my co-workers has decided to get with the 00s and start blogging.  Introducing David Snopek!  He is not a .Net developer, yet: silverlight+mono+DLR will win over even some diehard Microsoft haters.  David is my favorite sparring partner at CarSpot, so hopefully we can take our disagreements into the blogosphere for your entertainment.

Wednesday, October 31, 2007 1:06:09 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, October 21, 2007

I'm sitting at my kitchen table tonight burning about a dozen podcasts for my commute.  For a while I stuck to Dot Net Rocks but I've been throwing in the occasional Hanselminutes and Audioholics into the mix as well.  Tonight is the first time in a while I donn't truly have to do anything right now.  I still can't make any public announcements on the work situation but suffice to say my typical day is go to work --> pick up daughter --> put kiddo to bed at 8pm --> work till 12pm; throw in some required travel and marathon meetings and I'm more than a little tired.  I have two solid, relevant articles I need to complete and just haven't had the time.  In the next two weeks I'll be getting our new WPF based product into a demoable state and preparing for a talk in front of 600 people in Atlanta.

Tonight shall be spent catching up on Netflix night with my friend M. Chateauneuf du Pape and little else. 

Some people I know personally got an invitation to see Bram Stoker's Dracula on BD this weekend as one of my two Halloween movie nights this month.  I would encourage Milwaukee area nerds to try to make this one, in addition to the screening of one of my favorite films someone has promised to bring over a Halo edition 360 for some 106" front projection large and loud H3 action. 

Sunday, October 21, 2007 7:31:16 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, October 15, 2007

In previous articles I've shown how to host the Windows Forms designer outside of Visual Studio, which can be very useful in some sitations.  I had some down time before catching a plane (read: didn't want to start something bigger) so I started looking into the WPF designer.  The WPF designer, code-named "Cider", will not be hostable outside Visual Studio in the first release.  I will be providing feedback through the appropriate channels...

I'm going to go back and finish my ClickOnce thoughts next.

Monday, October 15, 2007 11:32:28 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, October 05, 2007

I just received my copy of "The Age of Turbulence: Adventures in a new world" by Alan Greenspan.  In college I didn't follow politics with the interest that I do now, but one of my best friends was studying finance and is now a major analyst for Bank One (or whoever bought them) in Chicago.  Despite having a bit of a bleeding heart sometimes, he always spoke highly of Mr. Greenspan, commenting on his clarity of analysis and his cold, appropriate focus on facts combined with his incredible vision.  When I learned that Greenspan had become a member of Ayn Rand's inner circle many years ago, I thought it likely that solid moral principles (as well as a great mind) had been guiding his intelligent decisions throughout his career.  I consider Greenspan a rare example in today's political climate, and he may be one of the most well known confirmed Objectivists still alive.  I wonder if the anti-life religoius zealots in the then-growing Republican Right knew what principles Greenspan really stood for; despite being callled a "Republican lacky" for many years, I don't think Greenspan thinks much of the current neocon nonsense.  Read the book to see.

Friday, October 05, 2007 2:33:57 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [1]  |  Trackback

I'm very excited about new toy #2 today.  This is the Splitfish FragFX for the PS3.  The XBox 360 needs an accessory like this as soon as possible.  The right analog stick has been turned into a mouse, and more importantly (though I have not tested it yet) they claim to have compensated for the analog accelleration (different sensitivity based on how far you push the stick) to make it smooth as silk.  Since I've been playing with a mouse since 1995 I've had trouble playing FPS games on consoles; I actually believe that anyone who were to learn both methods for the 1st time today would find the mouse to be superior anyway.  Those who claim the dual analog controllers are "just as good" will soon be very frustrated as I circle-strafe them.

Friday, October 05, 2007 9:38:36 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

This is my 1st new toy today, The Rocket.  This is a mobile wifi hotspot and router with a cellular card, running some kind of Linux distribution.  I think I shall plug this into my car adapter and go work from the lakefront later.

Friday, October 05, 2007 9:33:09 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, October 03, 2007

I need to hire some people into my department at CarSpot.com, I cannot share very many details right now but I'm hoping to get clearance to make some kind of announcement before Q1 2008.  I am looking for the following full time positions:

  • An entry level person, hiring from now to December.  UW-Whitewater, UW-Madison, MSOE, UW-Milwaukee December grads with .Net classroom experience are encouraged to apply.  This is a good chance to start your career doing real work.  May 2008 graduates, save my address.
  • An Electrical Engineer:  I can't share solid requirements on this position yet but will open dialogue with interested parties.
  • A very solid mobile/compact framework person, or an extremely solid .NET developer who can demonstrate ability to very quickly become a mobile superstar.  This position is unique in that it offers a combination of maintenance of current products, creation of new products, and will involve some open-ended R&D.
  • An all-around .NET person.  Windows Forms, Web Forms, Web Services, SQL skills, knowledge of UML, design patterns, likes NUnit and NCover, possibly interested in doing high level design.

It would be fantastic if one of these people had strong Win32/COM/C++ skills.  I will also consider local consultants for some specific work.

As I mentioned before,  I can't make any public announcement right now, but I can share the details in person with serious candidates.  I don't think I can over-state how f()*&*!ng cool CarSpot is right now.  We are taking over a very large space in our current building above the Milwaukee Ale House with a pool table and other niceties.  We've got .NET/Windows people, Linux people, MAC people, and there are some very cool things happening right now which should be obvious if I'm considering bringing four people on board.  There aren't many places in Milwaukee where beer-infested programmer meetings are expensable, you can get a wireless data card and work in the park, and the department head (moi) will feed you ribs and sweet corn during the summer.  Flexibility is critical here, once trust is established and it's shown that you get your work done, you are given a long leash.  I work from home sometimes, I work from the bar downstairs sometimes, some people work from the park, etc. 

We will be working with recruiters very soon, but for now forward resumes to damon.payne@carspot.com .

Wednesday, October 03, 2007 9:08:05 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback