Rants, rambles, news and notes from another geek

Apologies... RSS Feed Was Broken

Oops. When I switched to dasBlog, I didn’t realize that I had left all the people with my old RSS URL in the lurch.

My bad. If I had installed dasBlog in the same folder as my Radio weblog, it would have worked because Clemens wrote a nice regex based redirector that was already configured for this.

But, I put dasBlog in a new folder so none of that code fired. Tonight I added a redirect for IIS to solve it. Sorry.

"Why" Instead of "How" and "What"

Jimmy Nilsson writes:

If we transfer this little story to programming, it reminds me about that I think we should be asking ourselves “why?” when writing comments. If you also need to write comments for “how” and “what”, it might be a sure sign of smelly code and an indication that you need to do some refactoring.

Ahhh… that makes me feel good. Nice and simple. Comments should say WHY you did something. If you have to write WHAT or HOW, then you have a problem.

Thanks Jimmy!

CodeSmith + CodeDom

Yesterday Steve Eichert wrote:

This past week while working on a re-write of the framework that prompted the initial evaluation of Emit vs. CodeDOM I decided to revisit the debate.&nbsp_place_holder; After “thumbing” my way through the documentation of the CodeDOM classes I came across the ICodeCompiler.CompileAssemblyFromSource() method.&nbsp_place_holder; Rather then emitting OpCodes I decided to create a couple of templates for my code and use the ICodeCompiler to genearte an in memory assembly.&nbsp_place_holder; While I did miss the process of pushing things onto the call stack using OpCodes, I realized how much more productive I was creating “C# templates” for my code and compiling them with the CodeDOM classes.

As I started to think about this, I decided to try this out. Since CodeSmith will produce a template assembly that I can call from code, this should be easy as pie!

I started by creating this simple CodeSmith template:

**<%@ CodeTemplate Language="C#" TargetLanguage="C#" Description="" %>**
  
**<%@ Property Name="ClassName" Type="System.String" Default="MyClass"  
    Category="Options" Description="" %>**
  
**<%@ Property Name="SampleStringProperty" Type="System.String"  
    Default="SampleString" Category="Options" Description="" %>**
  
public class <%=ClassName%>
  
{
  
   public string <%= SampleStringProperty %>   
  
   {
  
      get { return _<%=SampleStringProperty%>; }
  
      set { _<%=SampleStringProperty%> = value; }
  
   }
  

  
   private string _<%=SampleStringProperty%>;
  
}  

Then using CodeSmith, I created an assembly from my template. Basically this creates a DLL that you can reference from your code that contains the code generation class defined by the CST file.

Once that was done, I created a simple forms app, added a button, and put the following code in the click handler:

private void button1_Click(object sender, System.EventArgs e)
  
{
  
   CodeSmithTemplates.SimpleTemplate template = 
  
      new CodeSmithTemplates.SimpleTemplate();
  
   template.ClassName = "MyClass";
  
   template.SampleStringProperty = "MyProperty";
  
   string source = template.RenderToString();
  

  
   CSharpCodeProvider cSharpProvider = new CSharpCodeProvider();
  
   ICodeCompiler compiler = cSharpProvider.CreateCompiler();
  

  
   CompilerParameters options = new CompilerParameters();
  
   options.GenerateInMemory = true;
  

  
   CompilerResults results = 
  
      compiler.CompileAssemblyFromSource( options, source );
  

  
   if( results.Errors.HasErrors )
  
   {
  
      StringBuilder sb = new StringBuilder();
  
      foreach( CompilerError error in results.Errors )
  
      {
  
         sb.Append( String.Format("{0} - {1}\n", error.Line, 
  
            error.ErrorText ) );
  
      }
  

  
      MessageBox.Show( sb.ToString(), "ERROR" );
  
      return;
  
   }
  

  
   Assembly assembly = results.CompiledAssembly;
  
   object o = assembly.CreateInstance( "MyClass" );
  

  
   Type t = o.GetType();
  
   t.InvokeMember( "MyProperty", BindingFlags.SetProperty, null,
  
      o, new object[] { "Test!" } );
  
   object result = t.InvokeMember( "MyProperty", 
  
      BindingFlags.GetProperty, null, o, null );
  

  
   MessageBox.Show( result.ToString() );
  

  
}  

That’s it! Granted I didn’t do anything particularly complex with it, but it is a very effective way to combine template generated code (a la CodeSmith) with CodeDom. Enjoy!

Silent Install of .NET Runtime

I had to find this for someone today, so I thought I’d post it here so it doesn’t get lost:

dotnetfx.exe /q /c:”install.exe /q”

What is happening here is the wrapper exe (dotnetfx.exe) is being called with two parameters. The first parameter tells it to run silently. The second tells it to run a specific command after extracting the contents. We then pass the silent flag to the “inner” installer.

Make sense? It doesn’t matter, because it works. ;-)

Anyone Blogging XP Universe?

I’m wondering (hoping) that someone is blogging XP Universe. My boss is there, but since I’m not, I’d love to follow along.

If you know of anyone who is blogging it, please post the URL in the comments. Thanks!

Color-coded C# for Weblogs

I know a lot of people were talking about the TripleASP.NET Code Formatter a few months ago, but sometimes I’m slow…

I’ve been very annoyed by code posting lately, so I’m going to try it out and see if it works for me.

Here is an attempt using some code from an earlier post:

public void SetPassword( DirectoryEntry entry, string password )
  
{
  
   // There should be a blank line after this...
  

  
   entry.Invoke("SetPassword", password );
  
}  

Not bad. I think I’ll start using it.

Windows Media Player on Dual Monitors

Windows Media player does something strange when you run on a dual monitor setup. Suppose you are watching a web demo that has the WMP Video Control embedded on the page. When the presentation starts, the video comes up full screen on the second monitor! The same thing happens with non-web-enabled WMP video content. So if you double-click on an AVI file, you will see it in a small WMP window on one monitor and full-screen on the other.

Does anyone know how to stop this behavior? Ideally it should be something I can control on the fly. It is very annoying when you don’t want it, but useful when you do want it.

Test Using Mail-to-Weblog

I’m hoping this will post properly. I’ve tried it a number of times in the past using dasBlog 1.0, and it didn’t work. Sorry for the useless OT post.

Programming Active Directory With the System.DirectoryServices Namespace

Since I haven’t been assigned to a project yet since starting with Interlink Group, I’ve been doing a lot of technical sales and internal projects. A couple of days ago, one of our network engineering guys asked me to help him port a VB6 application to .NET. After looking at it for 10 minutes I realized that I didn’t want to port it to VB.NET, I wanted to rewrite it from scratch. He didn’t really care, he just needed me to make a few changes. If it was in C# or VB.NET he didn’t care.

Basically the application needed to change the password every day on the local machine’s Administrator account to a predictable, but difficult guess value. A separate application is used by the helpdesk person to generate the same password given the machine’s name and the date. Simple.

I’d dabbled with Active Directory Services from .NET before, but hadn’t done anything real. So this would be fun.

As I produced my first Solution Spike in about an hour. I had a bunch of things to learn. Most important was how to use the Invoke method of the DirectoryEntry object.

This method lets you make direct method calls on the underlying ADSI interface. The reason&nbsp_place_holder; you have to do this is that the guys who created DirectoryEntry didn’t give us a full implementation. I don’t know why. But they did give us the Invoke method.

You need the invoke method to do a number of things such as changing a user’s password, getting a list of groups that a user is in, and adding a user to a group.

Here is a quick example of how to use the Invoke method from C#:

public void SetPassword( DirectoryEntry entry, string password )
  
{
  
   entry.Invoke("SetPassword", password );
  
}

Invoke is defined as follows:

public object Invoke( string methodName, params object[] args );

So in C# all parameters after the first parameter will be converted into an object array. This nice little C# feature lets us do this:

public string SetDescription( DirectoryEntry entry, string description )
  
{
  
   entry.Invoke( "Put", "Description", description );
  
}

You’ll notice that setting the description is different that setting the password. That is because IADsUser defines Description as a string property (hence the “Get” and “Put” method names) while SetPassword is a method. To see the full list of IADsUser methods and properties, refer to MSDN.

Once I wrapped the DirectoryEntry with a helper class to do all of this for me, writing my service and the help desk application was a snap.

(OK, it was a little more that a “snap”, but that is because I got carried away with the goldplating. A implemented a strategy pattern and a factory so I could sub out the password generation logic and/or the rename algorithm later. Oh well, sometimes we get carried away.)