PowerShell: XML editing

Given an app.config or web.config, I want to update the value of an attribute, without directly editing the config file. MSDN has an example we can use to test it out.

psxml01

Let’s set the debug and mode values to true and Forms respectively. This person has a good article all about it.

This is the saved content we can work with:

<?xml version="1.0"?>
<!--
    Note: As an alternative to hand editing this file you can use the
    Web Site Administration Tool to configure settings for your application. Use
    the Web site->Asp.Net Configuration option in Visual Studio.
    A full list of settings and comments can be found in
    machine.config.comments usually located in
    \Windows\Microsoft.Net\Framework\v2.x\Config
-->
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
    <appSettings/>
    <connectionStrings/>
    <system.web>
        <!--
            Set compilation debug="true" to insert debugging
            symbols into the compiled page. Because this
            affects performance, set this value to true only
            during development.
        -->
        <compilation debug="false"/>
        <!--
            The <authentication> section enables configuration
            of the security authentication mode used by
            ASP.NET to identify an incoming user.
        -->
        <authentication mode="Windows"/>
        <!--
            The <customErrors> section enables configuration
            of what to do if/when an unhandled error occurs
            during the execution of a request. Specifically,
            it enables developers to configure html error pages
            to be displayed in place of a error stack trace.

        <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
            <error statusCode="403" redirect="NoAccess.htm"/>
            <error statusCode="404" redirect="FileNotFound.htm"/>
        </customErrors>
        -->
    </system.web>
</configuration>
Here is the PowerShell that does it all:
$webConfig = "C:\data\sandbox\ASP\web.config"
$xml = [xml] (get-content $webConfig)
$xml.configuration.'system.web'.compilation.debug = "true"
$xml.configuration.'system.web'.authentication.mode = "Forms"
$xml.Save($webConfig);

psxml02

That’s the PowerShell object way – you could also use XPath.

A more complex example involves more than 1 element instance (i.e. of the same name), giving the parser a challenge working out how to uniquely identify the required attribute to be updated:

webconfig01

In this second example,let’s update a specific attribute within sectionGroup . Note that there are 2 of these sectionGroups. Let us say we only want the sectionGroup where the value of the attribute [name] is [system.net]. And let’s say that within that, we only want the [section] where name=”webRequestModules”. And then having found that, we want to update the corresponding [type] attribute to “test this”.

Probably the most compelling thing I can show you is the ISE entry to achieve this. There are a lot of variables going on, but you have the advantage of Intellisense, as you will see when you try it for yourself:

webconfig02

… which achieves the desired result, without any manual editing of the config file:

webconfig03

The aim of updating the post for a more complex scenario was to show that a not-very-technical support person could understand how to do this kind of update. However that is perhaps not a great idea: better perhaps to prepare a library of known entries that a support person could execute from a batch or powershell command line. I had just played with something that reasoned a bit more at runtime, but to avoid too much error handling, if we take the above example, we could just have something hardcoded like: Set-XMLConfigFile(“AuthenticationModules”, “Just a test 2”) where Set-XMLConfigFile would call into an crude validator that checks for a white list set of values that the “system” knows about, and updates those.

Leave a comment