locked
Active Directory Object Properties RRS feed

  • Question

  • Maybe I am completely missing something, but is there no way to create an array of properties from get-aduser? I need to iterate through the user properties to find certain criteria. Even if I do:

    $user = get-aduser $username -properties *
    $user.count

    The count returns 1. Now, I know it is only 1 user object, but is there a way to iterate through each property?

    Thanks!

    Tony

    Wednesday, August 20, 2014 9:13 PM

Answers

  • How about


    get-aduser $username -properties * |
      select-object -expandproperty PropertyNames


    -- Bill Stewart [Bill_Stewart]

    • Marked as answer by TonyL12345 Thursday, August 21, 2014 2:39 PM
    Wednesday, August 20, 2014 10:01 PM

All replies

  • get-aduser $username -Properties * | select propertycount |ft -auto

    HELP Get-AdUser -FULL


    ¯\_(ツ)_/¯

    Wednesday, August 20, 2014 9:21 PM
  • I don't think you read my question. How would I use the PropertyCount of 192 to iterate through each property? It won't let me use an index $user[0] etc.

    On a side note, I am really only selecting a subset of 10 properties. If I use the FT or FL at the end, it then returns a count of 5... Which is odd.

    Wednesday, August 20, 2014 9:34 PM
  • Maybe I am completely missing something, but is there no way to create an array of properties from get-aduser? I need to iterate through the user properties to find certain criteria. Even if I do:

    $user = get-aduser $username -properties *
    $user.count

    The count returns 1. Now, I know it is only 1 user object, but is there a way to iterate through each property?

    Thanks!

    Tony

    Something like this?

    $user = get-aduser $username -properties *
    
    foreach ($Property in $user.psobject.properties.name)
     {
      if ( $User.$Property -eq 'some value' ) 
        { Write-Output "Found value in property $Property" }
     }


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    Wednesday, August 20, 2014 9:55 PM
  • How about


    get-aduser $username -properties * |
      select-object -expandproperty PropertyNames


    -- Bill Stewart [Bill_Stewart]

    • Marked as answer by TonyL12345 Thursday, August 21, 2014 2:39 PM
    Wednesday, August 20, 2014 10:01 PM
  • $user = get-aduser $username -properties *

    New-Object PSObject -Property ([Ordered]@{ 
               AccountExpirationDate=$Object.AccountExpirationDate 
               accountExpires=$Object.accountExpires 
               AccountLockoutTime=$Object.AccountLockoutTime 
               AccountNotDelegated=$Object.AccountNotDelegated 
               adminCount=$Object.adminCount 
               AllowReversiblePasswordEncryption=$Object.AllowReversiblePasswordEncryption 
               BadLogonCount=$Object.BadLogonCount 
               badPasswordTime=$Object.badPasswordTime 
               badPwdCount=$Object.badPwdCount 
               CannotChangePassword=$Object.CannotChangePassword 
               CanonicalName=$Object.CanonicalName 
               City=$Object.City 
               CN=$Object.CN 
               codePage=$Object.codePage 
               Company=$Object.Company 
               Country=$Object.Country 
               countryCode=$Object.countryCode 
               Created=$Object.Created 
               createTimeStamp=$Object.createTimeStamp 
               Deleted=$Object.Deleted 
               Department=$Object.Department 
               Description=$Object.Description 
               DisplayName=$Object.DisplayName 
               DistinguishedName=$Object.DistinguishedName 
               Division=$Object.Division 
               DoesNotRequirePreAuth=$Object.DoesNotRequirePreAuth 
               EmailAddress=$Object.EmailAddress 
               EmployeeID=$Object.EmployeeID 
               EmployeeNumber=$Object.EmployeeNumber 
               Enabled=$Object.Enabled 
               Fax=$Object.Fax 
               GivenName=$Object.GivenName 
               HomeDirectory=$Object.HomeDirectory 
               HomedirRequired=$Object.HomedirRequired 
               HomeDrive=$Object.HomeDrive 
               HomePage=$Object.HomePage 
               HomePhone=$Object.HomePhone 
               Initials=$Object.Initials 
               instanceType=$Object.instanceType 
               isCriticalSystemObject=$Object.isCriticalSystemObject 
               isDeleted=$Object.isDeleted 
               LastBadPasswordAttempt=$Object.LastBadPasswordAttempt 
               LastKnownParent=$Object.LastKnownParent 
               lastLogoff=$Object.lastLogoff 
               lastLogon=$Object.lastLogon 
               LastLogonDate=$Object.LastLogonDate 
               lastLogonTimestamp=$Object.lastLogonTimestamp 
               LockedOut=$Object.LockedOut 
               logonCount=$Object.logonCount 
               LogonWorkstations=$Object.LogonWorkstations 
               Manager=$Object.Manager 
               MNSLogonAccount=$Object.MNSLogonAccount 
               MobilePhone=$Object.MobilePhone 
               Modified=$Object.Modified 
               modifyTimeStamp=$Object.modifyTimeStamp 
               msDS-User-Account-Control-Computed=$Object.msDS-User-Account-Control-Computed 
               Name=$Object.Name 
               ObjectCategory=$Object.ObjectCategory 
               ObjectClass=$Object.ObjectClass 
               Office=$Object.Office 
               OfficePhone=$Object.OfficePhone 
               Organization=$Object.Organization 
               OtherName=$Object.OtherName 
               PasswordExpired=$Object.PasswordExpired 
               PasswordLastSet=$Object.PasswordLastSet 
               PasswordNeverExpires=$Object.PasswordNeverExpires 
               PasswordNotRequired=$Object.PasswordNotRequired 
               POBox=$Object.POBox 
               PostalCode=$Object.PostalCode 
               PrimaryGroup=$Object.PrimaryGroup 
               primaryGroupID=$Object.primaryGroupID 
               ProfilePath=$Object.ProfilePath 
               ProtectedFromAccidentalDeletion=$Object.ProtectedFromAccidentalDeletion 
               pwdLastSet=$Object.pwdLastSet 
               SamAccountName=$Object.SamAccountName 
               sAMAccountType=$Object.sAMAccountType 
               ScriptPath=$Object.ScriptPath 
               sDRightsEffective=$Object.sDRightsEffective 
               SmartcardLogonRequired=$Object.SmartcardLogonRequired 
               State=$Object.State 
               StreetAddress=$Object.StreetAddress 
               Surname=$Object.Surname 
               Title=$Object.Title 
               TrustedForDelegation=$Object.TrustedForDelegation 
               TrustedToAuthForDelegation=$Object.TrustedToAuthForDelegation 
               UseDESKeyOnly=$Object.UseDESKeyOnly 
               userAccountControl=$Object.userAccountControl 
               UserPrincipalName=$Object.UserPrincipalName 
               uSNChanged=$Object.uSNChanged 
               uSNCreated=$Object.uSNCreated 
               whenChanged=$Object.whenChanged 
               whenCreated=$Object.whenCreated 
    }) 

    That took a function to build and there was only 92 [scalar] properties.

    select-object -expandproperty PropertyNames returns 109 properties

    Some properties are collections

    Wednesday, August 20, 2014 10:11 PM
  • $user = get-aduser $username -properties *

    That took a function to build and there was only about 100 properties.

    Why would you do that. Just select the properties you need directly.

    get-aduser $username -properties *| 
         Select AccountExpirationDate,
            accountExpires,
            AccountLockoutTime,
            adminCount,
            BadLogonCount, 
            badPasswordTime, 
            badPwdCount, 
            CanonicalName, 
            City, 
            CN, 
            codePage,
            Company, 
            Country, 
            countryCode,
            Created 
            createTimeStamp 
            Department 
            Description 
            DisplayName 
            DistinguishedName 
            Division 
            EmailAddress 
            EmployeeID 
            EmployeeNumber 
            Fax 
            GivenName 
            HomeDirectory 
            HomeDrive 
            HomePage 
            HomePhone 
            Initials 
            instanceType 
    


    ¯\_(ツ)_/¯

    Wednesday, August 20, 2014 10:27 PM
  • Your version will result in bad items due to wrapping of properties.

    ¯\_(ツ)_/¯

    Wednesday, August 20, 2014 10:28 PM
  • $user = get-aduser $username -properties *

    That took a function to build and there was only about 100 properties.

    Why would you do that. Just select the properties you need directly.

    ¯\_(ツ)_/¯

    Because the function is generic, it works for ADUser, WIN32_Classes, SQL Server, Office Applications, forms, controls, etc.

    It can be customized to build a psobject or more interesting to populate GUI parts.
    Wednesday, August 20, 2014 10:37 PM
  • $user = get-aduser $username -properties *

    That took a function to build and there was only about 100 properties.

    Why would you do that. Just select the properties you need directly.

    ¯\_(ツ)_/¯

    Because the function is generic, it works for ADUser, WIN32_Classes, SQL Server, Office Applications, forms, controls, etc.

    It can be customized to build a psobject or more interesting to populate GUI parts.

    But the output of these things is already a PsObject.  Select-Object creates a PsObject which is why it is called as it is.


    ¯\_(ツ)_/¯

    Wednesday, August 20, 2014 10:41 PM
  • I agree. With the above PSobject constructed on the fly, you could use the invoke-expression on it and it basically duplicates what Powershell provides for free.

    It's the difference between object.property and object."property"

    Odds are, at the Powershell prompt, you know what objects and properties you want to manipulate but in a GUI environment, that may not be the case. If an object is presented in a tree, it can be manipulated without knowing what the object is, in a generic way. In a tree view, it is important to distinguish between the scalar (string,int) and collection properties. The collection properties become child nodes for the parent object. 

    It depends on the need, if one is using ADUser objects, there is probably a specific need.

    Presenting objects in a tree is more of a learning exercise that can lead to a learning tool to help those that are using ASDUser or WIN32 or some other object.

    Thursday, August 21, 2014 3:26 AM
  • But! ... There are no generic properties across objects.  That is why we have Select-Object.

    We can also do simple things like this:

    Get-AdUser someuser | GM -MemberType Property

    I have built dozens of generic GUI wrappers for PS objects.  There is no single solution and no free lunch.

    Here is one way to do some of this: http://gallery.technet.microsoft.com/scriptcenter/Extract-arbitrary-list-of-6f59d3b4

    This is a very simple and flexible method and can be easily extended.



    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 3:35 AM
  • I downloaded it and check it out. It is generic in a specific way.

    I was thinking of uploading to a gallery what I have so far but was wondering can I update the upload  or do I have to get it right the first time?

    Just broke what I had with an ADUser object and now in the process of trying to figure what went wrong.

    It is functional but there are two things to do to finish it, add the collection properties to the tree and provide a prompt.

    I don't expect a free lunch, I am working for it.

    Thursday, August 21, 2014 6:20 AM
  • I downloaded it and check it out. It is generic in a specific way.

    I was thinking of uploading to a gallery what I have so far but was wondering can I update the upload  or do I have to get it right the first time?

    Just broke what I had with an ADUser object and now in the process of trying to figure what went wrong.

    It is functional but there are two things to do to finish it, add the collection properties to the tree and provide a prompt.

    I don't expect a free lunch, I am working for it.

    What does that have to do with the OPs original question.  If you have a specific question of your own you will need to open a new topic of your own.  It is not forum policy to have people add questions to another users topic.


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 6:28 AM
  • Sorry, I have not yet opened a topic and asked a question, I don't know how.

    To answer the question "is there a way to iterate through each property?"

    Here is one way. It iterates through the properties (of any object) and create the properties to create a PS-Object

    PS C:\> 
    Function Get-PSObjectFromObject
    {
        [CmdletBinding()]
        [OutputType([string])]
        param
        (
            [Parameter(Mandatory=$true, 
                       ValueFromPipeline=$false,
                       ValueFromPipelineByPropertyName=$false, 
                       ValueFromRemainingArguments=$false, 
                       Position=0,
                       ParameterSetName='Object')]
            [ValidateNotNull()]
            [ValidateNotNullOrEmpty()]
            [Object]$Object
        )
        Try
        {
            $Members=Get-Member -InputObject $Object 
            $ValidPropertyType = @{"{get;set;}"=$True;"{get;}"=$True;}
            $ValidReturnType = @{"bool"=$True;"byte"=$True;"string"=$True;"string[]"=$True;
                                 "int"=$True;"int16"=$True;"int32"=$True;"int64"=$True;
                                 "uint"=$True;"uint16"=$True;"uint32"=$True;"uint64"=$True;
                                 "datetime"=$True;"timespan"=$True;
                                 "system.boolean"=$True;"system.byte"=$True;"system.string"=$True;"system.string[]"=$True;
                                 "system.int"=$True;"system.int16"=$True;"system.int32"=$True;"system.int64"=$True;
                                 "system.uint"=$True;"system.uint16"=$True;"system.uint32"=$True;"system.uint64"=$True;
                                 "system.datetime"=$True;"system.timespan"=$True
                                }
            [string]$String=""
            $String=$String+"New-Object PSObject -Property ([Ordered]@{ `r`n"
    
            ForEach ($Member in $Members)
            {
                IF ($Member.MemberType -EQ "Property")
                {
                   [string]$Name=$Member.Name
                   IF ($Name.Substring(1,1) -NE "_")
                   {
                       IF (-NOT $Name.Contains("-"))
                       {
                           [String[]]$Definition=$Member.Definition.Split(" ")
                           [string]$PropertyType=$Definition[2]
                           IF ($ValidPropertyType[$PropertyType]) 
                           {
                               $ReturnType=$Definition[0]
                               If ($ValidReturnType[$ReturnType])
                               {
                                    $String=$String+"           $Name="+"$"+"Object.$Name `r`n"
                               }
                           }
                        }
                    }
                }
            }
            $String=$String+"}) `r`n"
            $String
        }
        Catch [System.Exception]
        {
            Write-Host $_.Exception.Message
        }
    }
    
    $Object = Get-aduser "Administrator" -Properties *
    $PSProperties = Get-PSObjectFromObject $Object
    $PSObject = Invoke-Expression $PSProperties
    "***********This is PSObject definition"
    $PSProperties
    "***********This is PSObject"
    $PSObject
    
    ***********This is PSObject definition
    New-Object PSObject -Property ([Ordered]@{ 
               AccountExpirationDate=$Object.AccountExpirationDate 
               accountExpires=$Object.accountExpires 
               AccountLockoutTime=$Object.AccountLockoutTime 
               AccountNotDelegated=$Object.AccountNotDelegated 
               adminCount=$Object.adminCount 
               AllowReversiblePasswordEncryption=$Object.AllowReversiblePasswordEncryption 
               BadLogonCount=$Object.BadLogonCount 
               badPasswordTime=$Object.badPasswordTime 
               badPwdCount=$Object.badPwdCount 
               CannotChangePassword=$Object.CannotChangePassword 
               CanonicalName=$Object.CanonicalName 
               City=$Object.City 
               CN=$Object.CN 
               codePage=$Object.codePage 
               Company=$Object.Company 
               Country=$Object.Country 
               countryCode=$Object.countryCode 
               Created=$Object.Created 
               createTimeStamp=$Object.createTimeStamp 
               Deleted=$Object.Deleted 
               Department=$Object.Department 
               Description=$Object.Description 
               DisplayName=$Object.DisplayName 
               DistinguishedName=$Object.DistinguishedName 
               Division=$Object.Division 
               DoesNotRequirePreAuth=$Object.DoesNotRequirePreAuth 
               EmailAddress=$Object.EmailAddress 
               EmployeeID=$Object.EmployeeID 
               EmployeeNumber=$Object.EmployeeNumber 
               Enabled=$Object.Enabled 
               Fax=$Object.Fax 
               GivenName=$Object.GivenName 
               HomeDirectory=$Object.HomeDirectory 
               HomedirRequired=$Object.HomedirRequired 
               HomeDrive=$Object.HomeDrive 
               HomePage=$Object.HomePage 
               HomePhone=$Object.HomePhone 
               Initials=$Object.Initials 
               instanceType=$Object.instanceType 
               isCriticalSystemObject=$Object.isCriticalSystemObject 
               isDeleted=$Object.isDeleted 
               LastBadPasswordAttempt=$Object.LastBadPasswordAttempt 
               LastKnownParent=$Object.LastKnownParent 
               lastLogoff=$Object.lastLogoff 
               lastLogon=$Object.lastLogon 
               LastLogonDate=$Object.LastLogonDate 
               lastLogonTimestamp=$Object.lastLogonTimestamp 
               LockedOut=$Object.LockedOut 
               logonCount=$Object.logonCount 
               LogonWorkstations=$Object.LogonWorkstations 
               Manager=$Object.Manager 
               MNSLogonAccount=$Object.MNSLogonAccount 
               MobilePhone=$Object.MobilePhone 
               Modified=$Object.Modified 
               modifyTimeStamp=$Object.modifyTimeStamp 
               Name=$Object.Name 
               ObjectCategory=$Object.ObjectCategory 
               ObjectClass=$Object.ObjectClass 
               Office=$Object.Office 
               OfficePhone=$Object.OfficePhone 
               Organization=$Object.Organization 
               OtherName=$Object.OtherName 
               PasswordExpired=$Object.PasswordExpired 
               PasswordLastSet=$Object.PasswordLastSet 
               PasswordNeverExpires=$Object.PasswordNeverExpires 
               PasswordNotRequired=$Object.PasswordNotRequired 
               POBox=$Object.POBox 
               PostalCode=$Object.PostalCode 
               PrimaryGroup=$Object.PrimaryGroup 
               primaryGroupID=$Object.primaryGroupID 
               ProfilePath=$Object.ProfilePath 
               ProtectedFromAccidentalDeletion=$Object.ProtectedFromAccidentalDeletion 
               pwdLastSet=$Object.pwdLastSet 
               SamAccountName=$Object.SamAccountName 
               sAMAccountType=$Object.sAMAccountType 
               ScriptPath=$Object.ScriptPath 
               sDRightsEffective=$Object.sDRightsEffective 
               SmartcardLogonRequired=$Object.SmartcardLogonRequired 
               State=$Object.State 
               StreetAddress=$Object.StreetAddress 
               Surname=$Object.Surname 
               Title=$Object.Title 
               TrustedForDelegation=$Object.TrustedForDelegation 
               TrustedToAuthForDelegation=$Object.TrustedToAuthForDelegation 
               UseDESKeyOnly=$Object.UseDESKeyOnly 
               userAccountControl=$Object.userAccountControl 
               UserPrincipalName=$Object.UserPrincipalName 
               uSNChanged=$Object.uSNChanged 
               uSNCreated=$Object.uSNCreated 
               whenChanged=$Object.whenChanged 
               whenCreated=$Object.whenCreated 
    }) 
    
    ***********This is PSObject
    
    
    AccountExpirationDate             : 
    accountExpires                    : 9223372036854775807
    AccountLockoutTime                : 
    AccountNotDelegated               : False
    adminCount                        : 1
    AllowReversiblePasswordEncryption : False
    BadLogonCount                     : 0
    badPasswordTime                   : 130524210883000074
    badPwdCount                       : 0
    CannotChangePassword              : False
    CanonicalName                     : Contoso.com/Users/Administrator
    City                              : 
    CN                                : Administrator
    codePage                          : 0
    Company                           : 
    Country                           : 
    countryCode                       : 0
    Created                           : 6/21/2014 12:48:03 AM
    createTimeStamp                   : 6/21/2014 12:48:03 AM
    Deleted                           : 
    Department                        : 
    Description                       : Built-in account for administering the computer/domain
    DisplayName                       : 
    DistinguishedName                 : CN=Administrator,CN=Users,DC=Contoso,DC=com
    Division                          : 
    DoesNotRequirePreAuth             : False
    EmailAddress                      : 
    EmployeeID                        : 
    EmployeeNumber                    : 
    Enabled                           : True
    Fax                               : 
    GivenName                         : 
    HomeDirectory                     : 
    HomedirRequired                   : False
    HomeDrive                         : 
    HomePage                          : 
    HomePhone                         : 
    Initials                          : 
    instanceType                      : 4
    isCriticalSystemObject            : True
    isDeleted                         : 
    LastBadPasswordAttempt            : 8/13/2014 9:31:28 AM
    LastKnownParent                   : 
    lastLogoff                        : 0
    lastLogon                         : 130530452556502145
    LastLogonDate                     : 8/12/2014 2:27:39 AM
    lastLogonTimestamp                : 130523092594640653
    LockedOut                         : False
    logonCount                        : 714
    LogonWorkstations                 : 
    Manager                           : 
    MNSLogonAccount                   : False
    MobilePhone                       : 
    Modified                          : 8/12/2014 2:27:39 AM
    modifyTimeStamp                   : 8/12/2014 2:27:39 AM
    Name                              : Administrator
    ObjectCategory                    : CN=Person,CN=Schema,CN=Configuration,DC=Contoso,DC=com
    ObjectClass                       : user
    Office                            : 
    OfficePhone                       : 
    Organization                      : 
    OtherName                         : 
    PasswordExpired                   : False
    PasswordLastSet                   : 6/14/2014 4:55:33 AM
    PasswordNeverExpires              : True
    PasswordNotRequired               : False
    POBox                             : 
    PostalCode                        : 
    PrimaryGroup                      : CN=Domain Users,CN=Users,DC=Contoso,DC=com
    primaryGroupID                    : 513
    ProfilePath                       : 
    ProtectedFromAccidentalDeletion   : False
    pwdLastSet                        : 130472205339962382
    SamAccountName                    : Administrator
    sAMAccountType                    : 805306368
    ScriptPath                        : 
    sDRightsEffective                 : 15
    SmartcardLogonRequired            : False
    State                             : 
    StreetAddress                     : 
    Surname                           : 
    Title                             : 
    TrustedForDelegation              : False
    TrustedToAuthForDelegation        : False
    UseDESKeyOnly                     : False
    userAccountControl                : 66048
    UserPrincipalName                 : 
    uSNChanged                        : 113679
    uSNCreated                        : 8196
    whenChanged                       : 8/12/2014 2:27:39 AM
    whenCreated                       : 6/21/2014 12:48:03 AM
    
    PS C:\> 

    The GUI version of this will be uploaded within a day or two. 

    Thursday, August 21, 2014 7:30 AM
  • Why would anyone do that.  It serves no purpose and has little to do with the OPs question.

    As I posted. THe result frm Get-AdUser is already and object. There is no need to create a copy of it. It is just a waste of time.

    If it is needed to get at the PsObject just reference it.

    $u=Get-AdUser test -Properties *
    $u.PsObject.Properties

    This available on every PowerShell object.  PowerShell buids a PsObject internally.  There is no need to do this.

    We can also get "PsBase" and "PsAdapted" forms of the object.

    What you are doing looks fancy but it is nothing.  It does nothing and adds nothing. You are fooling yourself because you do not understand what an object is and what PowerShell does with its objects.

    Here is your object without doing all of that mumbo-jumbo.  Try it.

    Get-AdUser test -Properties * | Format-List

    Same output, same object.  PowerShell already knows how to use it.


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 7:44 AM
  • Why would anyone do that.  It serves no purpose and has little to do with the OPs question.

    ...

    What you are doing looks fancy but it is nothing.  It does nothing and adds nothing. You are fooling yourself because you do not understand what an object is and what PowerShell does with its objects.

    ...


    ¯\_(ツ)_/¯

    Thanks for the almost compliment.

    I already agreed that it is basically duplicating what Powershell provides except for three things.

    It provides a template to copy and paste code from.

    It separates the scalar properties from the collection properties.

    It a provides a basic code structure from which to customize to suit any need/application.

    By itself, it's a fancy nothing, which is almost something.

    Thursday, August 21, 2014 8:14 AM
  • It doesn't do any of that.  It is just redundant.  The object itself provides all that is needed. You cannot escape managing and coding objects.

    You cannot show me any example that cannot be done directly with the object.  You are just adding complexity to a system that is designed to hide complexity.  You are deliberately unwinding the object.  This is counter to the philosophy of the object system. 

    Why?


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 8:22 AM
  • This is not the first time I have done this, I have done this before in VB awhile back. 

    It took weeks to do in VB what I have done so far in Powershell in a few days. 

    The first program was an object browser, the second program using the object browser as a base did object configuration based on a database. The third program based on the database design generated the code to create the objects into two DLLs for use in DCOM. That program generated hundreds of thousands of lines of code depending on the number of tables and queries. The data-driven generated objects were viewable in the first program, the object browser. 

    I don't want to do that again, times have changed. But the object browser was really handy for looking at objects and seeing the structure, a learning tool. A picture is worth a thousand words (plus it saves a lot of keystrokes). 


    Thursday, August 21, 2014 9:13 AM
  • What I am pointing out is that you can do all of that without reconstucting the object.  Net objects are "browseable"  They use Reflection to discover all elements of the object.  Each property is visible and has a type which can be read.

    We can read the structure of any object directly in PowerShell. PS comes with tools to extract structure and intellisense allows us to find all properties and methods.  I see no purpose in writing what is built into both PowerShell and Visual Studio.  I have been writing Net Framework programs and PowerShell Cmdlets since the first beta of both.  Visual studio comes with an object browser. We can also download and use the stand alone object browser to expand and view COM and Net classes.

    This is why I tell most to do more research and to learn the fundamentals. It save you from reinventing the wheel and doing it incorrectly.  Things learned this way are nearly always learned incorrectly.  After years of managing programmers I have seen the disaster of self-taught coders.  Most produce clumsy and very poorly designed code because they have not learned the discipline that trained programmers learn.  Most companies now require certification in languages and systems to avoid bad code.

    My point is - do not accept learning by accident.  Spend time reading the required books on the technology of choice.  Be sure you can pass the exams.  Now that you have a small amount of experience learn the formal side of scripting.  Don't quit learning because you think you know something.  You haven't even scratched the surface.


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 10:17 AM
  • Completely forgot about the -expandproperty switch... It was a long day :/ I will be able to get what I need from this.

    Thanks!

    Thursday, August 21, 2014 2:41 PM
  • Sorry, one final question since I can't seem to find much information about the -expandproperty switch. Is there a way to select the values associated with each property as well? I've tried:

    select-object -ExpandProperty PropertyNames,Propertyvalues
    select-object -ExpandProperty PropertyNames,values
    select-object -ExpandProperty PropertyNames,Propertyvalue
    select-object -ExpandProperty PropertyNames,Propertydata
    select-object -ExpandProperty PropertyNames,data
    

    and many other variations to no avail. Is this possible? Thinking I just don't know the heading of the value column...

    Thanks!

    Tony

    Thursday, August 21, 2014 3:14 PM
  • No - you can only expand one property at a time.

    Again - this gets all properties and values.

    get-aduser $username -properties * | Format-List

    Try it.


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 3:27 PM
  • And again, I have to say that doing that does not allow me to iterate through the properties. The -expandproperty switch will allow me to iterate through and get the values one at a time, just wanted to see if there was an easier way to get both.
    Thursday, August 21, 2014 3:40 PM
  • And again, I have to say that doing that does not allow me to iterate through the properties. The -expandproperty switch will allow me to iterate through and get the values one at a time, just wanted to see if there was an easier way to get both.

    Why?  What purpose does it server?

    You can get any property value like this as always:

    $user=Get-AdUser test -Properties *

    $user.Name
    $user.Mail

    etc...

    Or, as I posted above:

    $user=Get-AdUser test -Properties *
    $user.PsObject.Properties | select Name, Value

    I can pretty much gurantee that if you can tell us what you are trying to do that there is an easy way to do it.  Most of the time when we see this it indicates that the user is trying to do something odd because they do not know programming and how object systems work.  What I see is that you are trying to find a linear solution to an object problem.


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 4:50 PM
  • In case you haven't figured it out yet the "Proerties" collection is a "Keyed" collection:

    $user=Get-AdUser test -Properties *
    $user.PsObject.Properties['Name']
    $user.PsObject.Properties['Mail']If you want rue native properties (attributes) then we would do this:

    $user=[adsi]LDAP://$((Get-AdUser test).DistinguishedName)

    Now we can do the same thing with unmodified properties.

    $user.Properties['homedrive']  # note we now drop the PsObject.

    etc...

    With this version or $user we can edit the properties which we canot do with the user from Get-AdUser.

    $user.Properties[.mail'].Value='newmail@dom.com'
    $user.CommitChanges()


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 5:48 PM
  • Oh...a simple object browser:

    $user.PsBase.Properties|ft PropertyName,Value,@{N='Type';E={$_.Value.GetType().Name}}


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 5:55 PM
  • If you are still skeptical try these:

    #hash
    (@{}).PsObject.Properties
    
    #array
    (@()).PsObject.Properties
    
    #string
    ('Hello World'.PsObject.Properties
    
    #wmi objects
    (GWMI Win32_BIOS).PsObject.Properties
    
    #file system
    (Get-Item c:\windows).PsObject.Properties

    As you can see - everything in PowerShell is already a custom PsObject.  PowerShell builds this for you along with other variations called "PsBase" and "PsAdapted".


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 6:34 PM
  • Here is a sample, It uses a modified version of the function above.
    Thursday, August 21, 2014 7:02 PM
  • That looks strangely familiar......

    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    Thursday, August 21, 2014 7:08 PM
  • What does that have to do with the function.  I can do all of that without anything more than WMI and a simple form.

    I have two of those that use only the objects.

    I am asking what your function (?) can do that is not already part of PowerShell as I have posted above.

    All PS objects have a PsObject view.  You are just manually creating this view that already exists.  Why?


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 7:10 PM
  • That looks strangely familiar......

    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    Yes - It is nearly identical to one I have had for years.  Of course the original by Moss was done in PS v1 so it was a bit more difficult.

    I have one done in C# which is very similar.

    Reflection and object exposure make most of this very simple.  PowerShell also wraps this up in a "PsObject" view of every object.  This gives us a full description of every aspect of the object. "Properties" is only one part of the PsObject view.


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 7:14 PM
  • Are you suggesting that it would be a waste of time to upload it to a gallery and/or maybe write a wiki article about the Powershell GUI object browser application? It is not innovative enough because it has been done before?


    Thursday, August 21, 2014 8:00 PM
  • Are you suggesting that it would be a waste of time to upload it to a gallery and/or maybe write a wiki article about the Powershell GUI object browser application? It is not innovative enough because it has been done before?


    I know nothing about your WMI browser. It is just like most that have been posted but that shouldn't stop you.  My issue is that the script you posted above uses an unnecessary recreation of an object. It serves no purpose because PowerShell already does exactly that. 


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 8:05 PM
  • Are you suggesting that it would be a waste of time to upload it to a gallery and/or maybe write a wiki article about the Powershell GUI object browser application? It is not innovative enough because it has been done before?


    Here is one of the many: http://gallery.technet.microsoft.com/scriptcenter/89c759b7-20b4-49e8-98a8-3c8fbdb2dd69

    It was written by MOW back in 2006.  It also contains help and a method builder and code builder.  You should take a look at howhe did it initially.  With PosH v3 and later it can actually be simplified.


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 8:08 PM
  • Here are two more that are worth reviewing:

    http://gallery.technet.microsoft.com/scriptcenter/WMI-Explorer-Search-WMI-cd87e309

    http://gallery.technet.microsoft.com/scriptcenter/73af26e9-a6f8-49ab-a367-9daffc8081b4

    The reason I post these is because they are good learning tools.  They can help you see how to navigate complex objects in various ways.


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 8:11 PM
  • We have 10 custom fields under each user account in AD. 

    Get-ADUser $Username -Properties * | Where {$_ -like 'CustomField*'}

    This would return all fields but I could not iterate through to see which was empty and which had data. Would return a count of 1.

    Get-ADUser $Username -Properties * | select-object -ExpandProperty PropertyNames | Where {$_ -like 'CustomField*'}

    This however would return a count of 10 and give me the individual property Names from which I could iterate through and load a datatable with this and various other information. From the datatable I create an HTML email and send out reports to IT and the users.

    Tony


    • Edited by TonyL12345 Thursday, August 21, 2014 9:22 PM
    Thursday, August 21, 2014 9:21 PM
  • Custom properties do not exist on the object if they are empty.  Some attributes are mandatory and some not.  Only Mandatory properties are always available even if blank.

    What you are doing is not a way to solve this issue.

    Consider this:

    Get-AdUser testuser -Properties * | 
        select @{N='Custom1';E={if($_.Custom1){$_.Custom1}else{'BLANK'}}},
               @{N='Custom2';E={if($_.Custom2){$_.Custom2}else{'BLANK'}}},
               @{N='Custom3';E={if($_.Custom3){$_.Custom3}else{'BLANK'}}},
        ....  etc ...
    

    This is how to deal with items that may not exist.  Yu can just return blank or any value you want.  You can change the name to suit the content as needed.

    If you had actually said what you were trying to do this would have been much easier.  It has nothing to do with enumerating properties.  It is all about knowing how to use PowerShell.

    Try to avoid technical requestds when you don't quite know what you want.  A plain English statement is much easier to work with.


    ¯\_(ツ)_/¯

    Thursday, August 21, 2014 10:58 PM
  • Thanks, I checked out all 3 gallery downloads, I am always willing to learn.

    With the first download, I could not get a instance of a Win32 class. 

    With the second download, it gave a roadmap of the namespace and listed all of the classes in the console. With this roadmap, I went back to the first download and still not find or get a WIN32 class/instance.

    The third download was very similar to what I have. It did it in 112 lines of code. I wrote a script to generate a 400+ line function to add the 400+ WIN32 classes to the treeview in a 3 tier functional order. That did a query and listed the classes (WIN32 classes was a subset) in alphabetical order in a listview in a few lines. If learning/exploring is the objective, then the functional order is better because similar classes are grouped by function, whereas if you know what you want, then a alphabetical listing is preferable without trying to find it 3 levels down in a tree, that can be annoying. Having both options would probably be best.

    It listed the (subset) properties in a textbox like a console, making it hard to differentiate the different objects as they scrolled by. A tree is preferable, as GUI is suppose to be visual.

    This has convinced me it would not be a total waste of time to upload it, hope I have not wasted too much of yours.

    Friday, August 22, 2014 3:09 AM
  • Yes - the first one is old PS V1 code from 2006 and will have issues with V3 and later.

    I posted that to show you that there is a lot out there that has been around for quite some time.  I amnot rying to discourage you from doing uour own.  I am only showing you that there are many approaches.

    The New-Object build is all that I am criticizing.  It already exists on every object in PowerShell.  PS does this internally   Just add PsObject to any object and you have the PsObject you are trying to build.  All elements of an object are discoverable via PsObject, PsBase or PsAdapted.  You don't need to write these things.  That is all I am trying to get you to see.

    If you look at how PowerShell does these things you will see that you can easily extend all objects by creating extension files.  Each user can extend the system and it can be extended for all users or all systems.  Investigate how this is done.

    The WMI browser I built as a demo to show how to build forms for a class used PsObject and the WMI relationship and association mechanisms to walk the WMI hierarchy.  WMI also has its own property collection aside from Net.  This makes the structure and discovery much easier and it works pretty much the same in PowerShell, VB and C#.  In no case would we have to regenerate objects.  The property collections are always there.  This has been true for WMI since Windows 98 and has been used to create the WMI Toolkit in VBScript and HTML.   Ithinkyoucan still download the CIM Tools from the download center.


    ¯\_(ツ)_/¯

    Friday, August 22, 2014 3:29 AM
  • Yes - here it is.  The full CIM Studio from Microsoft updated for Windows 7.  This also allows for managing and building subscriptions which most WMI Explorers do not provide.  This was originally written almost 10 years ago.  It is a masterful use of scripting and custom COM.   I am sure much of this served as the model for many modern WMI toolkits.  I still use it to browse the subscriptions on many systems.

    http://www.microsoft.com/en-us/download/details.aspx?id=24045


    ¯\_(ツ)_/¯

    Friday, August 22, 2014 3:33 AM
  • In all honesty and with all due respect, I don't like your suggested way of doing this. The way Bill provided above will allow me to grab any field that the AD Admins decide they want to add (Say if they expand the custom fields to 15 or 100), and not have to modify my code due to static entries. My Code grabs everything and iterates through each property and returns $null or the given value.

    I feel my question was worded correctly and Bill understood what I was looking for.

    Friday, August 22, 2014 3:38 PM
  • In all honesty and with all due respect, I don't like your suggested way of doing this. The way Bill provided above will allow me to grab any field that the AD Admins decide they want to add (Say if they expand the custom fields to 15 or 100), and not have to modify my code due to static entries. My Code grabs everything and iterates through each property and returns $null or the given value.

    I feel my question was worded correctly and Bill understood what I was looking for.

    I do not think you understand what Bill's suggestion does.  It does not do what you think.  It cannot be used with a wildcard.  You can only expand one property.

    Test it and you will see what I mean.


    ¯\_(ツ)_/¯

    Friday, August 22, 2014 4:48 PM
  • Here is what i did and it is already being used... It works:

    $Properties = Get-ADUser $Username -Properties * | select-object -ExpandProperty PropertyNames | Where {$_ -like 'CustomField*'}    
    foreach ($code in $properties)
    {
        $row = $datatable.NewRow()
        $row["Property"] = $code.ToString()
        $row["Value"] = (Get-ADUser $Username -Properties $code | Select-Object $code).$code.tostring()
        $datatable.Rows.Add($row)
    }
    

    Friday, August 22, 2014 4:52 PM
  • And just to be clear, the properties are only getting pulled once from the first user in the list to create the properties list once. I know that's not how it looks here... And then for each user it fills the datatable with the property and values.
    Friday, August 22, 2014 5:05 PM
  • That function creating PSObjects duplicates what's in Powershell. The WIN32 classes that are retrieved through Get-WMIObject returns a wrapper class that GetType reports as WMI. If you use New-Object on a WIN32 class, the properties wont be populated, because WMI does that.

    It's only usefulness is to copy it into your own code so you don't have type out the property names. I rather copy something and pick and choose and delete what I don't need than type it out from scratch.

    I checked out the WMI download and it wouldn't run. I checked out the Google images for some screen shots.

    Here is a screen shot of a my WMI Class:


    This is where the true object browser comes in. This shows the same WIN32 class instance in the structure of the form. It drills down to the node that contains the same instance in the above screen shot.

    In this case, PSObject makes absolutely no sense.

    Should this be 1 or 2 uploads?

    Friday, August 22, 2014 7:09 PM
  • Here is what i did and it is already being used... It works:

    $Properties = Get-ADUser $Username -Properties * | select-object -ExpandProperty PropertyNames | Where {$_ -like 'CustomField*'}    
    foreach ($code in $properties)
    {
        $row = $datatable.NewRow()
        $row["Property"] = $code.ToString()
        $row["Value"] = (Get-ADUser $Username -Properties $code | Select-Object $code).$code.tostring()
        $datatable.Rows.Add($row)
    }

    I don't think I can get you to understand why and what you are doing is silly.  I am going to let you sort this oot however you wish.  One day you willlearn enough to understand why...maybe.


    ¯\_(ツ)_/¯

    Friday, August 22, 2014 8:16 PM
  • And just to be clear, the properties are only getting pulled once from the first user in the list to create the properties list once. I know that's not how it looks here... And then for each user it fills the datatable with the property and values.

    If an optional property is not used it will NOT show up in the properties of a user.  If you are lucky enough to choose a user where all of the properties are defined then you will get all properties. This is exactly what you said you do not want.


    ¯\_(ツ)_/¯

    Friday, August 22, 2014 8:18 PM
  • Brian - What?  What is the point?

    Images of the screen serve no purpose in this discussion and I give up.  You win.  It is pretty.  Be happy with it.


    ¯\_(ツ)_/¯

    Friday, August 22, 2014 8:20 PM