ConvertTo-HTML - format object properties? - powershell

I am outputing an array of objects in HTML using this:
$arrinfo | Where-Object {$_.Status -eq "Delivered"} | ConvertTo-HTML - PreContent "<h2><font color=green>Delivered:</font></h2>" -Property Name, Outputfile, StartTime,EndTime,TotalSeconds -fragment |Out-String
My question is, can I format things without creating a new object? Specifically, I am looking to format the dates (StartTime,EndTime) in a different format.
I guess I could create another array of objects with the format needed, but am wondering if there is a better way.

You can use calculated properties:
$arrinfo |
Where-Object {$_.Status -eq "Delivered"} |
Select-Object Name,Outputfile,#{n='StartTime';e={$_.StartTime.ToString('ddMMyyyy')}},#{n='EndTime';e={$_.EndTime.ToString('ddMMyyyy')}},TotalSeconds |
ConvertTo-HTML -PreContent "<h2><font color=green>Delivered:</font></h2>" -Fragment |
Out-String

June Blender explains calculated properties in Name that Property.
Get-ChildItem | Select-Object #{Name = "Attributes"; Expression = {$_.Mode}},
#{Name = "Updated_UTC"; Expression = {$_.LastWriteTime.ToUniversalTime()}}, Name

Related

Empty Value does not return

Get-VM |
Select Name, Operatingsystem, VMHost, PowerState,
#{N="Datastore"; E={$_ |
Get-Datastore}} |
Out-gridview
I ran this command. It will return and output a grid view with all rows filled in.
However, the field "OperatingSystem" returns a blank column, nothing there.
Untested, but I think you can do this:
Get-VM | Select-Object Name,
#{Name = 'Operatingsystem'; Expression = {$_.Guest.OsFullName}},
VMHost, PowerState,
#{Name = 'Datastore'; Expression = {$_ | Get-Datastore}} |
Out-GridView
You're looking for the "Guest" property I think. FYI you can also do this to view everything if you're not sure of the exact name
Get-VM |
Select-Object -Property * |
Out-gridview

Problem using select-object #{name="Name"; expression=$variable}

I tried something like this but it never gives the values, where my ifile.csv contains two columns displayname, grpmail
Import-Csv "E:\ifile.csv" | foreach {get-distributionGroupMember -Identity $_.displayname | select-Object #{Name= GroupName; Expression = {$_.grpmail}}, Recipienttype, Primarysmtpaddress} | Export-csv -no typeinformation "E:\Ofile.csv"
Can anyone advise me what I am doing wrong
I am expecting ofile.csv with 3 columns as GroupName, Recipienttype, Primarysmtpaddress
i get values for Recipienttype, Primarysmtpaddress columns but GroupName column is always empty.
It's because your $_ in the pipeline has changed to the result of your get-distributiongroupmember and is no longer your CSV file input.
Try this instead:
Import-Csv "E:\ifile.csv" | foreach {
$gname = $_.grpmail
Get-distributionGroupMember -Identity $_.displayname | Select #{Name= GroupName; Expression = {$gname}}, Recipienttype, Primarysmtpaddress} | Export-csv -no typeinformation "E:\Ofile.csv"
I've just split lines 2 and 3 to make it easier to read - you can put a semi-colon after $gname = $_.grpmail instead if you like.
As a general note, I like to assign specific variable names to pipeline objects to see what I'm actually working with, especially if they're being transformed on the way. Also, I like to use multiple lines to better see what's happening
foreach ($g in (Import-Csv "E:\ifile.csv")) {
Get-distributionGroupMember -Identity $g.displayname |
Select #{Name= GroupName; Expression = {$g.grpmail}},Recipienttype,Primarysmtpaddress
} | Export-csv -notypeinformation "E:\Ofile.csv"
EDIT
As per T-Me's suggestion, try this:
Import-Csv "E:\ifile.csv" | ForEach-Object {
$grpmail = $_.grpmail
get-distributionGroupMember -Identity $_.displayname | Select-Object #{ Name = 'GroupName'; `
Expression = "$grpmail" }, `
Recipienttype, Primarysmtpaddress
} | Export-csv -no typeinformation "E:\Ofile.csv"

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.

Force Convertto-html to only include an object's "MemberType" "property"

I have an array of system.data.datarow objects. Now the properties of these objects have the info I want. When I pass these objects to convertto-html though it picks up all this extra crap and I see rows with names like RowError,RowState,Table- when all I want is the objects properties.
Is there a way I can only include the object's properties to be converted to html (meaning if I do a Get-Member on the object the "MemberType" property).
Can I convert these objects to generic psobjects without having to loop through them all and rebuild them with New-Object?
You can grab the names of all the Property-type properties with Get-Member and Select-Object:
$Props = Get-Member -InputObject $DataRowObjects[0] -MemberType Property | Select-Object -ExpandProperty Name
$Html = $DataRowObjects | Select-Object -Property $Props | ConvertTo-Html
The only problem with the accepted answer is that it changes the order of the fields to alphabetical from the given field names
To avoid and keep the original order from the select statement, I used the following approach
$unwantedColumns = #('RowError','RowState','Table','ItemArray','HasErrors') # these guys get added automatically by Invoke-SqlCmd
$props = $sqlResult.PSObject.Properties.Name | Where-Object {$_ -NotIn $unwantedColumns}
$htmlBody = $sqlResult |
Select-Object -Property $props |
ConvertTo-Html #ConvertToHtmlArgs |
Out-String

Output data with no column headings using PowerShell

I want to be able to output data from PowerShell without any column headings. I know I can hide the column heading using Format-Table -HideTableHeaders, but that leaves a blank line at the top.
Here is my example:
get-qadgroupmember 'Domain Admins' | Select Name | ft -hide | out-file Admins.txt
How do I eliminate the column heading and the blank line?
I could add another line and do this:
Get-Content Admins.txt | Where {$_ -ne ""} | out-file Admins1.txt
But can I do this on one line?
In your case, when you just select a single property, the easiest way is probably to bypass any formatting altogether:
get-qadgroupmember 'Domain Admins' | foreach { $_.Name }
This will get you a simple string[] without column headings or empty lines. The Format-* cmdlets are mainly for human consumption and thus their output is not designed to be easily machine-readable or -parseable.
For multiple properties I'd probably go with the -f format operator. Something along the lines of
alias | %{ "{0,-10}{1,-10}{2,-60}" -f $_.COmmandType,$_.Name,$_.Definition }
which isn't pretty but gives you easy and complete control over the output formatting. And no empty lines :-)
A better answer is to leave your script as it was. When doing the Select name, follow it by -ExpandProperty Name like so:
Get-ADGroupMember 'Domain Admins' | Select Name -ExpandProperty Name | out-file Admins.txt
If you use "format-table" you can use -hidetableheaders
add the parameter -expandproperty after the select-object, it will return only data without header.
The -expandproperty does not work with more than 1 object. You can use this one :
Select-Object Name | ForEach-Object {$_.Name}
If there is more than one value then :
Select-Object Name, Country | ForEach-Object {$_.Name + " " + $Country}
Joey mentioned that Format-* is for human consumption. If you're writing to a file for machine consumption, maybe you want to use Export-*? Some good ones are
Export-Csv - Comma separated value. Great for when you know what the columns are going to be
Export-Clixml - You can export whole objects and collections. This is great for serialization.
If you want to read back in, you can use Import-Csv and Import-Clixml. I find that I like this better than inventing my own data formats (also it's pretty easy to whip up an Import-Ini if that's your preference).
First we grab the command output, then wrap it and select one of its properties. There is only one and its "Name" which is what we want. So we select the groups property with ".name" then output it.
to text file
(Get-ADGroupMember 'Domain Admins' |Select name).name | out-file Admins1.txt
to csv
(Get-ADGroupMember 'Domain Admins' |Select name).name | export-csv -notypeinformation "Admins1.csv"
$server = ('*')+(Read-Host -prompt "What Server Context?")+'*'
$Report = (Get-adcomputer -SearchBase "OU=serverou,DC=domain,DC=com" -filter {name -like $server} -SearchScope Subtree|select Name |Sort -Unique Name)
$report.Name | Out-File .\output\out.txt -Encoding ascii -Force
$Report
start notepad .\output\out.txt
Put your server SearchBase in above.
If you are not sure what your server OU is try this function below...
#Function Get-OSCComputerOU($Computername)
{
$Filter = "(&(objectCategory=Computer)(Name=$ComputerName))"
$DirectorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$DirectorySearcher.Filter = $Filter
$SearcherPath = $DirectorySearcher.FindOne()
$DistinguishedName = $SearcherPath.GetDirectoryEntry().DistinguishedName
$OUName = ($DistinguishedName.Split(","))[1]
$OUMainName = $OUName.SubString($OUName.IndexOf("=")+1)
# $Obj = New-Object -TypeName PSObject -Property #{"ComputerName" = $ComputerName
# "BelongsToOU" = $OUMainName
# "Full" = $DistinguishedName}
$Obj = New-Object -TypeName PSObject -Property #{"Full" = $DistinguishedName}
$Obj
}
Makes sure to run the Get-OSCComputerOU Servername with a select -expandproperty Full filter.
Then just plug in the response to the Searchbase...
All thanks to http://www.jaapbrasser.com