Set-ADuser not accepting Logonworkstations variable - powershell

Goal: Use a script to add 3 workstations to all users.
Problem: Receiving error thats says variable's format is invalid. $finalworkstations.gettype() brings up null-valued expression.
Receive an error:
Set-ADUser : The format of the specified computer name is invalid
At \\pathwaystuff\file.ps1:37 char:9
+ Set-ADUser $logonname -LogonWorkstations $finalworkstations
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (tester:ADUser) [Set-ADUser], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:1210,Microsoft.ActiveDirectory.Management.Commands.SetADUser
Here's the script I have now.
$list = Get-ADUser -filter {LogonWorkstations -like "*"} -properties name, LogonWorkstations | select name, logonworkstations
$logonname = "someone"
Function addspecificLogon {
param (
$logonname
)
$wrklist = Import-Csv "\\pathwaystuff\anotherplace\file.csv"
$Workstations = (Get-Aduser $logonname ` -Properties LogonWorkstations).LogonWorkstations
$workstations += ",work1, work2, work3"
#CONVERT WORKSTATION LIST TO AN ARRAY TO ALLOW FOR BETTER MANIPULATION OF DATA
$Workarray = $Workstations.Split(",")
#ERROR-CHECKING MEASURE: ELIMINATE DUPLICATE WORKSTATION NAMES
$Workarray = $Workarray | Sort-Object | Get-Unique
#CONVERTING ARRAY BACK TO STRING TO SET IN AD WORKSTATIONS (NEEDS TO BE A SPECIFIC STRING FORMAT TO ADD TO AD WORKSTATION)
$finalworkstations = ''
foreach ($work in $Workarray) {
$finalworkstations += ", $($work)"
}
Set-ADUser $logonname -LogonWorkstations $finalworkstations
$finalworkstations
}
addspecificLogon($logonname)
Get-ADUser -identity $logonname -properties * | select logonworkstations

Found a solution. That proved a lot simpler overall. Don't know exactly why but manipulating an array as long as possible helped.
function workstations{
$userWorkstationListLocation = Read-Host -Prompt "Enter the filepath of the CSV containing the allowed workstations"
if ($userworkstationlistlocation -eq ""){
$userWorkstationList = "empty"
$script:userworkstationlist = $userworkstationList
$script:userworkstationListLocation = $userWorkstationListLocation
} elseif ((test-path -path $userWorkstationListLocation) -eq $false) {
$userWorkstationListLocation = verify($userWorkstationListLocation)
}
$userWorkstations = Import-Csv -Path "$userWorkstationListLocation" | ForEach-Object {$_.userPC}
#CSV REFERENCE LIST FOR DEFAULT LOGON RIGHTS
$defaultWorkstationslist = Import-Csv '\\url\link\of\stations.csv'
foreach ($station in $defaultworkstationslist) {
$userWorkstations += "$($station.Infrastructure)"
}
#CONFIRMING IF NEEDED TO USE CITRIX
$CitrixUser = Read-Host "Will this user need access to Citrix? [Y/N]"
#FUNCTION TO CONFIRM ADD OR SKIP CITRIX LOGON RIGHTS
if ($CitrixUser -eq "Y"){
foreach($station in $defaultworkstationslist){
if ($station.Citrix -eq ""){
continue
} else {
$userWorkstations += "$($station.Citrix)"
}
}
}
#Removing Duplicates
$userworkstations = $userWorkstations | Sort-Object | Get-Unique
#Fixing for blanks
$userWorkstations.where({$_ -ne "" })
#converting to a list Set-AD can use
foreach ($s in $userWorkstations){
$s
if ($s -eq ""){
continue
} else {
$userworkstationlist += "$s,"
}
}
$userworkstationlist
$script:userworkstationListLocation = $userWorkstationListLocation
$script:userworkstationlist = $userworkstationlist
Write-Host "Within function $($userworkstationlist)"
}

Related

Refresh a variable within a foreach statement

We have a master registry within our on premise SharePoint environment, to keep this list accurate, we run a clean up script each day to remove the item within the list registry.
As part of this script, we wish to delete the AD permissions group at the same time.
Our script works when deleting a single site collection, but when multiple are deleted, the script removes the list item, but attempts to delete the same AD group over and over, it doesnt refresh the variables.
Here is part of the script:
Add-PSSnapin *sharepoint* -ErrorAction SilentlyContinue
Import-Module ActiveDirectory
#Adding variables
$siteRequestUrl = "https://contorso/sites/demo"
$siteRequestListTitle = "Registry"
$webAppArray = #()
$listSCArray = #()
$itemsToDeleteArray = #()
$dn = Get-ADDoman | select -ExpandProperty DistinguishedName
$ou = Get-ADOrganizationalUnit ('Ou=SharePoint, OU=Account Groups, OU=Groups,' + $dn)
$ouSDL = Get-ADOrganizationalUnit ('Ou=SharePoint, OU=Resource Groups, OU=Groups,' + $dn)
Start-SPAssignment -Global
$list = (Get-SPSite -Identity $siteRequestUrl).RootWeb.Lists | Where-Object { $_.Title -eq $siteRequestListTitle }
$expectedSCCount = $list.ItemCount
$WebAppSCCount = $list.ParentWeb.Site.WebApplication.Sites
If ($expectedSCCount -ne $webAppSCCount) {
$listItems = $list.Items
foreach ($webAppSC in $list.ParentWeb.Site.WebApplication.Sites) {
$webAppSCArray += $webAppSC.Url
}
foreach ($item in $listItems) {
$li = New-Object Microsoft.SharePoint.SPFieldUrlValue($item["URL_Link"])
$listSCArray += $i.Url.String()
}
$comparison = Compare-Object -ReferenceObject $webAppSCArray -DifferenceObject $listSCArray | where-Object -FilterScript { $_.SiteIndicator -eq '=>' }
foreach ($difference in $comparison) {
foreach ($item in $listItems) {
$i = New-Object Microsoft.SharePoint.SPFieldUrlValue($item["URL_Link"])
If ($i.Url -eq $difference.InputObject) {
$itemsToDeleteArray = + $item
}
}
}
$itemTitle - $itemToDelete.Title.ToString()
$itemTemplate - $itemToDelete["Template"].ToString()
###### Now I move onto the problem, these variables work but do not not refresh if more than one item is being deleted ############
foreach ($itemToDelete in $itemToDeleteArray) {
switch ($itemTemplate) {
"Branch1" {
$managedPath = "BR1"
}
"Branch2" {
$managedPath = "BR2"
}
}
$forceLowerCase = $itemTitle.ToLower()
$siteTitle = $forceLowerCase -replace '\W', '-'
$GroupName = $managedPath + "-" + $siteTitle
$SggGroupName = "SGG_" + $GroupName + "_Members"
$SdlGroupName = "SDL_" + $GroupName + "_Members"
Try {
Get-ADGroup -Filter 'GroupCatergory -eq "Security" -and GroupScope -ne "DomainLocal"' -SearchBase "CN=$SggGroupName,OU=SharePoint,OU=Account Groups,OU=Groups,DC=Contorso" | Remove-ADGroup -Confirm:$false
Get-ADGroup -Filter 'GroupCatergory -eq "Security" -and GroupScope -eq "DomainLocal"' -SearchBase "CN=$SdlGroupName,OU=SharePoint,OU=Resource Groups,OU=Groups,DC=Contorso" | Remove-ADGroup -Confirm:$false
Write-host "AD Groups $SggGroupName and $SdlGroupName deleted" -ForegroundColor -Green
}
Catch { write-host "AD Groups $SggGroupName and $SdlGroupName failed to delete" }
$itemToDelete.Delete()
}
}
Stop-SPAssignment -Global

PowerShell Get-ADUser - Using custom AD attibutes as IF condition

What I need to do is to export specific AD users and some of their properties to a CSV file. What I need to have there is some of the default properties like Name, SamAccountName, Enabled and some custom ones: businesscategory, extensionAttribute9 etc.
I'm struggling with my if - else statements, as they seem to not be comparing employeenumber to $null
$name = Read-Host -Prompt "Please enter the name for output file."
$filename = $name+".csv"
$domain = #('DOMAIN1','DOMAIN2','DOMAIN3','DOMAIN4')
$result = foreach ($item in $domain) {
Get-ADUser -server $item -Properties businesscategory, extensionAttribute4,
extensionAttribute9, extensionAttribute13, employeenumber, Enabled -ResultPageSize 100 -Filter *
if (($null -ne $_.employeenumber) -and ($_.employeenumber -notlike '*svc*')) {
Select-Object Name,
SamAccountName,
UserPrincipalName,
#{n="businesscategory"; e={$_.businesscategory -join ", "}},
#{n="extensionAttribute4";e={$_.extensionAttribute4 -join ", "}},
#{n="extensionAttribute9";e={$_.extensionAttribute9 -join ", "}},
#{n="extensionAttribute13";e={$_.extensionAttribute13 -join ", "}},
DistinguishedName, employeenumber, Enabled
} else { (...)
The above is part of my code where it should enter into first if. It does that, but it exports all accounts, whether employeenumber is present or not.
Another issue is that the exported CSV doesn't contain columns created from custom attributes, instead it shows some other properties that I did not ask for.
This used to work fine if I used Where-Object instead of if - else and checked the values like below:
Where-Object {
($_.SamAccountName -notlike '*proprietary*') -and
($_.UserPrincipalName -notlike '*proprietary*') -and
($_.SamAccountName -notlike '*mailbox*') -and (...)
Unfortunately I need to use if - else to make more complex comparisons and selections, but can't figure it out
The problem is in this line:
$result = foreach ($item in $domain) {
Get-ADUser -server $item -Properties ... # => not assigned to any variable
Then in this line:
if (($null -ne $_.employeenumber) -and ($_.employeenumber -notlike '*svc*')) {
Since $_ doesn't exist, you are comparing something like:
$null -ne $null -and $null -notlike '*svc*'
Which will always be $false. It's also worth mentioning that this is a foreach loop, different from ForEach-Object, the automatic variable $_ ($PSItem) doesn't mean anything here.
The next problem comes when using Select-Object as the beginning of the statement, there is no object being piped to it.
Select-Object Name, SamAccountName, UserPrincipalName, ...
In this case, the if condition could be removed completely with some LDAP Filtering:
# employee number is not `$null` AND employee number is not like `*svc*`
-LDAPFilter "(&(employeenumber=*)(!employeenumber=*svc*))"
The code would look like this:
$name = Read-Host -Prompt "Please enter the name for output file."
$filename = $name + ".csv" # Consider using `$HOME` here, or an absolute Path
$param = #{
LDAPFilter = "(&(employeenumber=*)(!employeenumber=*svc*))"
ResultPageSize = 100
Properties = #(
'businesscategory'
'extensionAttribute4'
'extensionAttribute9'
'extensionAttribute13'
'employeenumber'
)
}
'DOMAIN1','DOMAIN2','DOMAIN3','DOMAIN4' | ForEach-Object {
$param['Server'] = $_
foreach($user in Get-ADUser #param) {
[pscustomobject]#{
Name = $user.Name
SamAccountName = $user.SamAccountName
UserPrincipalName = $user.UserPrincipalName
BusinessCategory = $user.businesscategory -join ", "
extensionAttribute4 = $user.extensionAttribute4 -join ", "
extensionAttribute9 = $user.extensionAttribute9 -join ", "
extensionAttribute13 = $user.extensionAttribute13 -join ", "
DistinguishedName = $user.DistinguishedName
employeenumber = $user.employeenumber
Enabled = $user.Enabled
Domain = $_ # Adding the Domain of this user here
}
}
} | Export-Csv $filename -NoTypeInformation

Create New-AdUser IsValid parameter

I've got a function that checks AD before attempting to "choose" a username; it'll start by assuming first initial+last name, and see if that's already in AD.
If it is, it'll add letters from the first name until it finds an unused username. If it exhausts all letters in the first name, it'll tack an incrementing number on the end (i.e. jdoe, jodoe, johdoe, johndoe, johndoe1, johndoe2, etc.):
Note: this assumes you have the first name as $FirstName and the last name as $LastName
When attempting to run script then I got the following the error message:
Get-ADUser : Cannot find an object with identity: 'JDoe' under: >'DC=contoso,DC=com'.
At line:18 char:31
+ $usernameExists = Get-ADUser <<<< $username -ErrorAction >SilentlyContinue | format-wide IsValid
+ CategoryInfo : ObjectNotFound: (JDoe:ADUser) [Get-ADUser], >ADIdentityNotFoundException
+ FullyQualifiedErrorId : Cannot find an object with identity: 'JDoe' >under: >'DC=contoso,DC=com'.,Microsoft.ActiveDirectory.Management.Commands.GetADUser
Setting username as JDoe
I am assuming there is a problem related to the IsValid parameter?
$firstname_auto = $firstname.ToLower()
$lastname_auto = $lastname.ToLower()
$FirstNameLength = ($firstname_auto | Measure-Object -Character).Characters
$letterCount = 0
$username = ''
#Try to spell out the entire first name until we can get a unique username
do {
$letterCount++
$usernameExists = $false
$username = "$($firstname_auto.Substring(0,$letterCount))$($lastname_auto)"
$usernameExists = Get-ADUser $username -ErrorAction SilentlyContinue | format-wide IsValid
if ($usernameExists -eq $true) {
Write-Verbose "$username exists in AD. Trying again."
}
} until (($usernameExists -eq $false) -OR ($letterCount -eq $FirstNameLength))
#If we've used all the letters in the first name, and the username still isn't unique,
#start counting until we find one that is.
if ($usernameExists -eq $true) {
$usernameNumber = 0
Write-Verbose "Exhausted all non-numeric options! Trying with numbers."
do {
$usernameNumber++
$usernameExists = $false
$username = "$($firstname_auto.Substring(0,$letterCount))$lastname_auto$usernameNumber"
$usernameExists = Get-ADUser $username -ErrorAction SilentlyContinue | format-wide IsValid
if ($usernameExists -eq $true) {
Write-Verbose "$username already exists in AD. Trying again."
}
} until ($usernameExists -eq $false)
}
Write-host "Setting username as $username" -foregroundcolor Green

Powershell move AD object

i made this script to find all windows 10 machines which are not placed in the right OU, there is no action taken at this point - but i would like to move them once they had been found, we have over 30 country's and data centers so i would like to keep the OU string in the arrays, to keep the code to a minimal - how would one perform a move in this script? i could use some pointers.
$Script:OUBase = "OU=Countries,OU=Global,DC=internal"
Import-Module ActiveDirectory
$CountryDataCenter =
#(
[pscustomobject]#{Country="UK";DataCenter="CEN1"},
[pscustomobject]#{Country="UK";DataCenter="CEN2"}
)
Function GetWin10MachineAccounts($Country, $DataCenter){
#Build OUstring
$OUStringTarget = "*OU=Windows 10,OU=Computers,OU=" + $DataCenter + ",OU=" + $Country + "," + $Script:OUBase
$OUStringSource = "OU=Computers,OU=" + $DataCenter + ",OU=" + $Country + "," + $Script:OUBase
$countPC = ($Win10Computeraccounts).count
Write-Host "OU to search - " $OUStringSource -ForegroundColor Yellow
$Win10ComputerAccounts = Get-ADComputer -SearchBase $OUStringSource -Filter {(enabled -eq "true") -and (OperatingSystem -like "*Windows 10*")} -properties * | where {$_.DistinguishedName -notlike "$OUStringTarget"} | select CN -expandproperty Name
Return $Win10Computeraccounts
}
############### Main Script ##########################
##create empty array for use later
$DataArray = #()
ForEach ($Country in $CountryDataCenter)
{
$Win10Computeraccounts = GetWin10MachineAccounts $Country.Country $Country.DataCenter
$countPC = $Win10Computeraccounts.count
if(!$Win10Computeraccounts) {
write-host "No Windows 10 Computers are found in the container" $Country.Country $Country.DataCenter
}
foreach ($Computer in $Win10Computeraccounts){
Write-Host $Computer -ForegroundColor Red
#Store Data in foreach array
$DataArray += (Get-ADComputer $Computer )
Write-Host "$countPC" "Computers found in" $Country.Country $Country.DataCenter -ForegroundColor Green
}
}
$DataArray | Export-Csv "C:\log.csv" -Force
Use the Move-ADObject cmdlet:
foreach($Country in $CountryDataCenter)
{
$OUStringTarget = "OU=Windows 10,OU=Computers,OU={0},OU={1},{2}" -f $Country.DataCenter,$Country.Country,$Script:OUBase
$Win10Computeraccounts = GetWin10MachineAccounts $Country.Country $Country.DataCenter
foreach ($Computer in $Win10Computeraccounts){
Move-ADObject -Identity $Computer -TargetPath $OUStringTarget
}
}

Pull Active Directory user information

Hi I have a script that will partially work if I write "write-host" but doesn't work at all when exporting the information to a text file. I want to find the user ID's description, name, displayname and manager. Please help me understand why it isn't working.
Import-Module ActiveDirectory
$document = "C:\Temp\ADupdate yyyy.txt"
Clear-Content $document
<#
-ne = not equal CN=xxpc37254,OU=Standard,OU=Users,OU=Corporate,DC=we,DC=dirsrv
-eq = equal
-lt = less than
-gt = greater than
-ge = greater than or qual to
-le = less than or equal to
#>
$Header = `
"User ID" + "|" + `
"Display Name" + "|" + `
Description" + "|" + `
"ID Owner" + "|" + `
"ID Owner Name"
#Write out the header
$Header | Out-File $document -Append
#$Users = Get-ADUser -Filter {name -like "xxpc*" -or name -like "xxmd*"} - SearchBase "OU=Corporate,DC=we,DC=dirsrv,DC=com" -Properties name, displayname, description, manager
$Users = Get-ADUser -filter {name -like "xxpc*" -or name -like "xxmd*"} -Properties name, displayname, description, manager
foreach ($User in $Users)
{
#manager missing
if ($Users.Manager -eq $null) {
$owner = "MISSING"
$ownerid = "MISSING"
$ownername = "MISSING"
} else {
#grab the manager's name, surname, and department
$owner = Get-ADUser ($userid.Manager) -Properties GivenName, Surname, Department
$ownerid = $owner.Name
$ownername = $owner.Surname + "." + $owner.GivenName
}
$listing = `
$Users.Name + "|" + `
$Users.DisplayName + "|" + `
$Users.Description + "|" + `
$ownerid + "|" + `
$ownername
$listing | Out-File $document -Append
Ok. The reason why it's not working is probably because the if statement inside the foreach is wrong. You should use $user inside the foreach, not $users like you use here.
That being said, you should read up on creating custom objects, and get the data you want, create a custom object and write that to the pipeline. That way you can use the output in a lot of different ways, whether that is to write to a text file, a csv file, xml or just to the screen.