Can't seem to figure out what is causing the error with script below with the "New-ADUser" syntax. Not sure if anybody can spot the error?
"New-ADUser : The object name has bad syntax
At D:\ScriptPath\importadusersAndMoveOU.ps1:33 char:3"
The script works if I remove the "$NewOU" variable and have the users imported into the default "users" OU.
# Import active directory module for running AD cmdlets
Import-Module activedirectory
#Store the data from ADUsers.csv in the $ADUsers variable
$ADUsers = Import-csv 'D:\CSVPATH\adusers.csv'
$NewOU = New-ADOrganizationalUnit -Name "ADMINS"
#Loop through each row containing user details in the CSV file
foreach ($User in $ADUsers)
{
#Read user data from each field in each row and assign the data to a
variable as below
$DomainName = Get-ADDomain -current LocalComputer
$Username = $User.username
$Password = "TestPassword12345"
$Firstname = $User.firstname
$Lastname = $User.lastname
$OU = $NewOU+","+$DomainName.DistinguishedName
$upn = $Username+"#"+$DomainName.DNSRoot
#Check to see if the user already exists in AD
if (Get-ADUser -F {SamAccountName -eq $Username})
{
#If user does exist, give a warning
Write-Warning "A user account with username $Username already exist in Active Directory."
}
else
{
#User does not exist then proceed to create the new user account
#Account will be created in the OU provided by the $OU variable read from the CSV file
New-ADUser `
-SamAccountName $Username `
-UserPrincipalName $upn `
-Name "$Firstname $Lastname" `
-GivenName $Firstname `
-Surname $Lastname `
-Enabled $True `
-DisplayName "$Lastname, $Firstname" `
-Path $OU `
-AccountPassword (convertto-securestring $Password -AsPlainText -Force) -ChangePasswordAtLogon $True
Add-ADGroupMember "domain admins" $username
Add-ADGroupMember "enterprise admins" $Username
}
}
The New-ADOrganizationalUnit -Name "ADMINS" command creates a new OU under the default NC head for the domain.
If you want that elsewhere, you should use the -Path <DistinghuisedName of Parent OU> parameter.
However, as Drew Lean already commented, this code does not check if the OU exists before trying to create it, so a quick test might be in order here:
[adsi]::Exists("LDAP://OU=ADMINS,DC=domain,DC=com")
or
Get-ADOrganizationalUnit -Filter "distinguishedName -eq 'OU=ADMINS,DC=domain,DC=com'"
# don't filter on 'Name' because it is more than likely you have several OUs with the same name
Next, the part where you construct the distinguishedName for variable $OU results in a badly formatted string.
$OU = $NewOU+","+$DomainName.DistinguishedName will result in "ADMINS,DC=domain,DC=com" which is not a valid DistinghuishedName, hence the error The object name has bad syntax
Try getting the DN of the existing OU first and if that does not exist, capture it after the creation and store the DistinghuishedName in variable $OU
something like this:
$OU = "OU=ADMINS,DC=domain,DC=com"
if (-not (Get-ADOrganizationalUnit -Filter "distinguishedName -eq '$OU'")) {
$NewOU = New-ADOrganizationalUnit -Name "ADMINS" -PassThru
$OU = $NewOU.DistinghuishedName
}
ps. The Identity parameter for Get-ADOrganizationalUnit must be one of:
A distinguished name
A GUID (objectGUID)
A security identifier (objectSid)
A Security Account Manager account name (sAMAccountName)
Related
Essentially, my script is supposed to check if each user in the administrators group is listed inside of a text file, and if it is then ignore it and move on. If it isn't, it removes the user from the administrator group. However, Get-LocalGroupMember prepends the computer name to the username. This means that the username in the txt file (ex user1), does not match the $._Name variable from the Get-LocalGroupMember command (ex desktop/user1). Here is a copy of the code
$GroupName = "Administrators"
$Exclude = "Administrator","$env:UserName"
$AuthorizedAdmins = Get-Content C:\Users\$env:UserName\admins.txt
Get-LocalGroupMember $GroupName |
ForEach-Object{
if ($_.ObjectClass -eq 'User'){
if ($AuthorizedAdmins -contains $_.Name -or $Exclude -contains $_.Name){
Continue
}
else{
Remove-LocalGroupMember -Group $GroupName -Member $_.Name -Confirm
}
}
}
I have tried several solutions. In the code, I created a new variable that removed the first $env:ComputerName+1 characters of the $._Name string. While this did work to remove the computername, powershell errors out. Here is the error code and changed script:
Get-LocalGroupMember : System error.
At users.ps1:6 char:1
+ Get-LocalGroupMember $GroupName |
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-LocalGroupMember], ContinueException
+ FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand
$GroupName = "Administrators"
$Exclude = "Administrator","$env:UserName"
$AuthorizedAdmins = Get-Content C:\Users\$env:UserName\admins.txt
Get-LocalGroupMember $GroupName |
ForEach-Object{
$User = $_.Name
$length = $env:ComputerName.Length+1
$ShortUser = $User.Remove(0,$length)
if ($_.ObjectClass -eq 'User'){ #ignore groups and select only users
if ($AuthorizedAdmins -contains $ShortUser -or $Exclude -contains $ShortUser){
Continue
}
else{
Remove-LocalGroupMember -Group $GroupName -Member $_.Name -Confirm
}
}
}
The admin.txt file is formatted as follows:
user1
user2
user3
I cannot figure out how to fix this, though it is probably someting simple. Any help would be appreciated.
The real issue with your code is your use of continue in a ForEach-Object loop, see note from the docs. If you want to emulate continue in a pipeline processing function you should use return instead. So your code, with some improvements and simplifications would be:
$GroupName = "Administrators"
$exclude = #(
"Administrator"
$env:UserName
Get-Content C:\Users\$env:UserName\admins.txt
)
Get-LocalGroupMember $GroupName | ForEach-Object{
# if its not a user, skip this logic
if ($_.ObjectClass -ne 'User') {
return
}
# here we assume its a user
if ($_.Name.Split('\')[-1] -in $exclude) {
return
}
Remove-LocalGroupMember -Group $GroupName -Member $_.Name -Confirm
}
I've cobbled together (from various online sources) a script that can return data about AD users from a CSV file. It can clearly mark when a user has NOT been found, but perhaps just as important to me is a way of outputting a blank line to the CSV file when the input CSV file also has a blank. That would save a lot mucking around in Excel to make sure that all the blank lines correspond to each other (and subsequently where user data has been found). A 1-to-1 comparsion is the goal.
Here is what I have...
$ImportCSV = "C:\Users\x\Desktop\testCSV_in.csv"
$Names = Import-Csv -Path $ImportCSV
$Results = foreach ($Name in $Names) {
$filter = $Name.samAccountName
$User = Get-ADUser -Filter "SamAccountName -like '$filter'" -Properties Samaccountname, Givenname, Surname, EmailAddress, Name
#blank lines input CSV
if ( $User.SamAccountName -eq "" ) {
# please help
}
# found user
if ( $User ) {
$User |
Select-Object -Property Samaccountname, Givenname, Surname, EmailAddress, Name
}
# not found user
else {
[pscustomobject]#{
SamAccountName = 'MISSING ACCOUNT'
}
}
}
$Results | Export-Csv -Path "C:\Users\x\Desktop\testCSV_out.csv" -NoTypeInformation -Encoding UTF8
All the possible combinations that I can think of for $User.SamAccountName -eq "" just return back a CSV file that doesn't reflect the gaps that I purposely introduced (to mimic real use-cases).
I am sure, it's a just a line or two code that's needed. Thanks.
If you want a normalized export you need a normalized Object, meaning, all columns for your CSV must exist for all lines, even if they're $null. Try this code, see if it works:
$out = {
param($samAccountName)
[pscustomobject]#{
Samaccountname = $samAccountName
Givenname = $User.GivenName
Surname = $User.SurName
EmailAddress = $User.EmailAddress
Name = $User.Name
}
}
Import-Csv -Path 'C:\Users\x\Desktop\testCSV_in.csv' | ForEach-Object {
if([string]::IsNullOrWhiteSpace($_.samAccountName)) {
return & $out -samAccountName 'User Not Found on CSV'
}
$params = #{
Properties = 'Samaccountname', 'Givenname', 'Surname', 'EmailAddress', 'Name'
LDAPFilter = "(SamAccountName={0})" -f $_.samAccountName
}
$user = Get-ADUser #params
if(-not $user) {
return & $out -samAccountName 'User Not Found on AD'
}
& $out -samAccountName $user.samAccountName
} | Export-Csv -Path "C:\Users\x\Desktop\testCSV_out.csv" -NoTypeInformation -Encoding UTF8
Edit: Import-Csv, same as ConvertFrom-Csv will skip empty lines. At least one column has to be populated.
I found a way to get this same functionality and also add manager email and calculated fields as well:
Import-CSV C:\test\CSV_in.csv |
ForEach-Object {
Try{
$u = Get-ADUser $_.samaccountname -Properties * -ErrorAction Stop | Select GivenName, Surname, samaccountname, Title, Department, #{N='Manager';E={(Get-ADUser $_.Manager).Name}},#{N="ManagerEmail";E={(Get-ADUser -Property emailaddress $_.Manager).emailaddress}}
[PSCustomObject]#{User = $_.name; samaccountname = $u.samaccountname; Manager = $u.Manager; ManagerEmail = $u.ManagerEmail}
}
Catch{
[PSCustomObject]#{User = $_.name; samaccountname = 'Not Found'; Manager = 'N/A'; ManagerEmail = 'N/A'}
}
} | Export-CSV c:\test\CSV_out.csv -NoTypeInformation
I wanted to ask as I'm querying all users from AD whose Home Directory is in a certain directory from Powershell using Get-ADuser , and for most cases it retrieves null result.
The query I run is this:
$DirectoryInfo = Get-Item \\Fileserver\Users
$strFilter = $DirectoryInfo.FullName.Replace('\','\5c')
$AdUser = Get-AdUser -Filter {homeDirectory -like $strFilter}
echo $AdUser
If I look from AD admin center panel for a specific user, I can see it has set Home Directory inside path i've queried before in Powershell indeed.
Another thing that seems to me strange is that there are some users that appear in the query, so the previous case doesn't apply for all users.
Is it that AD admin center panel shows Home Directory of Group where this user belongs for example, or is just that I'm running a wrong query from Powershell?
Thanks in advance,
Juan Pablo.
I think because the HomeDirectory attribute is not in the default output set from Get-ADUser, you need to add it to the required Properties aswell.
This may be part of a larger script, but from the question I fail to see why you would need this:
$DirectoryInfo = Get-Item \\Fileserver\Users
$strFilter = $DirectoryInfo.FullName + '\*'
since you already have the UNC path for the users home directories.
I cannot test this right now, but you could try like this:
$strFilter = '\\Fileserver\Users\*'
$AdUser = Get-AdUser -Filter "HomeDirectory -like $strFilter" -Properties HomeDirectory
$AdUser
or use a Where-Object to get what you want:
$strFilter = '\\Fileserver\Users\*'
$AdUser = Get-AdUser -Filter * -Properties HomeDirectory | Where-Object { $_.HomeDirectory -like $strFilter }
$AdUser
If you prefer using the -LDAPFilter rather then -Filter, then you need to escape the special characters your string may contain.
* \2A
( \28
) \29
\ \5C
NUL \00
You do this by prepending a backslash \ to each of these characters and replacing the characters themselves by their ASCII code in hex.
The ( becomes \28, the backslash \ becomes \5c etc.
This uses a small function to escape these characters for a LDAP search filter:
function Escape-LdapSearchFilter([string] $Filter) {
return $Filter -creplace '\*', '\2a' `
-creplace '\(', '\28' `
-creplace '\)', '\29' `
-creplace '/' , '\2f' `
-creplace '`0', '\00' `
-creplace '\\(?![0-9A-Fa-f]{2})', '\5c'
}
$strFilter = Escape-LdapSearchFilter "\\Fileserver\Users\"
# for LDAP you must use the correct attribute name, so `homeDirectory` with a lower-case `h`
$AdUser = Get-AdUser -LDAPFilter "(homeDirectory=$strFilter*)" -Properties HomeDirectory
$AdUser
I don't know what \5c is doing in that code, so please forgive my ignorance.
if \Fileserver\Users is the root directory that contains home directories, then the following code should work:
$DirectoryInfo = Get-Item \\Fileserver\Users
$strFilter = $DirectoryInfo.FullName + '\*'
$AdUser = Get-AdUser -Filter {homeDirectory -like $strFilter}
$AdUser
The -like operator needs asterisks if your string is not an exact match.
I'm using PowerShell to add users to auditing for folders in Windows 10.
I'm using this code to set "EVERYONE" for Auditing.
But I need to do special rules for fail and special rules for Success and Fail, so I need it to save in 2 different lines. - like this picture:
This is the code I'm using:
$Folders = "C:\windows\system32\config"
Foreach ($Folder in $Folders) {
Write-Host "" # Empty line
Write-Host "Applying Auditing for folder", $Folder
Write-Host "" # Empty line
$ACL = Get-Acl $Folder
# Set Auditing for Success event for above Folders for EVeryone group
$PermAudited = "CreateFiles"
$AccessRule = New-Object System.Security.AccessControl.FileSystemAuditRule("Everyone", $PermAudited, "Failure")
$ACL.SetAuditRule($AccessRule)
# Set Auditing for Success event for Top folder
Write-Host $Folder, "for auditing Success event"
$ACL | Set-Acl $Folder
}
You can Specify those rules using the System.Security.AccessControl.FileSystemRights enum, Check the available rules like this:
[enum]::GetNames([System.Security.AccessControl.FileSystemRights])
Basically you need to take a look on one of the Constructors for the FileSystemAuditRule to understand how you need to set it, for your needs I think this is the right one:
FileSystemAuditRule(
string identity,
FileSystemRights fileSystemRights,
AuditFlags flags
)
So, you need to set Rights and AuditFlags, based on your example it should be something like this:
$Rights = "ReadAndExecute","Modify"
$Flags = "Failure"
$AccessRights = [System.Security.AccessControl.FileSystemRights]$Rights
$AuditFlags = [System.Security.AccessControl.AuditFlags]$Flags
Then Set the ACL like this:
$ACL = Get-Acl $Folder
$AccessRule = New-Object System.Security.AccessControl.FileSystemAuditRule("Everyone",$AccessRights, $AuditFlags)
$ACL.SetAuditRule($AccessRule)
Set-Acl -Path $Folder -AclObject $ACL
I was creating what I thought was a super-simple PowerShell script to update the location field with "Mobile: " + Mobile Phone number. Using the limited fields on GAL to show mobile number for all users.
Somehow, I only get the "Mobile: " without the number. I have tried many variations of this same script but ultimately $User.mobile is incorrect.
Import-Module ActiveDirectory
$Userlist = Get-ADUser -Server XXXXX -filter * -SearchBase "OU=Users,OU=Corporate,OU=XXXXXXXX,DC=XXXXXX,DC=com"
foreach ($User in $Userlist) {
$newlocation = "Mobile: "
$newlocation = $newlocation + $User.mobile
Set-ADUser -Instance $User
}
# Update properties.
Two things you need to change here:
Include the mobile and location attributes in the original Get-ADUser query, it won't retrieve these by default:
$Userlist = Get-ADUser -Server XXXXX -filter * -Properties mobile,physicalDeliveryOfficeName -SearchBase "OU=Users,OU=Corporate,OU=XXXXXXXX,DC=XXXXXX,DC=com"
and then make sure you actually modify the $User object before calling Set-ADUser:
foreach ($User in $Userlist) {
$newlocation = "Mobile: " + $User.mobile
$User.physicalDeliveryOfficeName = $newlocation
Set-ADUser -Instance $User
}
The Get-AdUser adding -properties was the answer. It worked like a charm.
$Userlist = Get-ADUser -Server XXXXX -filter * -Properties mobile,physicalDeliveryOfficeName -SearchBase "OU=Users,OU=Corporate,OU=XXXXXXXX,DC=XXXXXX,DC=com"
foreach($User in $userlist)
{
$newlocation = "Mobile: " + $User.mobile
$User.physicalDeliveryOfficeName = $newlocation
Set-ADUser -Instance $User
}