Archive for November, 2009

Managing Environment-Specific web.config, app.config and EntLib Config Files

Thursday, November 26th, 2009

When you need to deploy a solution to multiple environments (e.g. separate Development, Test, Acceptation and Production or DTAP environments), you often have a set of environment-specific settings that you need to manage.

Since version 2.1 the Macaw Solutions Factory supports environment-specific web.config, app.config and EntLib config files.

Recommendations

Managing environment specific settings is risky, because by definition you cannot test these settings anywhere else.

For this reason, the Microsoft .NET Architecture Style (MAST) recommends to minimize the number of environment specific settings that your solution needs by design.

Secondly, MAST recommends that you further reduce risk by avoiding duplication of environment specific settings in multiple config files within the same environment. Instead, try to place these settings as much as possible in one central repository for each environment, e.g. in a service, a database or a SharePoint list (the last one has the added benefit of a free management UI).

Still, some technologies require settings in configuration files. To support this, the Factory allows you to manage environment-specific web.config, app.config and MS Enterprise Library (EntLib) settings.

Note that each MAST product has separate app.config, web.config and entlib config files. However to further reduce duplication of config files when maintaining multiple Factory products in the same environment, it is possible to share config files from a single location in source control across multiple MAST products, by using e.g. Externals in Subversion source control or NTFS Junctions when using TFS source control.

To add an environment-specific app.config or web.config file:

  1. Browse to the folder where your shared app.config or web.config file is located.

    It should be located in a subfolder under the _ConfigFiles folder for the product dependency folder that contains your Visual Studio solution.
  2. Create the new app / web config file in this folder and prefix the file name with the environment name (this can be anything, e.g. ‘production’ or a specific machine name)
  3. For each machine that should use this configuration, specify the new environment-specific web / app config file name in the machine configuration file.

    Note that a sample.production.machine.config file is supplied with the Factory.

Now when you deploy a deployment package on any of these machines, or when you build a solution in Visual Studio on any of these machines, the environment-specific version of the config file will be deployed to the runtime locations as the web.config or app.config file.

To add a new environment to MS Enterprise Library settings:

We leverage the built-in EntLib feature ‘Environmental Overrides’.

  1. Select ‘Edit Enterprise Library product configuration’ in the Factory Guide:
  2. Create a new Environment, e.g. ‘Test’:

    Be sure to follow the naming convention for the environment-specific files as indicated below:

    When you click ‘Save’, the environment delta file will be created:

  3. Now you can specify an override for any EntLib setting, for the Test environment. First select the setting, then select the value ‘Override Properties’ for ‘Override on Test’, and finally supply the override value for the setting.

    E.g. to override a database connection string:

  4. Now add an override value for the Test environment for the Application Setting ‘MastEnvironmentMachineNames’:

    The MastEnvironmentMachineNames value is a comma-separated list of names of the machines that make up this environment. Wildcards * and ? are supported. These are the same machine names that are used in the filename of the machine configuration files.

    Note that when a machine name does not match any override value of MastEnvironmentMachineNames, the base EntLib configuration without any overrides will be used.

  5. Select ‘Save’ to save all override settings in the Test.dconfig file. Also right-Click the (Test) environment and select ‘Save Merged Configuration’ to create the environment-specific EntLib configuration file :


    Don’t forget to add both the <Environment>.dconfig and the Entlib-<Environment>-Product.exe.config to source control.

Now the correct environment-specific version of the EntLib configuration file will be deployed when you deploy a MAST package on a machine, or when you select the ‘Deploy Enterprise Library product configuration’ action in the Factory Guide:

To edit or add values in an existing environment-specific EntLib file:

  1. First open the base EntLib configuration via the ‘Edit Enterprise Library product configuration ‘ action in the Factory Guide. It will open without any environment overrides loaded.
  2. Then right-click the Environments node, select ‘Open Environment Delta’ and open the appropriate <Environment>.dconfig file:
  3. Once you are done editing and adding new override values, save both the Entlib .dconfig file and the merged configuration file again.

How to setup BizTalk 2009 BAM Portal on a 64 Bit OS in IIS 7

Tuesday, November 17th, 2009

I just finished setting up BizTalk 2009 (Developer Edition) on a W2008R2 x64 machine with the following components:

Initially, the BizTalk Server Configuration utility failed to install the BAM portal. The error log reported that IIS was in 64 bit mode where 32 bit mode was required.

MSDN guidance on configuring the BAM Portal said that in IIS 6 you should execute this script:

cscript c:\inetpub\adminscripts\adsutil.vbs SET W3SVC/AppPools/Enable32bitAppOnWin64 1

However, it also mentioned this:

However, the MSDN guidance did not specify what you should do if you use IIS 7.

After I found out that in IIS 7 you can specify per application pool whether you want to enable 32 bits processes, I found a clean and easy way to get the BAM Portal to install correctly:

  1. In IIS Manager, select Set Application Pool Defaults:
  2. Set the property “Enable 32-Bit Applications” to True:
  3. Run the BizTalk Server Configuration utility and configure the BAM Portal.
  4. If you want, you can now change the Application Pool Defaults back to what you prefer.

NJoy the green checkmarks.

Detect 32 or 64 bits Windows – regardless of WoW64 – with the PowerShell OSArchitecture function

Monday, November 2nd, 2009

In 64-bits versions of Windows Operating Systems, a subsystem called Windows on Windows 64 (WoW64) enables you to run 32 bits applications. Even to date, many Windows applications only exist in a 32 bits version – not the least of which is Microsoft’s own Visual Studio(!)

The purpose of WoW64 is to hide many of the structural differences between 32 bits and 64 bits Windows for 32 bits applications. This is a good thing. Most of the time, anyway…

However, when your PowerShell script runs in a 32 bits process on a 64 bits OS, and you want to integrate with 64-bits applications (e.g. you want to integrate SharePoint or SQL Server within Visual Studio), WoW64 can get in the way.

E.g., WoW64 hides the 64 bit registry and changes the environment variables for processor architecture and for the program files folder – in short, WoW64 hides that you are running on a 64 bits OS.

To detect a 64 bits OS from PowerShell on Vista, W2008 and later Windows versions, we could use WMI:

(Get-WMIObject win32_operatingsystem).OSArchitecture

However, this is not supported on W2003.

Fortunately, Microsoft provided an alternative, which is supported on all Windows versions that have Wow64: the IsWow64Process function. Since this is an unmanaged API call to Kernel32.dll, we need to do some extra work to call this in PowerShell.

We can write a simple managed C# wrapper around IsWow64Process:

using System;
using System.Runtime.InteropServices;
 
public class Kernel32
{
    [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo);
 
    // This overload returns True if the current process is running on Wow, False otherwise
    public bool CurrentProcessIsWow64()
    {
        bool retVal;
        if (!(IsWow64Process(System.Diagnostics.Process.GetCurrentProcess().Handle, out retVal))) { throw new Exception("IsWow64Process() failed"); }
        return retVal;
    }
}

When we use the PowerShell InvokeCSharp function, we can put this C# inline in our PowerShell script:

Function global:CurrentProcessIsWOW64
{
    # Use some inline C# code to call the unmanaged IsWow64Process() function in Kernel32.dll and return its result:
    $code = @"
        using System;
        using System.Runtime.InteropServices;
 
        public class Kernel32
        {
            [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo);
 
            // This overload returns True if the current process is running on Wow, False otherwise
            public bool CurrentProcessIsWow64()
            {
                bool retVal;
                if (!(IsWow64Process(System.Diagnostics.Process.GetCurrentProcess().Handle, out retVal))) { throw new Exception("IsWow64Process() failed"); }
                return retVal;
            }
        }
"@
    InvokeCSharp -code $code -class 'Kernel32' -method 'CurrentProcessIsWow64'
}
 
Function global:ProcessArchitecture
{
    switch ([System.IntPtr]::Size)
    {
        4 { 32 }
        8 { 64 }
        default { throw "Unknown Process Architecture: $([System.IntPtr]::Size * 8) bits" }
    }
}
 
Function global:OSArchitecture
{
    if (((ProcessArchitecture) -eq 32) -and (CurrentProcessIsWOW64)) { 64 } else { ProcessArchitecture }
    # Note that on Vista, W2008 and later Windows versions, we could use (Get-WMIObject win32_operatingsystem).OSArchitecture.
    # We don't use that because we also support W2003
}

So there you have it, some simple PowerShell functions to detect the process architecture and the OS architecture, regardless of whether or not you are running under WoW64.

P.S. I also added these functions to the global functions in the Macaw Solutions Factory, so they can be leveraged by anyone who wants to extend the Factory.