locked
Script - Query AD using Get-AdUser RRS feed

  • Question

  • Hi all,

    I have the below script to query AD... when running get a few users back and then script stops with no errors but does not collect all users in selected OU... Any ideas?

    #===================================================================================== # WINDOWS POWERSHELL SCRIPT # # TITLE: Get_UserInfo.ps1 # AUTHOR: Me # DATE: 19.JAN.2016 # # DESCRIPTION: The script is designed to collect user # information to include member of information for # multiple users. # # SCRIPT VERSION: 0.1 #===================================================================================== $ErrorActionPreference = "Continue" $VerbosePreference = "Continue" Import-Module ActiveDirectory #===================================================================================== # SCRIPT FUNCTIONS #===================================================================================== Function Get-UserInfo { [CmdletBinding()] Param ([Parameter(Mandatory=$True,ValueFromPipeline = $True,ValueFromPipelinebyPropertyName = $True)] [Microsoft.ActiveDirectory.Management.ADUser[]]$arrUserInfo)


    $currentPathFQDN = (Get-Item -Path ".\" -Verbose).FullName

    $csvUserData = "$currentPathFQDN\UserInformation.csv" ForEach($user in $arrUserInfo) { $strDisplayName = $user.DisplayName $strSAN = $user.SamAccountName $strGPIN = $user.EmployeeNumber $strDept = $user.Department $strDivision = $user.Division $strHomeDir = $user.HomeDirectory $strOffice = $user.Office $strRN = $user.roomNumber $strMemberGroups = $user.MemberOf ForEach($strGroup in $strMemberGroups) { Add-Content -Path $csvUserData -Value "$strDisplayName;$strSAN;$strGPIN;$strDept;$strDivision;$strHomeDir;$strOffice;$strGroup" } } } #===================================================================================== # MAIN SCRIPT #===================================================================================== Set-location C:\temp # SCRIPT VARIABLES $locationList = "1. France `n 2. Germany `n 3. Israel `n 4. Italy `n 5. Netherlands `n 6. Poland `n 7. Russia `n 8. Spain `n 9. Turkey `n 10. All Locations `n" # Collect location in order to filter the search $strSelection = Read-Host -Prompt "Select location number `n $locationList"

    $currentPathFQDN = (Get-Item -Path ".\" -Verbose).FullName

    $csvUserData = "$currentPathFQDN\UserInformation.csv"

    If(Test-Path $csvUserData){Remove-Item -Path $csvUserData -Force}
    Add-Content -Path $csvUserData -Value "DisplayName;UserName;GPIN;Department;Division;HomeDirectory;Office;RoomNumber;MemberGroup"

    Switch ($strSelection) { 1 {$strLocation = "France";$strCountryCode = "FRA";break} 2 {$strLocation = "Germany";$strCountryCode = "DEU";break} 3 {$strLocation = "Israel";$strCountryCode = "ISR";break} 4 {$strLocation = "Italy";$strCountryCode = "ITA";break} 5 {$strLocation = "Netherlands";$strCountryCode = "NLD";break} 6 {$strLocation = "Poland";$strCountryCode = "POL";break} 7 {$strLocation = "Russia";$strCountryCode = "RUS";break} 8 {$strLocation = "Spain";$strCountryCode = "ESP";break} 9 {$strLocation = "Turkey";$strCountryCode = "TUR";break} 10 {$strLocation = "France,Germany,Israel,Italy,Netherlands,Poland,Russia,Spain,Turkey";$strCountryCode = "FRA,DEU,ISR,ITA,NLD,POL,RUS,ESP,TUR";break} } If($strSelection -eq 10) { $strLoc = $strLocation -Split "," $strCode = $strCountryCode -Split "," $i = 0 # Search Active Directory for all countries ForEach ($location in $strLoc) { $searchBase = "OU=$strCode[$i],OU=ACCOUNTS,DC=TEST,DC=NET" Get-ADUser -Filter 'co -eq $location' -SearchBase $searchBase -ResultPageSize 100 -ResultSetSize 100 -Properties * | Get-UserInfo # Search Active Directory global OU containing any other accounts $searchBase = "OU=GLOBAL,OU=ACCOUNTS,DC=TEST,DC=NET" Get-ADUser -Filter 'co -eq $location' -SearchBase $searchBase -ResultPageSize 100 -ResultSetSize 100 -Properties * | Get-UserInfo } } Else { # Search Active Directory based on selected country $searchBase = "OU=$strCountryCode,OU=ACCOUNTS,DC=TEST,DC=NET" Get-ADUser -Filter 'co -eq $strLocation' -SearchBase $searchBase -ResultPageSize 100 -ResultSetSize 100 -Properties * | Get-UserInfo # Search Active Directory global OU containing any other accounts $searchBase = "OU=GLOBAL,OU=ACCOUNTS,DC=TEST,DC=NET" Get-ADUser -Filter 'co -eq $strLocation' -SearchBase $searchBase -ResultPageSize 100 -ResultSetSize 100 -Properties * | Get-UserInfo }



    JC - a.k.a Aramane




    • Edited by Aramane Friday, February 12, 2016 5:08 PM
    Friday, February 12, 2016 3:40 PM

Answers

  • Stop thinking that you are a programmer.  You are just over-complicating this.  What you are doing looks very official but is not based on any technical understanding. 

    Start by making you function look like this:

    Function Get-UserInfo{
         [CmdletBinding()]
         
    Param
              $strSAN     )

    Get-ADUser -Filter "co -eq $strLocation" -SearchBase $searchBase -ResultPageSize 100  |
                ForEach-Object{Get-UserInfo $_.SamAccountName}

    You cannot send a string to a an object declaration. Explicit type declarations are an advanced usage and should not be used until you understand what they are. In 99% of your scripting they are not necessary.  If you are passing only one default property to a function then why returm "-Properties *"?


    \_(ツ)_/

    • Marked as answer by Aramane Tuesday, February 16, 2016 3:36 PM
    Tuesday, February 16, 2016 3:15 PM

All replies

  • Remove this: "-ResultSetSize 100 "

    \_(ツ)_/

    Friday, February 12, 2016 7:12 PM
  • removed and still same results stops after collecting the first two users... no error, nothing... strange


    JC - a.k.a Aramane

    Monday, February 15, 2016 10:31 AM
  • Remove this line and fix the errors:

    $ErrorActionPreference = "Continue"


    \_(ツ)_/

    Monday, February 15, 2016 12:56 PM
  • Hi, I was under the impression that the continue would show the message and allow script to continue.  I have now changed to inquire to see if any results.  I still received no error message.  I have then removed completely and still no error.  Any other ideas are welcomed...  Interesting is that when running the following command it works with no issues and get back ~150 users:

    Get-AdUser -Filter 'co -eq "Germany"' -SearchBase "OU=DEU,OU=ACCOUNTS,DC=TEST,DC=NET" -Properties * |
    ForEach-Object -Process {If($_.SmartcardLogonRequired){$_.SamAccountName}}


    JC - a.k.a Aramane

    Monday, February 15, 2016 1:45 PM
  • Yes you need to debug your script. Unfortunately it is too hard to read as posted.


    \_(ツ)_/

    Monday, February 15, 2016 2:03 PM
  • It appears that $i is never used.


    \_(ツ)_/

    Monday, February 15, 2016 2:16 PM
  • Hi Guys, debuged the script and updated as per below code... all works as intended and the values are passed to the function properly.  The only issue that can not get around is the following error:

    Cannot convert 'Microsoft.ActiveDirectory.Management.ADUser[]' to the type 'Microsoft.ActiveDirectory.Management.ADUser' required by parameter 'Identity'. Specified method is not supported. At W:\PowerShellScripts\ColUserData\Get_UserInfo3.ps1:103 char:27
    +             ForEach-Object <<<<  -Process {$_.SamAccountName | Get-UserInfo}
        + CategoryInfo          : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
        + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.ForEachObjectCommand

    #=====================================================================================
    # WINDOWS POWERSHELL SCRIPT
    # 
    # TITLE: Get_UserInfo.ps1
    # AUTHOR: J Cruz
    # DATE: 19.JAN.2016
    #
    # DESCRIPTION: The script is designed to collect user inforamtion to include 
    # member of information for a single or multiple users.  The multiple users will 
    # search based on a single location.
    #
    # SCRIPT VERSION: 0.1
    #=====================================================================================
    $ErrorActionPreference = "Stop"
    $VerbosePreference = "Continue"
    Import-Module ActiveDirectory
    
    #=====================================================================================
    # SCRIPT FUNCTIONS
    #=====================================================================================
    Function Get-UserInfo
        {
            [CmdletBinding()]
            Param
                ([Parameter(Mandatory=$True,ValueFromPipeline = $True)]
                    [Microsoft.ActiveDirectory.Management.ADUser[]]$strSAN)
                
            $currentPath = (Get-Item -Path ".\" -Verbose).FullName
            $csvData = "$currentPathFQDN\UserInformation.csv"
            $strSAN
            
            Get-ADUser -Identity $strSAN -Properties * | ForEach-Object -Process {
                $strDisplayName = $_.DisplayName;
                $strSAN = $_.SamAccountName;
                $strGPIN = $_.EmployeeNumber;
                $strDept = $_.Department;
                $strDivision = $_.Division;
                $strHomeDir = $_.HomeDirectory;
                $strOffice = $_.Office;
                $strRN = $_.roomNumber;
                $strMemberGroups = $_.MemberOf;
                ForEach($strGroup in $strMemberGroups)
                    {
                        Add-Content -Path $csvData -Value "$strDisplayName;$strSAN;$strGPIN;$strDept;$strDivision;$strHomeDir;$strOffice;$strGroup"
                    }
                }
        }
    
    #=====================================================================================
    # MAIN SCRIPT
    #=====================================================================================
    Set-location P:\Documents
    
    # SCRIPT VARIABLES
    $locationList = "1. France `n 2. Germany `n 3. Israel `n 4. Italy `n 5. Netherlands `n 6. Poland `n 7. Russia `n 8. Spain `n 9. Turkey `n 10. All Locations `n" 
    
    # Collect location in order to filter the search
    $strSelection = Read-Host -Prompt "Select location number `n $locationList"
    $currentPathFQDN = (Get-Item -Path ".\" -Verbose).FullName
    $csvUserData = "$currentPathFQDN\UserInformation.csv"
    If(Test-Path $csvUserData){Remove-Item -Path $csvUserData -Force}
    Add-Content -Path $csvUserData -Value "DisplayName;UserName;GPIN;Department;Division;HomeDirectory;Office;RoomNumber;MemberGroup"
    
    Switch ($strSelection)
        {
            1 {$strLocation = "France";$strCountryCode = "FRA";break}
            2 {$strLocation = "Germany";$strCountryCode = "DEU";break}
            3 {$strLocation = "Israel";$strCountryCode = "ISR";break}
            4 {$strLocation = "Italy";$strCountryCode = "ITA";break}
            5 {$strLocation = "Netherlands";$strCountryCode = "NLD";break}
            6 {$strLocation = "Poland";$strCountryCode = "POL";break}
            7 {$strLocation = "Russia";$strCountryCode = "RUS";break}
            8 {$strLocation = "Spain";$strCountryCode = "ESP";break}
            9 {$strLocation = "Turkey";$strCountryCode = "TUR";break}
            10 {$strLocation = "France,Germany,Israel,Italy,Netherlands,Poland,Russia,Spain,Turkey";$strCountryCode = "FRA,DEU,ISR,ITA,NLD,POL,RUS,ESP,TUR";break}
        }
    
    If($strSelection -eq 10)
        {
            $strLoc = $strLocation -Split ","
            $strCode = $strCountryCode -Split ","
            $i = 0
            
            # Search Active Directory for all countries
            ForEach ($location in $strLoc)
                {
                    $searchBase = "OU=$strCode[$i],OU=ACCOUNTS,DC=TEST,DC=NET"
                    Get-ADUser -Filter 'co -eq $strLocation' -SearchBase $searchBase -ResultPageSize 100 -Properties * | 
                        ForEach-Object -Process {$_.SamAccountName | Get-UserInfo}
                    
                    # Search Active Directory global OU containing any other accounts
                    $searchBase = "OU=GLOBAL,OU=ACCOUNTS,DC=TEST,DC=NET"
                    Get-ADUser -Filter 'co -eq $strLocation' -SearchBase $searchBase -ResultPageSize 100 -Properties * | 
                        ForEach-Object -Process {$_.SamAccountName | Get-UserInfo}
                    $i++
                }
        }
    Else
        {
            # Search Active Directory based on selected country
            $searchBase = "OU=$strCountryCode,OU=ACCOUNTS,DC=TEST,DC=NET"
            Get-ADUser -Filter 'co -eq $strLocation' -SearchBase $searchBase -ResultPageSize 100 -Properties * | 
                ForEach-Object -Process {$_.SamAccountName | Get-UserInfo}
    
            # Search Active Directory global OU containing any other accounts
            $searchBase = "OU=GLOBAL,OU=ACCOUNTS,DC=TEST,DC=NET"
            Get-ADUser -Filter 'co -eq $strLocation' -SearchBase $searchBase -ResultPageSize 100 -Properties * | 
                ForEach-Object -Process {$_.SamAccountName | Get-UserInfo}
        }


    JC - a.k.a Aramane

    Tuesday, February 16, 2016 1:58 PM
  • Stop thinking that you are a programmer.  You are just over-complicating this.  What you are doing looks very official but is not based on any technical understanding. 

    Start by making you function look like this:

    Function Get-UserInfo{
         [CmdletBinding()]
         
    Param
              $strSAN     )

    Get-ADUser -Filter "co -eq $strLocation" -SearchBase $searchBase -ResultPageSize 100  |
                ForEach-Object{Get-UserInfo $_.SamAccountName}

    You cannot send a string to a an object declaration. Explicit type declarations are an advanced usage and should not be used until you understand what they are. In 99% of your scripting they are not necessary.  If you are passing only one default property to a function then why returm "-Properties *"?


    \_(ツ)_/

    • Marked as answer by Aramane Tuesday, February 16, 2016 3:36 PM
    Tuesday, February 16, 2016 3:15 PM
  • Hi, first I do not claim to be a programmer that is the reason why I have come to this forum... for understanding how to improve my script.  I would think that this is a friendly environment to share ideas and learn. I am new to powershell scripting and wanted to try and make my job easier. thank you for your suggestion and will continue to test and learn as you have suggested!

    JC - a.k.a Aramane

    Tuesday, February 16, 2016 3:28 PM
  • Hi, first I do not claim to be a programmer that is the reason why I have come to this forum... for understanding how to improve my script.  I would think that this is a friendly environment to share ideas and learn. I am new to powershell scripting and wanted to try and make my job easier. thank you for your suggestion and will continue to test and learn as you have suggested!

    JC - a.k.a Aramane

    It is not intended to be a negative comment.  It is intended to push you towards simplifying your approach. Don't use constructs that look "cool" without trying to understand them.  They will only make things harder for you to learn.

    I have told many junior programmers similar things when they have started. Keep it simple. Add things as you understand them and not just because you saw someone else use a construct. Remember that at lest half of what you see on the Internet is wrong.


    \_(ツ)_/

    Tuesday, February 16, 2016 3:38 PM
  • Hi, just trying to learn from this article how to apply the same for getting user information.  The script or original information: https://blogs.technet.microsoft.com/heyscriptingguy/2011/05/10/use-the-pipeline-to-create-robust-powershell-functions/ maybe others can use and learn from it.

    JC - a.k.a Aramane

    Tuesday, February 16, 2016 3:50 PM
  • Hi, just trying to learn from this article how to apply the same for getting user information.  The script or original information: https://blogs.technet.microsoft.com/heyscriptingguy/2011/05/10/use-the-pipeline-to-create-robust-powershell-functions/ maybe others can use and learn from it.

    JC - a.k.a Aramane

    But there is no reason to use a pipeline and you are not using it correctly anyway.  What you have posted is not a true pipeline.

    This would be a pipelined function:

    Get-Aduser -filter * | Get-AdUserInfo

    You would either bind by object of bind by "PropertyName".


    \_(ツ)_/

    Tuesday, February 16, 2016 4:09 PM
  • Here is a simple functional example of how to use a pipeline. All elements shown are required

    function Get-AdUserInfo{
        Param(
             [Parameter(ValueFromPipelineByPropertyName)]
             $SamAccountName
        )
        Process{
             Write-Verbose $SamAccountName
        }
    }
    
    get-aduser -filter *| Get-AdUserInfo -Verbose

    This is the minimal code for setting up a pipelined function.


    \_(ツ)_/


    • Edited by jrv Tuesday, February 16, 2016 4:22 PM
    Tuesday, February 16, 2016 4:21 PM
  • aha, see that is what I was looking for, so now understand better... so basically can build a filter such as:

    Get-AdUser -Filter 'co -eq $country' | Get-AdUserInfo -Verbose

    and do the processing withing the function, meaning working with the object or SamAccountName for example to do the heavy lifting.  I hope I am understanding this correctly :-)


    JC - a.k.a Aramane


    • Edited by Aramane Tuesday, February 16, 2016 4:51 PM sent to soon
    Tuesday, February 16, 2016 4:42 PM
  • aha, see that is what I was looking for, so now understand better... so basically can build a filter such as:

    Get-AdUser -Filter 'co -eq $country' | Get-AdUserInfo -Verbose

    and do the processing withing the function, meaning working with the object or SamAccountName for example to do the heavy lifting.  I hope I am understanding this correctly :-)


    JC - a.k.a Aramane


    I have no idea what you are trying to say.  Pipelines have nothing to do with Get-AdUser "filters".  I am only using your example to show you how to use a function in a pipeline.  You can bind by name to the incoming object.  TO do so you must have a "Process" section or the function will not work.  You were both trying to pipeline without a process section and using a type bound variable that did not match anything.


    \_(ツ)_/

    Tuesday, February 16, 2016 4:58 PM
  • As a final note, I have kept my script simple now and modified as below and now works like a champ!

    #=====================================================================================
    # WINDOWS POWERSHELL SCRIPT
    # 
    # TITLE: Get_UserInfo.ps1
    # AUTHOR: Juan Cruz
    # DATE: 19.JAN.2016
    #
    # DESCRIPTION: The script is designed to collect user inforamtion to include 
    # member of information for a single or multiple users.  The multiple users will 
    # search based on a single location.
    #
    # SCRIPT VERSION: 0.1
    #=====================================================================================
    $ErrorActionPreference = "Continue"
    $VerbosePreference = "Continue"
    Import-Module ActiveDirectory
    
    #=====================================================================================
    # SCRIPT FUNCTIONS
    #=====================================================================================
    Function Get-UserInfo
        {
            [CmdletBinding()]
            Param($strSAN,$csvData)
            
            Get-ADUser -Identity $strSAN -Properties * | ForEach-Object -Process {
                $strDisplayName = $_.DisplayName;
                $strSAN = $_.SamAccountName;
                $strGPIN = $_.EmployeeNumber;
                $strDept = $_.Department;
                $strDivision = $_.Division;
                $strHomeDir = $_.HomeDirectory;
                $strOffice = $_.Office;
                $strRN = $_.roomNumber;
                $strMemberGroups = $_.MemberOf;
                ForEach($strGroup in $strMemberGroups)
                    {
                        Add-Content -Path $csvData -Value "$strDisplayName;$strSAN;$strGPIN;$strDept;$strDivision;$strHomeDir;$strOffice;$strGroup"
                    }
                }
        }
    
    #=====================================================================================
    # MAIN SCRIPT
    #=====================================================================================
    Set-location P:\Documents
    
    # SCRIPT VARIABLES
    $locationList = "1. France `n 2. Germany `n 3. Israel `n 4. Italy `n 5. Netherlands `n 6. Poland `n 7. Russia `n 8. Spain `n 9. Turkey `n 10. All Locations `n" 
    $strLocations = "France,Germany,Israel,Italy,Netherlands,Poland,Russia,Spain,Turkey"
    $strCountryCodes = "FRA,DEU,ISR,ITA,NLD,POL,RUS,ESP,TUR"
    
    # Collect location in order to filter the search
    $strSelection = Read-Host -Prompt "Enter location number, e.g. 10 `n $locationList"
    # Collect current path in order to use and create csv file
    $currentPathFQDN = (Get-Item -Path ".\" -Verbose).FullName
    
    $csvUserData = "$currentPathFQDN\UserInformation.csv"
    
    # Remove csv file if exists
    If(Test-Path $csvUserData){Remove-Item -Path $csvUserData -Force}
    # Add header file for new csv file
    Add-Content -Path $csvUserData -Value "DisplayName;UserName;GPIN;Department;Division;HomeDirectory;Office;RoomNumber;MemberGroup"
    
    Switch ($strSelection)
        {
            1 {$strLocation = "France";$strCountryCode = "FRA";break}
            2 {$strLocation = "Germany";$strCountryCode = "DEU";break}
            3 {$strLocation = "Israel";$strCountryCode = "ISR";break}
            4 {$strLocation = "Italy";$strCountryCode = "ITA";break}
            5 {$strLocation = "Netherlands";$strCountryCode = "NLD";break}
            6 {$strLocation = "Poland";$strCountryCode = "POL";break}
            7 {$strLocation = "Russia";$strCountryCode = "RUS";break}
            8 {$strLocation = "Spain";$strCountryCode = "ESP";break}
            9 {$strLocation = "Turkey";$strCountryCode = "TUR";break}
            10 {break}
        }
    
    If($strSelection -eq 10)
        {
            $strLoc = $strLocations -Split ","
            $strCode = $strCountryCodes -Split ","
            $i = 0
            
            # Search Active Directory for all countries
            ForEach ($location in $strLoc)
                {
                    $searchBase = "OU=$strCode[$i],OU=ACCOUNTS,DC=TEST,DC=NET"
                    Get-ADUser -Filter 'co -eq $location' -SearchBase $searchBase -ResultPageSize 10000 | 
                        ForEach-Object -Process {Get-UserInfo $_.SamAccountName $csvUserData}
    $i++
                } # Search Active Directory global OU containing any other accounts $searchBase = "OU=GLOBAL,OU=ACCOUNTS,DC=TEST,DC=NET" Get-ADUser -Filter 'co -eq $location' -SearchBase $searchBase -ResultPageSize 10000 | ForEach-Object -Process {Get-UserInfo $_.SamAccountName $csvUserData} } Else { # Search Active Directory based on selected country $searchBase = "OU=$strCountryCode,OU=ACCOUNTS,DC=TEST,DC=NET" Get-ADUser -Filter 'co -eq $strLocation' -SearchBase $searchBase -ResultPageSize 10000 | ForEach-Object -Process {Get-UserInfo $_.SamAccountName $csvUserData} # Search Active Directory global OU containing any other accounts $searchBase = "OU=GLOBAL,OU=ACCOUNTS,DC=TEST,DC=NET" Get-ADUser -Filter 'co -eq $strLocation' -SearchBase $searchBase -ResultPageSize 10000 | ForEach-Object -Process {Get-UserInfo $_.SamAccountName $csvUserData} }
    So, basically I am happy with the results and will continue to experiment with the info you provided! Thanks for the help!


    JC - a.k.a Aramane



    • Edited by Aramane Wednesday, February 17, 2016 9:51 AM Noticed error in code
    Tuesday, February 16, 2016 5:03 PM
  • Here is how to pass whole objects in the pipelime:

    function Get-AdUserInfo{
        Begin{Write-Host 'begin' -fore green}
        Process{
             $_.DistinguishedName
        }
        End{Write-Host 'End' -fore green}
    }
    
    get-aduser -filter 'co -eq "United States"'| Get-AdUserInfo
    
    


    \_(ツ)_/

    Tuesday, February 16, 2016 5:04 PM
  • If you want support for common parameters. TO do so we must define at least one parameter from the pipeline:

    function Get-AdUserInfo{
        Param(
             [Parameter()]$SamAccountName)
        Begin{Write-Host 'begin' -fore green}
        Process{
             Write-Verbose $_.DistinguishedName
        }
        End{Write-Host 'End' -fore green}
    }
    
    get-aduser -filter *| Get-AdUserInfo -verbose
    
    


    \_(ツ)_/

    Tuesday, February 16, 2016 5:11 PM
  • Ignore erroractiopreference in post as I realized I cannot explain it in a short post and the explanation would then be misleading.


    \_(ツ)_/

    Tuesday, February 16, 2016 5:24 PM