Here’s an example of a PS object that has 3 properties, one is a ‘string’, one is an integer ‘unit32’, and one is a ‘double’:
$SampleObject = [PSCustomObject][Ordered]@{ ComputerName = $env:COMPUTERNAME MemoryGB = [Math]::Round((Get-WmiObject Win32_ComputerSystem).TotalPhysicalMemory/1GB,1) LogicalCores = (Get-WmiObject Win32_ComputerSystem -Property NumberofLogicalProcessors).NumberofLogicalProcessors } $SampleObject | FT -a $SampleObject | Get-Member ComputerName MemoryGB LogicalCores ------------ -------- ------------ MGMT-066VDI 63.9 48 TypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() ComputerName NoteProperty string ComputerName=MGMT-066VDI LogicalCores NoteProperty uint32 LogicalCores=48 MemoryGB NoteProperty double MemoryGB=63.9
I’d like to create a copy of this $Sample object that has the same members with same property types but not the data (blanks/zeros)
I can list the object properties and identify their types as in:
$Properties = $SampleObject | Get-Member -MemberType NoteProperty | % { [PSCustomObject][Ordered]@{ PropertyName = $_.Name DataType = $_.Definition.Split(' ')[0] } } $Properties | FT -a PropertyName DataType ------------ -------- ComputerName string LogicalCores uint32 MemoryGB double
Using Add-Member and trying to type-cast properties of a new object does not work:
$CopiedObject = New-Object -TypeName PSCustomObject $Properties | % { $CopiedObject | Add-Member -MemberType NoteProperty -Name $_.Name -Value [$_.DataType]0 } $CopiedObject | FT -a
This seems to fail because type-casting seems not to accept variables. The following attempts fail:
$DataType = 'String' [$DataType]0 [($DataType)]'0' [($DataType)]0 [($DataType)]'0' [$($DataType)]0 [$($DataType)]'0'
Also tried this but it copies both structure and data
$CopiedObject = $SampleObject.psobject.Copy() $CopiedObject | FT -a ComputerName MemoryGB LogicalCores ------------ -------- ------------ MGMT-066VDI 63.9 48
Copying the object and changing the property values to 0 does not work because it changes property types to int:
$CopiedObject = $SampleObject.psobject.Copy() $CopiedObject | Get-Member -MemberType NoteProperty | % { $PropertyName = $_.Name; $CopiedObject.$PropertyName = 0 } $CopiedObject | FT -a $CopiedObject | Get-Member ComputerName MemoryGB LogicalCores ------------ -------- ------------ 0 0 0 TypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() ComputerName NoteProperty int ComputerName=0 LogicalCores NoteProperty int LogicalCores=0 MemoryGB NoteProperty int MemoryGB=0
I can do something like this:
$CopiedObject = New-Object -TypeName PSCustomObject foreach ($Property in $Properties) { switch ($Property.DataType) { 'String' { $CopiedObject | Add-Member -MemberType NoteProperty -Name $Property.PropertyName -Value ([String]0) } 'Uint32' { $CopiedObject | Add-Member -MemberType NoteProperty -Name $Property.PropertyName -Value ([Uint32]0) } 'Double' { $CopiedObject | Add-Member -MemberType NoteProperty -Name $Property.PropertyName -Value ([Double]0) } } } $CopiedObject | FT -a $CopiedObject | Get-Member ComputerName LogicalCores MemoryGB ------------ ------------ -------- 0 0 0 TypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() ComputerName NoteProperty string ComputerName=0 LogicalCores NoteProperty uint32 LogicalCores=0 MemoryGB NoteProperty double MemoryGB=0
but then I have to anticipate and list every possible datatype. There must be a better way…