2016-08-24 14 views
0

次のコードは、自分の環境内のすべてのコントローラにクエリを送信し、最新のログインタイムスタンプを取得していることを確認します。それは私が働いている奇妙なユーザーのためのデータを取得するのに最適です。しかし、私はADで800人以上のユーザーを評価する必要があることを見出しています。 これは1.5GBを食べてから終了し、メモリ不足のエラーでスクリプトをクラッシュさせます。関数が終了した後にメモリを再利用する方法やガベージコレクションを強制する方法はありますか?私は可変変数や他のバリアントを削除しようとしました。私は時々システムのガベージコレクションを無駄にしようとしました。複数のユーザーの最後のログオンタイムスタンプを取得

私の推測はすべてのADクエリです。私が完了したら、それらをどう対処するかわかりません。

この関数の呼び出しは、関数呼び出しの前にプルしたリストから各ユーザーを送信しているforeachループの内部からのものです。私が得ることができる助けのために前もってありがとう。

$ domain変数、ちょうどそれが "example.contoso.ca"

function getDateTimeStamp 
{ 
    param 
    (
    [string]$userID, 

    [string]$domain, 

    [string]$attribute #this is an AD attribute in this case i used "lastlogon" 
) 
$domainSuffix = '*.'+$domain 
    $myForest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() 
    $domaincontrollers = $myForest.Sites | % { $_.Servers } | Select-Object Name | Where-Object Name -like $domainSuffix 
    $realUserDate = $null 
    foreach ($domainController in $domainControllers) 
    { 
     $userDateTime = Get-ADUser -Identity $userID -Properties $attribute -Server $domainController.Name 
     $userLastDateTime = $userDateTime.$attribute 
     if($userLastDateTime -eq $null){$userLastDateTime = 0} 
     elseif($userLastDateTime -eq 9223372036854775807){$userLastDateTime = 0} 
     if($userLastDateTime -is 'DateTime'){$tempUserDate = get-date -Date ($userLastDateTime)} 
     else{$tempUserDate = [DateTime]::FromFileTime([Int64]::Parse($userLastDateTime))} 
     if ($realUserDate -le $tempUserDate){$realUserDate = $tempUserDate} 
    } 
    return $realUserDate 
} 
+0

ここに私の答えを参照してくださいが、foreachの-オブジェクトを試してみてください http://superuser.com/questions/675484/why-does-foreach-object-behave-differently-when-called-as-foreach –

+0

I foreachを試しました($ x $ items) と私は$ items | foreach-object {} もリストの中で働いていませんでした。 – icomeinpieces

+0

'$ attribute'をどこで定義したかわかりません。 '$ attribute'にLastLogonDateを使うと、' [Int64] 'を' [DateTime] 'に変換する必要はありません。また、正確なLastLogonが必要ですか、LastLogonTimestampを使用できますか?それは複製され、私が信じる11日以内に正確です。 – TheMadTechnician

答えて

0

だけで簡単にポスト、お急ぎのビットであるふりをします。これは、関数処理をパイプライン化する方法の例です。パイプライン上で動作する場合、割り当てられたメモリはほとんど必要ありません。

function Get-ADDateTime 
{ 
    param 
    (
     [Parameter(ValueFromPipelineByPropertyName = $true)] 
     [Alias('SamAccountName')] 
     [string]$userID, 

     [Parameter(Mandatory = $true)] 
     [string]$domain, 

     [Parameter(Mandatory = $true)] 
     [string]$attribute 
    ) 

    begin { 
     $domainSuffix = '*.'+$domain 
     $myForest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() 
     $domaincontrollers = $myForest.Sites.Servers | Where-Object Name -like $domainSuffix 
    } 

    process { 
     # Pick an epoch, any epoch 
     $date = Get-Date '01/01/1601' 
     foreach ($domainController in $domainControllers) 
     { 
      $adUser = Get-ADUser -Identity $userID -Properties $attribute -Server $domainController.Name 
      if ($adUser.$attribute -notin $null, 9223372036854775807, 0) { 
       if ($adUser.$attribute -is [DateTime]) { 
        $thisDate = $adUser.$attribute 
       } else { 
        $thisDate = [DateTime]::FromFileTime([Int64]::Parse($adUser.$attribute)) 
       } 

       if ($thisDate -gt $date) { 
        $date = $thisDate 
       } 
      } 
     } 
     if ($date -eq (Get-Date '01/01/1601')) { $date = $null } 

     [PSCustomObject]@{ 
      UserID = $UserID 
      LastLogon = $date 
     } 
    } 
} 

Get-ADUser | Get-ADDateTime -Attribute $lastLogon -Domain 'domain'