How to convert directory objects to strings - Powershell

I have an array of paths that I retrieved from some registry queries. As of right now, they are still being returned as directory objects, but I need to convert them to just an array of strings. What is the most efficient way to do this in PS?

Code:

  $found_paths = @();

  $uninstall_keys = getRegistrySubkeys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" '\\Office[\d+.*]';
  if ($uninstall_keys -ne $null) 
  {
    foreach ($key in $uninstall_keys)
    {
      $product_name = getRegistryValue $key "DisplayName";
      $version = getRegistryValue $key "DisplayVersion";
      $base_install_path = getRegistryValue $key "InstallLocation"; 
      $full_install_path = Get-ChildItem -Directory -LiteralPath $base_install_path | Where-Object Name -match '^Office\d{1,2}\D?' | Select-Object FullName;

      $found_paths += ,$full_install_path
    }
  }

  write-output $found_paths; 

Output:

 FullName                                          
--------                                          
C:\Program Files\Microsoft Office Servers\OFFICE15
C:\Program Files\Microsoft Office\Office15        

Desired output:

C:\Program Files\Microsoft Office Servers\OFFICE15
C:\Program Files\Microsoft Office\Office15  

Solution 1:

The most efficient approach is to use member enumeration ((...).PropName):

$full_install_path = (
  Get-ChildItem -Directory -LiteralPath $base_install_path | Where-Object Name -match '^Office\d{1,2}\D?'
).FullName

Note: It sounds like maybe just one directory-info object is returned by your command, but the approach would also work with multiple ones, in which case an array of paths is returned.

The more objects you need to deal with, the greater the speed advantage of member enumeration vs. a Select-Object -ExpandProperty solution is (see below).


As for what you tried:

... | Select-Object FullName

doesn't return the value of the input objects' .FullName property, it returns a [pscustomobject] instance with a .FullName property that contains that value. To get the value only, you need to use ... | Select-Object -ExpandProperty FullName

$found_paths += , $full_install_path

You probably meant $found_paths += $full_install_path - there is no need to construct an array (with ,) on the RHS first.

In fact, if you do so and $full_install_path happened to contain multiple elements, you'd get a nested array.

Taking a step back: It is much more efficient to let PowerShell automatically collect outputs from a loop statement in an array for you:

  $uninstall_keys = getRegistrySubkeys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" '\\Office[\d+.*]'
  if ($null -ne $uninstall_keys) 
  {
    # Collect the `foreach` loop's outputs in an array.
    [array] $found_paths = foreach ($key in $uninstall_keys)
    {
      $product_name = getRegistryValue $key "DisplayName"
      $version = getRegistryValue $key "DisplayVersion"
      $base_install_path = getRegistryValue $key "InstallLocation"
      # Get and output the full path.
      (Get-ChildItem -Directory -LiteralPath $base_install_path | Where-Object Name -match '^Office\d{1,2}\D?').FullName
    }
  }

  $found_paths # output (implicit equivalent of Write-Output $found_paths