Author Posts

August 16, 2015 at 10:46 pm

this script edits the datasource value for one of the connection string in configurations and one value in appsettings of a web.config file. its works perfectly when run locally but when passed to invoke-command as a script block to run in on multiple servers it just doesnt do anything and throws error.


[CmdletBinding()]
param(
#To point the web.config towards (HDC) database.
[switch]$toHDC,

#To point the web.config towards (EDC) database.
[switch]$toEDC
)

#setting directory location and filepaths and user
$WorkingDir = Get-Location
$path = $WorkingDir.path + "\server.txt"
$cred = Get-Credential
$serverList = Get-content $path
$Logfile = $WorkingDir.Path + "\$(Get-date -Format "yyyy-MM-dd")_Log.txt"

#create new log file if not present
if(!(Test-Path $Logfile)){
    New-Item -Path $Logfile -ItemType File
}

#Create persistent session with the list of servers.
$session = New-PSSession $serverList -Credential $cred

$hdcDB = "A"
$edcDB = "B"

#to switch DB as per parameter and write to log
$script= {

    $webConfig = "C:\temp\Web.config"
    $doc = (Get-Content $webConfig) -as [Xml]
    
    # getting current connection String and Datacentre code
    $root = $doc.get_DocumentElement();
	$root.
    $connection = $root.connectionStrings.add | Where {$_.name -eq "ConnectionKey"}
    $datacentercode = $root.appSettings.add | where { $_.key -eq "DataCentreCode"}
    $connection

    if($toHDC){
        $newconnection=$connection.connectionString.Replace($edcDB,$hdcDB);
        $newconnection
        $datacentercode.value = "HDC"
        Write-Output "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") USER:$($cred.UserName) INFO:Datasource value changed to $newconnection" | Out-File -FilePath $Logfile -Append
    }


    if($toEDC){
        $newconnection=$connection.connectionString.Replace($hdcDB,$edcDB);
        $datacentercode.value = "EDC"
        Write-Output "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") INFO:Datasource value changed to $newconnection" | Out-File -FilePath $Logfile -Append
    }
    $newconnection
    $connection.connectionstring= $newconnection

    #save the config file
    $doc.Save($webConfig)

    #Restarts the application pool
    Import-Module WebAdministration
    Restart-WebAppPool ABC
    Write-Output "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") INFO:Application pool ABC restarted  " | Out-File -FilePath $Logfile -Append
 
}

# Remotely executes the function to switch DB in config file on all the servers listed 
Invoke-Command -Session $session -ScriptBlock $script
#switchdb 

August 16, 2015 at 11:09 pm

What does the error say?

August 16, 2015 at 11:15 pm

Cannot set "connectionString" because only strings can be used as values to set XmlNode properties.
+ CategoryInfo : NotSpecified: (:) [], SetValueException
+ FullyQualifiedErrorId : XmlNodeSetShouldBeAString
+ PSComputerName : localhost

August 17, 2015 at 7:26 am

It's possible that $newconnection is an XML object and that is where the error is coming from, you could validated with:

$newconnection.GetType()

To convert it to a string, you could try:

$connection.connectionstring= $newconnection.ToString()

or

$connection.connectionstring= ($newconnection | Out-String)

August 17, 2015 at 1:34 pm

Ankutosh,

The scriptblock is running in a different PowerShell session, so it does not have access to the variables in the parent script. You need to either pass them explicitly to the scriptblock using -Arguments in Invoke-Command and Param in the scriptblock, or implicitly using syntax like $Using:toEDC. The former method is generally preferred as it is easier to test and debug.

August 17, 2015 at 11:12 pm

When i try to read just the document and populate some variable in below statements it displays nothing.( commented the ifs and saving document part.)
Root and connection both variables are still empty i guess thats why not able to set newconnection.

I tried few other ways i can find online but none seems to initiate them, they remain blank.
Just cant understand whats happending

$root = $doc.get_DocumentElement();
	$root
    $connection = $root.connectionStrings.add | Where {$_.name -eq "ConnectionKey"}
    $datacentercode = $root.appSettings.add | where { $_.key -eq "DataCentreCode"}
    $connection