通过CSV文件为批量AD帐户创建定义AD帐户到期日期时间和AD组

qni6mghb  于 2023-04-27  发布在  其他
关注(0)|答案(1)|浏览(350)

我有一个脚本,自动批量广告帐户的创建。
该脚本工作正常,但当我尝试为每个用户定义帐户到期日期和时间(-AccountExpirationDate)时,它失败了。
脚本如下:

# Store the data from NewUsersFinal.csv in the $ADUsers variable
$ADUsers = Import-Csv C:\temp\NewUsersSent.csv

# Define UPN
$UPN = "my.domain.net"

# 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
    $username = $User.username
    $password = $User.password
    $firstname = $User.firstname
    $lastname = $User.lastname
    $OU = $User.ou #This field refers to the OU the user account is to be created in
    $email = $User.email
    $telephone = $User.telephone
    $jobtitle = $User.jobtitle
    $accountexpires = $User.accountexpires

    # 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 exists 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 "$username@$UPN" `
            -Name "$firstname $lastname" `
            -GivenName $firstname `
            -Surname $lastname `
            -Enabled $True `
            -DisplayName "$lastname, $firstname" `
            -Path $OU `
            -OfficePhone $telephone `
            -MobilePhone $telephone `
            -HomePhone $telephone `
            -EmailAddress $email `
            -Description $jobtitle `
            -AccountExpirationDate $accountexpires `
            -AccountPassword (ConvertTo-secureString $password -AsPlainText -Force) -ChangePasswordAtLogon $False -PasswordNeverExpires $True

        # If user is created, show message.
        Write-Host "The user account $username is created." -ForegroundColor Cyan
    }
}

CSV文件如下:

当我运行代码时,我得到以下错误(帐户实际上没有创建):

New-ADUser : Cannot bind parameter 'AccountExpirationDate'. Cannot convert value ""11/17/2023 2:22:48 PM"" to type "System.DateTime". Error: "String was not recognized 
as a valid DateTime."
At C:\Users\Me\Desktop\BulkNewUsers.ps1:45 char:36
+             -AccountExpirationDate $accountexpires `
+                                    ~~~~~~~~~~~~~~~
   + CategoryInfo          : InvalidArgument: (:) [New-ADUser], ParameterBindingException
   + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.ActiveDirectory.Management.Commands.NewADUser

The user account TTesting1 is created.
New-ADUser : Cannot bind parameter 'AccountExpirationDate'. Cannot convert value "0" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At C:\Users\Me\Desktop\BulkNewUsers.ps1:45 char:36
+             -AccountExpirationDate $accountexpires `
+                                    ~~~~~~~~~~~~~~~
   + CategoryInfo          : InvalidArgument: (:) [New-ADUser], ParameterBindingException
   + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.ActiveDirectory.Management.Commands.NewADUser

The user account TTesting2 is created.
Press Enter to exit:

PS好像不接受我的日期时间格式。
我试着从以下网站阅读:
https://ss64.com/ps/new-aduser.html
https://ss64.com/ps/syntax-dateformats.html
我相信我需要指定格式模式的PS接受我的日期时间在CSV。
我也读到过声明“0”设置帐户不过期-可以澄清一下吗?
我还想知道是否也可以定义要添加到CSV中的AD组,以便使用添加新用户;作为每个AD组名称的分隔符?-我认为我可能需要将Get-ADPrincipalGroupMembership合并到脚本中。

更新1

感谢Theo运行您的脚本执行没有错误,但帐户到期日未设置:

是否因为我在以前失败的尝试中创建了这些帐户(在尝试再次创建帐户之前是否需要等待24小时-缓存详细信息),我确实删除了帐户并在DC中强制复制。

更新2

西奥的要求。
我尝试了下面的第一个建议代码:

错误代码:

PS C:\Windows\system32> C:\Users\Me\Desktop\BulkNewUsers.ps1
At C:\Users\Me\Desktop\BulkNewUsers.ps1:48 char:67
+     $accountexpires = (Get-Date) ; [datetime]::TryParse(11/17/2023 2:22:48 PM, [ ...
+                                                                   ~
Missing ')' in method call.
At C:\Users\Me\Desktop\BulkNewUsers.ps1:48 char:68
+     $accountexpires = (Get-Date) ; [datetime]::TryParse(11/17/2023 2:22:48 PM, [ ...
+                                                                    ~~~~~~~
Unexpected token '2:22:48' in expression or statement.
At C:\Users\Me\Desktop\BulkNewUsers.ps1:8 char:29
+ foreach ($User in $ADUsers) {
+                             ~
Missing closing '}' in statement block.
At C:\Users\Me\Desktop\BulkNewUsers.ps1:48 char:100
+ ... $accountexpires) {
+                    ~
Unexpected token ')' in expression or statement.
At C:\Users\Me\Desktop\BulkNewUsers.ps1:64 char:1
+ }
+ ~
Unexpected token '}' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingEndParenthesisInMethodCall

我尝试了下面的第二个建议代码:

错误代码:

PS C:\Windows\system32> C:\Users\Me\Desktop\BulkNewUsers.ps1
At C:\Users\Me\Desktop\BulkNewUsers.ps1:48 char:72
+     $accountexpires = (Get-Date) ; [datetime]::TryParseExact(11/17/2023 2:22:48  ...
+                                                                        ~
Missing ')' in method call.
At C:\Users\Me\Desktop\BulkNewUsers.ps1:48 char:73
+     $accountexpires = (Get-Date) ; [datetime]::TryParseExact(11/17/2023 2:22:48  ...
+                                                                         ~~~~~~~
Unexpected token '2:22:48' in expression or statement.
At C:\Users\Me\Desktop\BulkNewUsers.ps1:8 char:29
+ foreach ($User in $ADUsers) {
+                             ~
Missing closing '}' in statement block.
At C:\Users\Me\Desktop\BulkNewUsers.ps1:48 char:159
+ ... $accountexpires){
+                    ~
Unexpected token ')' in expression or statement.
At C:\Users\Me\Desktop\BulkNewUsers.ps1:64 char:1
+ }
+ ~
Unexpected token '}' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingEndParenthesisInMethodCall

看起来像是同一个错误代码?
请参阅下面的CSV记事本格式:

FirstName,LastName,Username,Email,Password,Telephone,JobTitle,AccountExpires,OU
Test1,Test2,TTesting1,Testing1@email.co.uk,V6DyG3H7a,4.47723E+11,This is a Test 1,11/17/2023 2:22:48 PM,"CN=Users,DC=my,DC=domain,DC=net"
Test3,Test4,TTesting2,Testing2@email.co.uk,438MXn8D5,4.47723E+11,This is a Test 2,0,"CN=Users,DC=my,DC=domain,DC=net"

更新3

我照你说的做了

$accountexpires = (Get-Date)  
[datetime]::TryParseExact('11/17/2023 2:22:48 PM', 'MM/dd/yyyy h:mm:ss tt', [cultureinfo]'en-US', 'None',[ref]$accountexpires)

这在PowerShell中返回“true”。
奇怪的是,你提到了非打印字符,因为我们有一个问题,从MS SharePoint复制文本到记事本,然后到AD -这将包含特殊的隐藏字符,来克服这一点(懒惰)我,而不是复制到从微软SharePoint到微软Word,然后到广告,其中固定的特殊隐藏字符(为了查看特殊隐藏字符,我们对文本执行了“ASCII到十六进制”的转换,然后返回到“十六进制到ASCII”,这将显示特殊隐藏字符)
我做了你问我在记事本领域的双引号之间的变化,并重新键入到期日期,这解决了问题!到期日期显示在新创建的用户。
谢谢!!!
现在,我试图添加广告组和它半失败(我猜他们包含“-”和“_”在那里的名称的广告组的命名约定)
请参阅以下记事本格式的新CSV:

FirstName,LastName,Username,Email,Password,Telephone,JobTitle,AccountExpires,OU,ADGroups
"Test1","Test2","TTesting1","Testing1@email.co.uk","V6DyG3H7a","447723000000","This is a Test 1","11/17/2023 2:22:48 PM","CN=Users,DC=my,DC=domain,DC=net","ADGroupName1;AD_Group_Name_2;AD-Group-Name-3;"
"Test3","Test4","TTesting2","Testing2@email.co.uk","438MXn8D5","447723000001","This is a Test 2","0","CN=Users,DC=my,DC=domain,DC=net""ADGroupName1;AD_Group_Name_2;"

我在下面使用的代码:

# Store the data from NewUsersFinal.csv in the $ADUsers variable
$ADUsers = Import-Csv -Path 'C:\temp\NewUsersSent.csv'

# Define UPN
$UPN = "my.domain.net"

# Loop through each row containing user details in the CSV file
foreach ($User in $ADUsers) {
    # Read some user data from each field in each row and assign the data to a variable as below
    $username = $User.username

    # Check to see if the user already exists in AD
    if (Get-ADUser -Filter "SamAccountName -eq '$username'") {
        # If user does exist, give a warning
        Write-Warning "A user account with username $username already exists in Active Directory."
        continue  # skip this one and proceed with the next user
    }

    # 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

    # create some convenience variables from the csv data as these are used more than once
    $firstname      = $User.firstname
    $lastname       = $User.lastname
    $telephone      = $User.telephone

    # create a splatting Hashtable for the New-ADUser cmdlet
    $userParams = @{
        SamAccountName        = $username
        UserPrincipalName     = "$username@$UPN"
        Name                  = "$firstname $lastname"
        GivenName             = $firstname
        Surname               = $lastname
        Enabled               = $true
        DisplayName           = "$lastname, $firstname"
        Path                  = $User.ou
        OfficePhone           = $telephone
        MobilePhone           = $telephone
        HomePhone             = $telephone
        EmailAddress          = $User.email
        Description           = $User.jobtitle
        AccountPassword       = (ConvertTo-secureString $User.password -AsPlainText -Force)
        ChangePasswordAtLogon = $false
        PasswordNeverExpires  = $true
    }

    # see if we can get a valid DateTime from the csv field 'accountexpires'
    $accountexpires = (Get-Date)
    if ([datetime]::TryParseExact($User.accountexpires, 'MM/dd/yyyy h:mm:ss tt', [cultureinfo]'en-US', 'None',[ref]$accountexpires)) {
        # this user does have an account expiration date, so add it to the Hash
        $userParams['AccountExpirationDate'] = $accountexpires
    }
    # create the user (PassThru makes the cmdlet return the user object just created)
    $newUser = New-ADUser @userParams -PassThru
    Write-Host "The user account $username is created." -ForegroundColor Cyan

    #####################################################################################
    # If you have a field in the CSV where groups are listed the new user should become
    # a member of (as you said, separated by ;), you can add the user to these groups here:
    
    $User.adgroups -split ';' | Where-Object { $_ -match '\S' } | ForEach-Object {
         Add-ADGroupMember -Identity $_ -Members $newUser
     }

}

当我尝试使用AD组运行代码时,我从PS得到了错误消息:

PS C:\Windows\system32> C:\Users\Me\Desktop\BulkNewUsers.ps1
The user account TTesting1 is created.
New-ADUser : The object name has bad syntax
At C:\Users\Me\Desktop\BulkNewUsers.ps1:54 char:16
+     $newUser = New-ADUser @userParams -PassThru
+                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (CN=Test3 Test4,...AD_Group_Name_2;:String) [New-ADUser], ADException
    + FullyQualifiedErrorId : ActiveDirectoryServer:8335,Microsoft.ActiveDirectory.Management.Commands.NewADUser
 
The user account TTesting2 is created.

奇怪的是,第一个帐户被创建,但第二个没有。
我还必须在代码的$userParams部分定义Groups = $User.ADGroups吗?

更新4

Theo我发现UPDATE 3中的问题是CSV文件中第二个用户的OU字段和AD组字段的双引号之间没有定义“,”:
"CN=Users,DC=my,DC=domain,DC=net""ADGroupName1;AD_Group_Name_2;"
变更为:
"CN=Users,DC=my,DC=domain,DC=net","ADGroupName1;AD_Group_Name_2;"
这解决了问题!

9ceoxa92

9ceoxa921#

这里的主要问题是,当创建一个永远不会过期的用户时,不应该设置AccountExpirationDate。否则,应该使用有效的DateTime对象来设置过期日期和时间。(如果没有指定时间,则假定时间为本地时间12:00:00 AM。)
您的代码使用讨厌的反引号将New-ADUser的参数分隔在新的一行中,但更好的方法是在需要大量参数的cmdlet上使用Splatting
这样,代码就很容易阅读/维护,另外,您可以根据条件添加或省略某些参数,例如本例中的AccountExpirationDate
也请阅读底部的注解代码,以展示如何将新用户添加到组中。

# Store the data from NewUsersFinal.csv in the $ADUsers variable
$ADUsers = Import-Csv -Path 'C:\temp\NewUsersSent.csv'

# Define UPN
$UPN = "my.domain.net"

# Loop through each row containing user details in the CSV file
foreach ($User in $ADUsers) {
    # Read some user data from each field in each row and assign the data to a variable as below
    $username = $User.username

    # Check to see if the user already exists in AD
    if (Get-ADUser -Filter "SamAccountName -eq '$username'") {
        # If user does exist, give a warning
        Write-Warning "A user account with username $username already exists in Active Directory."
        continue  # skip this one and proceed with the next user
    }

    # 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

    # create some convenience variables from the csv data as these are used more than once
    $firstname      = $User.firstname
    $lastname       = $User.lastname
    $telephone      = $User.telephone

    # create a splatting Hashtable for the New-ADUser cmdlet
    $userParams = @{
        SamAccountName        = $username
        UserPrincipalName     = "$username@$UPN"
        Name                  = "$firstname $lastname"
        GivenName             = $firstname
        Surname               = $lastname
        Enabled               = $true
        DisplayName           = "$lastname, $firstname"
        Path                  = $User.ou
        OfficePhone           = $telephone
        MobilePhone           = $telephone
        HomePhone             = $telephone
        EmailAddress          = $User.email
        Description           = $User.jobtitle
        AccountPassword       = (ConvertTo-secureString $User.password -AsPlainText -Force)
        ChangePasswordAtLogon = $false
        PasswordNeverExpires  = $true
    }

    # see if we can get a valid DateTime from the csv field 'accountexpires'
    $accountexpires = (Get-Date)
    if ([datetime]::TryParse($User.accountexpires, [ref]$accountexpires)) {
        # this user does have an account expiration date, so add it to the Hash
        $userParams['AccountExpirationDate'] = $accountexpires
    }
    # create the user (PassThru makes the cmdlet return the user object just created)
    $newUser = New-ADUser @userParams -PassThru
    Write-Host "The user account $username is created." -ForegroundColor Cyan

    #####################################################################################
    # If you have a field in the CSV where groups are listed the new user should become
    # a member of (as you said, separated by ;), you can add the user to these groups here:

    # $User.groups -split ';' | Where-Object { $_ -match '\S' } | ForEach-Object {
    #     Add-ADGroupMember -Identity $_ -Members $newUser
    # }

}

除了使用[datetime]::TryParse(),您还可以使用[datetime]::TryParseExact()方法,具体取决于您如何格式化csv文件中的日期。
如果您使用这种英语12小时制时钟格式,[datetime]::TryParseExact($User.accountexpires, 'MM/dd/yyyy h:mm:ss tt', [cultureinfo]'en-US', 'None',[ref]$accountexpires)可以工作。
您可以在PowerShell中使用

$accountexpires = (Get-Date)  
[datetime]::TryParseExact('11/17/2023 2:22:48 PM', 'MM/dd/yyyy h:mm:ss tt', [cultureinfo]'en-US', 'None',[ref]$accountexpires)

返回True
如果返回False,那么要么是日期模式不匹配,要么是日期字符串被不可见的控制字符搞得一团糟。在这种情况下,手动重新输入日期并再次测试。

相关问题