cynicalswan77
cynicalswan77

Reputation: 289

Powershell function not returning output correctly

I have a Powershell function that formats out put from another function I have to gather version, path and file information based on some registry queries. It seems all the data is being stored to one variable and only printing one line altogether. Below is my code, the output and an explanation of what I need in the desired output.

Code:

 function getOffice()
{
  $list = new-object System.Collections.Generic.List[PSCustomObject];
  $found_paths = @();
  $final_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?').FullName;

      $found_paths += ,$full_install_path;

      $exes = @("MSOCF.DLL", "access.exe", "word.exe", "wordCnv.exe", "WordViewer.exe", "Excel.exe", "ExcelCnv.exe", "ExcelViewer.exe", "PowerPoint.exe", 
      "PowerPointViewer.exe", "PowerPointCnv.exe", "Publisher.exe", "Project.exe", "OneNote.exe", "InfoPath.exe Groove.exe", "FrontPage.exe", 
      "SharePointDesigner.exe", "Visio.exe", "VisioViewer.exe", "Lync.exeOutlook.exe", "WINPROJ.EXE");

      foreach($path in $found_paths)
      {
        foreach($exe in $exes)
        {
          $found_files = Get-Item ([System.IO.Path]::Combine($path, $exe)) -EA Ignore;
          $found_file = $found_files.Name;

          if ($found_file)
          {
            $office = makeFileResult $found_file, $path, $version, $product_name, $version; 
            $list.Add($office);
            $list 

          }
        }
      }
    }
  }
} 

function makeFileResult($name, $path, $file_version, $product_name, $product_version)
{
     return [PSCustomObject]@{
       path = $path;
       file = $name;
       product_version = $product_version;
       product_name = $product_name;
       file_version = $file_version;
     };
}

getOffice 

Output:

path            : 
file            : {MSOCF.DLL, C:\Program Files\Microsoft Office\Office15, 15.0.4569.1506, Microsoft Project Standard 2013...}
product_version : 
product_name    : 
file_version    : 

path            : 
file            : {WINPROJ.EXE, C:\Program Files\Microsoft Office\Office15, 15.0.4569.1506, Microsoft Project Standard 2013...}
product_version : 
product_name    : 
file_version    : 

path            : 
file            : {MSOCF.DLL, C:\Program Files\Microsoft Office\Office15, 15.0.4569.1506, Microsoft Project Standard 2013...}
product_version : 
product_name    : 
file_version    : 

path            : 
file            : {WINPROJ.EXE, C:\Program Files\Microsoft Office\Office15, 15.0.4569.1506, Microsoft Project Standard 2013...}
product_version : 
product_name    : 
file_version    : 

I am not sure why all the data is only being stored in the `file` key here.

I am not sure why all the data is only being stored in the file key here.

Desired Output:

path            : C:\Program Files\Microsoft Office\Office15
file            : MSOCF.DLL
product_version : 15.0.4569.1506
product_name    : Microsoft Project Standard 2013
file_version    : 15.0.4569.1506

path            : C:\Program Files\Microsoft Office\Office15
file            : WINPROJ.EXE
product_version : 15.0.4569.1506
product_name    : Microsoft Project Standard 2013
file_version    : 15.0.4569.1506

Upvotes: 0

Views: 111

Answers (1)

HAL9256
HAL9256

Reputation: 13453

Seems silly, but remove the commas and only have spaces when making the function call makeFileResult.

$office = makeFileResult $found_file $path $version $product_name $version

Since the parameters in the function call have no type defined, PowerShell will do it's best to "guess" what type you mean. The commas in between the variables end up being interpreted as a string array instead of a string like you are expecting. You can see this when you get the type:

PS C:\> $office.file.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

The spaces make the function call be evaluated like a traditional cmd call, with the Arg[] string array.

I personally would read about advanced Parameters and add named parameters which would make it easier to make sure everything gets logged in a consistent way.

Upvotes: 1

Related Questions