Retain type when using Select-Object

Welcome Forums General PowerShell Q&A Retain type when using Select-Object

Viewing 8 reply threads
  • Author
    Posts
    • #230776
      Participant
      Topics: 3
      Replies: 421
      Points: 1,479
      Helping Hand
      Rank: Community Hero

      This may be a silly question, but I’d really like to hear your opinions. I pick a module to install and pipe it to Install-Module which works fine.

      Find-Module -Name *somemodule* | install-module
      

      If I use Select-Object to get all the properties, it no longer works.

      Find-Module -Name *somemodule* | select-object * | install-module
      

      I assume it’s failing because it is now

      TypeName: Selected.System.Management.Automation.PSCustomObject

      instead of

      TypeName: Microsoft.PowerShell.Commands.PSRepositoryItemInfo

      The help for Install-Module is quite unhelpful as well.

          -InputObject <PSObject[]>
              {{Fill InputObject Description}}
              
              Required?                    true
              Position?                    0
              Default value                None
              Accept pipeline input?       True (ByPropertyName, ByValue)
              Accept wildcard characters?  false
      
      INPUTS
          PSGetItemInfo
      

      The reason this even came up is trying to give the user more info to choose which module(s) to install

      $modules = Find-Module -Name "*$searchterm*" | 
          select-object * | Out-Gridview -Title "Select the module(s) you want to install" -passthru
      

      Now of course I could work around in several ways such as

      $correctedmodules = $modules | foreach-object {find-module -name $_.name}
      

      Or just

      $modules | foreach-object {install-module -name $_.name}
      

      But I just wonder if there is a way to select more/all members while retaining the original type. Or if there is another reason the inputobject is not accepting the object. It says byvalue and byproperty – surely it still has the property/properties required and the value type shows simply PSObject which either should fulfill? I do plan on looking at the source code when I have some more time. Thanks in advance.

    • #230860
      Moderator
      Topics: 3
      Replies: 223
      Points: 1,221
      Helping Hand
      Rank: Community Hero

      PowerShell12 lines 1 2 3 4 5 6 7 8 9 10 11 12 -InputObject <psobject[]> {{Fill InputObject Description}} Required? true Position? 0 Default value None Accept pipeline input? True (ByPropertyName, ByValue) Accept wildcard characters? false INPUTS PSGetItemInfo</psobject[]>

      Here you should understand that the -InputObject parameter accepts the value in the form of a module as an object either by property name or by value itself, and that doesn’t mean that it can accept any psobject other than module object. Every CmdLet which accepts input in the form of psobject validates the object type first then proceed it further.

      However, Select-Object is not to select the object, it is to select the properties of an object and returns in the form of PSCustomObject

      Try this out to create an empty pscustomobject with the custom properties in the Select-Object statement

      C:\> ($Obj = “” | Select-Object -Property FirstName, LastName, Department, Role, IsEnabled)
      
      FirstName :
      LastName :
      Department :
      Role :
      IsEnabled :
      
      C:\> $Obj.GetType()
      
      IsPublic IsSerial Name BaseType
      ——– ——– —- ——–
      True False PSCustomObject System.Object
      
    • #230992
      Participant
      Topics: 1
      Replies: 114
      Points: 123
      Rank: Participant

      I’ve seen the same as what OP is describing and I understand the issue and it’s, as you said, related to parameter binding and binding by type. But doesn’t it seem odd that if you do ‘select *’ wouldn’t you assume it would return the same object type as you get without that? I suppose I can understand why this happens but curious if anything can be done with select-object or the PS parser that could help with this… For the time being you just have to understand and plan for these instances…

    • #231004
      Participant
      Topics: 3
      Replies: 421
      Points: 1,479
      Helping Hand
      Rank: Community Hero

      Yes it does seem to be inconsistent, given the following example, it suggests that it DOES in fact select the object (or should)

      $user = Get-ADuser -Filter "Name -like 'administrator*'" -Properties * | select *
      $user | gm
      

      which returns what I expect, an ADUser object with all properties

         TypeName: Selected.Microsoft.ActiveDirectory.Management.ADUser
      

      Kiran, what you are suggesting is that this is no longer a module, just because it has additional properties? Why isn’t that the case for ADUser?

      $module = Find-Module pscredentialtools | select *
      $module
      
      
      Name                       : PSCredentialTools
      Version                    : 1.1.0
      Type                       : Module
      Description                : PSCredentialTools provides various methods for securely storing and retrieving credentials used in PowerShell scripts
      Author                     : Mike Lacher
      CompanyName                : MikeLacher
      Copyright                  : (c) 2018 Microsoft Corporation. All rights reserved
      PublishedDate              : 5/9/2019 3:49:33 PM
      InstalledDate              : 
      UpdatedDate                : 
      LicenseUri                 : https://github.com/Microsoft/PSCredentiaTools/blob/master/LICENSE
      ProjectUri                 : https://github.com/Microsoft/PSCredentialTools
      IconUri                    : 
      Tags                       : {Credential, PowerShell, PSModule}
      Includes                   : {Function, RoleCapability, Command, DscResource...}
      PowerShellGetFormatVersion : 
      ReleaseNotes               : https://github.com/Microsoft/PSCredentialTools/blob/master/changelog.md
      Dependencies               : {}
      RepositorySourceLocation   : https://www.powershellgallery.com/api/v2
      Repository                 : PSGallery
      PackageManagementProvider  : NuGet
      AdditionalMetadata         : @{summary=PSCredentialTools provides various methods for securely storing and retrieving credentials used in PowerShell scripts; 
                                   releaseNotes=https://github.com/Microsoft/PSCredentialTools/blob/master/changelog.md; versionDownloadCount=275; ItemType=Module; 
                                   copyright=(c) 2018 Microsoft Corporation. All rights reserved; PackageManagementProvider=NuGet; CompanyName=Microsoft Corporation; 
                                   SourceName=PSGallery; description=PSCredentialTools provides various methods for securely storing and retrieving credentials used 
                                   in PowerShell scripts; created=5/9/2019 3:49:33 PM -05:00; published=5/9/2019 3:49:33 PM -05:00; developmentDependency=False; 
                                   NormalizedVersion=1.1.0; downloadCount=968; GUID=89b06e4f-42a4-4d7b-bb59-495e35d0b270; lastUpdated=5/25/2020 8:07:28 PM -05:00; 
                                   Authors=Mike Lacher; updated=2020-05-25T20:07:28Z; Functions=Export-PSCredential Import-PSCredential New-PSCredential 
                                   ConvertFrom-FIPSSecureString ConvertTo-FIPSSecureString ConvertTo-PKISecureString ConvertFrom-PKISecureString; 
                                   isLatestVersion=True; PowerShellVersion=4.0; IsPrerelease=false; isAbsoluteLatestVersion=True; packageSize=25765; tags=Credential 
                                   PowerShell PSModule; FileList=PSCredentialTools.nuspec|changelog.md|contributing.md|LICENSE|PSCredentialTools.psd1|readme.md|docs\C
                                   onvertFrom-FIPSSecureString.md|docs\ConvertFrom-PKISecureString.md|docs\ConvertTo-FIPSSecureString.md|docs\ConvertTo-PKISecureStrin
                                   g.md|docs\Export-PSCredential.md|docs\Import-PSCredential.md|docs\New-PSCredential.md|Functions\Convert-SecureStringTo32ByteKey.ps1
                                   |Functions\ConvertFrom-FipsSecureString.ps1|Functions\ConvertFrom-PKISecureString.ps1|Functions\ConvertTo-FIPSSecureString.ps1|Func
                                   tions\ConvertTo-PKISecureString.ps1|Functions\Export-PSCredential.ps1|Functions\Import-PSCredential.ps1|Functions\New-Password.ps1|
                                   Functions\New-PSCredential.ps1|Functions\Set-AzureCmdlets.ps1; requireLicenseAcceptance=False}
      

      It looks like a module to me. Why doesn’t it retain the type in this case when it does in so many others? That’s the question here.

    • #231241
      Participant
      Topics: 3
      Replies: 421
      Points: 1,479
      Helping Hand
      Rank: Community Hero

      Out of all the tests I’ve done so far, the module is the only object that doesn’t return as it’s own type, selected.

       

      Get-Process | select -First 1 -property * | gm
      
         TypeName: Selected.System.Diagnostics.Process
      
      Get-Service | select * | gm
      
         TypeName: Selected.System.ServiceProcess.ServiceController
      
      Get-ChildItem -File | select -First 1 -property * | gm
      
         TypeName: Selected.System.IO.FileInfo
      
      Get-Item C:\Windows | select * | gm
      
         TypeName: Selected.System.IO.DirectoryInfo
      
      Get-Command -Verb start | select -first 1 -property * | gm
      
         TypeName: Selected.System.Management.Automation.AliasInfo
      
      Get-Acl -Path C:\Windows | select * | gm
      
         TypeName: Selected.System.Security.AccessControl.DirectorySecurity
      
      get-date | select -Property * | gm
      
         TypeName: Selected.System.DateTime
      
      Get-WindowsCapability -Name rsat.act* -Online | select * | gm
      
         TypeName: Selected.Microsoft.Dism.Commands.AdvancedCapabilityObject
      

      So this leads me to believe there is a bug here and possibly elsewhere as Peter eluded to. The question is, is it an issue with Select-Object or with the Powershellget provider? If I had to guess I’d say select object. What do you guys/gals think?

    • #231307
      Moderator
      Topics: 3
      Replies: 223
      Points: 1,221
      Helping Hand
      Rank: Community Hero

      Not really sure, looks like the Get-Member is judging the type based on the parameters available, but if you actually go by GetType() method, it shows the type as PSCustomObject with the Select-Object statement…

      PS C:\Users\Kiran> $ServiceObject = Get-Service BITS
      PS C:\Users\Kiran> $ServiceObject.GetType()
      
      IsPublic IsSerial Name BaseType
      ——– ——– —- ——–
      True False ServiceController System.ComponentModel.Component
      
      PS C:\Users\Kiran> $ServiceSelect = Get-Service BITS | Select *
      PS C:\Users\Kiran> $ServiceSelect.GetType()
      
      IsPublic IsSerial Name BaseType
      ——– ——– —- ——–
      True False PSCustomObject System.Object
      
      

      With the best of my knowledge, what I know is Select-Object will create a new PSCustomObject and return the object.

      Please refer to the description section in the Microsoft Docs below…

      https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-object

      Thank you.

    • #231337
      Participant
      Topics: 3
      Replies: 421
      Points: 1,479
      Helping Hand
      Rank: Community Hero

      Thanks Kiran. So if I understand you correctly, you believe the select-object is working properly for modules but is not functioning properly for the other examples I’ve shown? Regardless of the type, the pipeline is halted in this particular scenario, while working fine in the many examples I’ve given, plus the countless more I didn’t post. As I told JRV, if you’re not sure why this is working differently then the rest, perhaps it’s better to let someone else answer? It seems you both are saying select-object shouldn’t be used in the pipeline… which is anti powershell from everything I’ve ever read. It just seems if this one or few cases fail when the rest do not, there is an issue?

    • #231397
      Participant
      Topics: 24
      Replies: 175
      Points: 587
      Helping Hand
      Rank: Major Contributor

      this could also be ps versioning issues for you.

      i just tested

      get-module activedirectory |gm

      get-module activedirectory|select *|gm

      get-module activedirectory|select verions|gm

      all 3 seem to be returning: TypeName: System.Management.Automation.PSModuleInfo

    • #231472
      Participant
      Topics: 3
      Replies: 421
      Points: 1,479
      Helping Hand
      Rank: Community Hero
Viewing 8 reply threads
  • You must be logged in to reply to this topic.