all,
I am trying to update a line in config file with powershell and I can't seem get it working properly...
I have this file: config.ini
version.clients.latest.location=.\
version.clients.latest.classpath=My.jar
version.clients.latest.mainclass=gui.Launch
version.clients.latest.jreLocation=C:\home\user\agent\install_master\Deploy\Admin\..\1AOpenJRE\jre1.8.0_342\jre8
version.clients.latest.jre.options=-Xmx256m -Dcrow.library.path=.\crow\crow-native -Dcrow.runtime.path=.\crow\cre\ -Denv.global.clp.enable=false
#version.clients.latest.xre.isUsed=true
#version.clients.latest.xre.version=2.2
#version.clients.latest.xre.location=L:\Cross-Projects\2.2\2.5\xre
version.client.latest.xre.isUsed=true
version.client.latest.xre.version=2.2
version.client.latest.xre.location=./xre
version.client.latest.xulWrapper.dllFile=./xre/XULWrapper.dll
version.client.latest.xre.cache.isEnabled=true
version.client.latest.xre.cache.isShared=true
version.client.latest.jreOptions=-Dsun.java2d.ddoffscreen=false
and I want to update this line
version.clients.latest.jreLocation=C:\home\user\agent\install_master\Deploy\Admin\..\1AOpenJRE\jre1.8.0_342\jre8
with a new path... Like so...
version.clients.latest.jreLocation=..\..\..\1AOpenJRE\jre1.8.0_342\jre8
and I made this script
# Config
$CfgFile = ".\cfg\cfg.ini"
$SearchString = "version.clients.latest.jreLocation="
$ConfigContent = Get-Content "$CfgFile"
$ConfigSelectLine = Get-Content -Path "$CfgFile" | Select-String $SearchString
$LineNum = $ConfigSelectLine.LineNumber
$key = $ConfigSelectLine -Split("=")[0]
$filePath = $ConfigSelectLine -Split("..")[1]
$ImportantPath = $filePath -Split("..")[1]
$NewLine = 'version.clients.latest.jreLocation=..\..\..' + $ImportantPath
$ConfigContent[$LineNum] = "$NewLine" | Set-Content ".\cfg\cfg-test.ini"
and when I run it, I a output file with one line ...
version.clients.latest.jreLocation=..\..\..\
How do we split a string on ".."? and why is the entire file wiped out when I try to update the single line in the file by line number?
Cheers,
X
The following line doesn't do what you intend:
$ConfigContent[$LineNum] = "$NewLine" | Set-Content ".\cfg\cfg-test.ini"
This saves the value of $NewLine
only to file .\cfg\cfg-test.ini
, and then stores the output from the Set-Content
call in the element with index $LineNum
of array $ConfigContent
(and, unless you use -PassThru
, `Set-Content produces no output).
While ($ConfigContent[$LineNum] = "$NewLine") | Set-Content ".\cfg\cfg-test.ini"
would - thanks to (...)
- first update the array element and then pass the updated value through, you'd still only save that element to the file.
The problem with the splitting by ..
is simply due to calling .Split('..')[1]
twice.
Replace:
$filePath = $ConfigSelectLine -Split("..")[1]
$ImportantPath = $filePath -Split("..")[1]
with:
$ImportantPath = $ConfigSelectLine -Split("..")[1]
Also, you should add the -SimpleMatch
switch to your Select-String
call to ensure that your search term is used literally.
The immediate fix for the single-line-only result is to first update the array element and then send the updated array as a whole to the output file:
$ConfigContent[$LineNum] = $NewLine
Set-Content ".\cfg\cfg-test.ini" -Value $ConfigContent
Note the use of the -Value
parameter rather than the pipeline, which speeds up the operation.
However, your code can be greatly streamlined, using a switch
statement:
$CfgFile = ".\cfg\cfg.ini"
$SearchString = "version.clients.latest.jreLocation="
$(
switch -WildCard -File $CfgFile {
"$SearchString*" {
$prop, $value = $_ -split '=', 2
"$prop=" + '..\..\..' + $value.Split('..')[1]
}
Default { $_ } # pass through
}
) | Set-Content .\cfg\cfg-test.ini