使用powershell编辑CSV值
对于一个小项目,我想从一个小的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.');
}
正如你已经注意到了,你目前的做法是行不通的。您抓取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
}
嗨塞斯,感谢您的帮助。我喜欢您所做的更改,但CSV中的状态不会以这种方式更改。它保持不变。另外,你不能使用Exit(); ()中没有任何表达式,我注意到了。 CSV文件插入了这一行:'#TYPE System.Management.Automation.PSCustomObject'。并且用户没有创建,但我注意到我在脚本中使用的变量不再存在,所以我将再次定义这些变量。 –
对不起,我专注于改变状态。你应该能够在没有括号的情况下运行'Exit'。猜测你的实际目标有点难。写主机将写入一个实际的控制台,并不容易被重定向。另外,通过使用圆括号调用'Exit',您可能(可能)从'Write-Host'中返回空的结果,这对于您来说并不会有任何帮助。 – Seth
你是对的,事情是我不需要去捕捉那些错误,我只想让脚本退出到他们身上。我想记录的唯一错误是如果在正在工作的命令中出现任何错误。我做了一些小的改变,并使其工作。非常感谢!我将用更新后的脚本编辑我的帖子。 –