ASP.NET Weblogs

Welcome to ASP.NET Weblogs Sign in | Join | Help
in Search

The Technical Adventures of Adam Weigert

  • LINQ: Expressive Html Tag Building

    I hate building HTML tags in code, but it needs to be done. I just wanted to make it a little cleaner. So I came up with this method that utilizes LINQ expressions to generate the attributes for the tag. This is really only clean with simple tags, but I use it with my other tag building methods to keep them clean as well. I've seen others look for something like this and thought it'd be helpful posting it here. I haven't deeply tested this code but it shows the general concept and I'm sure it needs cleaned up a little. The following is an example calling the Tag method:

       1:  Tag( "a", "The Technical Adventures of Adam Weigert", href => "http://weblogs.asp.net/adweigert/" );
       2:  Tag( "div", "LINQ Expressions Rock", style => "font-size: 250%; font-weight: bold;", id => "title" );

    This is the actual method, I love how simple the LINQ expression makes building the attributes.

       1:  public string Tag( string tagName, string innerHtml, params Expression<Func<string, string>>[] attributes )
       2:  {
       3:      XElement tag = new XElement( XName.Get( tagName, string.Empty ) );
       4:      
       5:      if ( attributes != null )
       6:      {
       7:          foreach ( var attribute in attributes )
       8:          {
       9:              string attributeName = attribute.Parameters[ 0 ].Name;
      10:              string attributeValue = attribute.Compile()(string.Empty);
      11:   
      12:              tag.SetAttributeValue( XName.Get( attributeName, string.Empty ), attributeValue );
      13:          }
      14:      }
      15:   
      16:      if ( !string.IsNullOrEmpty( innerHtml ) )
      17:      {
      18:          tag.Add( XElement.Parse( "<xml>" + innerHtml + "</xml>" ).Nodes() );
      19:      }
      20:   
      21:      return tag.ToString();
      22:  }

    Update: Used XElement instead, and better innerHtml handling. Thanks to everyone that helped improve this method.

  • PowerShell: Install-Gac (GACUTIL for PowerShell)

    So, I don't know about anyone else, but it is a pain to use GACUTIL on systems without the .NET SDK. So, I found out there is a .NET API for GACUTIL, so now I just wrapped it in PowerShell to make it easier to use. :)

       1:  BEGIN {
       2:      $ErrorActionPreference = "Stop"
       3:      
       4:      if ( $null -eq ([AppDomain]::CurrentDomain.GetAssemblies() |? { $_.FullName -eq "System.EnterpriseServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" }) ) {
       5:          [System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") | Out-Null
       6:      }
       7:      
       8:      $publish = New-Object System.EnterpriseServices.Internal.Publish
       9:  }
      10:  PROCESS {
      11:      $assembly = $null
      12:      
      13:      if ( $_ -is [string] ) {
      14:          $assembly = $_
      15:      } elseif ( $_ -is [System.IO.FileInfo] ) {
      16:          $assembly = $_.FullName
      17:      } else {
      18:          throw ("The object type '{0}' is not supported." -f $_.GetType().FullName)
      19:      }
      20:      
      21:      if ( -not (Test-Path $assembly -type Leaf) ) {
      22:          throw "The assembly '$assembly' does not exist."
      23:      }
      24:      
      25:      if ( [System.Reflection.Assembly]::LoadFile( $assembly ).GetName().GetPublicKey().Length -eq 0 ) {
      26:          throw "The assembly '$assembly' must be strongly signed."
      27:      }
      28:      
      29:      Write-Output "Installing: $assembly"
      30:      
      31:      $publish.GacInstall( $assembly )
      32:  }
  • CodePlex: The Weigert Repository

    I've been looking for a place to keep / manage all the snippets I develop or find and decided to use CodePlex for this. Feel free to use whatever you find useful.

    http://www.codeplex.com/Weigert

  • PowerShell: Oh Happy Days Are Here (Dynamically Compiling C# Code for Strongly Typed Objects within PowerShell)

    Ever wanted to build native .NET objects to use while in a PowerShell script? Well I certainly have, and finally took the time to figure out how easy it is to actually do! Enjoy!

    function Compile-Code {
        param (
            [string[]] $code       = $(throw "The parameter -code is required.")
          , [string[]] $references = @()
          , [switch]   $asString   = $false
          , [switch]   $showOutput = $false
          , [switch]   $csharp     = $true
          , [switch]   $vb         = $false
        )
        
        $options    = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]";
        $options.Add( "CompilerVersion", "v3.5")
        
        if ( $vb ) {
            $provider = New-Object Microsoft.VisualBasic.VBCodeProvider $options
        } else {
            $provider = New-Object Microsoft.CSharp.CSharpCodeProvider $options
        }
        
        $parameters = New-Object System.CodeDom.Compiler.CompilerParameters
        
        @( "mscorlib.dll", "System.dll", "System.Core.dll", "System.Xml.dll", ([System.Reflection.Assembly]::GetAssembly( [PSObject] ).Location) ) + $references | Sort -unique |% { $parameters.ReferencedAssemblies.Add( $_ ) } | Out-Null
        
        $parameters.GenerateExecutable = $false
        $parameters.GenerateInMemory   = !$asString
        $parameters.CompilerOptions    = "/optimize"
        
        if ( $asString ) {
            $parameters.OutputAssembly = [System.IO.Path]::GetTempFileName()
        }
        
        $results = $provider.CompileAssemblyFromSource( $parameters, $code )
        
        if ( $results.Errors.Count -gt 0 ) {
            if ( $output ) {
                $results.Output |% { Write-Output $_ }
            } else {
                $results.Errors |% { Write-Error $_.ToString() }
            }
        } else {
            if ( $asString ) {
                $content = [System.IO.File]::ReadAllBytes( $parameters.OutputAssembly )
                $content = [Convert]::ToBase64String( $content )
                
                [System.IO.File]::Delete( $parameters.OutputAssembly );
                
                return $content
            } else {
                return $results.CompiledAssembly
            }        
        }
    }

    Example usage:

    Compile-Code -csharp -code @"
        using System;
        
        public class Foo {
            public Foo ( string message ) {
                Message = message;
            }
        
            public string Message { get; private set; }
            
            public void Bar() {
                Console.WriteLine( "Foo.Bar: {0}", Message );
            }
        }
    "@
    
    $foo = New-Object Foo "hello world"
    $foo.Bar()

    Update: Added ability to compile C# or VB.NEt code and also to return the bytes for the compiled assembly for loading at a later time.

  • PowerShell: Keeping Secrets for Batch Scripts

    As a system administrator, I write a lot of utility scripts, and I love using PowerShell. However, I cannot always use the local scheduler with a service account to run a script, sometimes I have to provide a username and password to an application or service. I hate storing them in plaintext, and while I don't fully like storing the encrypted text, key, and IV in the script, it is one step better than the plaintext solution. While the ultimate solution would be to have it stored as part of the user profile for the job, this is an issue when I don't have direct access to the production system to be able to run as the service account and I just need an encrypted file / text to later decrypt and use.

    So, I started working with ConvertTo/From-SecureString and hit a little problem. I discovered, via Reflector, that the ConvertTo-SecureString and ConvertFrom-SecureString use an IV that is specific to that instance of the PowerShell runtime. Thus, using it at a later time is no good for me. So, long story short, I cranked up Reflector, took a look at the commands, and created a script version that does exactly what I need.

    You will find the script attached.

     

  • PowerShell: Adding the Using Statement

    So, I happened to come across a need for the using statement from C#. I basically didn't want to use Try...Finally when I am so used to the short-hand using statement. Thank goodness I already have a Try..Catch..Finally statement/function for PowerShell, I can just use that existing framework and make a using statement/function pretty easily.

    function Using {
        param (
            [System.IDisposable] $inputObject = $(throw "The parameter -inputObject is required."),
            [ScriptBlock] $scriptBlock = $(throw "The parameter -scriptBlock is required.")
        )
        
        Try {
            &$scriptBlock
        } -Finally {
            if ($inputObject -ne $null) {
                if ($inputObject.psbase -eq $null) {
                    $inputObject.Dispose()
                } else {
                    $inputObject.psbase.Dispose()
                }
            }
        }
    }
    
    # Short example ... 
    Using ($user = $sr.GetDirectoryEntry()) { 
      $user.displayName = $displayName 
      $user.SetInfo() 
    } 
    

    Update: Take note on variable scope, variables in the using statement will not be available outside of it, this can make it tricky, but it should be easy enough to work with.

  • PowerShell: Threading Enhancements FTW!

    To build on the threading library I mentioned here, I've added some functionality to make it easier to communicate with the seperate thread. Still, keep in mind that PowerShell will only allow one pipeline to be executing in a runspace at any given time. So, these new functions can only be used while the thread is inactive. But, they provide power into setting up the thread to be run and communicating with the original runspace.

    The new functions are as follows:

    Get-ThreadVariable - Accesses available variables from within the thread.
    Set-ThreadVariable - Sets a variable for use within the thread.
    Invoke-ThreadExpression - Allows synchronous execution of a script block within the thread.

    I also updated the Join-Thread function to include an optional -timeout parameter so that you could return control back if the thread didn't complete in the desired time. I also updated the Running property to IsRunning and changed it so that it will only return true while the asynchronous invoke command is executing.

    With this new example you can do even more now, as shown here.

    $thread = New-Thread
    Invoke-ThreadExpression $thread { function foo($bar) { echo "$bar!" } }
    Set-ThreadVariable $thread "name" "PowerShell Rocks"
    Start-Thread -thread $thread { $value = foo $name } | Out-Null
    Join-Thread $thread
    Get-ThreadVariable $thread "value"

    This should return "PowerShell Rocks!" when Get-ThreadVariable is called. I've already used this script to multi-thread our Exchange backup from a single script. It is working quite nicely (nice as in have cut our 8 hour backup down to 4 hours) and I can already imagine several other wonderful places it will be used.

  • PowerShell: Threading for PowerShell v1.0

    Ok, so this solution really isn't threading, but a neat way to get async scripts to run! The important thing to remember is that each "thread" is actually a PowerShell "runspace". Meaning, scripts run within the thread don't have access to objects or functions defined outside the thread. The script is composed of the following commands:

    New-Thread: Creates a new instance of a thread
    Start-Thread: Invokes an async execution of a script block
    Stop-Thread: Stops a thread from running if it is still executing
    Read-Thread: Reads all errors and output to the current runspace
    Join-Thread: Waits for the thread to complete and reads off the errors and output to the current runspace

    A simple example of how to use this is as follows.

    $thread = Start-Thread {
        foreach ($i in (1..5)) {
            echo "Sleeping for $i seconds..."
            Start-Sleep $i
        }
    }
    # ... do some work here or spawn other threads
    Join-Thread $thread

    I have some other ideas around injecting "variables" and being able to run script blocks within the new "thread" but I'll save that for a later post ...

  • Windows Server 2008 / Vista - Network Scalability "Feature"

    I highly recommend, if you are running Windows Server 2008 or Windows Vista, to disable the network scalability features. If you don't, you run the chance of one day running into "slow" performance of an application between one client or server and another. You will spend countless hours trying to debug why the network communication is so slow to that feature from that one client when it works fine for you and serveral others in the same area and with the same configuration. As far as I am concerned, TCP offloading has been a failure since the beginning, and I am not sure who is to blame, Microsoft or the hardware vendors. Oddly enough, I even saw the "symptoms" on a virtual server.

    From an Administrator command prompt:

    netsh int tcp set global rss=disabled chimney=disabled autotuninglevel=disabled

    Enjoy!

  • C#: My First Lambda Expression

    I don't know about anyone else, but I found it annoying to have to put on three-lines of code (or one ugly one-line of code) for an IF statement for argument validation. Mostly, I want to check a simple condition and if true, throw an exception. Well, lambda to the rescue! I find the lambda version much more readable than a one-line IF statement, but that is just me -- mainly because I dislike one-line IF statements.

    Another advantage of the lamba expression is that the "new Exception" is only created if the delegate is called when the condition is true. Who knows, maybe I'll change my mind on liking this after I have more experience with .NET 3.5, but for now I think this is very cool...

    I guess this will have to do until we have MACRO replacement in C# ... :)

    public delegate T CreateObjectDelegate<T>();

    internal static class Validator
    {
        public static void ThrowIf(bool condition, CreateObjectDelegate<Exception> createObject)
        {
            if (condition)
            {
                throw createObject();
            }
        }
    }

    internal static class Example
    {
        static void ShowName(string name)
        {
            // LAMBA expression
           
    Validator.ThrowIf(name.IsNullOrEmpty(), () => new ArgumentException("The parameter is required.", "name"));

            // IF statement
           
    if (name.IsNullOrEmpty()) throw new ArgumentException("The parameter is required.", "name");

            Console.WriteLine(name);
        }
    }

    Posted Dec 16 2007, 07:56 AM by adweigert with 5 comment(s)
    Filed under: , ,
More Posts Next page »