tags:

views:

598

answers:

2

I've already asked a related question, but sadly the answers, whilst correct, didn't actually solve my problem.

I'm using the ManagementClass/ManagementObject WMI API (because it's better at handling remote administration than the DirectoryEntry API). I'd like to completely remove the existing script maps from a

Using the common string format solution seems to work for VBS, but not for the ManagementClass API. So, I've been trying to write something that would create the correct array of script map objects e.g.

    foreach (var extension in extensions) {
        var scriptMap = scriptMapClass.CreateInstance();
        SetWmiProperty(scriptMap, "ScriptMap.Extensions", "." + extension);

Unfortunately, it doesn't seem possible to implement the function SetWmiProperty. If I attempt the following

wmiObject.Properties.Add(propertyName, CimType.SInt32);

I get "Operation is not valid due to the current state of the object.". On the other hand, if I just try to set the property, I get told that the property doesn't exist. The scriptMap class has the path "ScriptMap", which is what the existing objects display.

Does anyone have any working code that manipulates ScriptMaps using the ManagementClass API?

+1  A: 

I find it's very difficult to create WMI objects from scratch. Easier to Clone() an existing object you've queried from the system and then modify it. Here's a function I wrote recently to deal with ScriptMaps. It's in Powershell, not C#, but the idea is the same:

function Add-AspNetExtension
{
    [CmdletBinding()]
    param (
        [Parameter(Position=0, Mandatory=$true)]
        [psobject] $site  # IIsWebServer custom object created with Get-IIsWeb
        [Parameter(ValueFromPipeline=$true, Mandatory=$true)]
        [string] $extension
    )

    begin 
    {
        # fetch current mappings
        # without the explicit type, PS will convert it to an Object[] when you use the += operator
        [system.management.managementbaseobject[]] $maps = $site.Settings.ScriptMaps

        # whatever the mapping is for .aspx will be our template for mapping other things to ASP.NET
        $template = $maps | ? { $_.Extensions -eq ".aspx" }
    }

    process
    {
        $newMapping = $template.Clone()
        $newMapping.Extensions = $extension
        $maps += newMapping
    }

    end
    {
        $site.Settings.ScriptMaps = $maps
    }
}
Richard Berg
Exactly what I needed. Thankyou so much: this solved an annoyance I've had outstanding for two years.
Julian Birch
A: 

A C# example of the technique outlined by Richard Berg.

static void ConfigureAspNet(ManagementObject virtualDirectory, string version, string windowsLocation, IEnumerable<string> extensions)
    {
        var scriptMaps = virtualDirectory.GetPropertyValue("ScriptMaps");
        var templateObject = ((ManagementBaseObject[])scriptMaps)[0];
        List<ManagementBaseObject> result = new List<ManagementBaseObject>();
        foreach (var extension in extensions) {
            var scriptMap = (ManagementBaseObject) templateObject.Clone();
            result.Add(scriptMap);
            if (extension == "*")
            {
                scriptMap.SetPropertyValue("Flags", 0);
                scriptMap.SetPropertyValue("Extensions", "*");
            } else
            {
                scriptMap.SetPropertyValue("Flags", 5);
                scriptMap.SetPropertyValue("Extensions", "." + extension);
            }
            scriptMap.SetPropertyValue("IncludedVerbs", "GET,HEAD,POST,DEBUG");
            scriptMap.SetPropertyValue("ScriptProcessor",
                string.Format(@"{0}\microsoft.net\framework\{1}\aspnet_isapi.dll", windowsLocation, version));
        }
        virtualDirectory.SetPropertyValue("ScriptMaps", result.ToArray());
        virtualDirectory.Put();
    }
Julian Birch