2017-04-24 133 views
1

對於一個小項目,我想從一個小的CSV文件創建AD用戶。我做了每幾分鐘運行一次的作業(PowerShell腳本),以根據我在腳本中定義的用戶的狀態來提取用戶創建。每個例子;當在AD中創建用戶時,我將狀態更改爲addmailbox。然後,另一項工作將會添加郵箱。使用powershell編輯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交談行。

我試過在這裏和不同的網站上搜索解決方案,但我無法獲得其他人用於處理腳本的解決方案。有些腳本太高級了,我無法理解。

什麼是正確的方法來改變我正在循環中工作的線的狀態?

UPDATE:解決 工作腳本:

#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

正如你已經注意到了,你目前的做法是行不通的。您抓取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 
} 
+0

嗨塞斯,感謝您的幫助。我喜歡您所做的更改,但CSV中的狀態不會以這種方式更改。它保持不變。另外,你不能使用Exit(); ()中沒有任何表達式,我注意到了。 CSV文件插入了這一行:'#TYPE System.Management.Automation.PSCustomObject'。並且用戶沒有創建,但我注意到我在腳本中使用的變量不再存在,所以我將再次定義這些變量。 –

+0

對不起,我專注於改變狀態。你應該能夠在沒有括號的情況下運行'Exit'。猜測你的實際目標有點難。寫主機將寫入一個實際的控制檯,並不容易被重定向。另外,通過使用圓括號調用'Exit',您可能(可能)從'Write-Host'中返回空的結果,這對於您來說並不會有任何幫助。 – Seth

+0

你是對的,事情是我不需要去捕捉那些錯誤,我只想讓腳本退出到他們身上。我想記錄的唯一錯誤是如果在正在工作的命令中出現任何錯誤。我做了一些小的改變,並使其工作。非常感謝!我將用更新後的腳本編輯我的帖子。 –