Having issue in my scripts

Hello

I’m having issues with my scripts below. I’m trying to pull enabled users from AD that was created from 2/1/2018 until 2/1/2019 for many different OU’s. I have it export a file in the OU level, and at the All user level. I’m getting no output on the

Write-Output $Created in the foreach loop. Any one have any Ideas? Thanks for any help. My script is below.

[pre]

function Get-EnabledAccountsAD
{
[CmdletBinding()]
Param (
[string]
$Errorlog = “c:\ps\error.txt”,
[switch]
$RecordErrors = $false
)
if($RecordErrors)
{$Null | out-file -filePath $Errorlog}

$AllUsers = @()

function Get-MyUsers
{
Param (

[parameter(Mandatory=$true)]

[string]
$OU,
[string]
$Agency
)
$AgencyUsers = @()

$InfoNeeded = @{
Name = “Nothing”
Created = “1/2/1900”
Agency = $Agency
}

$enUser = Get-ADUser -Filter ‘enabled -eq $true’ -SearchBase $OU -Properties *

$enUser

ForEach ($User in $enUser)
{

$Name = $User.DisplayName

If ($User.whenCreated -ne $Null)
{
$Created = $User.whenCreated
} Else {
$Created = “1/1/1900” #if null give a very old date
}

Write-Output $Created
[datetime] $dateTester = “2/1/2018”

If (($Created -ge $dateTester) -and ($Created -le $dateTester.Add(365)))
{
$ThisUser = New-Object -TypeName psobject -Property $InfoNeeded
$ThisUser.Name = $Name
$ThisUser.LastLogIn = $Created

If ($AgencyUsers -eq $Null)
{
$AgencyUsers = $ThisUser
} else {
$AgencyUsers += $ThisUser
}
}

}
$AgencyUsers | Export-Csv -Path “C:\ps\accounts\active$Agency.csv”
if ($AgencyUsers -eq $Null)
{
Return “No Users”
} else {
Return $AgencyUsers
}
}

$JustHold = Get-MyUsers -OU ‘OU=thisagecy,DC=mydomain,DC=com’ -Agency thisagency
if ($JustHold -ne “No Users”)
{
$AllUsers = $JustHold
}
$JustHold += Get-MyUsers -OU ‘OU=thatagency,DC=mydomain,DC=com’ -Agency thatagency
if ($JustHold -ne “No Users”)
{
if ($AllUsers -eq $Null)
{
$AllUsers = $JustHold
} Else {
$AllUsers += $JustHold
}
}
$AllUsers | Export-Csv -Path “C:\ps\accounts\active\AllNewUsers.csv”

}

#########################test lines#######################
Get-EnabledAccountsAD

 

[/pre]

Sorry it cut off… I’m getting no output for the files at the ou level. 0 kb blank and at all users have 9 kb that looks like below

 

#TYPE System.String
“Length”
“43”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”
“Microsoft.ActiveDirectory.Management.ADPropertyValueCollection”

You could comment $enUser and Write-Output. As we see in other languages, the return keyword is not the only one returns the value from a function in PowerShell. Whatever is spitted from a function will be part of the output. Hence return only what you need from a function and try.

Dang I figured it out…

It all came down to the days. I cleaned it up a bit and had it return the same type of object all the time, pulled the function out… but it I put add instead of AddDays the below one is working

Thanks kvprasoon

[pre]

function Get-MyUsers
{
Param (

[parameter(Mandatory=$true)]

[string]
$OU,
[string]
$Agency
)
$AgencyUsers = @()

$InfoNeeded = @{
Name = “Nothing”
Created = “1/2/1900”
Agency = $Agency
}

$enUser = Get-ADUser -Filter ‘enabled -eq $true’ -SearchBase $OU -Properties *

ForEach ($User in $enUser)
{

$Name = $User.DisplayName

If ($User.whenCreated -ne $Null)
{
$Created = $User.whenCreated
} Else {
$Created = “1/1/1900” #give it an old unuseable date if it is blank
}

[datetime] $dateTester = “2/1/2018”

If (($Created -ge $dateTester) -and ($Created -le $dateTester.AddDays(365)))
{
$ThisUser = New-Object -TypeName psobject -Property $InfoNeeded
$ThisUser.Name = $Name
$ThisUser.Created = $Created

If ($AgencyUsers -eq $Null)
{
$AgencyUsers = $ThisUser
} else {
$AgencyUsers += $ThisUser
}
}

}
$AgencyUsers | Export-Csv -Path “C:\ps\accounts\active$Agency.csv”
if ($AgencyUsers -eq $Null)
{
$blankUser = New-Object -TypeName psobject -Property $InfoNeeded #just one
$blankUser.Name = “No Users”
Return $blankUser
} else {
Return $AgencyUsers #this could be an array of users might be just one. but all are the same type now.
}
}

function Get-EnabledAccountsAD
{
[CmdletBinding()]
Param (
[string]
$Errorlog = “c:\ps\error.txt”,
[switch]
$RecordErrors = $false
)
if($RecordErrors)
{$Null | out-file -filePath $Errorlog}

$AllUsers = @()

$JustHold = @()

$JustHold = Get-MyUsers -OU ‘OU=ThisAgency,DC=mydomain,DC=com’ -Agency ThisAgency
if ($JustHold.Name -ne “No Users”)
{
$AllUsers = $JustHold
}
$JustHold = Get-MyUsers -OU ‘OU=ThatAgency,DC=mydoamin,DC=com’ -Agency Apache
if ($JustHold.Name -ne “No Users”)
{
if ($AllUsers -eq $Null)
{
$AllUsers = $JustHold
} Else {
$AllUsers += $JustHold
}
}

$AllUsers | Export-Csv -Path “C:\ps\accounts\active\AllNewUsers.csv”

}

#########################test lines#######################
Get-EnabledAccountsAD

[/pre]

You are doing some fairly odd things in the script.

You have a nested function, but that child function has params that need to be supplied. Yet, I see no place in the parent function where you are supplying that.

As kvprasoon points out, you really are just trying to get a report, so, there is little reason to dump anything to the screen, except during dev / debug sessions, to ensure you are getting what you think you should be getting. So, using Write-* is really not prudent, you can just convert your function to an advanced function so that you can support using the -Verbose switch to see output.

You also, will probably want to look a use the Trace-Command cmdlet to show what you script is really doing.

As a rule, functions should do one thing, provide one result that you can output or pipe to a secondary command to get additional info.

Depending on what PowerShell version you are on, you are really over engineering this. Just use the built-in search cmdlet, Search-ADAccount So, take a step back and rethink your approach one step at a time. This can be extremely simplified, making it better understood and maintainable.

# All Help topics and locations
Get-Help about_*
Get-Help about_Functions

Get-Help about* | Select Name, Synopsis

Get-Help about* | 
Select-Object -Property Name, Synopsis |
Out-GridView -Title 'Select Topic' -OutputMode Multiple |
ForEach-Object { Get-Help -Name $_.Name -ShowWindow }

explorer "$pshome\$($Host.CurrentCulture.Name)"

# Get parameters, examples, full and Online help for a cmdlet or function

# Get a list of all functions
Get-Command -CommandType Function | 
Out-GridView -PassThru -Title 'Available functions'

# Get a list of all commandlets
Get-Command -CommandType Cmdlet | 
Out-GridView -PassThru -Title 'Available cmdlets'

# Get a list of all functions for the specified name
Get-Command -Name '*ADAccount' -CommandType Function | 
Out-GridView -PassThru -Title 'Available named functions'

# Get a list of all commandlets for the specified name
Get-Command -Name '*ADAccount**'  -CommandType Cmdlet | 
Out-GridView -PassThru -Title 'Available named cmdlet'

# get function / cmdlet details
(Get-Command -Name Search-ADAccount).Parameters.Keys | Sort
Get-help -Name Search-ADAccount -Full
Get-help -Name Search-ADAccount -Online
Get-help -Name Search-ADAccount -Examples

Function Get-HelpExamples
{
    [CmdletBinding()]
    [Alias('ghe')]

    Param
    (
        [string]$CmdletName = (
            Get-Command -Name '*' | 
            Out-GridView -PassThru -Title 'Select a cmdlet to see examples'
        )
    )

    If ((Get-Help -Name $CmdletName).Examples)
    {
        (((Get-Help -Name $CmdletName).Examples | 
        Out-String -Stream) -match '.*\\>|C:\\PS>') -replace '.*\\>|C:\\PS>' | 
        Out-GridView -Title 'Select a sample to use' -PassThru
    }
    Else {Write-Warning -Message "The were no help examples discovered"}
}

ghe -CmdletName Search-ADAccount

# Results

Search-ADAccount -AccountDisabled | FT Name,ObjectClass -A
Search-ADAccount -AccountDisabled -UsersOnly | FT Name,ObjectClass -A
Search-ADAccount -AccountExpired | FT Name,ObjectClass -A
Search-ADAccount -AccountExpiring -TimeSpan 6.00:00:00 | FT Name,ObjectClass -A
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 | FT Name,ObjectClass -A
Search-ADAccount -PasswordExpired | FT Name,ObjectClass -A
Search-ADAccount -PasswordNeverExpires | FT Name,ObjectClass -A
Search-ADAccount -LockedOut | FT Name,ObjectClass -A
Search-ADAccount -AccountDisabled -ComputersOnly | FT Name,ObjectClass -A
Search-ADAccount -AccountExpiring -DateTime "3/18/2009" | FT Name,ObjectClass -A
Search-AdAccount -AccountDisabled -SearchBase "DC=AppNC" -Server "FABRIKAM-SRV1:60000"

I need to run through the same things with my scripts… so I put a function in it… seemed easier…

$JustHold = Get-MyUsers -OU ‘OU=ThisAgency,DC=mydomain,DC=com’ -Agency ThisAgency

This is where the primary calls the secondary. In my production script I had to call it close to 30 times… this one I only left 2. It does return an array so I have a variable that catches it.

 

When I was trying to push things to the screen I had an issue that I was troubleshooting so I put in writes to try to figure out where the issue was. I never figured out why the writes never gave any data. After I got everything working I just took the writes out.

 

Nothing is really odd here… it grabs users then figures out if it’s in a time frame I’m looking for then puts it to a csv file. Kinda standard stuff.