Reputation: 59
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
Upvotes: 0
Views: 508
Reputation: 30153
$XMLPaths.GetType().Name
returns String
. Use
$auxiliaryPath = "\\DFSRoot\DFS Share\view\Profiles\*\AppData\Roaming\Trillian"
$XMLPaths = (Get-ChildItem "$auxiliaryPath\Events.xml" -Recurse -Force).FullName
Upvotes: 0
Reputation: 333
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
Upvotes: 0