how to update particular value in the appdomain file through powershell

I have many server having appdomain, i want to update only one value on multiple servers.
eg:
<appdomai>
  <test>
    <test acc> ....</test acc>
     </test>
     <data storage sql server=' nameof sqlserver'/>
</appdomain>
i want to update name of sql server in the xml file on multiple server.
LVL 5
VIVEKANANDHAN_PERIASAMYAsked:
Who is Participating?
 
chrismerrittCommented:
Please try this one out. I have tested it locally but you will probably want to test it against a couple of servers first with some dummy data maybe.

Usage:

Change the variables under the Customise Vars section to fit your needs:

#Customise Vars
$ServerListFile = "C:\TEMP\servers.txt"
$XMLRootPath = "E:\amdroot"
$FileSearchName = "appdomain"
$Filter = "*.xml"
$NewSQLServer = "NewSQLServer"

Then you should be able to run the code OK :)

My Testing:

I created a dummy servers.txt file in C:\temp\servers.txt with the following content to mimic multiple servers:

127.0.0.1
localhost

Then I ran my script against it and had the following results:

Server: 127.0.0.1
Network Path: \\127.0.0.1\E$\amdroot
Found File: \\127.0.0.1\E$\amdroot\Microsoft\microsoftmicrosoftappdomain.xml
Found File: \\127.0.0.1\E$\amdroot\Yahoo\yahoochatappdomain.xml
Found File: \\127.0.0.1\E$\amdroot\google1appdomain.xml
New Connection String: Server=NewSQLServer;Database=databasename;Trusted_Connection=Yes;Connect Timeout=3000
Saving XML to file: \\127.0.0.1\E$\amdroot\Microsoft\microsoftmicrosoftappdomain.xml
File saved successfully!
New Connection String: Server=NewSQLServer;Database=databasename;Trusted_Connection=Yes;Connect Timeout=3000
Saving XML to file: \\127.0.0.1\E$\amdroot\Yahoo\yahoochatappdomain.xml
File saved successfully!
New Connection String: Server=NewSQLServer;Database=databasename;Trusted_Connection=Yes;Connect Timeout=3000
Saving XML to file: \\127.0.0.1\E$\amdroot\google1appdomain.xml
File saved successfully!
Server: localhost
Network Path: \\localhost\E$\amdroot
Found File: \\localhost\E$\amdroot\Microsoft\microsoftmicrosoftappdomain.xml
Found File: \\localhost\E$\amdroot\Yahoo\yahoochatappdomain.xml
Found File: \\localhost\E$\amdroot\google1appdomain.xml
New Connection String: Server=NewSQLServer;Database=databasename;Trusted_Connection=Yes;Connect Timeout=3000
Saving XML to file: \\localhost\E$\amdroot\Microsoft\microsoftmicrosoftappdomain.xml
File saved successfully!
New Connection String: Server=NewSQLServer;Database=databasename;Trusted_Connection=Yes;Connect Timeout=3000
Saving XML to file: \\localhost\E$\amdroot\Yahoo\yahoochatappdomain.xml
File saved successfully!
New Connection String: Server=NewSQLServer;Database=databasename;Trusted_Connection=Yes;Connect Timeout=3000
Saving XML to file: \\localhost\E$\amdroot\google1appdomain.xml
File saved successfully!

The Code!

Function ChangeSQL-XML
{
	param
	(
		$FileName,
		$NewSQLServer
	)
	
	#Attempt to get XML Content
	$XMLError = 0

	if (Test-Path $FileName)
	{
		Try
		{
			$FileContent = Get-Content $FileName
			$XMLFileContent = [xml]$FileContent
		}
		Catch [Exception]
		{
			$XMLError = 1
			Write-Host -ForeGroundColor "Red" -BackGroundColor "Black" "$($_.Exception)"
		}
	}
	else
	{
		$XMLError = 1
		Write-Host "File not Found"
	}

	if ($XMLError -eq 0)
	{
		#Get Current Connect String
		$ConnectString = $XMLFileContent.AppDomain.DataStorage.ConnectString

		#Get SQL Server from Connect String
		$SQLServer = $ConnectString.Substring(0, ($ConnectString.IndexOf(";")))
		$SQLServer = $SQLServer.SubString($SQLServer.IndexOf("=") + 1)

		#Replace SQL Server in Connect String
		$NewConnectString = $ConnectString.Replace($SQLServer, $NewSQLServer)
		$XMLFileContent.AppDomain.DataStorage.ConnectString = $NewConnectString
		
		Write-Host -ForeGroundColor "Yellow" "New Connection String: $NewConnectString"

		#Save XML		
		$SaveXMLError = 0

		Try
		{
			$XMLFileContent.Save($FileName)
			Write-Host -ForeGroundColor "Yellow" "Saving XML to file: $FileName"
		}
		Catch [Exception]
		{
			$SaveXMLError = 1
			Write-Host -ForeGroundColor "Red" -BackGroundColor "Black" "$($_.Exception)"
		}
		Finally
		{
			if ($SaveXMLError -eq 0)
			{
				Write-Host -ForeGroundColor "Yellow" "File saved successfully!"
			}
		}
	}
}

Function ScanFor-XML
{
	param
	(
		$NetworkPath,
		$FileSearchName,
		$Filter
	)
	
	$FileArray = @()
	
	if (Test-Path $NetworkPath)
	{
		[array]$FileCollection = gci $NetworkPath -Include $Filter -recurse
		
		if ($FileCollection.Count -gt 0)
		{
			foreach ($File in $FileCollection)
			{
				if ($File.Name -match $FileSearchName)
				{
					Write-Host -ForeGroundColor "Yellow" "Found File: $($File.FullName)"
					$FileArray += $File
				}
			}
		}
	}
	
	return $FileArray
	
}

#Customise Vars
$ServerListFile = "C:\TEMP\servers.txt"
$XMLRootPath = "E:\amdroot"
$FileSearchName = "appdomain"
$Filter = "*.xml"
$NewSQLServer = "NewSQLServer"

[array]$ServerList = Get-Content $ServerListFile

#Check if ServerList contains any entries
if ($ServerList.Count -gt 0)
{
	foreach ($Server in $ServerList)
	{
		Write-Host -ForeGroundColor "Magenta" "Server: $Server"
		
		$XMLNetworkPath = $XMLRootPath.Replace(":","$")
		$NetworkPath = "\\" + $Server + "\" + $XMLNetworkPath
		
		Write-Host -ForeGroundColor "Yellow" "Network Path: $NetworkPath"
		
		[array]$XMLNetworkFiles = ScanFor-XML $NetworkPath $FileSearchName $Filter
		
		if ($XMLNetworkFiles.Count -gt 0)
		{
			foreach ($XMLNetworkFile in $XMLNetworkFiles)
			{
				ChangeSQL-XML $XMLNetworkFile $NewSQLServer
			}
		}
	}
}

Open in new window

0
 
chrismerrittCommented:
Can you give me an exact copy of the XML document?

Replace any server names etc for security purposes if you want to.
0
 
VIVEKANANDHAN_PERIASAMYAuthor Commented:

<AppDomain Name="Name" Running="Enabled" LoggingStr="EventLog;AMDRoot\logs\AMD.log" Assembly="AMDRoot\AMDEngine\AMDAgent.exe" ReferencePath="AMDRoot\Name">

                <DataCollector CycleTime="60" CycleStartDelay="0" ThreadMaxStartDelay="evenly" EngineTimeout="50" ApplicationName="Name" SimulatorKind="DOTNET" SimulatorRunAt="Local" SimulatorAssembly="AMDRoot\Name.dll" SimulatorClassName="RelationshipManagement" SessionConfigFile="AMDRoot\Name\Personal.xml" SimulatorTraceFile="AMDRoot\logs\Name\NameTrace.txt" SimulatorLoginAccount="" SimulatorLoginDomain="" SimulatorLoginPassword="" ConnectionLimit="1" MaxServicePoints="" SessionStartBoundaryMinute="1" Debug="1">

                                <AccountDatabase Application="Name" Environment="Production" AccountType="Login" AMDEngine="ServerName" AccountGroup="" UserLoginNameWithDomain="False" ConnectStringEncrypt="False" ConnectString="Server=AMDCentral;Database=Test;Trusted_Connection=Yes;Connect Timeout=60"/>

                                <AccountGroup ScenarioID="Name" TestMode="PersonaTest" UserLoginName="" UserPassword="" Domain="Domainname" Timeout=""  PersonaURL="http://website" BatchAdminURL="http://website" URL="http://website" URL="http://website" PlatformURL="http://website" ErrorFileURL="\\AMDFILE\AMDRoot\logs\Name\Errors\" Trace="1">

                                                <Account TestDataId="Personal" UserAccountHost="Email" Transactions="Dummy_Trans_EA,CreateSync_EA,Lookup"/>
                                                <Account TestDataId="Personan" UserAccountHost="Email4" Transactions="Dummy_Trans_EA,CreateSync_EA,Lookup"/>
                                </AccountGroup>
                                <ShuffledParams></ShuffledParams>
                </DataCollector>
                <DataStorage Source="SQL" UpdateType="SQL" DataSaveMode="Own" CycleTime="" XmlSchemaFile="AMDRoot\Logs\Name\NameDataStorage.xsd" SaveDir="AMDRoot\Logs\Name" MaxLocalFileSize="" ConnectStringEncrypt="False" ConnectString="Server=sqlname;Database=databasename;Trusted_Connection=Yes;Connect Timeout=3000"/>
</AppDomain>


0
On-Demand: Securing Your Wi-Fi for Summer Travel

Traveling this summer?Check out our on-demand webinar to learn about the importance of Wi-Fi security and 3 easy measures you can start taking immediately to protect your private data while using public Wi-Fi. Follow us today to learn more!

 
chrismerrittCommented:
You can try this, however it kicks up an error with your XML saying that the "URL" attribute on Line 7 is a duplicate attribute name, and it's right it is. If I remove one of them it works just fine. Is this a problem in your real files or just the one you put here?

As normal I would highly recommend testing this against a copy of your original files, back stuff up etc before making changes in live! Can't stress this enough!

Assumptions:

I assume here we are updating the SQL server in the connection string, let me know if I've missed the mark.

Alternative Approaches

Some other approaches may include replacing the existing files with an updated copy you have, assuming all the appdomain files have the same content this may be preferable to file level modifications. Likewise if the connection string as a whole needs to be replaced it might be preferable to just update the lot instead of doing what i'm doing, which is trying to split the text out and find what needs to be replaced.

If you can't get the XML to validate in PowerShell then you can echo through the file as a normal file system object operation and replace the content anyway, but the XML method i've used should be more precise as it works against the nodes directly.

Running against multiple machines:

If you can test this against a single file, we can then worry about changing lots of files across your systems, in my experience though get the basics working first, we can use this as an inner code block for an outer query that loops through systems/files so no worries there.

Error Handling:

I included some basic error handling in this, i.e. if you don't provide a valid file path it won't process it, and if the file causes an exception when trying to parse the XML it won't proceed either, and finally any errors on the save will be picked up and return an Exception as well.

The code:

#Customise Vars

$FileName = "C:\TEMP\file1.xml"
$NewSQLServer = "NewSQLServer"

#Attempt to get XML Content

$XMLError = 0

if (Test-Path $FileName)
{
	Try
	{
		$FileContent = Get-Content $FileName
		$XMLFileContent = [xml]$FileContent
	}
	Catch [Exception]
	{
		$XMLError = 1
		Write-Host -ForeGroundColor "Red" -BackGroundColor "Black" "$($_.Exception)"
	}
}
else
{
	$XMLError = 1
	Write-Host "File not Found"
}

if ($XMLError -eq 0)
{
	#Get Current Connect String

	$ConnectString = $XMLFileContent.AppDomain.DataStorage.ConnectString

	#Get SQL Server from Connect String

	$SQLServer = $ConnectString.Substring(0, ($ConnectString.IndexOf(";")))
	$SQLServer = $SQLServer.SubString($SQLServer.IndexOf("=") + 1)

	#Replace SQL Server in Connect String

	$NewConnectString = $ConnectString.Replace($SQLServer, $NewSQLServer)
	$XMLFileContent.AppDomain.DataStorage.ConnectString = $NewConnectString

	#Save XML

	Try
	{
		$XMLFileContent.Save($FileName)
	}
	Catch [Exception]
	{
		Write-Host -ForeGroundColor "Red" -BackGroundColor "Black" "$($_.Exception)"
	}
}

Open in new window

0
 
VIVEKANANDHAN_PERIASAMYAuthor Commented:
Yes it works. But when i run under mutiple server, nodes will be the same but content inside will varies.So want to confirm will not be affected.

And now how can we make chages to multiple servers?
0
 
chrismerrittCommented:
Are the files always in the same locations on all the servers? or would you need to feed it a CSV with content like this?

Server   | Path
Server1 | C:\Folder\file.xml
Server2 | C:\Folder\SubFolder\file.xml
Server3 | C:\Folder\SubFolder\file2.xml

If the locations are always the same it's simpler to handle but I need your guidance on this really.
0
 
VIVEKANANDHAN_PERIASAMYAuthor Commented:
chrismerritt: First of all I like to appreciate your support and help,being so patient and understanding.
Your are quite different from others.


actually i have like below

server1|e:\amdroot\messenger\messengerlogappdomain.xml
server1|e:\amdroot\microsoftmicrosoftappdomain.xml
server2|e:\amdroot\yaoo\yahoochatappdomain.xml
server3|e:\amdroot\google\google1appdomain.xml

e:\amdroot\nameoftheapplication\there will be many subfiles.
But in the subfiles we will only one appdomain file.
similarity will be nameoftheapplication+appdomain


0
 
chrismerrittCommented:
Are you able to easily formulate an import list of these in that CSV format? or would you prefer to check the e:\amdroot\ folder for any .xml files and attempt to modify them all automatically for each server?

Either way is good for me, I would just prefer not to make any assumptions on the way you would prefer to do this :)
0
 
VIVEKANANDHAN_PERIASAMYAuthor Commented:
would prefer to check the e:\amdroot\ folder\xmlfiles for any .xml files and attempt to modify them all automatically for each server

but there are many other xml files ,which shouldn't be disturbed.

For the information: other xml file will not have same set of nodes.
0
 
chrismerrittCommented:
Will the name of the file always contains "appdomain"?
0
 
VIVEKANANDHAN_PERIASAMYAuthor Commented:
yes it will always contain appdomain.
 like nameoftheapplication+appdomain
0
 
VIVEKANANDHAN_PERIASAMYAuthor Commented:
$XMLRootPath = "E:\amdroot"
$NewSQLServer = "NewSQLServer"


for this two variable,i like to pass the value through text file.
I tried using
$XMLRootPath = gci c:\temp\path.txt
$NewSQLServer =  gci c:\temp\value.txt

It's giving exception error. how to achieve the above requirement.
0
 
chrismerrittCommented:
You need to use gc instead of gci
0
 
VIVEKANANDHAN_PERIASAMYAuthor Commented:
yes, i tried get-content as well but it was giving me the same error
0
 
chrismerrittCommented:
I created a file called C:\TEMP\path.txt and put the following in it:

E:\amdroot

Then I ran this in PowerShell:

PS C:\Users\Chris> $XMLRootPath = gc "C:\TEMP\path.txt"
PS C:\Users\Chris> $XMLRootPath | Out-Host
E:\amdroot
PS C:\Users\Chris>

So it appears to work fine via text file.

If you're trying to pass multiple values in those text files it won't work, as you would need a looping logic to handle multiple values.

What is the exception you get?
0
 
VIVEKANANDHAN_PERIASAMYAuthor Commented:
the below code i have used. and i getting following error

PS C:\Users\vivek\Desktop\sql> & '.\Changing SQL Server name in the appdomain.ps1'
Get-Content : Cannot find path 'C:\Users\vivek\Desktop\sql\servername' becaus
e it does not exist.
At C:\Users\vivek\Desktop\sql\Changing SQL Server name in the appdomain.ps1:1
08 char:33
+ [array]$ServerList = Get-Content <<<<  $ServerListFile
    + CategoryInfo          : ObjectNotFound: (C:\Users\vivek\Desktop\sql\servername:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetCo
   ntentCommand

in the error i have replaced the my hostname with the servername for security reason.
Function ChangeSQL-XML
{
	param
	(
		$FileName,
		$NewSQLServer
	)
	
	#Attempt to get XML Content
	$XMLError = 0

	if (Test-Path $FileName)
	{
		Try
		{
			$FileContent = Get-Content $FileName
			$XMLFileContent = [xml]$FileContent
		}
		Catch [Exception]
		{
			$XMLError = 1
			Write-Host -ForeGroundColor "Red" -BackGroundColor "Black" "$($_.Exception)"
		}
	}
	else
	{
		$XMLError = 1
		Write-Host "File not Found"
	}

	if ($XMLError -eq 0)
	{
		#Get Current Connect String
		$ConnectString = $XMLFileContent.AppDomain.DataStorage.ConnectString

		#Get SQL Server from Connect String
		$SQLServer = $ConnectString.Substring(0, ($ConnectString.IndexOf(";")))
		$SQLServer = $SQLServer.SubString($SQLServer.IndexOf("=") + 1)

		#Replace SQL Server in Connect String
		$NewConnectString = $ConnectString.Replace($SQLServer, $NewSQLServer)
		$XMLFileContent.AppDomain.DataStorage.ConnectString = $NewConnectString
		
		Write-Host -ForeGroundColor "Yellow" "New Connection String: $NewConnectString"

		#Save XML		
		$SaveXMLError = 0

		Try
		{
			$XMLFileContent.Save($FileName)
			Write-Host -ForeGroundColor "Yellow" "Saving XML to file: $FileName"
		}
		Catch [Exception]
		{
			$SaveXMLError = 1
			Write-Host -ForeGroundColor "Red" -BackGroundColor "Black" "$($_.Exception)"
		}
		Finally
		{
			if ($SaveXMLError -eq 0)
			{
				Write-Host -ForeGroundColor "Yellow" "File saved successfully!"
			}
		}
	}
}

Function ScanFor-XML
{
	param
	(
		$NetworkPath,
		$FileSearchName,
		$Filter
	)
	
	$FileArray = @()
	
	if (Test-Path $NetworkPath)
	{
		[array]$FileCollection = gci $NetworkPath -Include $Filter -recurse
		
		if ($FileCollection.Count -gt 0)
		{
			foreach ($File in $FileCollection)
			{
				if ($File.Name -match $FileSearchName)
				{
					Write-Host -ForeGroundColor "Yellow" "Found File: $($File.FullName)"
					$FileArray += $File
				}
			}
		}
	}
	
	return $FileArray
	
}

#Customise Vars
$ServerListFile = gc C:\Users\vivek\Desktop\sql\servers.txt
$XMLRootPath = gc "C:\Users\vivek\Desktop\sql\amdpath.txt"
$FileSearchName = "appdomain"
$Filter = "*.xml"
$NewSQLServer = gc "C:\Users\vivek\Desktop\sql\sqlservername.txt"

[array]$ServerList = Get-Content $ServerListFile

#Check if ServerList contains any entries
if ($ServerList.Count -gt 0)
{
	foreach ($Server in $ServerList)
	{
		Write-Host -ForeGroundColor "Magenta" "Server: $Server"
		
		$XMLNetworkPath = $XMLRootPath.Replace(":","$")
		$NetworkPath = "\\" + $Server + "\" + $XMLNetworkPath
		
		Write-Host -ForeGroundColor "Yellow" "Network Path: $NetworkPath"
		
		[array]$XMLNetworkFiles = ScanFor-XML $NetworkPath $FileSearchName $Filter
		
		if ($XMLNetworkFiles.Count -gt 0)
		{
			foreach ($XMLNetworkFile in $XMLNetworkFiles)
			{
				ChangeSQL-XML $XMLNetworkFile $NewSQLServer
			}
		}
	}
}

Open in new window

0
 
chrismerrittCommented:
Problem is as far as I can see is that you've said:

$ServerListFile = gc C:\Users\vivek\Desktop\sql\servers.txt

Then:

[array]$ServerList = Get-Content $ServerListFile

Basically you're getting the content of the file, then getting the content of the content of the file?

Try this:

$ServerListFile = "C:\Users\vivek\Desktop\sql\servers.txt"

[array]$ServerList = Get-Content $ServerListFile

That should work.
0
 
VIVEKANANDHAN_PERIASAMYAuthor Commented:
Experts was really very good to work with, i really appreciate his work.
I like award him more points to him.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.