使用ActiveDirectory cmdlet批量执行Active Directory临时错误

时间:2018-11-26 10:00:51

标签: powershell active-directory

我有一个可以同步数据源中的用户的系统。数据源由用户信息组成。同步新用户时,将触发PowerShell任务,该任务创建或更新用户。一切都很好,但是当新用户/更新用户的数量过多时,某些任务将失败,并出现一些有趣的错误,例如:

  

“服务器已返回以下错误:无效的枚举   上下文。”

  

“与要处理请求的目录的连接为   不可用。这可能是暂时情况。”

进行故障排除时,似乎很明显这些错误发生的原因是资源不足。这是因为所有同时触发的任务都在自己的PS会话上导入模块。

因此,我尝试了一些不同的事情并测量了Import-Module的速度等。因此,我得出结论,例如,运行Import-Module然后运行Get-ADUser更快,然后运行{{1} }(也将导入模块)。

Get-ADUser
  

平均时间340毫秒

Measure-Command {Import-Module ActiveDirectory}
  

平均时间420毫秒

Measure-Command {Get-ADUser -Filter *} 在导入模块后

  

平均时间10毫秒

但是这些边际差异并不能解决这个问题。所以我不得不进一步看。我发现禁用驱动器可能有助于加快此过程,因此在导入模块之前添加了以下内容:

Get-ADUser
  

平均时间85毫秒

快4倍!但是错误仍然在大量用户同时持续存在(例如50个任务)。因此,我考虑过轮询脚本中的可用性,或进行一个$Env:ADPS_LoadDefaultDrive = 0 Measure-Command {Import-Module ActiveDirectory} 循环。或者,可能需要重新设计触发单独任务的系统,以使其具有某种队列。

有人知道这种情况吗?还是他们想就此主题分享一些想法?

1 个答案:

答案 0 :(得分:2)

  

这是因为所有同时触发的任务都在其自己的PS会话上导入模块。

然后,您需要确保不会发生这种情况,或者至少不要那么做,以免耗尽资源。因此,您有两种选择:

  1. 限制一次可以运行的任务数(一次可以运行5个)。
  2. 使它成为一项可以在多个帐户上运行的任务。这样,模块仅加载一次。

我认为选项2是更好的解决方案。例如,同步作业可以立即将用户名写入文件(甚至在内存中),而不是立即触发脚本,一旦找到所有用户,它就会触发PowerShell脚本并传递列表(或脚本)可以读取写入的文件)。您在那里有选择-最好的选择。

更新:所有.NET都可以在PowerShell中使用,因此另一种选择是更改整个脚本以使用.NET的DirectoryEntry而不是ActiveDirectory模块,该模块将减少使用记忆。在PowerShell中甚至还有快捷方式。例如,[ADSI]"LDAP://$distinguishedName"将为用户创建一个DirectoryEntry对象。这是一个实质性的重写,但是性能(速度和内存消耗)要好得多。

以下是使用DirectorySearcher(使用[ADSISearcher]快捷方式)进行搜索的一些示例:https://blogs.technet.microsoft.com/heyscriptingguy/2010/08/23/use-the-directorysearcher-net-class-and-powershell-to-search-active-directory/

下面是使用DirectoryEntry创建帐户的示例:https://www.petri.com/creating-active-directory-user-accounts-adsi-powershell