使用powershell

时间:2017-04-24 08:32:20

标签: powershell csv

对于一个小项目,我想从一个小的CSV文件创建AD用户。我创建了每隔几分钟运行一次的作业(PowerShell脚本),根据我在脚本中定义的用户的状态来选择用户创建。每个例子;在AD中创建用户时,我将状态更改为addmailbox。然后另一个工作将来添加邮箱。

一切进展顺利,但我发现了一个错误。我在CSV文件中编辑状态的方式是错误的,因为当我只想更改CSV文件时,我会更改CSV中所有用户的状态。但我似乎无法使用任何其他方法。

#When encountering any error, stop the script.
$ErrorActionPreference = "Stop";

#Check if there is a data file.
$FileExists = Test-Path C:\inetpub\wwwroot\melle\data.csv

if($FileExists -eq $true) {
    $Users = Import-Csv -Path "C:\inetpub\wwwroot\melle\data.csv"
    foreach ($user in $Users) {
        $Status = $User.Status;
        $userPrincipalName = $User.userPrincipalName;
        $SAMAccountName = $User.SAMAccountName;
        $userInstance =  $User.userInstance;
        $Name = $User.Name;
        $displayName = $User.DisplayName;
        $Path = '"' + $User.Path + '"';
        $GivenName = $User.GivenName;
        $Surname = $User.Surname;
        $SIP = $userPrincipalName;

        if ($Status -eq "CreateUser") {
            try {
                #create user
                Import-Module ActiveDirectory; 
                New-ADUser -SAMAccountName $SAMAccountName -Instance $userInstance -Name $name -DisplayName $displayName -Path "correct.path.com" -GivenName $givenname -Surname $surname -userPrincipalName $userprincipalname -AccountPassword (ConvertTo-SecureString -String "bla" -AsPlainText -Force) -PassThru | Enable-ADAccount;

                #change status
                (Get-Content  C:\inetpub\wwwroot\melle\data.csv) | Foreach-Object {$_ -replace 'CreateUser','AddMailbox'}  | Out-File  C:\inetpub\wwwroot\melle\data.csv

                #exit on completion
                Exit(Write-Host 'User was created in AD.');
            } Catch {
                #write any errors to error log.
                $_ | Out-File C:\inetpub\wwwroot\melle\errors.log -Append;
            }
        } else {
            Exit(Write-Host 'No user with status CreateUser was found.');
        }
    }
}else {
    Exit(Write-Host 'No data.csv file was found.');
}

我现在的方式是(Get-Content C:\inetpub\wwwroot\melle\data.csv) | Foreach-Object {$_ -replace 'CreateUser','AddMailbox'} | Out-File C:\inetpub\wwwroot\melle\data.csv,但我想只为脚本在foreach中与之交谈的行定义它。

我尝试在这里和不同的网站上搜索解决方案,但我无法获得其他人用来处理我的脚本的解决方案。有些脚本太先进了,我无法理解。

只更改我在循环中处理的行的状态的正确方法是什么?

更新:已解决 工作脚本:

#Check if there is a data file.
$FileExists = Test-Path C:\inetpub\wwwroot\melle\data.csv

if($FileExists -eq $true) {
$Users = Import-Csv -Path "C:\inetpub\wwwroot\melle\data.csv"

$UsersThatNeedToBeCreated = $Users | Where-Object {$_.Status -eq 'CreateUser'};

# Check that we have users that need to be created, might need fine-tuning.
if($UsersThatNeedToBeCreated -eq $null -or $UsersThatNeedToBeCreated.Count -eq 0){
    # Write-Host doesn't have a meaningful return code, so you can separate those lines.

    Exit(Write-Host 'No user with status CreateUser was found.');
}else{
    # This way it's only run once
    Import-Module ActiveDirectory; 
}

$Users | ForEach-Object {
    if($_.Status -eq 'CreateUser'){
        try {
            #create user
            New-ADUser -SAMAccountName $_.SAMAccountName -Instance "'" + $_.userInstance + "'" -Name $_.name -DisplayName $_.displayName -Path "working.path.here" -GivenName $_.givenname -Surname $_.surname -userPrincipalName $_.userprincipalname -AccountPassword (ConvertTo-SecureString -String "Welcome01" -AsPlainText -Force) -PassThru | Enable-ADAccount;

            #change status
            $_.Status = 'AddMailbox';
        } Catch {
            #write any errors to error log.
            $_ | Out-File C:\inetpub\wwwroot\melle\errors.log -Append;
        }
    }
}

$Users | ConvertTo-Csv | Out-File 'C:\inetpub\wwwroot\melle\data.csv'


Exit(Write-Host 'User was created in AD.');
}else {

Exit(Write-Host 'No data.csv file was found.');
}

1 个答案:

答案 0 :(得分:1)

正如您已经注意到的,您当前的方法不起作用。您正在抓取CSV的全部内容并替换每个实例。 Import-Csv语句实际上为您提供了一个允许您更改值的数据结构。你只需要在之后写回来。

这种方法仍然容易出错,你会遇到问题。如果我正确理解你,你想要跟踪状态,并有多个脚本做不同的事情。迟早您会遇到由于竞争访问请求而覆盖彼此更改和/或锁定的情况。如果你想这样做,你应该考虑使用支持基于行的锁定的数据库(最有可能)。否则,您将需要找到一种方法使它们顺序运行或自己实现基于行的锁定。

尽管如此,一种可能的解决方案可能如下所示。我没有运行它,但基本结构应该是正确的。用于覆盖更改的示例将是创建邮箱所花费的时间。由于文件只在脚本开头读取并在结尾写入,因此可能会在两者之间发生变化。

#When encountering any error, stop the script.
$ErrorActionPreference = "Stop";

#Check if there is a data file.
$FileExists = Test-Path C:\inetpub\wwwroot\melle\data.csv

if($FileExists -eq $true) {
    $Users = Import-Csv -Path "C:\inetpub\wwwroot\melle\data.csv"

    $UsersThatNeedToBeCreated = $Users | Where-Object {$_.Status -eq 'CreateUser'};

    # Check that we have users that need to be created, might need fine-tuning.
    if($$UsersThatNeedToBeCreated -eq $null -or $UsersThatNeedToBeCreated.Count -eq 0){
        # Write-Host doesn't have a meaningful return code, so you can separate those lines.
        Write-Host 'No user with status CreateUser was found.'
        Exit;
    }else{
        # This way it's only run once
        Import-Module ActiveDirectory; 
    }

    $Users | ForEach-Object {
        $Status = $User.Status;
        $userPrincipalName = $User.userPrincipalName;
        $SAMAccountName = $User.SAMAccountName;
        $userInstance =  $User.userInstance;
        $Name = $User.Name;
        $displayName = $User.DisplayName;
        $Path = '"' + $User.Path + '"';
        $GivenName = $User.GivenName;
        $Surname = $User.Surname;
        $SIP = $userPrincipalName;

        if($_.Status -eq 'CreateUser'){
            try {
                #create user
                New-ADUser -SAMAccountName $SAMAccountName -Instance $userInstance -Name $name -DisplayName $displayName -Path "correct.path.com" -GivenName $givenname -Surname $surname -userPrincipalName $userprincipalname -AccountPassword (ConvertTo-SecureString -String "bla" -AsPlainText -Force) -PassThru | Enable-ADAccount;

                # change status
                $_.Status = 'AddMailbox';
            } Catch {
                # write any errors to error log.
                $_ | Out-File C:\inetpub\wwwroot\melle\errors.log -Append;
            }
        }
    }

    $Users | ConvertTo-Csv -NoTypeInformation | Out-File 'C:\inetpub\wwwroot\melle\data.csv'

    Write-Host 'User was created in AD.'
    Exit
}else {
    Write-Host 'No data.csv file was found.'
    Exit
}