Function return array in PowerShell - arrays

I have a problem when I'm trying to return an array from a PowerShell function.
My function:
function filter-SWCluster {
param($Path, $FolderList)
$OldSWCluster = New-Object System.Collections.ArrayList
ForEach ($y in $FolderList) {
Get-ChildItem -Path $Path -Filter $y* | sort { [version]($_.Name -replace '^.*_(\d+(\.\d+){1,3})$', '$1') } -Descending | Select-Object -skip 3 | ForEach-Object { $OldSWCluster.Add($Path + "\" + $_) }
}
Write-Output $OldSWCluster
}
The function call:
$FilerSWCluster = filter-SWCluster $NetworkPath $SWCluster
The output I get:
0 1 \\server.domain\C$\TEMP\Folders\Testcluster_1.0.2 \\server.domain\C$\TEMP\Folders\Testcluster_1.0.1
The output I want and need would be:
\\server.domain\C$\TEMP\Folders\Testcluster_1.0.2 \\server.domain\C$\TEMP\Folders\Testcluster_1.0.1
I need just the paths. I know there will already be some solutions, but please excuse me. I didn't find one which was working for me or I were to dumb to use it right (could be).

You could also wrap the Add method with the [void] class accelerator. It will hide any output, like this:
function filter-SWCluster {
param($Path, $FolderList)
$OldSWCluster = New-Object System.Collections.ArrayList
ForEach ($y in $FolderList) {
Get-ChildItem -Path $Path -Filter $y* | sort { [version]($_.Name -replace '^.*_(\d+(\.\d+){1,3})$', '$1') } -Descending | Select-Object -skip 3 | ForEach-Object { [void]$OldSWCluster.Add($Path + "\" + $_) }
}
Write-Output $OldSWCluster
}

wOxxOm already provided you a solution to your problem. However, consider to just return the path using a simple select. You also don't have to join the path since the FullName property already contains the full path:
function filter-SWCluster {
param($Path, $FolderList)
ForEach ($y in $FolderList) {
Get-ChildItem -Path $Path -Filter $y* |
sort { [version]($_.Name -replace '^.*_(\d+(\.\d+){1,3})$', '$1') } -Descending |
Select-Object -skip 3 |
select -ExpandProperty FullName
}
}

Related

Object of arrays in powershell not showing anything in CSV

I have an object which contains multiple arrays of strings. Nothing I do can display these in a decent format in Powershell. I have looked everywhere on this site and many others and been unable to find an answer. Is this something that should be done with Python or a separate programming language? It appears powershell doesn't want users to export arrays to CSV. Anyways let me know if you all have a fix for this.
Import-Module VMware.VimAutomation.Core
Connect-VIServer -Server vcenter-appliance.swacu.net -Force $prodservers = get-vm | select Name Connect-VIServer -Server drvcenter-appliance.swacu.net -Force $replicaserversfull = get-vm | select Name
$notinprod = Foreach($replica in $replicaservers){
$shortname = $replica.name.trim('_replica')
$shortnametwo = if($shortname -like "*_TTN"){$shortname.trim('_TTN')}
$shortnames = New-Object -TypeName PSObject -Property #{
ShortName = $replica.name.trim('_replica')
}
if($prodservers.name -contains $shortname){
}
elseif($prodservers.name -contains $shortnametwo) {
}
else{
New-Object -TypeName PSObject -Property #{
SystemName = $replica.name
} | Select SystemName
} }
$NotInReplica = Foreach($prodserver in $prodservers){
$half = $replicaservers.name.trim('_replica')
$correct = if($half -like "*_TTN"){$half.trim('_TTN')}
if($half -contains $prodserver.name){
}
elseif($correct -contains $prodserver.name) {
}
else{
New-Object -TypeName PSObject -Property #{
SystemName = $prodserver.name
} | Select SystemName
}
}
Write-host $half $whole = New-Object -TypeName PSObject -Property #{
Replica = $replicaservers.name | out-string
Prod = $prodservers.name | out-string
NotInProd = $notinprod.SystemName | out-string
NotInReplication = $NotInReplica.SystemName | out-string
}
$whole | Select-Object prod, replica, NotInReplication, notinprod | Out-file -Path '.\Results\Noprod.csv'
This would be a fine output. Or having them each in their own column.
It appears powershell doesn't want users to export arrays to CSV.
Unless you use Export-CSV instead of Out-File.

Using two arrays to create registry keys/values

Trying to automate our font installation process for new PCs.
To install fonts, Windows adds the .ttf, .otf, etc. file to C:\Windows\Fonts and then creates a corresponding registry key in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts. A typical registry key would look like this:
Arial (TrueType) | Arial.ttf
To automate this, I've made two arrays using Get-ChildItem:
$names = Get-ChildItem -Path "C:\corp\install\fonts" | Select-Object name | Out-String | ForEach-Object {$_ -Replace "----","" ` -Replace "Name","" ` -Replace ".otf","" ` -Replace ".ttf","" } | ForEach-Object { $_.Trim() }
$files = Get-ChildItem -Path "C:\corp\install\fonts" | Select-Object name | Out-String | ForEach-Object {$_ -Replace "----","" ` -Replace "Name","" } | ForEach-Object { $_.Trim() }
Each $name in $names will be the name of the registry key, and each $file in $files will be the data for that registry key.
How would I go about doing this? I've attempted to use hash tables, PSObjects, nested ForEach loops, all to no avail. I have had difficulty finding anything on here and elsewhere that matches this situation exactly.
Error checking is not really necessary since there will always be a corresponding value.
REVISED FINAL SOLUTION:
Write-Host "Installing corporate fonts..."
Copy-Item -Path "C:\corp\install\fonts\*" -Destination "C:\Windows\Fonts" -Force -Recurse
$fontList = #()
$fonts = Get-ChildItem "C:\corp\install\fonts" | Select-Object -ExpandProperty Name
ForEach ( $font in $fonts ) {
$fontList += [PSCustomObject] #{
Name = $font -Replace ".otf","" ` -Replace ".ttf",""
File = $font
} |
ForEach-Object {
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" -Name $_.Name -Value $_.File
}
}
I must admit I don't fully understand your question so forgive me if this response is way off base, but it this what you're looking for? A table with both pieces of data in one?
Function CreateVariables {
$namevariables = #()
$filenames = ( Get-ChildItem "C:\corp\install\fonts" ).name
Foreach ( $name in $filenames ){
$namevariables += [PSCustomObject] #{
Name = $name -Replace "----","" ` -Replace "Name","" ` -Replace ".otf","" ` -Replace ".ttf",""
File = $name -Replace "----","" ` -Replace "Name",""
}
}
Return $namevariables
}
CreateVariables
Piping both name and value to set-itemproperty seem impossible. Foreach-object seems the way to go.
$path = 'hklm:\software\microsoft\windows nt\currentversion\fonts'
[pscustomobject]#{name='a name';value='a value'} |
foreach { set-itemproperty $path $_.name $_.value -whatif }
What if: Performing the operation "Set Property" on target "Item: HKEY_LOCAL_MACHINE\software\microsoft\windows nt\currentversion\fonts Property: a name".
You may prefer using this vbscript-like method to install fonts:
https://www.mondaiji.com/blog/other/it/10247-windows-install-fonts-via-command-line

wildcard in array

How can I use the 1709 as a wildcard? The value 1709 is stored in an array as $MoveItem.Version, but I can't figure out how do a -like, when the value comes from an array, as I can't put in a wildcard *. I also tried to do a match.
The file name looks like this: REFW10-X86-1709_01-12-2017.wim.
The below code works fine, but I would like to automate it, so everything comes from the array. Is that possible?
Get-ChildItem -Path $OSPathTemp -Recurse | Where {
($_.Name -eq $MoveItem.File) -and
($_.Name -like "*1709*")
} | Select-Object -ExpandProperty FullName
$MoveItem.Version contains 1607,1706,1709. I would like to choose only the one with 1709. The final output should look like this:
foreach ($MoveItem in $MoveItems) {
Get-ChildItem -Path $OSPathTemp -Recurse | Where {
($_.Name -eq $MoveItem.File) -and
($_.Name -like $MoveItem.Version)
} | Select-Object -ExpandProperty FullName
}
The Array looks like this:
$MoveItem = #(
[pscustomobject]#{File="REFW10-X86-1709_01-12-2017.wim";Version=1709}
[pscustomobject]#{File="REFW10-X86-1706_01-12-2017.wim";Version=1706}
)
So you have a hash table (or similar) named $MoveItem that has a .File property that is a filename, and you have a .Versions property that's a string array?
Test name: REFW10-X86-1709_01-12-2017.wim
Get-ChildItem -Path $OSPathTemp -Recurse |
ForEach-Object {
If ($_.Name -match '-\d{4}_') { $Version = $Matches[0] }
If ($Version -in $MoveItem.Versions -and
$_.Name -eq $MoveItem.File) { $_.FullName }
}

Assign all child paths in the parent directory to an array

I am trying to assign all child paths of files in a directory to an array but not assigning the directories.
I am using the following command:
$a = Get-ChildItem -path "C:\test\" -recurse | ?{!$_.PSIsContainer } | % { Write-Host $_.FullName }
The output is printed to the console and not saved in the variable.
Any idea way?
The reason it is writing to the console is because you are saying Write-Host. If you use Write-Output instead, it will save to the variable.
$a = Get-ChildItem -path "C:\test\" -recurse | ?{!$_.PSIsContainer } | % { Write-Output $_.FullName }
Or try using the "Select-Object" instead of write host.
It would look like this:
$a = Get-ChildItem -path "C:\test\" -recurse | ?{!$_.PSIsContainer } | select-object -expand FullName
The console output from Write-Host is only displayed, not returned.
You will need to save the value in a variable first, then you can print it:
$a = Get-ChildItem -path "C:\test\" -recurse | ?{!$_.PSIsContainer };
$a | % { Write-Host $_.FullName }

powershell pipe to array returns as character array

I am trying to build an array with the results of the following powershell script. I would then like to only output the unique results in that array (I am expecting duplicates). I tried but it does not work. One thing I noticed is that my array is being converted to a character array. So if I call a single object in the array ($array[1]) it only displays one character, which may be why the select -unique is not working.
Please help.
$servers="Server1","server2"
$regex="(\.\d\d\d.*\()"
$path = "SomePath"
$yesterday = (get-date).Date.AddDays(-1)
Foreach ($server in $servers) {Get-ChildItem -Path $path -recurse | where { $_.LastWriteTime -le $yesterday } | ForEach-Object { Get-Content -Path "$_" -TotalCount 2 | select-string $regex | % { $_.Matches } | % { $array += $_.Value.Substring(5,6) } }}
$array|select -Unique
If you initialize the $array value as an array, then your code will work. Without this knowledge, PowerShell is treating $array += like concatenating strings together.
$array = #()
$servers="Server1","server2"
$regex="(\.\d\d\d.*\()"
$path = "SomePath"
$yesterday = (get-date).Date.AddDays(-1)
Foreach ($server in $servers) {Get-ChildItem -Path $path -recurse | where { $_.LastWriteTime -le $yesterday } | ForEach-Object { Get-Content -Path "$_" -TotalCount 2 | select-string $regex | % { $_.Matches } | % { $array += $_.Value.Substring(5,6) } }}
$array|select -Unique

Resources