获取特定日期之后创建的所有 AD 计算机

Leo*_*res 5 powershell powershell-5.1

我创建了下面的脚本来查找自特定日期以来创建的所有 Unix 计算机。它不会返回错误,但也不起作用。脚本中仅使用一个日期,但两种格式具有相同的结果。

两种日期格式都不会失败,但它们不会返回任何内容——查询只是显示为正在运行,但从不返回任何数据:

$SomeDate1 = 'Wednesday, November 7, 2018 2:41:59 PM'
$SomeDate2 = '2018-11-07 14:41:59.000'

Get-ADComputer -Filter '*' -Properties *  | Where {$($PSitem.CanonicalName) -like '*Unix*'  -and  $($PSitem.whenCreated) -gt $SomeDate1 } |` 
        Select Name,OperatingSystem,OperatingSystemVersion,ipv4Address,Created,whenCreated,Deleted,whenChanged,Modified,Description,@{Label="ServicePrincipalNames";Expression={$_.ServicePrincipalNames -join ";" }},DisplayName,Location,DistinguishedName,DNSHostName 
Run Code Online (Sandbox Code Playgroud)

Ben*_*est 7

使用-Filter参数来执行此操作,但我们需要做一些跑腿工作来获取适合 的格式的日期whenCreated,因为它在 AD 架构中的定义与其他一些“日期”类型属性不同。下面的代码可以工作,解释如下:

注意:-Properties *我在下面简要提到它,但如果你能控制它,你就不想这样做。返回对象的所有静态属性可能会对您所访问的 DC 造成过度负载。仅指定您要返回的属性。有关更详细的解释,请参阅此答案底部的链接答案。


# Create a yyyMMddHHmmss.Z formatted date string in UTC
$SomeDate1= ( Get-Date 'Wednesday, November 7, 2018 2:41:59 PM' ).ToUniversalTime().ToString('yyyMMddHHmmss.Z')

# These are the properties we both want to return from AD and include in the final output
$propertiesToReturn =
  "Name",
  "OperatingSystem",
  "OperatingSystemVersion",
  "ipv4Address",
  "Created",
  "whenCreated",
  "Deleted",
  "whenChanged",
  "Modified",
  "Description",
  "DisplayName",
  "Location",
  "DistinguishedName",
  "DNSHostName"

# These are properties we need from AD but are not required directly in the final output
$additionalProperties =
  "CanonicalName",
  "ServicePrincipalNames"

# Define the computed property here for clarity
$spnComputedProperty = @{
  Label = "ServicePrincipalNames";
  Expression = {
    $_.ServicePrincipalNames -join ";"
  } 
}

# Obtain the target computer list and apply your select-object expression to it
Get-ADComputer -Filter "whenCreated -gt '${SomeDate1}'" -Properties ( $propertiesToReturn + $additionalProperties ) | Where-Object {
  $_.CanonicalName -match 'Unix'
} | Select-Object ( $propertiesToReturn + $spnComputedProperty )

Run Code Online (Sandbox Code Playgroud)

现在,这里有很多变化,所以我将解释我所做的事情以及原因:


新变量和对现有变量的更改

  • 我省略了$SomeDate2,因为在您的代码示例中没有引用它。
  • $SomeDate1Interval与其他日期类型属性(例如LastLogonDate. 相反,它以UTC格式定义为通用时间字符串yyyMMddHHmmss.Z,因此我们需要以这种方式格式化的时间戳,而不是依赖ToString()[DateTime]. 如果我们不这样做,日期比较将不起作用。这很令人困惑,因为 RSAT AD Cmdlet会将其(以及其他通用时间字符串)转换为本地化DateTime字符串,以便最终返回数据时更容易进行 PowerShell 处理。
    • 请注意,yyyMMddHHmmss.Z不能直接转换回DateTime对象以在其他地方使用。
  • 为了清楚起见,我定义了从数组返回的通用属性Get-ADComputer
    Select-Object并定义了另一个数组,其中包含我们只想从 AD 返回以进行进一步处理的元素。它们分别是$propertiesToReturn$additionalProperties。这使我们不必在多个地方重新定义这些属性,并允许我们避免昂贵的
    -Properties *调用。
    • ServicePrincipalNames包含在下面是$additionalProperties因为您要将属性值转换为字符串,因此我们不想将其原始值包含在 中Select-Object
    • CanonicalName是一个计算属性,不能在 或 中进行-Filter过滤
      -LDAPFilter。我们必须在本地返回并处理该属性,即使您不希望它出现在最终输出中。
    • 不管怎样都会返回下面定义的一些属性名称$propertiesToReturn,但将它们包含在数组中也没有坏处-Properties
  • 另外为了清楚起见,我将您的计算属性定义为Select-Object变量$spnComputedProperty。这可以在单行上,但为了便于阅读,我在这里将其设置为多行。

Get-ADComputer用适当的方式调用-Filter

现在我们的属性数组和日期字符串格式正确,我们终于可以调用
Get-ADComputer.

  • 我们可以使用"whenCreated -gt '${SomeDate1}'"过滤字符串(不要使用with ScriptBlock-Filter来返回ADComputers之后创建的所有内容$SomeDate1
  • 通常我不建议使用连接字符串或数组+,但这是一个方便的例外,不太可能导致内存问题。因为Get-ADComputer -Properties我们提供$propertiesToReturn$additionalProperties作为单个数组。
    • 尝试使用该语法-Properties $propertiesToReturn, $additionalProperties将导致类型不匹配错误。
  • 我已将您的Where-Object条款简化为仅进一步过滤CanonicalName. 如上所述,CanonicalName是一个计算属性,不能使用
    -Filteror进行过滤-LDAPFilter,必须在此处完成。
    • 我还更改-like并从(技术上正则表达式)表达式中-match删除了 the ,但如果您愿意,您可以将原始子句与 glob 一起使用。*-like
  • Select-Object最后,我们像之前一样将结果通过管道传递给,并执行与 相同的串联技巧Get-ADComputer -Properties。不过,这次我们$spnComputedProperty改为添加。

这应该为您提供在 中指定的日期之后创建的所有属性ADComputers以及您想要的属性,包括自定义字段。$SomeDate1UnixCanonicalNameServicePrincipalNames


关于避免将目标转换DateTime通用时间格式的注意事项

从技术上讲,您可以使用以下任一过滤器来避免需要转换DateTime为使用通用时间格式:

Get-ADComputer -Filter 'whenCreated -lt $SomeDate1'

# Double-quoted variant is useful if you have other variables which
# should be directly rendered as part of the -Filter string
Get-ADComputer -Filter "whenCreated -lt `$SomeDate1"
Run Code Online (Sandbox Code Playgroud)

我避免提及这一点的原因是因为这种行为没有得到很好的理解或记录。cmdlet 会使用一些魔法来获取变量值,即使它不应该被呈现,因为它是文字字符串。由于人们对其了解甚少,并且不清楚什么规则集定义了如何DateTime转换(例如,每个属性和类型的规则是否会更改,是否DateTimes总是转换为通用时间字符串?我们不知道)我不推荐这种方法。

AD Schema 文档中详细记录了的行为whenCreated,如果我从一开始就查阅这些内容,就会清楚需要如何-Filter设计,而不是为了理解比较问题而进行的反复试验。文档链接如下。


其他资源

如果您在 AD 属性上遇到奇怪的行为,无法正确过滤,或者您只是想了解有关不同属性的更多信息,我建议您在OpenSpecsAD Schema文档中查找该属性。

另外,请参阅我的这个答案,其中详细介绍了-FilterRSAT AD cmdlet 上的参数。