If you remove the array subexpression @(...) and just precede with a comma. The below code seems to work:
Copyfunction TestReturn {
$returnList = New-Object System.Collections.Generic.List[string]
$returnList.Add('Testing, one, two')
return , $returnList
}
$testList = TestReturn
$testList.GetType().FullName
Note: technically this causes the return of [Object[]] with a single element that's of type [System.Collections.Generic.List[string]]. But again because of the implicit unrolling it sort of tricks PowerShell into typing as desired.
On your later point, the syntax [Type]$Var type constrains the variable. It's basically locking in the type for that variable. As such subsequent calls to .GetType() will return that type.
These issues are due to how PowerShell implicitly unrolls arrays on output. The typical solution, somewhat depending on the typing, is to precede the return with a , or ensure the array on the call side, either by type constraining the variable as shown in your questions, or wrapping or casting the return itself. The latter might look something like:
Copy$testList = [System.Collections.Generic.List[string]]TestReturn
$testList.GetType().FullName
To ensure an array when a scalar return is possible and assuming you haven't preceded the return statement with , , you can use the array subexpression on the call side:
Copy$testList = @( TestReturn )
$testList.GetType().FullName
I believe this answer deals with a similar issue
Answer from Steven on Stack Overflowpowershell - [System.Collections.Generic.List[string]] as return value - Stack Overflow
System.Collections.Generic.List[PSObject]
PowerShell should support creating an List similar to how it supports arrays
Powershell Array list
Videos
If you remove the array subexpression @(...) and just precede with a comma. The below code seems to work:
Copyfunction TestReturn {
$returnList = New-Object System.Collections.Generic.List[string]
$returnList.Add('Testing, one, two')
return , $returnList
}
$testList = TestReturn
$testList.GetType().FullName
Note: technically this causes the return of [Object[]] with a single element that's of type [System.Collections.Generic.List[string]]. But again because of the implicit unrolling it sort of tricks PowerShell into typing as desired.
On your later point, the syntax [Type]$Var type constrains the variable. It's basically locking in the type for that variable. As such subsequent calls to .GetType() will return that type.
These issues are due to how PowerShell implicitly unrolls arrays on output. The typical solution, somewhat depending on the typing, is to precede the return with a , or ensure the array on the call side, either by type constraining the variable as shown in your questions, or wrapping or casting the return itself. The latter might look something like:
Copy$testList = [System.Collections.Generic.List[string]]TestReturn
$testList.GetType().FullName
To ensure an array when a scalar return is possible and assuming you haven't preceded the return statement with , , you can use the array subexpression on the call side:
Copy$testList = @( TestReturn )
$testList.GetType().FullName
I believe this answer deals with a similar issue
In addition to Steven's very helpful answer, you also have the option to use the [CmdletBinding()] attribute and then just call $PSCmdlet.WriteObject. By default it will preserve the type.
Copyfunction Test-ListOutput {
[CmdletBinding()]
Param ()
Process {
$List = New-Object -TypeName System.Collections.Generic.List[System.String]
$List.Add("This is a string")
$PSCmdlet.WriteObject($List)
}
}
$List = Test-ListOutput
$List.GetType()
$List.GetType().FullName
For an array, you should specify the type.
Copyfunction Test-ArrayOutput {
[CmdletBinding()]
Param ()
Process {
[Int32[]]$IntArray = 1..5
$PSCmdlet.WriteObject($IntArray)
}
}
$Arr = Test-ArrayOutput
$Arr.GetType()
$Arr.GetType().FullName
By default the behaviour of PSCmdlet.WriteObject() is to not enumerate the collection ($false). If you set the value to $true you can see the behaviour in the Pipeline.
Copyfunction Test-ListOutput {
[CmdletBinding()]
Param ()
Process {
$List = New-Object -TypeName System.Collections.Generic.List[System.String]
$List.Add("This is a string")
$List.Add("This is another string")
$List.Add("This is the final string")
$PSCmdlet.WriteObject($List, $true)
}
}
Test-ListOutput | % { $_.GetType() }
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
True True String System.Object
True True String System.Object
(Test-ListOutput).GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
# No boolean set defaults to $false
function Test-ListOutput {
[CmdletBinding()]
Param ()
Process {
$List = New-Object -TypeName System.Collections.Generic.List[System.String]
$List.Add("This is a string")
$List.Add("This is another string")
$List.Add("This is the final string")
$PSCmdlet.WriteObject($List)
}
}
Test-ListOutput | % { $_.GetType() }
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True List`1 System.Object
(Test-ListOutput).GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True List`1 System.Object
Just wanted to add some information on what I usually use in functions and how to control the behaviour.
You need a For-Each Loop like follows:, but with your parameters in it:
Get-ADComputer -Filter {Enabled -eq "true"} -Searchbase " OU=DISABLED,OU=COMPUTERS, OUs,DC=STORE,DC=NETWORK" -Properties * | ?{($_.LastLogonDate -lt (Get-Date).AddDays(-120)) -and ($_.LastLogonDate -ne $NULL)} | Select Name | Out-File C:\users\user\Desktop\DisabledPcs.csv
$computers = gc C:\users\user\Desktop\disabledpcs.csv
ForEach ($computer in $computers){
get-adcomputer $computer | Move-ADObject -TargetPath "OU=DISABLED,OU=COMPUTERS, OUs,DC=STORE,DC=NETWORK"
}
Write-Host "Disabled Pcs moved to Disabled OU" -ForegroundColor Green
So I can get the results I want by one computer but how can i get this to run against a list of computers?
param
(
[Parameter(Mandatory=$true)]
[String]$Computername
)
Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion | Format-Table –AutoSize
I am trying to understand when to us what.
I use generic.list a peer uses ArrayList.
Just curious.