CHiLL Posted June 16, 2015 Posted June 16, 2015 I have this Powershell script that I've amended (and edited for this post to remove specific details out)...but it works great, except for one flaw...it doesn't create the home folder on the share and I don't know why! Import-Module ActiveDirectory $objOU=[ADSI]”LDAP://LDAPCONNECTION" $dataSource=import-csv “C:\Users\username\Desktop\users.csv” foreach($dataRecord in $datasource) { $cn=$dataRecord.FirstName + ” ” + $dataRecord.LastName #$sAMAccountName=$dataRecord.FirstName + “.” + $dataRecord.LastName $sAMAccountName=$dataRecord.Intake + $dataRecord.FirstName.Substring(0,$string.Length+3) + $dataRecord.LastName.Substring(0,$string.Length+4) $givenName=$dataRecord.FirstName $sn=$dataRecord.LastName $sAMAccountName=$sAMAccountName.ToLower() $ADGroup="Intake " + $dataRecord.Intake $displayName=$givenName + " " + $sn $userPrincipalName=$sAMAccountName + “@stjohnwall.local” $objUser=$objOU.Create(“user”,”CN=”+$cn) $objUser.Put(“sAMAccountName”,$sAMAccountName) $objUser.Put(“userPrincipalName”,$userPrincipalName) $objUser.Put(“displayName”,$displayName) $objUser.Put(“givenName”,$givenName) $objUser.Put(“sn”,$sn) $objUser.Put("description","Intake " + $dataRecord.Intake) $objUser.Put("mail",$sAMAccountName + "@emailaddress") $objUser.Put("profilepath","\\SERVER1\netlogon\mandatory3") $objUser.Put("scriptpath","students.bat") $objUser.Put("HomeDrive","H:") $objUser.Put("HomeDirectory","\\SERVER1\users\" + $sAMAccountName) $objUser.SetInfo() $objUser.SetPassword(“password”) $objUser.psbase.InvokeSet(“AccountDisabled”,$false) $objUser.SetInfo() Add-ADGroupMember -Identity "Domain Guests" -Member $sAMAccountName Add-ADGroupMember -Identity "Curriculum" -Member $sAMAccountName Add-ADGroupMember -Identity $ADGroup -Member $sAMAccountName } Can anybody help?
halbaradkenafin Posted June 16, 2015 Posted June 16, 2015 Does it set the HomeDirectory details in the AD account that's created? If it does then I'd guess it's a permissions problem on the parent folder. I'm also curious why you're not using New-ADUser to create accounts, it's a bit more readable and makes it easier to troubleshoot as you can specify -Verbose for extra logging when creating the accounts. Are all your pupil accounts part of Domain Guests? I've never put any users into that group and just use the default Domain Users and any extras we need (intake etc). 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 Does it set the HomeDirectory details in the AD account that's created? If it does then I'd guess it's a permissions problem on the parent folder. I'm also curious why you're not using New-ADUser to create accounts, it's a bit more readable and makes it easier to troubleshoot as you can specify -Verbose for extra logging when creating the accounts. Are all your pupil accounts part of Domain Guests? I've never put any users into that group and just use the default Domain Users and any extras we need (intake etc). Yes, it sets the HomeDirectory details in the properties of the AD account. To be honest, I'm a complete novice with Powershell. The above script is one that I've robbed from the Internet and modified to suit my needs. I'm not entirely sure how to use the New-ADUser commands in Powershell to perform what I'm after. As for Domain Guests, it appears that's the way its always been done here and we don't want to change that in fear of breaking things.
halbaradkenafin Posted June 17, 2015 Posted June 17, 2015 Then I'd check the permissions on the folder where the home drives should be created and ensure the security group (probably the intake one) has modify permissions. 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 Does it set the HomeDirectory details in the AD account that's created? If it does then I'd guess it's a permissions problem on the parent folder. I'm also curious why you're not using New-ADUser to create accounts, it's a bit more readable and makes it easier to troubleshoot as you can specify -Verbose for extra logging when creating the accounts. Are all your pupil accounts part of Domain Guests? I've never put any users into that group and just use the default Domain Users and any extras we need (intake etc). Yes, it sets the HomeDirectory details in the properties of the AD account. To be honest, I'm a complete novice with Powershell. The above script is one that I've robbed from the Internet and modified to suit my needs. I'm not entirely sure how to use the New-ADUser commands in Powershell to perform what I'm after. As for Domain Guests, it appears that's the way its always been done here and we don't want to change that in fear of breaking things.
sted Posted June 17, 2015 Posted June 17, 2015 assuming its like batch file dsadd for creating users creating the user doesn't create folders you need to do that as a separate command unlike creating them manually that does create them. All the command does is add records to the ad database it doesn't do anything to the file structure 1
sted Posted June 17, 2015 Posted June 17, 2015 for what its worth if it helps heres my ds add code for doing it (I do it all in an excel sheet and just copy and paste code lines out to a batch file rather than parsing a csv as that way I can autogenerate names etc dsadd user cn="4someone",ou="2014",ou="pupils",ou="curriculum users2",dc="domain",dc="local" -upn "[email="[email protected]"][email protected][/email]" -display "someone user" -disabled no -hmdir "[url="file://\\domain.local\dfs\users\2014\4someone"]\\domain.local\dfs\users\2014\4someone[/url]" -hmdrv u: -profile "[url="file://\\server\profiles$\roam\pupils\4someone"]\\server\profiles$\roam\pupils\4someone[/url]" -memberof cn="2014",ou="2014",ou="pupils",ou="curriculum users2",dc="domain",dc="local" -fn "someone" -ln "user" -desc 2014 -mustchpwd no -canchpwd no -loscr "pupil.bat" -pwdneverexpires yes pause md "d:\users\2014\4someone" pause cacls "d:\users\2014\4someone" /T /E /G 4someone:C as you can see line 1 is creating the user account line 2 creates the folder line 3 sets permissions (ignoring pause lines) 1
SteveM555 Posted June 17, 2015 Posted June 17, 2015 Here is what we use for creating home directories and Importing users from CSV all in one.. CSV File Structure: Forename,Surname,Username,Password,EmailAddress,Description,UPN,OU,City,Department,Script,HomeDir,Telephone,Web,Country,State,Post Test,User,Test User,s0sqv5,[email protected],Pupil,12345678,"OU=2015,OU=Current Years,OU=Users - Pupils,DC=SCH,DC=local",Sheffield,Pupil TG,pupils.bat,\\someserver\pupils\2015\,1111 111111,www.school.com,England,Somewhere,555 555 And the Powershell... It defaults to users.csv in the same directory. It may need some modifying for your setup though, it also writes to duplicates.txt if it can't import. By default the home directories are stored as firstname surname in the folder specified in the CSV. It also adds Read, Write and Modify permissions to the home folder. I can't take credit for it as it's one I found a while ago online and modified it to suit. Import-Module ActiveDirectory $Users = Import-Csv -Delimiter "," -Path "./users.csv" foreach ($User in $Users) { $OU = $User.OU $Password = $User.password $description = $User.description $Detailedname = $User.forename + " " + $User.surname $EmployeeID = $User.upn $UserFirstname = $User.forename $emailAddress = $User.EmailAddress $SAM = $Detailedname $homedir = $User.homedir $homedirAD = $homedir + $Detailedname New-ADUser -ErrorAction SilentlyContinue -Name $Detailedname -SamAccountName $SAM -City $User.city -telephoneNumber $User.telephone -wWWHomePage $User.web -department $User.department -postOfficeBox = $User.country -state = $User.state -postalCode = $User.post -EmailAddress $emailAddress -EmployeeID $EmployeeID -UserPrincipalName $SAM -DisplayName $Detailedname -GivenName $user.forename -Surname $user.surname -AccountPassword (ConvertTo-SecureString $Password -AsPlainText -Force) -Enabled $true -Description $description -HomeDrive "H:" -HomeDirectory $homedirAD -ScriptPath $User.script -Path $OU if(!$?) { if($error[0] = "The specified account already exists") { $errorStr = $error[0] + ": " + $SAM Write-Warning $errorStr $tentry = "`n" + $Detailedname Add-Content ./duplicates.txt $tentry } } else { New-Item -path $homedir -Name $Detailedname -ItemType Directory $userDir = "$homedir\$Detailedname" $Rights= [system.Security.AccessControl.FileSystemRights]::Read -bor [system.Security.AccessControl.FileSystemRights]::Write -bor [system.Security.AccessControl.FileSystemRights]::Modify $Inherit=[system.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [system.Security.AccessControl.InheritanceFlags]::ObjectInherit $Propogation=[system.Security.AccessControl.PropagationFlags]::None $Access=[system.Security.AccessControl.AccessControlType]::Allow $AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule("$Detailedname",$Rights,$Inherit,$Propogation,$Access) $ACL = Get-Acl $userDir $ACL.AddAccessRule($AccessRule) $Account = new-object system.security.principal.ntaccount($Detailedname) $ACL.setowner($Account) $ACL.SetAccessRule($AccessRule) Set-Acl $userDir $ACL $out = "The AD Account: " + $Detailedname + " and Home Directory: " + $homedirAD + " have been created." Write-Host $out } } 1
halbaradkenafin Posted June 17, 2015 Posted June 17, 2015 From looking over your script and mine and doing a bit more testing it's almost certainly because you're not creating the folder as part of the script. Both the scripts posted by @sted and @SteveM555 do create the folders and assign permissions and I'd guess don't have the problem. I'm in the process of updating my script to do this (I thought AD would do it automatically like it does with Profiles but apparently not), I'll post my script once I'm done with it (mostly writing help comments) to give you another perspective on it. 1
sted Posted June 17, 2015 Posted June 17, 2015 From looking over your script and mine and doing a bit more testing it's almost certainly because you're not creating the folder as part of the script. Both the scripts posted by @sted and @SteveM555 do create the folders and assign permissions and I'd guess don't have the problem. I'm in the process of updating my script to do this (I thought AD would do it automatically like it does with Profiles but apparently not), I'll post my script once I'm done with it (mostly writing help comments) to give you another perspective on it. ad itself dosent create profiles (if you check your profiles folder after creating a user there isn't one for that user) BUT a user can self create at first logon (assuming correct permissions etc) 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 Thanks for the replies so far. I've created a new script based on @SteveM555's script, but I'm getting an error message that I don't understand! Import-Module ActiveDirectory $CSV = Import-CSV -Delimiter "," "D:\PS\New-ADUser.csv” foreach ($User in $CSV) { $sAMAccountName = $_.Intake + $_.Forename.Substring(0,$string.Length+3) + $_.Surname.Substring(0,$string.Length+4) $UserPrincipalName = $sAMAccountName + “@stjohnwall.local” $DisplayName = $_.Forename + " " + $_.Surname $Surname = $_.Surname $GivenName = $_.Forename $Path = "Intake " + $_.Intake + "OU=Curriculum,OU=St John Wall Student Accounts,DC=stjohnwall,DC=local" $EmailAddress = ($sAMAccountName + "@sjw.bham.sch.uk") $AccountPassword = ConvertTo-SecureString -AsPlainText "password" -Force $Enabled = $true $ChangePasswordAtLogon = $true $Description = "Intake" + $_.Intake $HomeDirectory = "\\curricsvr-01\users\" + $sAMAccountName $HomeDrive = "H:" $ProfilePath = "\\CURRICSVR-01\netlogon\mandatory3" $ScriptPath = "students.bat" New-ADUser -ErrorAction SilentlyContinue ` -sAMAccountName $sAMAccountName ` -UserPrincipalName $UserPrincipalName ` -DisplayName $DisplayName ` -Surname $Surname ` -GivenName $GivenName ` -Path $Path ` -EmailAddress $EmailAddress ` -AccountPassword $AccountPassword ` -Enabled $Enabled ` -ChangePasswordAtLogon $ChangePasswordAtLogon ` -Description $Description ` -HomeDirectory $HomeDirectory ` -HomeDrive $HomeDrive ` -ProfilePath $ProfilePath ` -ScriptPath $ScriptPath } { New-Item -path $HomeDirectory -Name $DisplayName -ItemType Directory $userDir = "$HomeDirectory\$DisplayName" $Rights= [system.Security.AccessControl.FileSystemRights]::Read -bor [system.Security.AccessControl.FileSystemRights]::Write -bor [system.Security.AccessControl.FileSystemRights]::Modify $Inherit=[system.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [system.Security.AccessControl.InheritanceFlags]::ObjectInherit $Propogation=[system.Security.AccessControl.PropagationFlags]::None $Access=[system.Security.AccessControl.AccessControlType]::Allow $AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule("$DisplayName",$Rights,$Inherit,$Propogation,$Access) $ACL = Get-Acl $userDir $ACL.AddAccessRule($AccessRule) $Account = new-object system.security.principal.ntaccount($DisplayName) $ACL.setowner($Account) $ACL.SetAccessRule($AccessRule) Set-Acl $userDir $ACL $out = "The AD Account: " + $DisplayName + " and Home Directory: " + $userDir + " have been created." Write-Host $out } I am getting the following error message: You cannot call a method on a null-valued expression. At line:6 char:52 + $sAMAccountName = $_.Intake + $_.Forename.Substring <<<< (0,$string.Length+3) + $_.Surname.Substring(0,$string.Length+4) + CategoryInfo : InvalidOperation: (Substring:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull I need to include this as this determines our username convention. (Intake year + 3 letters of forename + 4 letters of surname | 14tesUser)
halbaradkenafin Posted June 17, 2015 Posted June 17, 2015 You cannot call a method on a null-valued expression. At line:6 char:52 + $sAMAccountName = $_.Intake + $_.Forename.Substring <<<< (0,$string.Length+3) + $_.Surname.Substring(0,$string.Length+4) + CategoryInfo : InvalidOperation: (Substring:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull I need to include this as this determines our username convention. (Intake year + 3 letters of forename + 4 letters of surname | 14tesUser) You need to change the line slightly as you don't have a $string variable in use. You'll need to change it to: $sAMAccountName = $_.Intake + $_.Forename.Substring(0,$_.Forename.length+3) + $_.Surname.Substring(0,$_.Surname.length+4) 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 You need to change the line slightly as you don't have a $string variable in use. You'll need to change it to: $sAMAccountName = $_.Intake + $_.Forename.Substring(0,$_.Forename.length+3) + $_.Surname.Substring(0,$_.Surname.length+4) Still getting the same error with the amended line You cannot call a method on a null-valued expression. At line:6 char:52 + $sAMAccountName = $_.Intake + $_.Forename.Substring <<<< (0,$_.Forename.length+3) + $_.Surname.Substring(0,$_.Surname.length+4) + CategoryInfo : InvalidOperation: (Substring:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull When I run the script (currently using Windows PowerShell ISE), it is showing a popup box. Screenshot attached. [ATTACH=CONFIG]31110[/ATTACH]
halbaradkenafin Posted June 17, 2015 Posted June 17, 2015 (edited) Still getting the same error with the amended line You cannot call a method on a null-valued expression. At line:6 char:52 + $sAMAccountName = $_.Intake + $_.Forename.Substring <<<< (0,$_.Forename.length+3) + $_.Surname.Substring(0,$_.Surname.length+4) + CategoryInfo : InvalidOperation: (Substring:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull When I run the script (currently using Windows PowerShell ISE), it is showing a popup box. Screenshot attached. [ATTACH=CONFIG]31110[/ATTACH] Just noticed the foreach loop is actually using $User instead of $_ for the variable name, that is likely causing a problem. Might also be worth wrapping the $User.Forename and $User.Surname in () brackets before the .substring section to ensure it's evaluating each part individually. You'll also have to specify the -name property for New-ADUser as it's a required parameter. I'm guessing it will be the same value as your sAMAccountname but it depends on what you'd like to use, Get-ADUser -Identity will tell you what format you currently use if you don't know which one to use. Edited June 17, 2015 by halbaradkenafin 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 Just noticed the foreach loop is actually using $User instead of $_ for the variable name, that is likely causing a problem. Might also be worth wrapping the $User.Forename and $User.Surname in () brackets before the .substring section to ensure it's evaluating each part individually. You'll also have to specify the -name property for New-ADUser as it's a required parameter. I'm guessing it will be the same value as your sAMAccountname but it depends on what you'd like to use, Get-ADUser -Identity will tell you what format you currently use if you don't know which one to use. What should I enter instead of $Users in the foreach loop? Simply just $_? So those two lines would look like this? foreach ($_ in $CSV) { $sAMAccountName = $_.Intake + ($_.Forename).Substring(0,$_.Forename.length+3) + ($_.Surname).Substring(0,$_.Surname.length+4)
halbaradkenafin Posted June 17, 2015 Posted June 17, 2015 What should I enter instead of $Users in the foreach loop? Simply just $_? So those two lines would look like this? foreach ($_ in $CSV) { $sAMAccountName = $_.Intake + ($_.Forename).Substring(0,$_.Forename.length+3) + ($_.Surname).Substring(0,$_.Surname.length+4) Just replace all instances of $_ with $User (Find/Replace tool will make this easy), it should fix the code and make it more readable. 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 (edited) After finding typing mismatches between my CSV file and code (which I've now corrected), I'm now getting a different error message: Exception calling "Substring" with "2" argument(s): "Index and length must refer to a location within the string. Parameter name: length" At line:7 char:60 + $sAMAccountName = $User.Intake + ($User.Forename).Substring <<<< (0,$User.Forename.length+3) + ($User.Surname).Substring(0,$User.Surname.length+4) + CategoryInfo : NotSpecified: ( [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException Edit: I've changed the problematic line to: $sAMAccountName = $User.Intake + ($User.Forename).Substring(0,3) + ($User.Surname).Substring(0,4) That has now sorted that error, but now I'm encountering more errors further down the script! Edited June 17, 2015 by CHiLL
halbaradkenafin Posted June 17, 2015 Posted June 17, 2015 Done that, but still the same error message: You cannot call a method on a null-valued expression. At line:6 char:60 + $sAMAccountName = $User.Intake + ($User.Forename).Substring <<<< (0,$User.Forename.length+3) + ($User.Surname).Substring(0,$User.Surname.length+4) + CategoryInfo : InvalidOperation: (Substring:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull Does the csv contain columns called Forename, Surname etc? If it does then I'd next see what data the script is trying to work with, before the $sAMAccountName line add in Write-Host $User.Forename Write-host $User.Surname This should give you an idea of what the field actually contains. If it shows two blank lines before the error message then it means your columns aren't named the same as the script is looking for (it shouldn't be case sensitive). If it shows the correct data from your csv then I'd resorted to messing around in the command line view using various lines one at a time, probably something like: $test = Import-csv -path "D:\PS\New-ADUser.csv" Write-host $Test[0] Write-host ($test[0].forename).Substring(0,$test[0].forename.length+3) If that gives any error messages then I'd expect it to be on the last line. Also, that popup is still occurring. You'll need to add -Name to the New-ADUser command, before the -ErrorAction parameter would be best. 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 (edited) I've managed to sort that, though it's now failing on the creation of the home folder section, with the following messages: Exception calling "AddAccessRule" with "1" argument(s): "Some or all identity references could not be translated." At line:57 char:31 + $ACL.AddAccessRule <<<< ($AccessRule) + CategoryInfo : NotSpecified: ( [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException Exception calling "SetOwner" with "1" argument(s): "Some or all identity references could not be translated." At line:59 char:26 + $ACL.setowner <<<< ($Account) + CategoryInfo : NotSpecified: ( [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException Exception calling "SetAccessRule" with "1" argument(s): "Some or all identity references could not be translated." At line:60 char:31 + $ACL.SetAccessRule <<<< ($AccessRule) + CategoryInfo : NotSpecified: ( [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException Edit: I edited the $userDir variable to be just $HomeDirectory and now it creates the home folder...however it does not assign the permissions for the user. (Still shows the same error message as above) Edited June 17, 2015 by CHiLL
halbaradkenafin Posted June 17, 2015 Posted June 17, 2015 You may need to modify the lines around there that say "$Displayname" to "\$Displayname". I've found that to cause problems in the past when assigning ACEs this way. If it's still occurring then I'd add in Start-Sleep -s 10 after the New-ADUser statement to allow it time to properly update the DCs. 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 Thanks, that's working! Another question though, our username naming convention is based on the year a student leaves year 11 (don't ask me why). Is there an easy way to take the Intake variable and plus 5 onto it? So I can create that as a variable for building the $sAMAccountName?
halbaradkenafin Posted June 17, 2015 Posted June 17, 2015 Thanks, that's working! Another question though, our username naming convention is based on the year a student leaves year 11 (don't ask me why). Is there an easy way to take the Intake variable and plus 5 onto it? So I can create that as a variable for building the $sAMAccountName? That's quite an easy one to handle (though it will look a little convoluted at first) and depends on how your csv stores the intake year. Assuming you store it as just the two digit number then you can do this: $LeavingYear = [int]$_.Intake + 5 And then substitute $LeavingYear in your $sAMAccountName where it currently has $_.Intake. If you do 4 digit intake year in the csv then it's just a slight modification to the above code: $LeavingYear = [int]($_.Intake.substring(2)) + 5 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 Thanks. Currently getting this error: Exception calling "Substring" with "2" argument(s): "Index and length must refer to a location within the string. Parameter name: length" At D:\PS\Complete.ps1:12 char:51 + $sAMAccountName = $Leaving + ($Forename).Substring <<<< (0,3) + ($Surname).Substring(0,4) + CategoryInfo : NotSpecified: ( [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException The code up that point of error is: foreach ($User in $CSV) { $Forename = $User.Forename $Surname = $User.Surname $Intake = $User.Intake $Leaving = [int]$User.Intake + 5 #Based on 2 digit year in CSV #$Leaving = [int]($User.Intake.substring(2)) + 5 #Based on 4 digit year in CSV $Name = $User.Forename + " " + $User.Surname $sAMAccountName = $Leaving + ($Forename).Substring(0,3) + ($Surname).Substring(0,4) I think it has something to do with the fact $Leaving has been converted to an integer. I have attempted to convert it back to a string but it still isn't working.
halbaradkenafin Posted June 17, 2015 Posted June 17, 2015 One solution to that is to wrap the $Leaving part of $sAMAccountName in "" and it will parse it as a string with the value of the variable. 1
CHiLL Posted June 17, 2015 Author Posted June 17, 2015 One solution to that is to wrap the $Leaving part of $sAMAccountName in "" and it will parse it as a string with the value of the variable. Unfortunately, that hasn't worked, still the same issue.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now