好的。这就是我想要做的。我基本上是试图通过从AD和SQL数据库导入内容在powershell中制作2D数组。稍后,我将在脚本中使用数组写入,更新和删除数据库中的行。我遇到的问题是将所有内容都放入一个变量中。
当我运行代码时,它会反复将同一用户添加到所需的数组中。创建到$ Table变量中的最后一项将覆盖$ ToWrite内的每个实例。
在将所有变量输入$ Table之后,将$ Table写入控制台,然后将$ ToWrite写入控制台后,我尝试暂停。 $ Table在每个循环中都正确更改,但是再次写入$ ToWrite后,它将覆盖每个实例。我已经尝试了多种方法,例如.add(),PsCustomObject []等。我现在仍然受困。
这是我的半功能代码:
$AllPOCs = Get-ADGroupMember 'ALL POC'
$POCs = @()
$Counter = 0
$AllPOCs | ForEach-Object {
$Name = $AllPOCs[$Counter].SamAccountName
$TestPOC = Invoke-Sqlcmd -Query "SELECT * FROM TABLE WHERE CLIENT = '$Name'" -ServerInstance "SERVER\INSTANCE"
if ($TestPOC -eq $null) {
$POCs += Get-ADUser $Name -Properties * |
select -Property SamAccountName, GivenName, Surname, SID, EmailAddress
}
$Counter += 1
}
$ToWrite = @()
$Counter = 0
$SEQUENCE = Invoke-Sqlcmd -Query "Select TABLEFIELD FROM DATABASE WHERE NAME = 'FIELDID'" -ServerInstance "SERVER\INSTANCE"
$SEQUENCE = $SEQUENCE.RECNUM + 1
$Table = "" | select SEQUENCE, LASTUSER, GROUP, CLIENT, FNAME, NAME, EMAILID, USEDEPT, USELOCATION, CREATEDFROMSSD, DISPLAYCLIENTCOMMENTS, _INACTIVE_, WINUSERID, SELFSERVICEACCESS, SELFSERVICELICENSE, WIAENABLED, SID
#everything works correctly up to here
$POCs | ForEach-Object {
$Table.SEQUENCE = $SEQUENCE
$Table.LASTUSER = 'SYSTEMACCOUNT'
$Table.GROUP = 1
$Table.CLIENT = $POCs[$Counter].SamAccountName.ToUpper()
$Table.FNAME = $POCs[$Counter].GivenName.ToString()
$Table.Name = $POCs[$Counter].surname.ToString()
$Table.EmailID = 'SMTP:{' + $POCs[$Counter].EmailAddress.ToString() + '}' +
$POCs[$Counter].EmailAddress.ToString()
$Table.USEDEPT = 0
$Table.USELOCATION = 0
$Table.CREATEDFROMSSD = 0
$Table.DISPLAYCLIENTCOMMENTS = 0
$Table._INACTIVE_ = 0
$Table.WINUSERID = '\DOMAIN' + $POCs[$Counter].SamAccountName.ToString()
$Table.SELFSERVICEACCESS = 'TYPE'
$Table.SELFSERVICELICENSE = 1
$Table.WIAENABLED = 1
$Table.SID = $POCs[$Counter].SID.ToString()
$ToWrite += $Table #THIS DOESN'T WORK PROPERLY.
$SEQUENCE += 1
$Counter += 1
}
输出示例:
SEQUENCE : 1206 LASTUSER : SYSTEMACCOUNT GROUP : 1 CLIENT : USERNAME FNAME : FIRSTNAME NAME : LASTNAME EMAILID : SMTP:{EMAIL}EMAIL USEDEPT : 0 USELOCATION : 0 CREATEDFROMSSD : 0 DISPLAYCLIENTCOMMENTS : 0 _INACTIVE_ : 0 WINUSERID : DOMAIN\USERNAME SELFSERVICEACCESS : TYPE SELFSERVICELICENSE : 1 WIAENABLED : 1 SID : S-1-Z-XX-CCCCCCCCCC-YYYYYYYYY-VVVVVVVVVV-125121 SEQUENCE : 1206 LASTUSER : SYSTEMACCOUNT GROUP : 1 CLIENT : USERNAME FNAME : FIRSTNAME NAME : LASTNAME EMAILID : SMTP:{EMAIL}EMAIL USEDEPT : 0 USELOCATION : 0 CREATEDFROMSSD : 0 DISPLAYCLIENTCOMMENTS : 0 _INACTIVE_ : 0 WINUSERID : DOMAIN\USERNAME SELFSERVICEACCESS : TYPE SELFSERVICELICENSE : 1 WIAENABLED : 1 SID : S-1-Z-XX-CCCCCCCCCC-YYYYYYYYY-VVVVVVVVVV-125121 SEQUENCE : 1206 LASTUSER : SYSTEMACCOUNT GROUP : 1 CLIENT : USERNAME FNAME : FIRSTNAME NAME : LASTNAME EMAILID : SMTP:{EMAIL}EMAIL USEDEPT : 0 USELOCATION : 0 CREATEDFROMSSD : 0 DISPLAYCLIENTCOMMENTS : 0 _INACTIVE_ : 0 WINUSERID : DOMAIN\USERNAME SELFSERVICEACCESS : TYPE SELFSERVICELICENSE : 1 WIAENABLED : 1 SID : S-1-Z-XX-CCCCCCCCCC-YYYYYYYYY-VVVVVVVVVV-125121
有什么想法吗?
答案 0 :(得分:1)
问题在于,您要一遍又一遍地更新同一对象$Table
,并将对该对象的引用添加到输出数组$ToWrite
-因此,所有其元素最终都指向一个唯一的$Table
对象,该对象的属性值在该点包含在 last 迭代中分配的那些。
this answer中详细说明了该问题,该问题显示了使用自定义类(在PowerShell v5及更高版本中可用)的可能解决方案。
没有 自定义类的解决方案要求您在每次迭代中 克隆自定义$Table
对象:
# Create a new instance with the same properties:
$Table = $Table.psobject.Copy()
注意:此克隆技术仅对自定义对象有效,即[System.Management.Automation.PSCustomObject]
的实例,例如由Select-Object
创建的实例cmdlet和文字语法[pscustomobject] @{ ... }
也就是说,由于您要在循环中分配自定义对象的 all 个属性,因此预先创建 template 对象没有任何好处-相反,只需在循环内部使用文字自定义对象创建语法[pscustomobject] @{ ... }
(PSv3 +) ,即可隐式创建一个 new 实例在每次迭代中。
此外,您的解决方案可以简化,因为让PowerShell通过为变量创建多个对象的命令收集输出,使PowerShell为您创建数组既简单又有效。。 / p>
这是一个简化的示例,将所有内容放在一起:
# Loop over the input and instantiate a new custom object
# in each iteration, then let PowerShell collect the results
# in array variable $ToWrite
[array] $ToWrite = 1..3 | ForEach-Object {
# Instantiate and output a new custom object in each iteration.
[pscustomobject] @{
PropA = "ValueA-$_"
PropB = "ValueB-$_"
}
}
# Output the resulting array
$ToWrite
注意:仅在需要确保[array]
总是 一个数组时,才需要$ToWrite
类型约束。没有它,如果碰巧只是一个单循环迭代,因此输出对象,$ToWrite
会按原样存储该输出对象,而不是包装在数组中(此行为对于PowerShell的管道)。
上面的代码产生了以下内容,表明创建了不同的对象:
PropA PropB
----- -----
ValueA-1 ValueB-1
ValueA-2 ValueB-2
ValueA-3 ValueB-3
答案 1 :(得分:1)
为了说明-此处需要说明的是,我在家里,所以无法测试其中任何一个,但是它应该给您一个想法:
$AllPOCs = Get-ADGroupMember 'ALL POC'
$Table = $AllPOCs | ForEach-Object {
$Name = $_.SamAccountName
$TestPOC = Invoke-Sqlcmd -Query "SELECT * FROM TABLE WHERE CLIENT = '$Name'" -ServerInstance "SERVER\INSTANCE"
If($TestPOC -eq $null) {
$POC = get-aduser $Name -Properties * | select -Property SamAccountName, GivenName, Surname, SID, EmailAddress
$SEQUENCE = Invoke-Sqlcmd -Query "Select TABLEFIELD FROM DATABASE WHERE NAME = 'FIELDID'" -ServerInstance "SERVER\INSTANCE"
$SEQUENCE = $SEQUENCE.RECNUM + 1
[pscustomobject]@{SEQUENCE = $SEQUENCE;
LASTUSER = 'SYSTEMACCOUNT';
GROUP = 1;
CLIENT = $_.ToUpper();
FNAME = $_.GivenName.ToString();
Name = $_.surname.ToString();
EmailID = 'SMTP:{' + $_.EmailAddress.ToString() + '}' + $_.EmailAddress.ToString();
USEDEPT = 0;
USELOCATION = 0;
CREATEDFROMSSD = 0;
DISPLAYCLIENTCOMMENTS = 0;
_INACTIVE_ = 0;
WINUSERID = '\DOMAIN' + $_.SamAccountName.ToString();
SELFSERVICEACCESS = 'TYPE';
SELFSERVICELICENSE = 1;
WIAENABLED = 1;
SID = $_.SID.ToString()}
$SEQUENCE += 1
}
}
上面的内容也可以简化,但我尝试使其与您的现有代码相似