Monday, March 9, 2009

Economics of Publishing

This Week In Tech, episode 184, has a very interesting discussion on what’s going on with content distribution. In particular, the fate of newspapers, the impact of the Kindle and what Amazon’s plans might be, and the economics of book publishing.

Wednesday, February 18, 2009

Using External .NET Config Files in a Windows Service

The .NET platform provides an easy way to configure your .NET application using an xml configuration file. At design time, the file is named “App.Config”. When you build your project (console application, Windows service, etc.), the file is renamed to the form [ProgramName].exe.config. The file is deployed in the same directory as the executable. At runtime, the file is automatically picked up from the current directory by the Configuration class.

The single App.config file works pretty well for simple stuff, but at some point it gets unwieldy and you want to separate the configuration into separate files. For example. log4net and Spring.NET both provide mechanisms for using external config files. In a normal deployment scenario (e.g. a console application), it just works.

Often, trouble arises when combining these external configuration files with a Windows service deployment. The built-in configuration classes seem to locate the main config file well enough, but the external files cannot be located. They are attempted to be loaded from %SystemRoot%\System32. Why? This is the location of the net command, which is the host process for the service. I suspect the implementers of the external configuration files refer to the CurrentDirectory of the process, instead of the file location of the executable module.

You can fix the problem by setting the CurrentDirectory of the process:

   25 var process = Process.GetCurrentProcess();

   26 if (process.MainModule != null)

   27 {

   28     string newFilePath = process.MainModule.FileName.Substring(0,

   29         process.MainModule.FileName.LastIndexOf(@"\"));

   30     Directory.SetCurrentDirectory(newFilePath);

   31 }

If you like, you can put this code into the OnStart method of your service. But you might need the info before that. In that case, put the code as early as possible.

 

Credit goes to Jose Joye, who posted this idea back in 2005.

Reblog this post [with Zemanta]

Friday, January 2, 2009

Basic Log4net Configuration

Logging
Image via Wikipedia

(This post is mostly a reminder to myself on how to do this.  I have to rediscover it whenever I create a new app.  Maybe it will be useful for you too.)

Most of the time, when I want to setup logging with log4net, I want to put the log4net configuration into the application config file.  This is what I’ll be showing here.  So the first step is to put the necessary info into the App.config file:
    2 <configuration>
    3     <configSections>
    4         <section name="log4net"
    5                 type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
    6     </configSections>
    7     <appSettings>
    8         <add key="log4net.Internal.Debug" value="false"/>
    9     </appSettings>
   10     <log4net>
   11         <appender name="DefaultAppender" type="log4net.Appender.ConsoleAppender">
   12             <layout type="log4net.Layout.PatternLayout">
   13                 <conversionPattern value="%message%newline" />
   14             </layout>
   15         </appender>
   16         <root>
   17             <level value="DEBUG" />
   18             <appender-ref ref="DefaultAppender" />
   19         </root>
   20     </log4net>
   21 </configuration>

A few things to note here:
  1. In the appSettings section is a key-value pair that when set to true will output log4net internal debug information.  This can be useful if something isn’t working right and you can’t figure out why.  I find that using dbgview is the best way to monitor this information.
  2. In this example, I’m using the ConsoleAppender, but you could use anything.  I stripped out most of the pattern information since I don’t want things like threadId on the console output window.
  3. The log4net assembly must be reachable by your application, which usually means having it either in the local directory or in the GAC.

The other thing you need to do is to mark the assembly so that log4net knows where to pick up the configuration settings.  Add this line to your AssemblyInfo.cs file:
   37 [assembly: log4net.Config.XmlConfigurator(Watch = true)]

You can find detailed configuration instructions in the log4net manual.
Reblog this post [with Zemanta]

Wednesday, December 17, 2008

BabySmash and Oxite: A Tale of Two Projects

Scott Hanselman makes an interesting comparison between BabySmash and Oxite.  BabySmash was pretty warmly received (the odd "Microsoft is teh suck" comment notwithstanding) and accepted as a starting point, while many seem to have reacted to Oxite with hostility.  Why?

I suspect this has to do with the Microsoft name and expectations.  BabySmash started on Scott’s personal blog and didn't have any appearance of being a Microsoft endeavor.  He intentionally set expectations very low.  People cut it (and him) a lot of slack and took it in the spirit in which it was intended.

On the other hand, Oxite is sponsored by Microsoft so the expectations are higher, even for a sample project.  I suspect many people don't see it as a project with individual names on it (even though it is - their names are right there for everyone to see).   Likely they see it as something that got thrown over the wall by a big corporation, and so are less good-natured about their criticism.  Of course, there's no good reason for being uncivil, but it may explain the prevalent tone.

Thursday, October 16, 2008

Generic foreach Loop Automatically Uses Explicit Cast

I ran into this curiosity today:

    5     public interface IFoo {}
    6     public class Foo : IFoo {}
    7     public interface IBar {}
    8     public class Bar : IBar {}
    9 
   10     internal class Foo2
   11     {
   12         public void X()
   13         {
   14             IList<Foo> foos = new List<Foo>();
   15             IList<IFoo> ifoos = new List<IFoo>();
   16             IList<IBar> ibars = new List<IBar>();
   17             IList<Bar> bars = new List<Bar>();
   18 
   19             foreach (IBar value in foos)
   20             {
   21                 ibars.Add(value);
   22             }           
   23 
   24             foreach (IBar value in ifoos)
   25             {
   26                 ibars.Add(value);
   27             }
   28 
   29             foreach (Bar value in ifoos)
   30             {
   31                 ibars.Add(value);
   32                 bars.Add(value);
   33             }
   34         }
   35     }

In each case, the compiler is using an explicit cast to convert the object.  Per the C# Language Specification:
The type of the expression of a foreach statement must be a collection type (as defined below), and an explicit conversion (Section 6.2) must exist from the element type of the collection to the type of the iteration variable.
In each of these cases, an explicit conversion does exist, and so it compiles.  Of course, at runtime an InvalidCastException is thrown because it’s not valid.  So much for all that generic type safety happiness.
Apparently, this question has been asked and answered before.  They considered making it a compiler warning but decided that would be a “breaking change”:
I considered adding a warning to the compiler for this case to say hey, be aware that your collection is of a more general type, this could fail at runtime. It turns out that there are so many programs which use this programming style, and so many of them have “compile with warnings as errors” turned on in their builds, that this would be a huge breaking change. So we opted to not do it.
This is specious.  The purpose of warnings is to advise you that you are engaging in dangerous behavior.  If I were the owner of one of these “many programs” I would want to know, not to have it swept under the rug so that my build succeeds.  If people want to ignore the warning, they’re free to do so in their configuration.  The result is that the rest of us are left with no safety net whatsoever.

How can we mitigate this?   Not great options, but here’s what we can do:
  • unit testing – if our coverage is good, we’ll catch them at runtime
  • use the var keyword, which will cause the Add( ) call to be complained about.
  • use static analysis to detect the explicit cast added by the compiler

Special thanks to my coworkers who solved this problem (corporate policy prohibits me from disclosing anything more).  I work with some smart people (at least I think I do).

Saturday, July 26, 2008

Will PutPlace Supplant Mozy for My Online Storage?

I'm currently using Mozy for backing up my data.  (Are you backing up your data offsite?  You should.)  I selected Mozy because all my data are encrypted prior to transmission.  Furthermore, I control the key, so even Mozy cannot access my data.  However, they don't offer a way to share files, which is kind of a bummer.

Today, I learned about new kid on the block PutPlace (“secure, organize, and share your digital life.”), who are currently in open beta.   One thing PutPlace provides that Mozy does not is the ability to share selected data with others.  Also, PutPlace versions your files, allowing you access to prior versions.  That’s pretty cool. 

On the down side, I expected a lot more in terms of data security.  PutPlace does not encrypt your data prior to transmission, nor is it encrypted prior to storage on Amazon S3 (although the transmissions channel itself is encrypted).  Instead, they rely on passwords:

PutPlace stores your data using Amazon's S3 storage service-the web’s safest possible storage ‘facility’.

We also ensure that no-one else can see your content by password protecting all of it. Only you, and the people you share your password with, will be able to view your stuff. Plus, we’ll soon offer an encryption service. That’s pretty much the equivalent of lead-lining your content.

and security through obscurity:

Even if we wanted to, we can’t see any of your data because your account is password protected. If you forget or lose your username or password, we will can assist you in setting up a new one, but we can’t retrieve your old one.

As a default, we use the Amazon's S3 service to store your data (unless you request a different storage service). In Amazon, all links are private, so there’s no easy way to connect data back to a PutPlace account. Additionally, we upload data over encrypted links, which ensure your data is safe during the upload process.

Finally, in the PutPlace database, we de-couple the filename from the user ID, which makes it impossible for unauthorized users to access your data.

It’s a good start.  But that encryption is a must-have, it’s not secure without it.  Just ask Iron Mountain.

Will PutPlace supplant Mozy for my online storage?  No, not quite yet.  But it looks promising, and I’ll be watching.

Sunday, May 18, 2008

Fixed: SlickRun Flashing

While using SlickRun, I had the experience that periodically it would go into what I call "seizure induction" mode, where it seemed the command box would try to grab screen focus, only to have it pulled away, only to grab it back, ad infinitum.  The only way out of this loop that I could find was to keep clicking on the command box, and eventually it would stop.

It turns out there is a very simple fix to the problem, but you must have the 3.9.8 Beta or later:

  1. Open the SlickRun INI file, which is usually located in "C:\documents and settings\<username>\application data\slickrun"
  2. Find the section marked [General]
  3. Add the following on a separate line: AggressiveShowWindow=0
  4. Restart SlickRun.

Tuesday, May 13, 2008

Fixing the Mysterious Extra Lines in Email

When I send messages from my Outlook client to an Internet address, the spacing between lines doesn't work out quite right. Do you have this problem?

WindowClipping (2)

Not quite what you wanted, right? It's a minor annoyance, but pretty persistent. Whether you're using Rich Text or HTML, the problem remains. It is not consistent, however, as the problem occurs for some fonts, but not others. Using Firebug, you can see that each line in the message is a paragraph (the <p> element).

To fix the problem, in Outlook go to Tools/Options/Mail Format and deselect "Reduce the file size of the message..."

Options

Here is the another similar message sent using the new options:

WindowClipping (4)

Monday, May 12, 2008

SlickRun for Search

Here are a couple of SlickRun commands I'm using frequently. There are lots of things the browser can do that you can hook into with SlickRun. The most obvious is search.

Here are a few that I use a lot (grabbed from the slickrun.srl file, located in ...\ApplicationSettings\SlickRun). They're probably obvious, but I use them constantly.

Google

[g]
Filename="firefox"
Path=""
Params="http://www.google.com/search?hl=en&btnG=Google+Search&q=$W$"
Notes=""Go to" web search from Google"

Searching Google is as easy as <ctr+ q>, g <search term>


Del.icio.us

I use the same approach for searching my del.icio.us links:

[d]
Filename="firefox"
Path=""
Params="http://del.icio.us/search/?fr=del_icio_us&p=$w$&type=user"
Notes=""

Note that this is not the default del.icio.us search. It searches only my bookmarks, which is much much faster. Using the del.icio.us web site as a model, it was a simple task to figure out the query string parameters I needed.

Wednesday, April 30, 2008

Visual Studio Tip: Jump to Item in Solution Explorer

In his blog, Daniel Cazzulino observes a difficulty in working with large projects in Visual Studio, and provides a helpful tip to locate the currently active file in the editor. As Daniel points out, there is a setting in Visual Studio that will ensure that the current file in the editor is always highlighted in the Solution Explorer.

If you are using ReSharper, you have an even better alternative. There is a ReSharper command called ReSharper_LocateSolutionInExplorerAction. By default, the command is mapped to <alt>+<shift>+L, and it will select the file in the Solution Explorer (including putting focus on the pane).

UPDATE: Kevin Dente posted a follow-up on the topic. Kevin shows a two-line macro that accomplishes the same feat, which is great for those without ReSharper.