-1

trying to find all *.config files which contain specific assembly info. In my case, I want to find all config files which has System.Net.Http with version 4.0.0.0

this is how the example content looks like:

     <dependentAssembly>
        <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf38564e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="5.2.4.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f750a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bfad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="4.0.0.0" />
      </dependentAssembly>

so I need the location of that config file which

starts with: <assemblyIdentity name="System.Net.Http" AND

ends with: newVersion="4.0.0.0" which are in same dependentAssembly

the lines can have nasty empty spaces before and at the end of line some line endings (\r\n)

appreciate any help!

This is what I have tried:

$dDir = Get-ChildItem -Recurse -File -Filter "*.config" -ErrorAction SilentlyContinue
$dDir |  ?{$_ | Select-String -Pattern "System.Net.Http"} | ?{$_ | Select-String -Pattern "newVersion=\`"4.0.0.0\`""} | select fullname

but this also returns if the newVersion="4.0.0.0" was found in different dependentAssembly

So I tried using regex (regex noob):

$dDir |  ?{$_ | Select-String -Pattern '(.*)\<assemblyIdentity name=\"System.Net.Http\"(.*)newVersion=\"4.0.0.0\"(.*)' -AllMatches}

but this return nothing

pandemic
  • 1,135
  • 1
  • 22
  • 39
  • 1
    What have you tried so far? – TobyU Aug 23 '18 at 07:47
  • got all files which are *config using gci *.config -recurse and then tried `Select-String` with multiple patterns but it also returns the filenames if the `newVersion="4.0.0.0"` was found in different `DependentAssembly` .This is what I have tried so far: `$dDir | ?{$_ | Select-String -Pattern "System.Net.Http"} | ?{$_ | Select-String -Pattern "newVersion=`"4.0.0.0`""} | select fullname – pandemic Aug 23 '18 at 07:50
  • 2
    Please edit your question and enter what you tried so far there. – Paxz Aug 23 '18 at 07:51
  • Ive edited my question with the what I have tried so far section – pandemic Aug 23 '18 at 07:57
  • What's the desired output for that file? – Paolo Aug 23 '18 at 08:12
  • just to return the name of the file if the regex pattern is found in that particular file – pandemic Aug 23 '18 at 08:26
  • 1
    [Do not parse XML with regex.](http://stackoverflow.com/a/1732454/1630171) – Ansgar Wiechers Aug 23 '18 at 08:29
  • In your particular case, you parsing xml files which are structured. So why not open and read all files and follow normal xml probing? – Alex Sarafian Aug 23 '18 at 09:50

2 Answers2

0

Since the config file appears to be xml, I suggest you use PowerShell's XML capabilities.
The fragment of the .config file is unfortunately incomplete and misses the root tag.

Let's assume it is like this:

<root>
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf38564e35" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="5.2.4.0" />
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f750a3a" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="4.0.0.0" />
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bfad364e35" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="4.0.0.0" />
    </dependentAssembly>
</root>

Then you could do something like this:

$configFiles = Get-ChildItem $path -Recurse -File -Filter "*.config" -ErrorAction SilentlyContinue
foreach ($file in $configFiles) {
    [xml]$XmlDocument = Get-Content -Path $file.FullName

    $test = $XmlDocument.root.dependentAssembly | 
        Where-Object {$_.assemblyIdentity.name -eq 'System.Net.Http' -and $_.bindingRedirect.newVersion -eq '4.0.0.0'} |
        Select-Object @{Name = 'AssemblyName'; Expression = {$_.assemblyIdentity.name}}, 
                      @{Name = 'Version'; Expression = {$_.bindingRedirect.newVersion}}

    if ($null -ne $test) {
        Write-Host $file.FullName
    }
}

There is probably a much easier way to do this using XPath, but I'm not very familiar with that..

However

If you MUST/REALLY WANT TO do this using Regular Expression, maybe because the the config files contain non 'Well-Formed' xml or you are simply interested in how this can be done with a Select-String construct, try:

$rx = '(?s)<dependentAssembly>\s*<assemblyIdentity\s+(name\s*=\s*"System\.Net\.Http")[^<]+<bindingRedirect[^<]+(newVersion\s*=\s*"4\.0\.0\.0")\s+/>\s*</dependentAssembly>'

Get-ChildItem -Path D:\test -Recurse -Filter '*.config' | ForEach-Object {
    if ($_ | Get-Content -Raw | Select-String -Pattern $rx -Quiet) {
        Write-Host $_.FullName
    }
}
Theo
  • 57,719
  • 8
  • 24
  • 41
-1

I am writing down the Python code. I think you can find equivalent in PowerShell.

for match in regex.finditer('(System\.Net\.Http).+?newVersion\=\"(4\.0\.0\.0)',text):
    print (match)
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Madh
  • 21
  • 4