getting property value in powershell when running convertto-html - powershell

I'm still new to powershell, and recently i came to know about get-member properties. However when i pipe the command to convertto-html the value disappear.
i have a data which is called link.csv and below is the content of the file
Target Node Address Status
------ ---- ------- ------
server01 0:2:3 20230002AC0153AF Up
server01 0:2:4 20240002AC0153AF Up
server01 1:2:3 21230002AC0153AF Up
server01 1:2:4 21240002AC0153AF Up
I'm able to get the property value as per below.
PS C:\Report\script\Temp> $a= Import-Csv .\link.csv | select Target,Node,Address,Status
PS C:\Report\script\Temp> $a.Node[1]
0:2:4
PS C:\Report\script\Temp> $a.Status[1]
Up
PS C:\Report\script\Temp> $a.Target[1]
server01
However when i output it to Convertto-Html
PS C:\Report\script\Temp> $a= Import-Csv .\link.csv | select Target,Node,Address,Status | ConvertTo-Html -Fragment -PreContent "<font color=`"Black`"><H4>Remote Copy Group - $b</H4></font> "
PS C:\Report\script\Temp> $a.Target[1]
Cannot index into a null array.
At line:1 char:1
+ $a.Target[1]
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
How can i get the property value while running convertto-html command.
Hope you can help me with the issue.
Thank You in advance.

If you want to capture intermediate results in the pipeline, use the -OutVariable / -ov common parameter with a variable name in order to store these results in that variable:
$html = Import-Csv .\link.csv |
Select-Object Target, Node, Address, Status -OutVariable a |
ConvertTo-Html -Fragment -PreContent "<font color=`"Black`"><H4>Remote Copy Group - $b</H4></font> "
$a.Target[1]
Note how the pipeline overall returns HTML (as an array of lines), whereas the intermediate custom objects filtered from the CSV input are stored in variable $a via -OutVariable, for later use - note how you must pass just the variable name to -OutVariable, without the $ sigil, i.e., just a rather than $a.

Related

How to use previous command output as a parameter in Powershell?

I need to write a Powershell one-liner to do a complex task. I need it to be strictly one line because I want to run it in a Go and Python script. The task requires taking the output of the first command and use it as a parameter in the second command.
I thought it was a simple task but I am struggling with it quite a bit. For example, the below command does not work:
$obj = Get-Item . | Get-Item $obj.Root | Format-List *
Get-Item : The input object cannot be bound to any parameters for the command either because the command does not take
pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
At line:1 char:21
+ $obj = Get-Item . | Get-Item $obj.Root | Format-List *
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (C:\Users\fhcat:PSObject) [Get-Item], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.GetItemCommand
What am I doing wrong?
Strictly one line sounds like a personal preference rather than a technical requirement.
However, you can end a statement with a semicolon or process the input via ForEach-Object
$obj = Get-Item .; Get-Item $obj.Root | Format-List *
or
Get-Item . | ForEach-Object {Get-Item $_.Root} | Format-List *

Trouble accessing members of select-string output when input is a system.array

I am calling restAPIs and some of them return multiple results, I am trying use Select-String to get the correct line in the Array, but it returns a matchinfo object with a value starting with #{... I can't get this value into a hashtable or object so I can extract a member from the string.
I tried converting the MatchInfo object to a string with out-string and then putting that result in a hashtable. Get following error:
Cannot convert the "
#{id=352475; href=/api/v1/exports/458234/export_files/352475; export_id=458234; status=Available}
" value of type "System.String" to type "System.Collections.Hashtable".
Have a PSCustomObject with the following contents:
PS C:> $_expFilesRet
href export_files
---- ------------
/api/v1/user_identities/289362/export_files {#{id=352475;
href=/api/v1/exports/458234/export_files/3...
The export files method of the above is
PS C:\> $_ExpFilesRet.export_files.getType();
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
with the following value:
PS C:\> $_expFilesRet.export_files
id href export_id status
-- ---- --------- ------
352475 /api/v1/exports/458234/exp... 458234 Available
278697 /api/v1/exports/357459/exp... 357459 Available
Attempted the following
PS C:\> $_temp=$_ExpFilesRet.export_files | select-string -pattern $_postret.export_files.export_id
PS C:\> $_temp
#{id=352475; href=/api/v1/exports/458234/export_files/352475; export_id=458234; status=Available}
PS C:\> $_temp=$_ExpFilesRet.export_files | select-string -pattern $_postret.export_files.export_id | out-str
ing -width 1000
PS C:\> $_temp
#{id=352475; href=/api/v1/exports/458234/export_files/352475; export_id=458234; status=Available}
PS C:\> [hashtable]$_temp=$_temp
Cannot convert the "
#{id=352475; href=/api/v1/exports/458234/export_files/352475; export_id=458234; status=Available}
" value of type "System.String" to type "System.Collections.Hashtable".
At line:1 char:1
+ [hashtable]$_temp=$_temp
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
I am trying to get the value of ID (352475) from the resulting string in $_temp.
Use Where-Object rather than Select-String to filter objects:
$_temp = $_ExpFilesRet.export_files |Where-Object export_id -eq $_postret.export_files.export_id |Select -Expand id

calling a variable in select -expandproperty

I'm trying to make a report that lists a server name, vm name, and notes section from the vm but I cannot seem to get this code to run, it always gives me this error:
Select-Object : Cannot convert 'System.Object[]' to the type
'System.String' required by parameter 'ExpandProperty'. not supported.
At C:\Cooper\Jobs\Get-VmNotes - Copy.ps1:32 char:48 + get-vm -server
FA0150 | Select -expandproperty $server, Name, Notes +
~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument:
(:) [Select-Object], ParameterBindingException +
FullyQualifiedErrorId :
CannotConvertArgument,Microsoft.PowerShell.Commands.SelectObjectCommand
I can get the vmname and notes to output together but I just want to have a column that lists the vcenter server it is associated with.
Expand property is like the same as saying (Get-VM -Server FA0150).Name. It expands the property name you are selecting. You were trying to expand 3 properties (System.Object[]), but it is looking for just a string name of the property you want to expand. Use -Property instead.
get-vm -server FA0150 | Select-Object -Property Name,Notes
get-vm -server FA0150 | Select-Object -Property Name,Notes | Format-Table -Autosize
To also include the server name I made it into a script form since it can no longer be a one-liner:
[CmdletBinding()]
Param ( $Server )
$VMs = Get-VM -Server $Server
$VMs | Select-Object -Properties #(
#{ Label = 'Server';Expression = { $Server } }
'Name'
'Notes'
)
I found a solution to my problem using New-ViProperty. The only problem is now it creates four separate csv files and I want to combine them all into one based on the filename, keeping the same format, and delete the four others based on their filename. Is there an easy way to do this?

Instantiate empty csv variable

I'm using methods to pick records from different csv files and I want to know how to create an empty variable that would act like a csv file. For Example...
an empty array would be $array = #()
an empty hash table would be $hashTable = #{}
a non-empty csv object would be $csvFileRecords = Import-Csv $someFileName
an empty csv object would be ????
What would the syntax be?
A "CSV object" is actually just an array (of psobjects).
$csvFileRecords = #()
To add new records to that array, you just need to add psobjects with appropriate attributes corresponding to the desired columns. One way to create a psobject with desired properties is from a hash table.
$obj = new-object psobject -property #{fname="Fiddle";lname="Freak"}
$csvFileRecords += $obj
Well, CSV's can't created from $null, but you could do something like this:
PS C:\> New-Object -TypeName System.Object | ConvertTo-Csv
#TYPE System.Object
But your challenge is that this doesn't work back and forth. For example:
PS U:\> ((New-Object -TypeName System.Int32 ) | ConvertTo-Csv).GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
means that the output of ConvertTo-CSV is not null, but this shows where you've lost the pipeline:
PS U:\> ((New-Object -TypeName System.Int32 ) | ConvertTo-Csv | ConvertFrom-csv).GetType()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ ((New-Object -TypeName System.Int32 ) | ConvertTo-Csv | ConvertFrom-c ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The help says:
Inputs
System.Management.Automation.PSObject
You can pipe any object that has an Extended Type System (ETS) adapter to ConvertTo-CSV.
So I bet your issue is that $null or blank doesn't have an ETS Adapter.
Here's some more reading on this: https://blogs.msdn.microsoft.com/besidethepoint/2011/11/22/psobject-and-the-adapted-and-extended-type-systems-ats-and-ets/

Why don't errors get returned when calling properties that don't exist?

Given the following snippet
$drives = Get-PSDrive
foreach($drive in $drives)
{
Write-Host $drive.Name "`t" $drive.Root
Write-Host " - " $drive.Free "`t" $drive.PropertyDoesntExist
}
The drive.PropertyDoesntExist property doesn't... erm... exist so I would expect an error to be thrown but instead it returns a null.
How can I get errors or exceptions?
EDIT - Me bad - I asked 2 questions in one so I moved one into a separate question.
The NextHop Blog provides a good solution to this problem. It doesn't give you an error, but instead a boolean. You can use Get-Member to get a collection of all of the real properties of the object's type and then match for your desired property.
Here's an example for strings:
PS C:\> $test = "I'm a string."
PS C:\> ($test | Get-Member | Select-Object -ExpandProperty Name) -contains "Trim"
True
PS C:\> ($test | Get-Member | Select-Object -ExpandProperty Name) -contains "Pigs"
False
If you explicitly want an error, you may want to look into Set-Strictmode as Set-StrictMode -version 2 to trap non-existent properties. You can easily turn it off when you're done with it, too:
PS C:\> Set-StrictMode -version 2
PS C:\> "test".Pigs
Property 'Pigs' cannot be found on this object. Make sure that it exists.
At line:1 char:8
+ "test". <<<< Pigs
+ CategoryInfo : InvalidOperation: (.:OperatorToken) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFoundStrict
PS C:\> Set-StrictMode -off