Find duplicate values in an array - arrays

i have the following code:
cls
Get-Module -ListAvailable | Import-Module
Import-Module ActiveDirectory
$Groups = Get-ADGroup -Filter {name -like 'XYZ'} | select name -
ExpandProperty name
$i=0
$tot = $Groups.count
$Table = #()
$Record = #{
"Group Name" = ""
"Name" = ""
"username" = ""
}
Foreach ($Group in $Groups) {
#// Set up progress bar
$i++
$status = "{0:N0}" -f ($i / $tot * 100)
Write-Progress -Activity "Exporting AD Groups" -status "Processing
Group $i of $tot : $status% Completed" -PercentComplete ($i / $tot *
100)
$Arrayofmembers = Get-ADGroupMember -identity $Group -recursive |
select name, SamAccountName
foreach ($Member in $Arrayofmembers) {
$Record."Group Name" = $Group
$Record."Name" = $Member.name
$Record."username" = $Member.SamAccountName
$objRecord = New-Object PSObject -property $Record
$Table += $objrecord
}
}
Write-Host $Table
which works perfectly but i want to list all duplicates in the $Record."Name" = $Member.name with specific group so for example:
username=barry is duplicated in GROUP XYZ
i tried already the following:
ForEach ($Element in $Table)
{
If (($Table -match $Element).count -gt 1)
{
"Duplicates detected"
}
}

The simplest answer is to just pipe $Table to Group-Object and filter for groups with a count greater than one at the end as such:
$Table | Group 'Group Name','Name' | Where{$_.Count -gt 1}
If you are looking to do this in the middle of your loop you could do so by grouping the results of Get-ADGroupMember, but I think it'll probably be faster to do it all at the end.

You could simply keep track of the members using a hashtable:
$seen = #{};
foreach ($Member in $Arrayofmembers)
{
if($seen[$Member.Name])
{
Write-Host "$($Member.Name) is duplicated in group $Group";
}
else
{
$seen.Add($Member.Name, $true);
}
# ... rest of the loop
}

Related

New-Object : Cannot bind parameter 'Property'. Cannot convert the "" value of type PSCustomObject to type IDictionary

I'm having a hard time converting results from Invoke-SqlCmd to a PSCustomobject.
So, I input my query and SQL server, then I run the Invoke-SqlCmd function, and then I try to add data from that (the database logical name, and the autogrowth status) to my PSCustomobject, so I can return it back to my modules public function.
$sqlinstance = "---"
$query = "---"
if ($sqlInstance -match "---") {
$dbAutogrowIGP = Invoke-Sqlcmd -Query $query -ServerInstance $sqlInstance
if ($dbAutogrowIGP.Growth -gt 100 -and $dbAutogrowIGP.Growth -lt 500) {
$autogrowStatus = [PSCustomObject]#{
'SQL_Instance' = $dbAutogrowIGP.LogicalName
'Check' = "Autogrow"
'Status' = "green"
'Status_reason' = ""
}
New-Object -Type Dictionary -Property $autogrowStatus
}
foreach ($db in $dbAutogrowIGP) {
if ($db.Growth -lt 100 -or $db.Growth -gt 500 -and $db.Growth -notlike "%") {
$autogrowStatus = [PSCustomObject]#{
'SQL_Instance' = $db.LogicalName
'Check' = "Autogrow"
'Status' = "red"
'Status_reason' = "$($db.LogicalName) has autogrowth set to $($db.Growth)."
}
New-Object -Type Dictionary -Property $autogrowStatus
}
if ($db.Growth -like "%") {
$autogrowStatus = [PSCustomObject]#{
'SQL_Instance' = $db.LogicalName
'Check' = "Autogrow"
'Status' = "yellow"
'Status_reason' = "$($db.LogicalName) has autogrowth set percentually, it should be an absolute number."
}
New-Object -Type Dictionary -Property $autogrowStatus
}
}
}
return $autogrowStatus
I've debugged it, and I've noticed it fails on the New-object call. I've tried both Dictionary and PSObject/PSCustomObject - however neither works
In my other functions, this works as expected, however in those, I'm using dbatools to make a call.
$getLogSizeIGP = Get-DbaDbLogSpace -sqlInstance $sqlInstance
if ($getLogSizeIGP.LogSize.Gigabyte -lt 10 -and $getLogSizeIGP.LogSpaceUsedPercent -lt 50) {
$logStatus = #{
'SQL_Instance' = $getLogSizeIGP.SqlInstance
'Check' = "Log_size"
'Status' = [gmEnvStatuses]::green
'Status_reason' = ""
}
New-Object -Type PSObject -Property $logStatus
}
How would I go about solving this issue?
This is the whole error message:
New-Object : Cannot bind parameter 'Property'. Cannot convert the "#{SQL_Instance=Maintenance_log; Check=Autogrow; Status=red; Status_reason=Maintenance_log has autogrowth set to 10%.}" value of type "System.Management.Automation.PSCustomObject" to type
"System.Collections.IDictionary".
At C:\Users\---\Desktop\autogrowth.ps1:50 char:55
+ New-Object -Type Dictionary -Property $autogrowStatus
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.NewObjectCommand
Thanks!
The easiest way of collecting this data is by capturing it all at the beginning of the if ($sqlInstance -match "---") { statement and simply output the PsCustomObjects without trying to convert them.
Something like
$sqlinstance = "---"
$query = "---"
$autogrowStatus = if ($sqlInstance -match "---") {
$dbAutogrowIGP = Invoke-Sqlcmd -Query $query -ServerInstance $sqlInstance
if ($dbAutogrowIGP.Growth -gt 100 -and $dbAutogrowIGP.Growth -lt 500) {
# output the object to be captured in the $autogrowStatus variable
[PSCustomObject]#{
'SQL_Instance' = $dbAutogrowIGP.LogicalName
'Check' = "Autogrow"
'Status' = "green"
'Status_reason' = ""
}
}
foreach ($db in $dbAutogrowIGP) {
if ($db.Growth -lt 100 -or $db.Growth -gt 500 -and $db.Growth -notlike "%") {
[PSCustomObject]#{
'SQL_Instance' = $db.LogicalName
'Check' = "Autogrow"
'Status' = "red"
'Status_reason' = "$($db.LogicalName) has autogrowth set to $($db.Growth)."
}
}
if ($db.Growth -like "%") {
[PSCustomObject]#{
'SQL_Instance' = $db.LogicalName
'Check' = "Autogrow"
'Status' = "yellow"
'Status_reason' = "$($db.LogicalName) has autogrowth set percentually, it should be an absolute number."
}
}
}
}
return $autogrowStatus
The variable $autogrowStatus will become an array of PSCustomObjects to handle in the rest of your functions.
Hope this helps

Slow array operations after DB resultset

I need help optimizing my PowerShell script.
$sorted = #()
$firsttime = 0
$j = 0
$zaehler = $results.Count-1
for ($i=0; $i -le $results.Count-1; $i++) {
$j = $i+1
while ($results.GUID[$i] -eq $results.GUID[$j]) {
$klassen = ""
$rec = $results | where {$_.GUID -eq $results.GUID[$i]}
if ($firsttime -eq 0 -or !$sorted.GUID.contains($rec[0].GUID)) {
$firsttime = 1
foreach ($item in $rec.Klasse) {
if ($klassen -eq "") {
$klassen += $item
} else {
if (!$klassen.Contains($item)) {
$klassen += "," + $item
}
}
}
$rec[0].Klasse = $klassen
$sorted += $rec[0]
}
$j = $j+1
}
Write-Host ($i/$zaehler).ToString("P") "von Schule" $schule
}
if (!$sorted) {
$results
} else {
$sorted
}
Basically in my resultset ($results) I got duplicate lines of teachers and the only difference is the class ("Klasse/Klassen") they are teaching at.
To minimize the output I am checking if the first GUID is the same as the second and then the script appends the second class to the first one. So the $sorted array has just one line per teacher with a comma-seperated string which shows all classes.
Sample line of $results:
#{
GUID={1234567-1234-1234-1234-1234567};
userrole=teacher;
Vorname=Max;
Nachname=Mustermann;
Geburtstag=01.01.2000;
Klasse=9A;
Schule=123456
}
#{
GUID={1234567-1234-1234-1234-1234567};
userrole=teacher;
Vorname=Max;
Nachname=Mustermann;
Geburtstag=01.01.2000;
Klasse=9B;
Schule=123456
}
Sample line of $sorted[0]:
#{
GUID={1234567-1234-1234-1234-1234567};
userrole=teacher;
Vorname=Max;
Nachname=Mustermann;
Geburtstag=01.01.2000;
Klasse=9A,9B,9C,5A;
Schule=123456
}
The sorting process (check if contains, foreach $item, add to $klassen) is pretty slow.
I would be very grateful for any kind of ideas how to optimize the script.
Maybe something like this would work:
$results | ForEach-Object {
New-Object -Type PSObject -Property $_
} | Group-Object GUID | ForEach-Object {
$teacher = $_.Group
$teacher | Select-Object -First 1 -Exclude Klasse -Property *, #{n='Klasse';e={
$teacher | Select-Object -Expand Klasse
}}
}
Convert your hashtables into custom objects, group them by GUID, then replace the original "Klasse" property with a new one containing an array of the values from all objects in that group, and select the first result.
Should $results already be a list of objects you can skip the first ForEach-Object:
$results | Group-Object GUID | ForEach-Object {
$teacher = $_.Group
$teacher | Select-Object -First 1 -Exclude Klasse -Property *, #{n='Klasse';e={
$teacher | Select-Object -Expand Klasse
}}
}

Why is my object array doubling results?

The the set of code below, everything works except 1 thing I can not figure out.
while Get-CSUserStandardsValidatedSet is processing the data, The object count array stays in tact. whether I have 1 or 100 object in the array the count is good. But when Get-CSUserStandardsValidatedSet passes the object array via return $return back to the Caller Function Invoke-MRC_CSSkypeObjects_ImportCSV. The Object count Doubles everytime.
If I pass the parameter Select -unique I actually loose records I want to process.
Any Ideas?
Function Get-CSUserStandardsValidatedSet
{
param ($users)
[array]$UserInfoArray = #()
$DNStandardGlobalCpAnswer = $null
$DNStandardGlobalCuAnswer = $null
$SIPStandardGlobalCpAnswer = $null
$UMMStandardGlobalAnswer = $null
foreach ($user in $users)
{
$PhoneNumberIsInUse = $false
$UserInfoCopy = New-UserInfo
######################################################## #Still Need to validate the correct OU Location Based on AccountTypes# ########################################################
Write-host "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
Write-Host "$($user.DisplayName) $($user.CSVtelephoneNumber) $user"
Write-host "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
#This must be populated for OU Validation, and Cu DisplayName Validation
$UserInfoCopy.AllowRecordToConinueNoErrorsFound = $true
Write-Host 'SiteCode'
$UserInfoCopy.CSVSiteCode = $user.SiteCode
Write-host "$($UserInfoCopy.CSVSiteCode)"
$UserInfoCopy.CSVPrivateSiteCode = $user.SiteCode -replace "[^0-9]" #To be removed and replaced with CSVSiteCode
Write-host "$($UserInfoCopy.CSVPrivateSiteCode)"
#if ($user.SiteCode -match "^\d+$")
# { $user.SiteCode -replace "[^0-9]"}
# else { write-host "Site Code is not numeric or does not exist: $($user.PrivateSiteCode)";end}
Write-Host 'Acct Type (U, Cu, Cp, F, H)'
$UserInfoCopy.CSVAccountTypes =
Switch ($user.AccountTypes)
{
'U' {$user.AccountTypes}
'F' {$user.AccountTypes}
'Cu' {$user.AccountTypes}
'Cp' {$user.AccountTypes}
'H' {$user.AccountTypes}
default {"Unknown Type of Skype Account to create: $($user.AccountTypes) for $($UserInfoCopy.DisplayName) ";stop}
}
Write-host "$($UserInfoCopy.CSVAccountTypes)"
Write-Host 'Private or Public'
$UserInfoCopy.CSVPhoneExtensionType_S_P = if ($user.PhoneExtensionType_S_P -eq 'S') {$true} else {$false}
Write-host "$($UserInfoCopy.CSVPhoneExtensionType_S_P)"
Write-Host 'OU'
$UserInfoCopy.CSVOU = Get-VerifyOUbyTypeForADLocation -Type $UserInfoCopy.CSVAccountTypes -SiteCode $UserInfoCopy.CSVSiteCode -OU $user.CSVOU
Write-host "$($UserInfoCopy.CSVOU)"
#region PHONE NUMBER AND POLICY OR PLAN AND POOL
Write-Host 'Telephone Number'
$UserInfoCopy.CSVtelephoneNumber =
if ((Exists-PhoneNumberisUnUsed -PhoneNumber ($user.telephoneNumber -replace "[^0-9]")))
{$user.telephoneNumber -replace "[^0-9]"}
else
{
#write-host "Telephone Number $($User.telephoneNumber) is already in use. Please remove the number from active use or change the phone number being assigned."; break
$PhoneNumberIsInUse = $True
$user.telephoneNumber -replace "[^0-9]"
}
Write-host $UserInfoCopy.CSVtelephoneNumber
Write-Host 'Ext'
$UserInfoCopy.CSVExt = $user.Ext -replace "[^0-9]"
Write-host $UserInfoCopy.CSVExt
Write-Host 'Dial Plan'
$UserInfoCopy.CSVDialPlan = if (Exists-VoiceOrDataPlanTorF -Exists_Plan $User.DialPlan -VoiceSearch $false)
{$user.DialPlan}
else {write-host "User: $($user.DisplayName) DialPlan: $($user.DialPlan) - DOES NOT EXIST";
if (($user.AccountTypes -eq 'U') -or ($user.AccountTypes -eq 'Cu') -or ($user.AccountTypes -eq 'Cp'))
{Break}
else {write-host ' Not a User/Common Area Phone Account, Allowed to Continue'} #Do not proceed if Dial Plan can not be found
}
Write-host $UserInfoCopy.CSVDialPlan
Write-Host 'Voice Policy'
$UserInfoCopy.CSVVoicePolicy = if (Exists-VoiceOrDataPlanTorF -Exists_Plan $user.VoicePolicy -VoiceSearch $true)
{$user.VoicePolicy}
else {write-host "User: $($user.DisplayName) VoicePolicy: $($user.VoicePolicy) - DOES NOT EXIST";
if (($user.AccountTypes -eq 'U') -or ($user.AccountTypes -eq 'Cu') -or ($user.AccountTypes -eq 'Cp'))
{Break}
else {write-host ' Not a User/Common Area Phone Account, Allowed to Continue'} #Do not proceed if Voice Policy can not be found
}
Write-host $UserInfoCopy.CSVVoicePolicy
Write-Host 'UM Mailbox Policy'
$UserInfoCopy.CSVUMMailboxPolicy = Get-UMMailPolicyAssigned -Type $UserInfoCopy.CSVAccountTypes -RequestUMMailboxPolicyAssign $user.UMMailboxPolicy
Write-host $UserInfoCopy.CSVUMMailboxPolicy
############################################################################################################################
#REGISTRAR POOL
Write-Host 'RegistrarPool'
$UserInfoCopy.CSVRegistrarPool = if ((Exists-MRCCSSkypeRegistrarPool -PoolCheck $user.RegistrarPool) -or ($user.AccountTypes -eq 'U'))
{$user.RegistrarPool}
else {write-host "User: $($user.DisplayName) RegistrarPool: $($user.RegistrarPool) - DOES NOT EXIST";
if (($user.AccountTypes -eq 'Cu') -or ($user.AccountTypes -eq 'Cp'))
{Break}
else {write-host 'Not a User Account, Allowed to Continue'}
}
Write-host $UserInfoCopy.CSVRegistrarPool
#PHONE NUMBER
#Private -replace "[^0-9]"
#$UserInfoCopy.PrivateExtension = $PrivSiteExtNumber + $UserInfoCopy.CSVExt
Write-Host 'Private Extension'
$UserInfoCopy.PrivateExtension = $UserInfoCopy.CSVExt -replace "[^0-9]"
Write-host $UserInfoCopy.PrivateExtension
#New Logic
#Due to the variable ways private extensions are assigned, it will be up to the user to put the correct private extension into the csv file
#Old Logic
#if (($user.SiteCode -match "^\d+$") -and ($UserInfoCopy.CSVExt -match "^\d+$")) {($user.SiteCode -replace "[^0-9]") + ($UserInfoCopy.CSVExt -replace "[^0-9]")} else {" Site Code is not a numeric number $($user.SiteCode) or Private Extension is not a numeric number $($user.CSVExt)";break}
Write-Host 'LineURI Private'
$UserInfoCopy.LineuriPrivate = [String]::Format('tel:+{0:###########};ext={1:####}',([int64]$UserInfoCopy.CSVtelephoneNumber -replace "[^0-9]"),[int64]$UserInfoCopy.PrivateExtension -replace "[^0-9]")
Write-host $UserInfoCopy.LineuriPrivate
Write-Host 'Telephone Number Private'
$UserInfoCopy.telephoneNumberPrivate_Format1 = [String]::Format('tel:{0:+#-###-###-####};ext={1:####}',[int64]$UserInfoCopy.CSVtelephoneNumber,[int64]$UserInfoCopy.PrivateExtension -replace "[^0-9]")
Write-host $UserInfoCopy.telephoneNumberPrivate_Format1
$UserInfoCopy.telephoneNumberPrivate_Format2 = [String]::Format('{0:(###) ###-####};ext={1:####}',([int64]$UserInfoCopy.CSVtelephoneNumber - 10000000000),[int64]$UserInfoCopy.PrivateExtension -replace "[^0-9]")
Write-host $UserInfoCopy.telephoneNumberPrivate_Format2
#Not Private
Write-Host 'LineURI Public'
$UserInfoCopy.Lineuri = [String]::Format('tel:+{0:###########};ext={1:####}',([int64]$UserInfoCopy.CSVtelephoneNumber),$UserInfoCopy.CSVtelephoneNumber.Substring(($UserInfoCopy.CSVtelephoneNumber.Length-4)))
Write-host $UserInfoCopy.Lineuri
Write-Host 'telephone Number Public'
$UserInfoCopy.telephoneNumber_Format1 = [String]::Format('{0:+#-###-###-####}',[int64]$UserInfoCopy.CSVtelephoneNumber)
Write-host $UserInfoCopy.telephoneNumber_Format1
$UserInfoCopy.telephoneNumber_Format2 = [String]::Format('{0:(###) ###-####}',([int64]$UserInfoCopy.CSVtelephoneNumber - 10000000000))
Write-host $UserInfoCopy.telephoneNumber_Format2
#endregion
#region NAME SECTION
#First and Last name we only care about if Cu since AD User account is being Created
#Last name must exist for Cp to generate the sip
Write-Host 'Last Name'
$UserInfoCopy.CSVLastName =
if ((($user.AccountTypes -eq 'Cu') -or ($user.AccountTypes -eq 'Cp')) -and ($user.LastName -eq ''))
{
if($CSVPhoneExtensionType_S_P)
{$UserInfoCopy.telephoneNumber_Format2}
else
{$UserInfoCopy.telephoneNumberPrivate_Format2}
#"Error no Last name for $($user.DisplayName)";stop
}
else {$user.LastName}
Write-host $UserInfoCopy.CSVLastName
Write-Host 'First Name'
$UserInfoCopy.CSVFirstName =
if (($user.AccountTypes -eq 'Cu') -or ($user.AccountTypes -eq 'Cp'))
{
if ($UserInfoCopy.CSVSiteCode -match "^\d+$")
{
$MySiteCode = $UserInfoCopy.CSVSiteCode -replace "[^0-9]"
"BR$($MySiteCode.ToString("000"))"
}
Else
{
"BR$($UserInfoCopy.CSVSiteCode)"
}
}
else {$user.FirstName}
Write-host $UserInfoCopy.CSVFirstName
Write-Host 'Display Name'
$UserInfoCopy.CSVDisplayName = Get-DisplayName -Type $UserInfoCopy.CSVAccountTypes -DisplayNameRequest $user.DisplayName `
-IsSiteNotPrivateExtension $UserInfoCopy.CSVPhoneExtensionType_S_P -Extension $UserInfoCopy.PrivateExtension `
-PublicNumber $UserInfoCopy.CSVtelephoneNumber -PrivateNumber $UserInfoCopy.CSVtelephoneNumber `
-SiteCode $UserInfoCopy.CSVSiteCode -LastName $UserInfoCopy.CSVLastName
Write-host $UserInfoCopy.CSVDisplayName
#endregion
#region SAM ACCOUNT
Write-Host 'SAM Account Name'
$MySAM = Get-UserSAMAccountName -Type $UserInfoCopy.CSVAccountTypes -SAM $User.SamAccountName -DisplayName $UserInfoCopy.CSVDisplayName -LastName $UserInfoCopy.CSVLastName -FirstName $UserInfoCopy.CSVFirstName
$UserInfoCopy.CSVSamAccountNameFound = if ($MySAM.SamAccountName.Length -ne 0) {$true} else {$false}
Write-host 'AD Account Found: ' + $UserInfoCopy.CSVSamAccountNameFound
$UserInfoCopy.CSVSamAccountName = $MySAM.SamAccountName
Write-host $UserInfoCopy.CSVSamAccountName
#Phone Number is already in use
if (($PhoneNumberIsInUse) -and ($UserInfoCopy.CSVSamAccountNameFound))
{
If
(
(
( (get-csuser $UserInfoCopy.CSVSamAccountName).lineuri -eq $UserInfoCopy.LineuriPrivate ) -and ($UserInfoCopy.CSVPhoneExtensionType_S_P -eq $False)
) `
-or
(
( (get-csuser $UserInfoCopy.CSVSamAccountName).lineuri -eq $UserInfoCopy.Lineuri ) -and ($UserInfoCopy.CSVPhoneExtensionType_S_P -eq $True)
)
)
{
#The current user is assigned the phone number and we are allowed to Proceed
#Nothing needs done to allow this
}
else
{
"Telephone Number $($User.telephoneNumber) is already in use. Please remove the number from active use or change the phone number being assigned."; "This record will not be Processed"
#Phone number is in use
#We do not want the script to stop rather ignore the user account
$UserInfoCopy.CSVSamAccountNameFound = $false #This is a partial solution as it will only stop User Account Modifications not the others
$UserInfoCopy.AllowRecordToConinueNoErrorsFound = $false #This will be a new parameter used
}
#write-host "Telephone Number $($User.telephoneNumber) is already in use. Please remove the number from active use or change the phone number being assigned."; break
}
$UserInfoCopy.telephoneNumberOriginal = $MySAM.telephoneNumberOrigional
Write-host $UserInfoCopy.telephoneNumberOriginal
$UserInfoCopy.CSVMail = $MySAM.mail
Write-host $UserInfoCopy.CSVMail
$UserInfoCopy.info = $MySAM.info
Write-host $UserInfoCopy.info
Write-Host 'SIP'
$UserInfoCopy.CSVSIP =
if ($UserInfoCopy.CSVPhoneExtensionType_S_P)
{
Get-SIPAddress -Type $UserInfoCopy.CSVAccountTypes -SAM $UserInfoCopy.CSVSamAccountName -LastName $UserInfoCopy.CSVLastName -FirstName $UserInfoCopy.CSVFirstName -SiteCode $UserInfoCopy.CSVSiteCode -LineURI $UserInfoCopy.Lineuri
}
else
{
Get-SIPAddress -Type $UserInfoCopy.CSVAccountTypes -SAM $UserInfoCopy.CSVSamAccountName -LastName $UserInfoCopy.CSVLastName -FirstName $UserInfoCopy.CSVFirstName -SiteCode $UserInfoCopy.CSVSiteCode -LineURI $UserInfoCopy.LineuriPrivate
}
Write-host $UserInfoCopy.CSVSIP
#endregion
if ($User.ExtensionAttribute7.length -ne 0)
{
$UserInfoCopy.CSVExtensionAttribute7 = [String]::Format('+{0:#-###-###-####}',([int64]($User.ExtensionAttribute7 -replace "[^0-9]")))
}
Write-host $UserInfoCopy.CSVExtensionAttribute7
$UserInfoCopy | Select-Object -Property *
Write-Host '#####################################################'
$UserInfoCopy | Select-Object -Property * | Write-Host
Write-Host '#####################################################'
Write-Host ($UserInfoCopy | Select-Object -Property *)
$UserInfoArray += $UserInfoCopy
}
$UserInfoArray | Export-CSV $LOG_csv
#$UserInfoArray | Export-CSV $LOG_csv
$return = $UserInfoArray
Return $return
}
Function Invoke-MRC_CSSkypeObjects_ImportCSV
{
param ($Import_CSVFile = $Import_CSV, [bool]$ValidateOnly = $false, $Export_ValidatedObjectCSVFile = $LOG_csv)
$FileNameTranscript = "C:\ScriptOut\Transcript-SkypeObject-CompanyPolicies-$((get-date).toString(‘yyyyMMdd-HHmmss’)).log"
Start-Transcript -Path $FileNameTranscript -Append
########################################################################################################
### IMPORT CSV AND VALIDATE INFORMATION ACCORDING TO STANDARDS ###
########################################################################################################
Write-Host '---------------------------------------------------------------------------------------------------------------------------------------------'
Write-Host ' Validating the CSV File'
Write-Host '---------------------------------------------------------------------------------------------------------------------------------------------'
$UserInfoArraySet = ''
$CSVusers=Import-Csv $Import_CSVFile
$UserInfoArraySet = (Get-CSUserStandardsValidatedSet -users $CSVusers | Select -Unique)
$UserInfoArraySet | Export-CSV $Export_ValidatedObjectCSVFile
if ($ValidateOnly -eq $false)
{
Set-MRC_SkypeWorkFlow_ProcessObjectModification -users $UserInfoArraySet
}
Else
{ #Return the Validate object Details
Return $UserInfoArraySet
}
Stop-Transcript
}

How to add a number at end of username

I need to generate usernames that start with a letter of the alphabet, followed by the date and that ends with numbers from 1 to 20. For a total of 520 names.
Here's the variables I came up with:
$letter = 97..122 | foreach {[char]$_}
$date = get-date -UFormat %a%y%d
$name = $letter | ForEach-Object { $_ + $date }
So I managed to put my letters and my dates together, to form names like aWed1513, which is exactly what I need, but when it comes to make each to end with numbers, I'm stuck. Tried with a For loop by adding incrementing $i to $name, but doesn't work..
It seems like you're just about there. Your for loop should look like this:
$names = #()
$letter = 97..122 | foreach {[char]$_}
$date = get-date -UFormat %a%y%d
for($i = 1; $i -le 20; $i++) {
$names += $letter | ForEach-Object { '{0}{1}{2}' -f $_, $date, $i }
}
$names
An alternate approach to the answer given that just adds another ForEach-Object to the OP's original code:
$letter = 97..122 | foreach {[char]$_}
$date = get-date -UFormat %a%y%d
$names = $letter | ForEach-Object { $_ + $date } | ForEach-Object { for($i=1;$i -le 20;$i++) { $_ + $i } }
And to shorten to get same result:
$letter = 97..122 | foreach {[char]$_}
$date = get-date -UFormat %a%y%d
$names = $letter | ForEach-Object { for($i=1;$i -le 20;$i++) { $_ + $date + $i } }

Powershell: Add user to groups from array

I am trying to write a PowerShell script that will create a user based off of Department and Position and add them to the AD groups specific to that position. I have a function that creates the new user and attempts to join the user to a list of groups in an array.
function CreateUser{
$sam = "$first.$last";...;$pwd = ConvertTo-SecureString "password" -AsPlainText -Force
New-ADUser -Company "MyCompany" -Department $dept -Description $desc -DisplayName $dname -EmailAddress $email -GivenName $first -Office $office -Path $path -SamAccountName $sam -Surname $last -UserPrincipalName $email
foreach ($group in $groups) { if (Get-ADGroup $group) { Add-ADGroupMember $group $sam } }
}
I have another bit of code that creates the $groups array
$positions = #()
if ($dept -eq "CSR") { $positions += "CSR Rep","CSR Lead","CSR Manager" }
if ($dept -eq "IT") { $positions += "Sysadmin","Netadmin","Sqladmin" }
...
$groups = #()
if ($position -eq "CSR Rep") { $groups += "group1","group2","group3",...,"groupN" }
if ($position -eq "CSR Lead") { $groups += "group1","group2","group3","group4",...,"groupN" }
if ($position -eq "CSR Manager") { $groups += "group1","group2","group3","group4","group5",...,"groupN" }
if ($position -eq "Sysadmin") { $groups += "group6","group7",...,"groupN" }
if ($position -eq "Netadmin") { $groups += "group7","group8","group9",...,"groupN" }
if ($position -eq "Sqladmin") { $groups += "group10","group11","group12",...,"groupN" }
After I've specified which department and position the groups array is created and I call the CreateUsers function but I get errors back like it is an empty array.
Is there something I am missing with trying to pass the parameters to the function or is there a better way to accomplish this task?
Any assistance would be greatly appreciated.
Since your code does not show the function call and your function does not have any parameters defined i assume you are not passing anything to it.
Here is how to use parameters with three example parameters, one of them a String[]:
function CreateUser{
param(
[parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string[]] $groups,
[parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[hashtable] $userInfo,
[parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[securestring] $pwd
)
New-ADUser -Company "MyCompany" -Department $userInfo.dept -Description $userInfo.desc -DisplayName $userInfo.dname -EmailAddress $userInfo.email -GivenName $userInfo.first -Office $userInfo.office -Path $userInfo.path -SamAccountName $userInfo.sam -Surname $userInfo.last -UserPrincipalName $userInfo.email
foreach ($group in $groups) { if (Get-ADGroup $group) { Add-ADGroupMember $group $userInfo.sam } }
}
To keep the number of parameters low i have consolidated the user info into a hashtable. Hashtables are key-value sets and can be created like this:
$userInfo = #{sam="sam"; dept="department"; desc="description"; ...}
To call your function correctly do something like this:
CreateUser -groups $groups -userInfo $userInfo -pwd $pwd
You can of course add more parameters. For documentation on possible definitions and validationmethods see Technet
If you're going to create functions that are going to be more than simple things that take parameters I would strongly suggest including parameters with them. Such as:
function CreateUser{
Param([Parameter(Position=0)][string]$First = $(throw "You must specify a first name"),
[Parameter(Position=1)][string]$Last = $(throw "You must specify a last name"),
[Parameter(Position=2)][string]$Desc = $(throw "You must specify a description"),
[Parameter(Position=3)][string]$Dept = $(throw "You must specify a department"),
[Parameter(Position=4)][string]$Office = $(throw "You must specify an office"),
[Parameter(Position=5)][string]$Password = $(throw "You must specify a password"),
[string[]]$Groups
)
$sam = "$first.$last"
$pwd = ConvertTo-SecureString $Password -AsPlainText -Force
$email = "$first.$last#company.com"
$dname = "$First $Last"
$Path = "ou=$office,ou=Users,DN=company,DN=local"
New-ADUser -Company "MyCompany" -Department $dept -Description $desc -DisplayName $dname -EmailAddress $email -GivenName $first -Office $office -Path $path -SamAccountName $sam -Surname $last -UserPrincipalName $email
foreach ($group in $groups) { if (Get-ADGroup $group) { Add-ADGroupMember $group $sam } }
}
Then when you call the function you do it as such:
CreateUser "Jim" "Kirk" "Captain Extraordinaire" "Space" "$uper$ecret123" #("ExploreNewWorlds","WhereNoManHasGone")
Or you can specify arguments by name:
CreateUser -First "Jim" -Last "Kirk" -Desc "Captain Extraordinaire" -Dept "Space" -Password "$uper$ecret123" -Groups #("ExploreNewWorlds","WhereNoManHasGone")
...and while I got caught up in work trying to post this Paul beat me to it. Nice work Paul!
Edit: On a side note, I would like to introduce you to the Switch cmdlet. I think you would benefit greatly from it. While your several If statements probably do work, consider this:
Switch($position){
"CSR Rep" { $groups += "group1","group2","group3",...,"groupN";continue }
"CSR Lead" { $groups += "group1","group2","group3","group4",...,"groupN";continue }
"CSR Manager" { $groups += "group1","group2","group3","group4","group5",...,"groupN";continue }
"Sysadmin" { $groups += "group6","group7",...,"groupN";continue }
"Netadmin" { $groups += "group7","group8","group9",...,"groupN";continue }
"Sqladmin" { $groups += "group10","group11","group12",...,"groupN" }
}
That's simplistic, and in your case may not offer too much in performance improvement, but Switch offers a cleaner solution, and improved performance over several If statements. It also allows for more logic such as:
Switch($position){
{$_ -match "CSR" } { $groups += "group1", "group2" }
{$_ -match "CSR" -and -not $_ -match "Rep"} { $groups += "group3","Group4" }
}
That would add groups 1 and 2 for all CSR, and only Leads and Managers get groups 3 and 4. Anyway, just something to consider.

Resources