Übersetzung vorschlagen
 
Andere Vorschläge:

progress indicator
Keine anderen Vorschläge
TechNet Magazine > Home > Alle Ausgaben > 2009 > TechNet Magazine Oktober 2009 >  Windows PowerShell: Doppelte Benutzernamen
Inhalt anzeigen:  Englisch mit deutscher ÜbersetzungInhalt anzeigen: Englisch mit deutscher Übersetzung
Dies sind maschinell übersetzte Inhalte, die von den Mitgliedern der Community bearbeitet werden können. Sie können die Übersetzung verbessern, indem Sie auf den jeweils zum Satz gehörenden Link "Bearbeiten" klicken.Mithilfe des Dropdown-Steuerelements "Inhalt anzeigen" links oben auf der Seite können Sie zudem bestimmen, ob nur der englische Originaltext, nur die deutsche Übersetzung oder beides nebeneinander angezeigt werden.
Windows PowerShell Planning to Break
Don Jones


Recently, I wrote a four-part series in this column that focused on writing a user-provisioning script using Windows PowerShell. One reader, Jim, wrote to ask a pretty detailed question about how to improve the script.
Essentially, Jim has written similar scripts in the past and struggled with ways to handle the errors that occur when you're trying to create a username that already exists. His solution has been to write a "pre-test loop," where he checks to see whether the directory objects already exist before proceeding, but he wanted to know how I'd deal with it in my provisioning script's Provision() function.
It's a great question—and one that I'll answer in this column. Bear in mind, though, that the techniques I'll discuss are pretty universal; you might use similar approaches to deal with other situations where you know that an error can occur. I call my approach "planning to break," and it's how I write scripts that handle potential error conditions a bit more gracefully.

By All Means, Check First
I definitely agree with Jim's approach as a preferred technique. Jim said, "I hate writing error handling," and I tend to agree. Windows PowerShell v1's error handling is a bit primitive for my tastes, so if I can avoid the error entirely, I'll do so.
Let me say first that there are probably an infinite number of variations on my approach, but a finite number of pages for me to work with here, so I'll take just one variation. My basic goal is to detect any user accounts that already exist, and to log them rather than trying to create them a second time. To refresh your memory, the basic Provision() function might look like this:
Function Provision {
  PROCESS {
    CreateUser $_
    CreateHomeFolder $_
    AddToGroups $_
    UpdateAttributes $_
  }
}
The Provision function is expecting pipeline input from a second function whose job it is to import user data from someplace (such as a database or .CSV file) and construct a standardized hash table containing the new user's attributes. So $_['samaccountname'], for example, would contain the user's log-on name. Given that username—which is about the only guaranteed-unique information that I have for a user—I can try to see whether the account already exists. The easiest way is to utilize the Get-QADUser cmdlet (available in the cmdlet package at quest.com/powershell), so I'll modify the Provision function as shown in Figure 1.
Function Provision {
  PROCESS {
    $count = Get-QADUser –samAccountName $_['samaccountname'] | Measure-Object
    if ($count.count –gt 0) {
      $_['samaccountname'] | Out-File c:\not-created.txt -append
    } else {

      CreateUser $_
      CreateHomeFolder $_
      AddToGroups $_
      UpdateAttributes $_
  }
  }
}
The modification attempts to retrieve the specified user from the directory and then measure the number of objects retrieved. The measurement object goes into the $count variable, which offers a Count property ($count.count). If the count is more than zero, then the user exists and I use Out-File to pass the username to a log file. If the user doesn't exist, however, then $count will be populated with nothing, and its Count property will not be more than zero—so I proceed with the provisioning.
This approach—checking one user at a time—is the only feasible one given the way the Provision function is built. That's because its PROCESS script block only gets a single user at a time; there's no way to do a "pre-loop" to check all the users first. There's really no need, though, because checking one at a time doesn't significantly alter the performance.
An advantage to this approach over the next one I'll present is that the error-checking—seeing whether the user already exists—is done up-front. In fact, that's the only really viable approach here because the Provision function calls on other functions after attempting to create the user. If I added error-checking to only the Create­User function, the other three—CreateHomeFolder, AddToGroups and UpdateAttributes—might still try to execute.

Or Just Deal with It
But, in general, another valid approach is to attempt to trap the error. Error-trapping in Windows PowerShell v1 is a bit tricky, but it works something like this:
  • You must tell the cmdlet that might run into an error to generate an actual exception, not just print a red error message
  • You must define a trap, where you'll deal with the consequences of the error
I can actually make this sophisticated enough to work with the Provision function. The work starts, however, in the CreateUser function. Somewhere in there is a cmdlet that attempts to create a new user—either New-QADUser, or the New-Mailbox cmdlet if you're using Exchange Server 2007 to create users and mailboxes all at once. In either case, you add the –ErrorAction (or –EA) parameter to tell the cmdlet to change its default error behavior.
You also have to define a trap, which is where the shell will go when an exception actually occurs. The changes to the CreateUser function might look something like this:
Function CreateUser {
  Param ($userinfo)
  Trap {
    $userinfo['samaccountname'] | Out-File c:\errors.txt -append
    break
  }
  New-Mailbox . . . -EA Stop
}
I've omitted the rest of the syntax for New-Mailbox just to make this illustration clearer. Essentially, if New-Mailbox fails, the –EA parameter tells it to stop and throws an exception. This forces the shell to look for an already-defined trap and execute it. In that trap, I log the username to a file and then execute a break, which exits the current function and passes the original error back to whatever called this function. In other words, the Provision function will end up with the error.
To keep Provision from executing the other three functions, I need to modify the way it executes them (see Figure 2).
Function Provision {
  PROCESS {
    $go = $true
    trap {
      $go = $false
      continue
    }
    CreateUser $_
    If ($go) {
      CreateHomeFolder $_
      AddToGroups $_
      UpdateAttributes $_
    }
  }
}
As you can see, I've defined another trap. If CreateUser ends with an error, then the trap here in Provision will execute. It simply sets a variable, $go, to the Boolean value False, and instructs the shell to continue—meaning to continue execution on the line following the one that caused the error. That line is an "If" statement, which checks to see if $go contains $True or not. If it does, then the remaining three functions execute; if $go contains $False, those three functions do not execute. I reset that value of $go at the top of the PROCESS scriptblock so that the next user will be attempted.
The reason I used this particular approach (versus any number of others I might have chosen) is that it allows me to have additional code that executes even if the user creation failed (see Figure 3).
Function Provision {
  PROCESS {
    $go = $true
    trap {
      $go = $false
      continue
    }
    CreateUser $_
    If ($go) {
      CreateHomeFolder $_
      AddToGroups $_
      UpdateAttributes $_
    }
    OutputToHTML $_
  }
}
In the variation shown, I've added a call to a function named OutputToHTML. This will execute even if the current user already existed and CreateHomeFolder, AddToGroups and UpdateAttributes did not execute.

Better in Version 2
Windows PowerShell v2, which will ship for the first time in Windows 7 (and which will eventually be available for older versions of Windows), adds new error-handling functionality that's a bit easier to work with: Try…Catch blocks. A full discussion is beyond the scope of this article, so I'll just say that this new feature offers more structured error handling that gives you more options for a bit less complexity.

Don Jones is one of the nation's most experienced Windows PowerShell trainers and writers. He blogs weekly Windows PowerShell tips at ConcentratedTech.com; you may also contact him or ask him questions there.

Windows PowerShell Doppelte Benutzernamen
Don Jones


Vor kurzem habe ich einen vierteiligen Reihe in dieser Spalte, die konzentriert sich auf ein mit Windows PowerShell Benutzerbereitstellung Skript zu schreiben. Ein Leser, Jens, die in einer ziemlich detaillierten Frage Informationen zum Verbessern des Skripts geschrieben werden.
Jim hat im Wesentlichen ähnlichen Skripts in der Vergangenheit geschrieben und kämpfen Möglichkeiten, um die Fehler Behandlung auftretenden Wenn Sie einen Benutzernamen erstellen, der bereits vorhanden ist. Seine Lösung wurde zum Schreiben von "für Vortest ausführen Schleife"wobei er überprüft, ob die Verzeichnisobjekte bereits, bevor Sie fortfahren vorhanden, aber er wollte wissen, wie ich es in Meine Bereitstellung Skript Provision() Funktion Umgang mit würden.
Es ist eine gute Frage –, die ich in dieser Rubrik beantworten werde. Bedenken Sie jedoch, dass ich eingehen werde Verfahren recht universellen; sindähnliche Ansätze können zum Umgang mit anderen Situationen, in denen Sie wissen, dass ein Fehler auftreten kann. Mein Ansatz, „ Planen der aufteilen, „ aufgerufenund wie ich Skripts schreiben, die potenzielle Fehlerbedingungen etwas ordnungsgemäß zu behandeln.

Von all Fall zuerst überprüfen
Ich stimme definitiv mit Gérards Ansatz als bevorzugte Verfahren. Jim gesagt, "Ich hasse Fehlerbehandlung schreiben"und ich stimme zu. Windows PowerShell v1 Fehlerbehandlung ist ein bit für meine Geruchs-primitive, wenn ich den Fehler vollständig vermeiden können, ich tun müssen.
Lassen Sie mich zunächst angenommen, es sind wahrscheinlich eine unbegrenzte Anzahl von Variationen auf meinen Ansatz, aber eine begrenzte Anzahl von Seiten für mich hier arbeiten, damit ich nur eine Variante werden müssen. Meine grundlegende Ziel ist es, alle Benutzerkonten zu erkennen, die bereits vorhanden sind und sich bei dem Versuch ein zweites Mal zu erstellen, anstatt diese. Um den Speicher zu aktualisieren, könnte die grundlegende Funktion Provision() wie folgt aussehen:
Function Provision {
  PROCESS {
    CreateUser $_
    CreateHomeFolder $_
    AddToGroups $_
    UpdateAttributes $_
  }
}
Pipeline eine zweite Funktion, deren Auftrag Eingaben von es ist, importieren Sie Benutzerdaten irgendwo (z. B. eine Datenbank oder eine CSV-Datei) aus und erstellen Sie eine standardisierte Hashtabelle, enthält die Attribute des neuen Benutzers erwartet die Provision-Funktion. So wäre $ _ ['Samaccountname'], z. B. den Namen des Benutzers anmelden enthalten. Angegeben, dass Benutzername – die Informationen für einen Benutzer habe nur garantiert eindeutig ist, können Sie versuchen, Sie, ob das Konto bereits vorhanden ist. Am einfachsten das Cmdlet „ Get-QADUser (verfügbar in das Cmdlet-Paket am quest.com/powershell) verwenden, so wird die Provision-Funktion wie in Abbildung 1 gezeigt geändert werden.
Function Provision {
  PROCESS {
    $count = Get-QADUser –samAccountName $_['samaccountname'] | Measure-Object
    if ($count.count –gt 0) {
      $_['samaccountname'] | Out-File c:\not-created.txt -append
    } else {

      CreateUser $_
      CreateHomeFolder $_
      AddToGroups $_
      UpdateAttributes $_
  }
  }
}
Die Änderung versucht, den angegebenen Benutzer aus dem Verzeichnis abrufen und messen die Anzahl der abgerufenen Objekte. Maßeinheit Objekt wechselt in die $ Count-Variable, die Count-Eigenschaft ($ count.count) bietet. Wenn die Anzahl größer als Null ist, dann der Benutzer vorhanden ist und Verwendung out, um den Benutzernamen an eine Protokolldatei zu übergeben. Wenn der Benutzer ist nicht vorhanden, jedoch anschließend $ Count mit nothing gefüllt wird und die Count-Eigenschaft wird nicht mehr als 0 (null) – damit ich die Bereitstellung fortzusetzen.
Dieser Ansatz – ein Benutzer zu einem Zeitpunkt überprüfen – nur durchführbar eine erhält die Möglichkeit die Provision-Funktion erstellt wird. Da der Skriptblock PROCESS nur einen einzelnen Benutzer zu einem Zeitpunkt; RuftEs gibt keine Möglichkeit dazu "Pre-loop"Um alle Benutzer zuerst zu überprüfen. Es ist wirklich nicht notwendig, allerdings da nacheinander überprüft die Leistung erheblich ändern nicht.
Ein Vorteil dieses Ansatzes über die nächsten ich vorstellen werde ist die Fehlerüberprüfung – sehen, ob der Benutzer bereits vorhanden ist – Weise erfolgt. In der Tat ist, hier der wirklich nur geeignete Ansatz, da die Funktion Provision andere Funktionen aufruft, nach dem Versuch, den Benutzer zu erstellen. Wenn nur das Erstellen ­ User Fehlerüberprüfung hinzugefügt Funktion, die anderen drei – CreateHomeFolder, AddToGroups und UpdateAttributes – möglicherweise weiterhin versuchen, auszuführen.

Oder nur mit behandeln
Aber ein anderer gültiger Ansatz ist im Allgemeinen versuchen zum Abfangen des Fehlers. Fehlerbehebung in Windows PowerShell v1 ist etwas kompliziert, aber es funktioniert ungefähr folgendermaßen:
  • Sie müssen das Cmdlet mitteilen, das möglicherweise, in einen Fehler eine tatsächliche Ausnahme generiert ausgeführt, nicht nur einen roten Fehlermeldung drucken
  • Sie müssen einen Trap definieren, wo Sie die Konsequenzen der Fehler behandeln werde
Ich tatsächlich machen diesem anspruchsvolle genug ist, zum Arbeiten mit der Funktion Provision. Die Arbeit beginnt jedoch in die CreateUser-Funktion. Irgendwo in es ist ein Cmdlet, das versucht, einen neuen Benutzer erstellen, neue QADUser, oder das New-Mailbox-Cmdlet, wenn Sie Exchange Server 2007 verwenden, um Benutzer und Postfächer auf einmal zu erstellen. In beiden Fällen fügen Sie die –ErrorAction (oder –EA) Parameters an das Cmdlet um seinen Fehler Standardverhalten zu ändern.
Sie können auch einen Trap definieren, wo die Shell tatsächlich tritt eine Ausnahme. Die Änderungen an die CreateUser-Funktion könnte wie folgt aussehen:
Function CreateUser {
  Param ($userinfo)
  Trap {
    $userinfo['samaccountname'] | Out-File c:\errors.txt -append
    break
  }
  New-Mailbox . . . -EA Stop
}
Ich habe die restlichen die Syntax für New-Mailbox nur damit in dieser Abbildung klarer weggelassen. Im Wesentlichen wenn New-Mailbox fehlschlägt, der –EA-Parameter weist er beendet und löst eine Ausnahme aus. Dies zwingt die Shell suchen Sie nach einer Auffangroutine bereits definiert und ausgeführt. In dieser Trap ich den Benutzernamen in einer Datei protokollieren und führen Sie dann eine Pause, beendet die aktuelle Funktion und übergibt den ursprünglichen Fehler zurück, an was diese Funktion aufgerufen. Anders ausgedrückt, wird die Provision-Funktion, mit dem Fehler beendet.
Damit Provision die drei Funktionen ausführen, müssen die Möglichkeit, er einen ausgeführt wird (siehe Abbildung 2) ändern.
Function Provision {
  PROCESS {
    $go = $true
    trap {
      $go = $false
      continue
    }
    CreateUser $_
    If ($go) {
      CreateHomeFolder $_
      AddToGroups $_
      UpdateAttributes $_
    }
  }
}
Wie Sie sehen können, habe ich ein anderes Trap definiert. CreateUser mit einem Fehler beendet wird, wird die Auffangroutine in Provision ausgeführt. Wird einfach eine Variable, $ wechseln, auf den booleschen Wert False, und weist die Shell zum Fortfahren – d. h., Fortsetzen der Ausführung auf der Zeile, die den Fehler verursacht hat. Die Zeile ist eine "If"-Anweisung, die überprüft, wenn $ gehen enthält $ True oder nicht. Wenn dies der Fall ist, führen dann die verbleibenden drei Funktionen;Wenn $ $ False, enthält diese drei Funktionen führen. Ich den Wert $ zurücksetzen am oberen Rand der PROCESS-Skriptblock zu wechseln, so dass der nächste Benutzer versucht.
Der Grund ich ausgewählt haben, kann dieser bestimmten Ansatz (im Gegensatz zu beliebig viele andere) verwendet ist, dass dadurch mich zusätzlichen Code haben, der selbst wenn die Erstellung des Benutzers fehlgeschlagen ist (siehe Abbildung 3) ausgeführt wird.
Function Provision {
  PROCESS {
    $go = $true
    trap {
      $go = $false
      continue
    }
    CreateUser $_
    If ($go) {
      CreateHomeFolder $_
      AddToGroups $_
      UpdateAttributes $_
    }
    OutputToHTML $_
  }
}
In der Variante angezeigt wurde einen Aufruf einer Funktion mit dem Namen OutputToHTML hinzugefügt. Dies wird ausgeführt, selbst wenn der aktuelle Benutzer ist bereits vorhanden und CreateHomeFolder, AddToGroups und UpdateAttributes wurde nicht ausgeführt.

Verbesserte in Version 2
Windows PowerShell v2, die zum ersten Mal in Windows 7 ausgeliefert wird (und die werden schließlich für ältere Versionen von Windows zur Verfügung stehen), fügt neue Fehlerbehandlungs-Funktionalität, die zum Arbeiten mit ein wenig einfacher: Try … catch-Blöcke. Eine vollständige Erörterung sprengen den Rahmen dieses Artikels, damit ich nur sagen werde, dass dieses neue Feature Weitere strukturierte Fehlerbehandlung bietet, das Ihnen weitere Optionen für etwas weniger Komplexität bietet.

Don Jones ist eine von der Nation erfahrene Windows PowerShell Schulungsleiter und Schreiber. Er Blogs Tipps wöchentlichen Windows PowerShell ConcentratedTech.com;Sie können auch kontaktieren Sie ihn oder Fragen ihn vorhanden.

Page view tracker