0

I created a script to loop through our user directories and modify and XML document to change a setting in an application. Normally when I use a foreach it would make my variable = one item from collection. Instead this script is putting everything from $XMLPaths into my $Path variable.

$XMLPaths = Get-ChildItem \\DFSRoot\DFSShare\view\Profiles\*\AppData\Roaming\Trillian\ -Recurse -Force |
            Where-Object {$_.Name -contains 'Events.xml'} |
            Select FullName |
            FT -HideTableHeaders |
            Out-String

foreach ($Path in $XMLPaths) {
  $xml = [xml](Get-Content $Path)
  $node = $xml.events.prefs.setting | Where {$_.Name -eq 'Sounds'}
  $node.value = '1'
  $XML.Save($Path)
  $Path
  $node
}

Here is the XML document I am using.

<?xml version="1.0" encoding="utf-8" ?>
    <!DOCTYPE events
        PUBLIC "--//IETF//DTD RFCxxxx XEVENTS 1.0//EN" "xevents.dtd">

<!-- WARNING: This is a generated file by Trillian.  Do not update while -->
<!--          Trillian is running otherwise updates will be erased       -->

    <events>
        <version>1.0</version>
        <Prefs>
            <setting name="idle" value="1"/>
            <setting name="sounds" value="1"/>
            <setting name="sounds_away" value="1"/>
            <setting name="sounds_suppress" value="1"/>
            <setting name="automatic_outbound" value="1"/>
            <setting name="hide_disabled" value="1"/>
            <setting name="video_capture" value="1"/>
            <setting name="buzz_sound" value="1"/>
            <setting name="game_status" value="0"/>
            <setting name="awaymessage_song" value="0"/>
            <setting name="awaymessage_autosave" value="1"/>
            <setting name="awaymessage_update2" value="1"/>
            <setting name="away_autoresponse" value="0"/>
        </Prefs>
        <AwayList>
            <AwayGroup name="Root">
                <AwayMessage label="Set%20all%20Do%20Not%20Disturb" text="" awayState="1" awayMenu="1" autoRespond="0" system="1">
                    <Status medium="ASTRA" type="Do%20Not%20Disturb"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Offline" text="" awayState="1" awayMenu="0" autoRespond="1" system="1">
                    <Status medium="ASTRA" type="Offline"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Away" text="Away%20since%20%25time%25%20%28%25timeZoneOffset%25%29" awayState="1" awayMenu="1" autoRespond="1" system="1">
                    <Status medium="ASTRA" type="Away"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Invisible" text="" awayState="1" awayMenu="1" autoRespond="0" system="1">
                    <Status medium="ASTRA" type="Invisible"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Back" text="" awayState="0" awayMenu="1" autoRespond="0" system="1">
                    <Status medium="ASTRA" type="Online"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Idle" text="Idle%20since%20%25time%25%20%28%25timeZoneOffset%25%29" awayState="1" awayMenu="0" autoRespond="1" system="1">
                    <Status medium="ASTRA" type="Away"/>
                </AwayMessage>
            </AwayGroup>
        </AwayList>
    </events>

The variable $Path which should only have one directory in it at a time instead has this in it.

\\DFSROOT\DFSSHare\view\Profiles\User1\AppData\Roaming\Trillian\users\User1\Events.xml
\\DFSROOT\DFSSHare\view\Profiles\User2\AppData\Roaming\Trillian\users\User2\Events.xml
\\DFSROOT\DFSSHare\view\Profiles\User3\AppData\Roaming\Trillian\users\User3\Events.xml
\\DFSROOT\DFSSHare\view\Profiles\User4\AppData\Roaming\Trillian\users\User4\Events.xml
\\DFSROOT\DFSSHare\view\Profiles\User5\AppData\Roaming\Trillian\users\User5\Events.xml
2
  • Do not use Format-Table as intermediate step in pipeline. Commented Feb 14, 2017 at 22:03
  • Also don't use Out-String unless you actually intend the result to be a string. Commented Feb 14, 2017 at 22:50

2 Answers 2

0

The problem lies in that your resulting $XMLPaths variable is a string and not an array. Thus, your ForEach expression interprets the variable $XMLPaths as an array of one element, with the one element being a string containing all of the paths concatenated together.

You can always check the type of a variable $Variable by typing $Variable.GetType(). For example, when I ran your first line of code this is what I saw:

PS > $XMLPaths.GetType()

IsPublic IsSerial Name    BaseType
-------- -------- ----    --------
True     True     String  System.Object

Try replacing the first line with this:

#Remote Computers
$XMLPaths = (Get-ChildItem \\DFSRoot\DFS Share\view\Profiles\*\AppData\Roaming\Trillian\ -Recurse -Force | Where-Object {$_.Name -contains 'Events.xml'} | Select FullName).FullName

After the Select FullName clause, an array of objects that contain the property FullName is returned. So by calling .FullName on that, it returns an array of the file names.

You should be able to check that $XMLPaths is of type array:

PS > $XMLPaths.GetType()

IsPublic IsSerial Name      BaseType
-------- -------- ----      --------
True     True     Object[]  System.Array
Sign up to request clarification or add additional context in comments.

Comments

0

$XMLPaths.GetType().Name returns String. Use

$auxiliaryPath = "\\DFSRoot\DFS Share\view\Profiles\*\AppData\Roaming\Trillian"
$XMLPaths = (Get-ChildItem "$auxiliaryPath\Events.xml" -Recurse -Force).FullName

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.