Table format, columns order - powershell

I need to decide the columns' orders of my table. My actual command is that one:
$tab | Sort-Object "Pourcentage" -Descending |
Format-Table -AutoSize |
Out-String -Width 4000 |
Out-File -Append O:\sigdci\public\parcoursArborescence\bilanAnalyse.txt
It gives me that order:
Derniere modification Categorie recherchee Dernier acces Dossier Pourcentage
But I need "Dossier" to be first, then "Categorie recherchee" and "Pourcentage" shall be 2nd and 3rd. How shall I proceed?

Specify the column headers in the desired order:
$tab | Sort-Object "Pourcentage" -Descending |
Format-Table 'Dossier', 'Categorie recherchee', 'Pourcentage',
'Derniere modification', 'Dernier acces' -AutoSize |
Out-String -Width 4000 |
Out-File -Append 'O:\sigdci\public\parcoursArborescence\bilanAnalyse.txt'
If you need to dynamically determine the column names you could do it like this:
$headers = $tab[0].PSObject.Properties |
Where-Object MemberType -eq NoteProperty |
Select-Object -Expand Name
However, you'd have to bring that list into your desired order somehow. Perhaps you could do it like this:
$allHeaders = 'Dossier', 'Categorie recherchee', 'Pourcentage',
'Derniere modification', 'Dernier acces'
$actualHeaders = $tab[0].PSObject.Properties |
Where-Object { MemberType -eq NoteProperty } |
Select-Object -Expand Name
$headers = $allHeaders | Where-Object { $actualHeaders -contains $_ }
$allHeaders is an array that contains all headers in the correct order. Then you remove all items that aren't present in $actualHeaders from that list, preserving the order of the remaining headers.

Related

when exporting to the text file compare-object issue

I want to get an output like below.
My output now :
Name Active PrimarySmtpAddress
---- ------ ------------------
DG_Group1 True mail1#contoso.com
DG_Group2 False mail2#contoso.com
DG_Group3 True mail3#contoso.com
My desired output :
mail1#contoso.com
mail2#contoso.com
mail3#contoso.com
script :
$DistroLists = Get-DistributionGroup -ResultSize Unlimited
$MessageTrace = Get-MessageTrace -RecipientAddress $DistroLists.PrimarySmtpAddress -startdate (Get-Date).AddDays(-8) -EndDate (Get-Date)
$DistroLists |
Foreach-Object {
$_ | Add-Member -MemberType NoteProperty -Name Active -Value (
$_.PrimarySmtpAddress -in $MessageTrace.RecipientAddress
) -PassThru
} |
Select-Object Name, Active, PrimarySmtpAddress | Where-Object Active -EQ "FALSE"
Out-File C:\output.txt
You can use Select-Object -ExpandProperty or ForEach-Object -MemberName to grab only the value of a specific property from one or more piped input objects:
... |Select-Object Name, Active, PrimarySmtpAddress | Where-Object Active -eq $false | ForEach-Object -MemberName PrimarySmtpAddress | Out-File...
You can skip first two lines and split the line using space characters. Finally pick the last column as given below:
Get-Content C:\Projects\logtext.txt | Select-Object -Skip 2 | ForEach-Object { "$(($_
-split '\s+',3)[2])" }
mail1#contoso.com
mail2#contoso.com
mail3#contoso.com

Powershell conundrum: how to compare to CSVs and pull matching data from each?

I've got a CSV file with a list of names in a "name" column. In a second CSV I have a list of names in a "name" column, and also their employee IDs in an "employeeid" column.
My desired output is this: take the "name" column in CSV1, compare it to the "name" column in CSV2, and wherever there's a match, take the name from the "name" column of CSV1 and the matching employee ID in CSV2, and create a new CSV3 with a "name" column and corresponding "employeeid" column.
Here is an image describing my question
I've started playing with import-csv to pull each CSV in as a variable, and also tinkered with piping that with select headers, but I don't understand the logic necessary to take username column matches between CSV1 and CSV2 and then combine that with employeeID from CSV2.
Thanks in advance for any guidance you can provide.
Brian
--
Updated 3/19
$csv1 = import-csv -Path "C:\csv1.csv" | select-object -ExpandProperty 'accountname' | Sort-Object | where {$_ -ne ""}
$csv2 = import-csv -Path "C:\csv2.csv" | select 'accountname','employeeid'
$accountNamesFromCSV2 = $csv2 | select-object -ExpandProperty accountname
$compareTheTWo = Compare-Object -ReferenceObject $csv1 -DifferenceObject $accountNamesFromCSV2 -ExcludeDifferent -IncludeEqual -passThru
It's friday so I'll be nice. To do it at the prompt:
$csv2 = import-csv .\bar.csv; Import-CSV .\foo.csv | %{$name1 = $_.name;$id = ($csv2 | ?{$_.Name -eq $name1}).EmployeeID; Add-Member -InputObject $_ -MemberType NoteProperty -Name EmployeeID -Value $id; $_} | select Name, EmployeeID | Export-CSV .\result.csv
Or, a little more human friendly version in a script:
$csv2 = Import-CSV .\bar.csv
$result = New-Object System.Collection.ArrayList
foreach($user in (Import-CSV .\foo.csv)){
$id = ($csv2 | Where-Object{$_.Name -eq $user.Name).EmplyeeID
Add-Member -InputObject $user -MemberType NoteProperty -Name EmployeeID -Value $id
$result.Add($user) | Out-Null
}
$result | Export-CSV .\result.csv -NoTypeInformation

Split property value in Powershell

I am currently trying to do an Out-GridView to get a simple overview about our group policy objects. To do so, I am using the Get-GPO cmdlet, like so:
Get-GPO -all |
Select-Object -Property DisplayName, Description |
Sort-Object -Property DisplayName |
Out-GridView
In our company we use the first line of the description field to store the name of the admin who created the policy, and all following lines hold a short description.
I would want to be able to grab the first line of the the Description field with the column header Responsability and all other lines of the field in a separate column. So assuming my current code would give me a table like this:
DisplayName | Description
-------------------------
GPO1 | Username
| stuff
| stuff
I would want it to look like this:
DisplayName | Responsability | Description
------------------------------------------
GPO1 | Username | stuff
| | stuff
How can I achieve this?
As #Matt suggested, you can use a calculated property.
Then since Description is a string, rather than an array of strings, you will need to split the line at the line breaks. This can be done by using -split and since it's information from a GPO we can assume Windows line endings `r`n (Otherwise you could use [environment]::newline)
The first property, use array element [0] will be the first line. For the second property, we'll need to save the array in a variable. Then we can use the length of that variable to get first element through the last.
Get-GPO -all |
Select-Object -Property DisplayName, #{
Name = "Responsibility"
Expression = {($_.Description -split "`r`n")[0]}
}, #{
Name = "Description"
Expression = {
$linearray = ($_.Description -split "`r`n")
$linearray[1..($linearray.length - 1)] | Out-String
}
} |
Sort-Object -Property DisplayName |
Out-GridView
Alternatively, you could create a new object rather than using the calculated property.
Get-GPO -all |
ForEach-Object {
$linearray = ($_.Description -split "`r`n")
[pscustomobject]#{
"DisplayName" = $_.DisplayName
"Responsibility"= $linearray[0]
"Description" = $linearray[1..($linearray.length - 1)] | Out-String
}
} |
Sort-Object -Property DisplayName |
Out-GridView
The first thing to understand is what Get-GPO is returning: an array of objects, each of which has a set of properties.
What is displayed in your table is a series of rows (one per object), with the columns being the values of the properties for that object.
Therefore if you want a new column, you need a new property.
There are two ways you can do this: create a calculated property with Select-Object or add a property to the objects via Add-Member.
Calculated
You may provide a hashtable as a property to Select-Object, and the hashtable must have two keys:
Name (the name of the property)
Expression (a scriptblock that will be executed to determine the value, where $_ refers to the object itself)
Get-GPO -all |
Select-Object -Property DisplayName, Description, #{
Name = 'Responsibility'
Expression = {
($_.Description -split '\r?\n')[0] # First line
}
} |
Sort-Object -Property DisplayName |
Out-GridView
New Member
You can use a ScriptProperty that will execute a scriptblock each time the property is called on the object. Use $this to refer to the object in this context.
Get-GPO -all |
Add-Member -MemberType ScriptProperty -Name Responsibility -Value {
($this.Description -split '\r?\n')[0] # First line
} -Force -PassThru |
Select-Object -Property DisplayName, Responsibility, Description |
Sort-Object -Property DisplayName |
Out-GridView
I would probably use something like this:
Get-GPO -All | ForEach-Object {
$info = $_.Description
$pos = $info.IndexOf([Environment]::NewLine)
if ( $pos -gt 0 ) {
$responsibility = $info.Substring(0,$pos)
$description = $info.Substring($pos + [Environment]::NewLine.Length)
}
else {
$responsibility = ""
$description = $info
}
[PSCustomObject] #{
"DisplayName" = $_.DisplayName
"Responsibility" = $responsibility
"Description" = $description
}
}
This way you can preserve formatting.

Append results or text to text file by using Powershell

I have a collection of objects with properties: ProductName and PartName. The content of collection is output to a file first:
$colProducts | sort-object ProductName | `
Select-object ProductName PartName | `
Format-Table -autosize ProductName, PartName | `
Out-File myProducts.txt
So far so good. However, I have trouble to append a text message to the result file like this:
Add-Content myProducts.txt "`nParts in more than one Product`n"
I found that the appended text is not readable at the end. One thing I notice is that the output of the first collection to a file is in Unicode, and the second one code (add-content) is in ASCII if only to a new file.
After this, I would like to continue to add the following information the same result file:
$colProducts | Group-object PartName | sort-object PartName | `
Where-Object {$_.Count -gt 1 } | `
Select-object ProductName PartName | `
Format-Table -autosize ProductName, PartName | `
Out-File myProducts.txt
The above codes will overwrite to the result file. I need to append to the file. Greatly appreciate help!
Update: It is good to know -Append option. How about Add-Content? It seems adding some unreadable chars to the file after Out-File from collection.
I would first try:
$colProducts | Group-object PartName | sort-object PartName | `
Where-Object {$_.Count -gt 1 } | `
Select-object ProductName PartName | `
Format-Table -autosize ProductName, PartName | `
Out-File -Append myProducts.txt
And then look at this to get a feel for what you were encountering.
Essentially, Out-File (and Out-File -Append) gives you Unicode by default and Add-Content gives ASCII by default. My advice would be stick to the same command and you shouldn't have a problem.
And, of course, help Out-File -Detailed! Always check out the powershell examples because they help a great deal, not just to figure out their common usage, but to grok them as well.
Try:
$colProducts | Group-object PartName | sort-object PartName | `
Where-Object {$_.Count -gt 1 } | `
Select-object ProductName PartName | `
Format-Table -autosize ProductName, PartName | `
Out-File -Append myProducts.txt
Another option:
$colProducts | sort-object ProductName | `
Select-object ProductName PartName | `
Format-Table -autosize ProductName, PartName | `
Out-String | Add-Content myProducts.txt
Add-Content myProducts.txt "`nParts in more than one Product`n"

Modifying CSV content with Powershell

I have a CSV file, Devices.csv, containing IP Address, DeviceName, SerialNumber, MAC Address, UserName.
The Users column in all the rows of Devices.csv is prepopulated with a value [Unknown]
The code...
{Import-CSV Devices.csv | Where-Object {$_.IPAddress -eq '192.168.2.124'} | Select-Object -last 1 | FT IPAddress, devicveName, SerialNumber, MACAddress, User -AutoSize }
....outputs
IPAddress deviceName SNumber MACAddress User
--------- ----- ------- ---------- ----
192.168.2.124 ComputerA 1ABCDEFG 00xxYYbbCCdd [Unknown]
I want to be able to replace the [Unknown] text with a Username I have retrieved from a different source. Can I update just the User column on this line in Devices.csv using powershell and keep the rest of the CSV file intact ?
Thanks, Brian
$csv = Import-CSV Devices.csv
$csv | Where-Object {$_.IPAddress -eq '192.168.2.124'} | Select-Object -Last 1 | ForEach-Object {$_.User = $user}
$csv | Export-Csv Devices.csv -NoTypeInformation
Try this:
$otheruser = '...'
Import-Csv Devides.csv | % {
if ($_.User -eq '[Unknown]') { $_.User = $otheruser }
$_
} | Export-Csv Divices_modified.csv -NoTypeInformation