How to extract attribute and value from XML inside a Powershell script? - powershell

I have written the following XML, which allows me to extract data values from a Visual Studio Resources.resx file where the name contains a certain value:
Select-Xml -XPath '//data[contains(#name,''QIM'')]/value' -Path 'Resources.resx' | Select-Object -Expand Node | Select-Object -Expand '#text'
How can I expand this Powershell script to add the name attribute as a heading (ideally surrounded by some characters like ** to identify it as a heading) before each set of text in the resulting file - this is for a diff to allow an email notification of changes, so any suggestions that would allow it to be diffed against an existing file are also appreciated.

Try the following, which provides the results as [pscustomobject] instances, which results in a two-column tabular display:
Select-Xml -XPath '//data[contains(#name,''QIM'')]' -Path 'Resources.resx' |
ForEach-Object {
[pscustomobject] #{
NameAttributeValue = $_.Node.name
ElementText = $_.Node.value
}
}
The output will be something like this:
NameAttributeValue ElementText
------------------ -----------
foo QIM some text
bar QIM some other text

Related

Powershell Select Specific Text

Hello and thank you for your time. Here is what I am looking to do. I have several log files that I need to search through. I do this by using Get-ChildItem -Path C:\mylogfiles\*.log | Select-String -Pattern 'MyTextHere' However, now I want to complicate my life and only select text that is between single quotes in the log files.
Here is a sample of my log file:
This is some sample text in my log file. It has a lot of garbage that I don't want to see. However, it has text that I want to find, and if found I would like it to save just the selected text to a CSV file. I want to copy everything that is between single quotes. Here comes the text 'Please copy this text that is between the single quotes'
Any idea how I would go about doing this?
The following combines Select-String with ForEach-Object to extract only the phrases of interest (the parts of the line that matched the regex), wraps them in a [pscustomobject] instance with a .Phrase property and exports the results with Export-Csv:
Select-String -Path C:\mylogfiles\*.log -AllMatches -Pattern "'.*?'" |
ForEach-Object {
foreach ($phrase in $_.Matches.Value) {
[pscustomobject] #{ Phrase = $phrase.Trim("'") }
}
} |
Export-Csv -NoTypeInformation -Encoding utf8 result.csv
Note: If there can only ever be at most one phrase of interest per line, you can omit the -AllMatches switch and replace the ForEach-Object call with the following Select-String call, which uses a calculated property:
# ... |
Select-Object -Property #{ Name='Phrase'; Expression={ $_.Matches.Value.Trim("'") } } |
# ...

powershell compare properties of two network adapters side-by-side

I'm just beginning Powershell, and I want to look at all the properties of two network adapters side-by-side in order to easily see differences.
I've used:
Get-NetAdapter -name "(adapter's name)" | Format-List -Property "*"
multiple times to display all the properties of each adapter one after the other, but it's hard to compare this way.
The perhaps easiest way of doing this is to DIY create a csv file.
I think this will work:
# get the info for the two adapters
$info = Get-NetAdapter -Name 'LAN-connection 1', 'LAN-connection 2'
# create a template string to output csv rows.
# use the systems ListSeparator character so you can double click to open in Excel
$csvline = '"{0}","{1}","{2}"' -replace ',', (Get-Culture).TextInfo.ListSeparator
# create a List object to store the content in
$csvOut = [System.Collections.Generic.List[string]]::new()
# add a headers line
[void]$csvOut.Add(($csvline -f 'Property', $info[0].Name, $info[1].Name))
$info[0].PsObject.Properties | Select-Object * | ForEach-Object {
# get the matching property fro the second adapter
$prop2 = $info[1].PsObject.Properties[$_.Name]
# add the data row
[void]$csvOut.Add(($csvline -f $_.Name, $_.Value, $prop2.Value))
}
# show on screen (although it will probably not fit..)
$csvOut | ConvertFrom-Csv -UseCulture
# write to CSV file to open in Excel
$csvOut | Set-Content -Path 'D:\Test\AdapterInfo.csv'

Convert a list of URLs into clickable HTML links using ConvertTo-HTML

I have the function below that will create an HTML table however I want the values in my table to hyperlinks.
Function MyFunction{
clear-host
$item=$null
$hash = $null #hashTable
$hash =#{"Google.com" = "www.google.com"; "Yahoo" = "www.yahoo.com";"My Directory" ="C:\Users\Public\Favorites" ;"MSN" = "www.msn.com"}
ForEach($item in #($hash.KEYS.GetEnumerator())){
$hash | Sort-Object -Property name
}
$hash.GetEnumerator() | sort -Property Name |Select-Object Name, Value | ConvertTo-HTML | Out-File .\Test.html
}
MyFunction
Small side note before we start: The ForEach seems pointless as it just outputs the sorted table for each element in the table. So that gets removed.
ConvertTo-HTML on its own is great for making table with PowerShell object but was we need is hyperlinks instead. ConvertTo-HTML does support calculated properties so at first it would seem easy to just make a formatted hyperlink.
ConvertTo-HTML -Property *,#{Label="Link";Expression={"<a href='$($_.Value)'>$($_.Name)</a>"}}
The small issue with that is ConvertTo-Html does some conversion on the string being sent to it which obfuscates our intention. Looking in the output file that is created we see the following for the Yahoo link:
<td><a href='www.yahoo.com'>Yahoo</a></td>
ConvertTo-Html made our text browser friendly which would be nice normally but hinders us now. Reading a blog from PowerShell Magazine covers this issue by decoding the html before it is send to file.
Function MyFunction{
clear-host
$hash = #{"Google.com" = "www.google.com"; "Yahoo" = "www.yahoo.com";"My Directory" ="C:\Users\Public\Favorites" ;"MSN" = "www.msn.com"}
$hash.GetEnumerator() | sort -Property Name | Select-Object Name, Value |
ConvertTo-HTML -Property *,#{Label="Link";Expression={"<a href='$($_.Value)'>$($_.Name)</a>"}}
}
$html = MyFunction
Add-Type -AssemblyName System.Web
[System.Web.HttpUtility]::HtmlDecode($html) | Out-File C:\temp\test.html
Using [System.Web.HttpUtility]::HtmlDecode converts values like < back to what we want them to be. Have a look at the output
Went looking to see if this has been asked before and there is a similar answer: How to generate hyperlinks to .htm files in a directory in Powershell?. It is handled in a different way so im on the fence about marking this as a duplicate.

Add character end of line in PowerShell

I'm looking for a solution for the following challenge:
I run the following command in PowerShell.
Import-Module servermanager
Get-WindowsFeature | where {$_.Installed -eq "True"} | ft DisplayName, Installed > output.txt
Now I want to add a character at the end of each row. How can I do that?
I think I have to add the content into an array, but I don't know how to finish the code.
At the end I have to load the content into the EventViewer. If I send it directly, the event description isn't formatted well.
You could add another field to the records like this:
Get-WindowsFeature | ? { $_.Installed } |
select DisplayName, Installed, #{n='Other',e={'c'}} | ft
It sounds like instead of using ft > output.txt, you want something like:
foreach { echo ( $_.DisplayName + " " + $_.Installed + " extra_stuff" ) } > output.txt
It doesn't give you a nicely formatted table though.
It's a little outside the scope of what you directly asked, but I'd suggest skipping the 'write to text file' stage and pass directly to the destination.
Import-Module servermanager
$installedFeatures = #() # Creates a blank array for the features
$output = #() # Creates a blank array for formatted results
$yourChar # The character/ string you want to add at the end of each row
$installedFeatures = Get-WindowsFeature | Where-Object {$_.Installed -eq "True"}
foreach($feature in $installedFeatures)
{
$output += "$($feature.displayName) $($feature.installed) $yourChar"
}
Once you've iterated through all the Windows features, your $output variable will have an array of strings in the format of displayName installed $yourChar. You can then write to disk, or send the object somewhere else (this is the beauty of PowerShell objects!).

In Powershell -- Export object to textfile in custom format

Since, i am a beginner, i 've no much hands-on to the powershell programming.Although
i had a script developed to insert data from an array to the csv file as follows:
#Following is the array
$InventoryReport = New-Object -TypeName PSobject -Property #{
ComputerName = "1myComputerName"
DomainName = "2myComputerDomain"
Manufacturer = "3myComputerManufacturer"
}
#Now to export the data to csv, i am using following:
$InventoryReport |Select-Object -Property ComputerName, DomainName, Manufacturer | Export-Csv -Path "c:\abc.csv" -NoTypeInformation -ErrorAction Stop
#This works fine
and the output of above is :
"ComputerName","DomainName","Manufacturer"
"1myComputerName","2myComputerDomain","3myComputerManufacturer"
....
Now, i don't want this , i want the ouput to appear in columnar fashion i.e.
"ComputerName","1myComputerName"
"DomainName","2myComputerDomain"
"Manufacturer","3myComputerManufacturer"
What code changes should be done to achieve this. ?
Either you want CSV, which you already have, or you want a custom txt-file. If you want the latter, try this:
$comp = gwmi win32_computersystem
#"
"ComputerName","$($comp.Name)"
"DomainName","$($comp.Domain)"
"Manufacturer","$($comp.Manufacturer)"
"# | Out-File test.txt
sample of test.txt output below. I've got a non-domain, custom built pc, so don't worry about the values.
"ComputerName","GRAIMER-PC"
"DomainName","WORKGROUP"
"Manufacturer","System manufacturer"
EDIT I suggest you learn what CSV is. Remember that CSV is not a fileformat, it's a formatting-style used in a normal textfile. The .csv extension is just cosmetic to let people know that the textfile uses the csv-style. Check out Wikipedia and Technet
In the CSV file, each object is represented by a comma-separated list
of the property values of the object. The property values are
converted to strings (by using the ToString() method of the object),
so they are generally represented by the name of the property value.
Export-CSV does not export the methods of the object.
The format of an exported file is as follows:
-- The first line of the CSV file contains the string '#TYPE ' followed by the fully qualified name of the object, such as #TYPE
System.Diagnostics.Process. To suppress this line, use the
NoTypeInformation parameter.
-- The next line of the CSV file represents the column headers. It contains a comma-separated list of the names of all the properties of
the first object.
-- Additional lines of the file consist of comma-separated lists of the property values of each object.
You could try something like this:
$InventoryReport | Format-List ComputerName, DomainName, Manufacturer `
| Out-String -Stream `
| ? { $_ -ne '' } `
| % { $_ -replace '\s+:\s+', '","' -replace '(^|$)', '"' }