• Reflection.Emit.DeclareLocal and Reflection.Emit.DefineLabel

    Working with Reflection.Emit today I ran into two thing that I couldn’t

    quickly find answers to. First, was regarding the br.s (OpCodes.Br_S)

    code. Secondly, was regarding an error ‘Common Language Runtime

    detected an invalid program’ which didn’t provide much help and the

    cause was not obvious. After a lot of research and trial and error I

    found some answers.

    Regarding the first issue, I found this page on MSDN which also show’s

    how to create a switch statement.

    http://msdn2.microsoft.com/en-us/library/csx7wsz2(vs.80).aspx. The

    solution is to create a Label object and MakeLabel method when Emitting

    the IL.

    Label endOfMethod = il.DefineLabel();
    ...
    il.Emit(OpCodes.Br_S, endOfMethod);
    il.MarkLabel(endOfMethod);

    The above will create IL like this:

    IL_0017:  br.s       IL_001
    IL_0019:  ldloc.1

    The second problem maybe should have been obvious, but most of what I
    read didn’t cover this. If you need to store something you need to
    create local storage before trying to store objects there. Not doing
    this will result in a System.InvalidProgramException. You need to
    create the storage with the il.DeclareLocal method passing in the Type
    of the object you will store there.

    il.DeclareLocal(stringBuilderType);
    il.DeclareLocal(typeof(string));

    The above will create IL like:

    .locals init (class [mscorlib]System.Text.StringBuilder V_0,
                string V_1)

    Working sample command line application (.net2.0) flie – Program.cs.txt (2.45 KB)

  • Deleting files recursively with PowerShell

    This is not the hardest script to come up with, but I can think of a few times I could have used something like this.

    ls -rec -inc .svn -fo | foreach {del $_ -rec -fo}</font></pre>
    
    
    

    It will delete any file or folder named </em>.svn in the current directory or below.

  • NHibernate access strategy names

    Here are the naming strategies for the NHibernate access attribute.

    • property
    • field
    • field.camelcase
    • field.camelcase-underscore
    • field.pascalcase-m-underscore”
    • field.lowercase-underscore
    • nosetter.camelcase
    • nosetter.camelcase-underscore
    • nosetter.pascalcase-m-underscore
    • nosetter.lowercase-underscore
    [Id(Column = “id”, Name = “Id”, 
    Type = “Int32”, UnsavedValue = “0”,
    Access = “nosetter.camelcase-underscore”),
    Generator(1, Class = “native”)]
  • Switch statement and the goto command.

    The goto command can be used to within a switch statement to transfer control to other case statements or the default case statement. Using **goto case ** will transfer control to that case statement. Using **goto default** will transfer execute to the default statement. I’m not sure it produces the cleanest code, but here’s an example anyway.

    public void SwitchMe(StatesEnum state) 
    {
    switch (state)
    {
    case StatesEnum.Stopped:
    Start();
    goto case StatesEnum.Starting;
    case StatesEnum.Started:
    Stop();
    goto case StatesEnum.Stopping;
    case StatesEnum.Stopping:
    state = StatesEnum.Stopping;
    goto default;
    case StatesEnum.Starting:
    state = StatesEnum.Starting;
    goto default;
    default:
    Log(state);
    break;
    }
    }

    public enum StatesEnum
    {
    Stopped,
    Starting,
    Started,
    Stopping
    }

    So, looking above, if state = Stopped and was passed to the SwitchMe method, the code would execute as follows:

    1. the Stopped case would execute calling the Start method
    2. the Starting case would execute setting the value of state to Starting
    3. the default case would execute calling the Log method
  • Fully qualified type names for generic types

    Syntax for generic types names:

    MyAssembly.MyClass`[[MyAssembly.MyOtherClass, MyAssembly]], MyAssembly

    Should be able to use this format anywhere a type name is required, including the Inherits attribute on ASPX Page declarations.

    </p>
  • Using AppDomains to run a process outside of the ASP.NET Context

    There a few reasons why you might want to run a process in an AppDomain.

    For example, if you need to be able to unload and update the loaded

    assemblies. Or in my case, use an assembly which actively blocks

    execution in your currentAppDomain which may be under the ASP.NET context.

    In

    this simple example the same security evidence and configuration of the

    current domain is used. Further the current assembly happens to be the

    one we want to execute, this doesn’t need to be the case however. TheAppDomain.CreateDomain method creates a new AppDomain

    and returns a reference to it. This will be used to call create the

    processing class and unload the domain when it’s no longer needed.

    Next an interface is needed (suggested) for the object that is going to be executed. Here it’s IMyProcess

    which defines a Process method. The implementation needs to inherit

    from MarshalByRefObject. This allows the framework to handle garbage

    collection and life cycle management of the object across the two

    domains. Also any object passed across the domain should inherit from

    MarshalByRefObject. If the process is really long running, some of the

    life cycle properties of MarshalByRefObject will need to be changed.

    A

    context object is used here to pass data to the processing class, this

    isn’t explicitly needed but makes for a little cleaner code. It is also

    a MarshalByRefObject. TheCreateInstanceAndUnwrap method creates a proxy

    to the specified type and Unwraps it making it usable as if the object

    was created in the current domain. The full assembly name, the type

    name,BindingFlags, args (for the constructor in this case), CultureInfo, and security evidence need to be passed to the CreateInstanceAndUnwrap

    method. The returned object needs to be cast to the Interface type,

    done with the as keyword here. Now the Process method of theIMyProcess can be called.

    Lastly, the created domain should be unloaded using the AppDomain.Unload method, passing the domain reference from the CreateDomain method. This should be in a finally block to make sure the domain is unloaded. Creating AppDomains

    is an expensive process and should be done with this consideration in

    mind. Below is most likely not the best way to minimize that expense.

    
    
    
    using System;
    using System.Globalization;
    using System.IO;
    using System.Reflection;
    using System.Security.Policy;

    namespace AppDomainSample
    {
    static class Program
    {
    [STAThread]
    static void Main()
    {
    Execute(1, "connection...");
    Console.ReadKey();
    }

    public static void Execute(int id, string connectionString)
    {
    Assembly assembly = Assembly.GetExecutingAssembly();
    string assemblyName = assembly.FullName;
    string basePath = new Uri(Path.GetDirectoryName(assembly.CodeBase)).LocalPath;

    AppDomain currentDomain = AppDomain.CurrentDomain;
    Evidence evidence = currentDomain.Evidence;

    AppDomainSetup ads = new AppDomainSetup();
    ads.ConfigurationFile = currentDomain.SetupInformation.ConfigurationFile;
    ads.ApplicationBase = basePath;
    ads.PrivateBinPath = basePath;
    ads.ShadowCopyFiles = "true";

    AppDomain d = AppDomain.CreateDomain("AppDomainSampleName", evidence, ads);
    try { MyContext context = new MyContext(id, connectionString);

    d.Load(assemblyName);
    object[] args = new object[] { context };
    IMyProcess r =
    d.CreateInstanceAndUnwrap(assemblyName, "AppDomainSample.MyProcessImpl", false,
    BindingFlags.CreateInstance, null, args, CultureInfo.CurrentCulture, null, evidence) as IMyProcess; r.Process(); } finally { AppDomain.Unload(d); } } } internal class MyProcessImpl : MarshalByRefObject, IMyProcess
    {
    private readonly MyContext _context;

    public MyProcessImpl(MyContext context)
    {
    _context = context;
    }

    public void Process()
    {
    Console.WriteLine("ConnectionString: {0} from {1} domain.", _context.ConnectionString,
    AppDomain.CurrentDomain.FriendlyName);
    }
    }

    internal interface IMyProcess
    {
    void Process();
    }

    internal class MyContext : MarshalByRefObject
    {
    private readonly int _id;
    private readonly string _connectionString;

    public MyContext(int id, string connectionString)
    {
    _id = id;
    _connectionString = connectionString;
    }

    public int Id
    {
    get { return _id; }
    }

    public string ConnectionString
    {
    get { return _connectionString; }
    }
    }
    }
  • Initializing excel for use from a service account

    Sometimes you need to use excel automation and you’d like to have your service or web application running under an service account identity. In some cases excel wants to run some setup on first use by an account. One way is to log into the machine using that account and open excel. A quicker way is to use the following command.

    C:\Program Files\Microsoft Office\OFFICE11>runas /user:MyServiceAcct excel.exe