Trying to combine replace and new-item in powershell

前提是你 提交于 2020-12-27 05:39:15

问题


I have a task to make changes to some Config files in a Directory, and the files that need changing are 7, all starting with "Monitoring_Tran_xx".

Within these files there are certain values (TransactionID="01" AgreedResponseTime="500" SearchProfileID="216") that need changing but not present across all 7, and will need to check if they are present before replace or creating them. Also I am trying to insert a new parameter(using new-item) if a certain parameter is equal to a certain value e.g. if TemplateType = "4152" then create a new parameter next to it "DirectoryPoolID = '3' "

I will appreciate your help on this please.

Thanks

Example of Config file below:

<?xml *version="1.0"* ?>
<Monitor>
    <Configuration OperatingMode="Transaction" LogFileName="C:\Program Files\*******s\MonitoringOMTR\MonitorLog_01.log" WriteFileInterval="120" ConnectionKey="**********" />
    <TransactionMonitoringConfig TransactionID="01" AgreedResponseTime="500" SearchProfileID="216" />
    <ShowMessages>
        <Message Name="MOISearchStart" />
        <Message Name="MOOSearchFound" />
        <Message Name="MOOSearchEnd" />
        <Message Name="MOOAlert" />
    </ShowMessages>
    <PerformanceCounters TransactionCount="191" TransactionBreaches="0" />
</Monitor>

Powershell script that i tried but it didn't quite result well:

(Get-Content -Path '***FS2072\UserData$\aroyet01\Desktop\HostPS.txt') |
    if ([bool]((Get-Content -Path "***FS2072\UserData$\aroyet01\Desktop\HostPS.txt") -like '*DirectoryPool*', '*SearchProfile*')) { 
write-host "Found it"
}
else {
 write-host "Did not find it"
}
    ForEach-Object {$_ -replace 'TransactionCount="191"', 'TransactionCount="196"'} |
        Set-Content -Path '***FS2072\UserData$\aroyet01\Desktop\HostPS.txt'
Get-Content -Path '***FS2072\UserData$\aroyet01\Desktop\HostPS.txt'

回答1:


I have a task to make changes to some Config files in a Directory, and the files that need changing are 7, all starting with "Monitoring_Tran_xx".

Stop treating your XML files as raw text - they can be parsed and treated with much better precision :)

First up, we need to parse the document(s) as XML, the easiest way probably being:

$xmlDocument = [xml](Get-Content C:\Path\To\)

Since you have multiple documents with a common naming pattern, we might use Get-ChildItem to discover the files on disk and loop over them to get the paths:

Get-ChildItem -Path C:\path\to\config\files\Monitoring_Tran_*.ps1 |ForEach-Object {
  # read each document from disk with `Get-Content`, convert to [xml]
  $xmlDocument = [xml]($_ |Get-Content)
}

Next, we need to be able to navigate our XML document. PowerShell has native syntax bindings for this:

$tmConfig = $xmlDocument.Monitor.TransactionMonitoringConfig

or, you can use XPath expressions to navigate the document as well:

$tmConfig = $xmlDocument.SelectSingleNode("/Monitor/TransactionMonitoringConfig")

Within these files there are certain values (TransactionID="01" AgreedResponseTime="500" SearchProfileID="216") that need changing but not present across all 7, and will need to check if they are present before replace or creating them

To check whether a named attribute exists on a node we can use the HasAttribute() method:

if($tmConfig.HasAttribute('TransactionID')){
  # attribute exists, let's update it!
  $tmConfig.SetAttribute('TransactionID', 123) # replace 123 with whatever ID you need
}

Also I am trying to insert a new parameter(using new-item) if a certain parameter is equal to a certain value e.g. if TemplateType = "4152" then create a new parameter next to it "DirectoryPoolID = '3' "

In the case where you want to add a new attribute to a node only if another attribute has a specific value, you can use GetAttribute() and SetAttribute():

if($xmlNode.GetAttribute('TemplateType') -eq "4152"){
  $xmlNode.SetAttribute("DirectoryPoolID", 3)
}

Whenever you're done, save the document back to file:

Get-ChildItem -Path C:\path\to\config\files\Monitoring_Tran_*.ps1 |ForEach-Object {
  # read each document from disk with `Get-Content`, convert to [xml]
  $xmlDocument = [xml]($_ |Get-Content)

  <# write all the code to inspect and update the attributes here #>

  # write document back to disk
  $xmlDocument.Save($_.FullName)
}



回答2:


Looking at your code snippet i can only assist by giving you the advice to start with basic Powershell syntax documentation.

help about_If
help about_Pipelines

To give you an idea... Your if is placed in a pipeline. Your ForEach-Object is not placed in a pipeline. Both of these don't work the way you posted it. You can start from something like this:

$Content = '***FS2072\UserData$\aroyet01\Desktop\HostPS.txt'
if ($Content -condition 'Yourcondition') {
    $Content | ForEach-Object {
        $_ -replace 'Regex', 'Replacement'
    }
} else {
    'Your else here'
}

For editing the xml file you can take a look at this post as hinted by vonPryz in this question today.



来源:https://stackoverflow.com/questions/63470287/trying-to-combine-replace-and-new-item-in-powershell

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!