Erst einmal vorweg: ich bin kein Entwickler. Insofern kann sicher vieles einfacher oder einfach anders gemacht werden… Aber: es funktioniert.

Trotzdem habe ich mich getraut, mich durchzukämpfen: Ich hatte die Anfoderung, dass ich für unsere Demo-Umgebung regelmäßig mehrere Benutzer in Office 365 ändern musste. Da dabei auch z. B. die Domäne – und damit der Anmeldename und u. U. auch das Passwort des Benutzers geändert werden musste – verfiel ich auf die Idee, ein kleines Programm in C# anzulegen, das es mir erlaubte, alle Benutzer, die eine Lizenz haben aus einem aktiven Office 365 – Tenant auszulesen und mit neuen Daten (Anmeldename, Vor-/Nachname sowie wenn gewünscht neuem Passwort) wieder zu speichern.
Ich habe viel Zeit gebraucht, um in den verschiedenen Foren Lösungen zu finden – aber letztendlich habe ich dann die nötige Information gefunden und konnte daraus mein eigenes kleines Programm schreiben.

Im ersten Schritt werden die Grundinformationen erfasst:

  • Wie heißt der Tenant
  • Wie heißt der Admin-User
  • Passwort des Admin-Users
  • Soll eine neue Domäne vergeben werden? (muss dem Tenant aber schon zugeordnet sein)
  • Soll ein neues Passwort vergeben werden?
  • Wie soll der Benutzername aufgebaut sein?

Über den Button “Load” können dann die Benutzer aus Office 365 geladen werden.

Anschließendkönnen den Benutzern neue Vor- und Nachnamen zugeordnet werden.

Über den “Change”-Button werden die Benutzer, die neue Namen zugeordnet bekommen haben, in Office 365 zurückgeschrieben.

Viele der gefundenen und genutzten Codefragmente stammen aus dem DEV Center von Microsoft oder von MSDN. So wird z. B.

und weiteren öffentlich zugänglichen Quellen genutzt.

Für das Programm werden folgende Bibliotheken genutzt:

[code language=”csharp”]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using Microsoft.SharePoint.Client;
using System.Collections.ObjectModel;
using System.Security;
[/code]

Nachdem in die Felder die notwendige Information eingegeben wurde und der Load-Button angeklickt wurde, werden die Daten aus dem Office 365 Tenant ausgelesen:

[code language=”csharp”]

/// <summary>
/// Erzeugen einer temporären Benutzerliste.
/// </summary>
/// <param name=”sender“></param>
/// <param name=”EventArgs“></param>
/// <return value=”void”></return>

private void BT_PeopleLoad_Click(object sender, EventArgs e)
{
try
{
Cursor.Current = Cursors.WaitCursor;
UserCredential.UserName = TB_User.Text;
UserCredential.Password = get_password();
// Befehl zum Verbinden mit Officee 365 wird erstellt.
List<Command> psCommand = new List<Command>();    
// Anlegen des Initial Session State
InitialSessionState initialSession = InitialSessionState.CreateDefault();
initialSession.ImportPSModule(new[] { “MSOnline” });
// Anlegen des CredentialObjects
PSCredential credential = new PSCredential(UserCredential.UserName, UserCredential.Password);
// Erzeugen des Befehls zum Verbinden mit Office 365.
 psCommand.Add(new Command(“Connect-MsolService”));
 psCommand[0].Parameters.Add((new CommandParameter(“Credential”, credential)));
// Erzeugen des Befehls zum extrahieren der Office 365 Benutzer.
 psCommand.Add(new Command(“Get-MsolUser”));
// Ermitteln der Benutzerliste innerhalb des Tenants.
Collection<PSObject> results = execute_ps(psCommand);
if (results != null && results.Count > 0)
{
FillUserList(results);      // Benutzerliste wird gefüllt
}
else
{
Cursor.Current = Cursors.Default;
return;
}
Cursor.Current = Cursors.Default;
    }
 catch (Exception ex)
{
Cursor.Current = Cursors.Default;
MessageBox.Show(ex.Message);
return;
}

 }

[/code]

Das Passwort wird in der Routine get_password() generiert – Ziel ist es, einen Secure-Passwort-String zu übergeben:

[code language=”csharp”]

/// <summary>
/// Erstellen eines sicheren Passwort-Strings
/// </summary>
///
/// <return value=”SecureString”></return>

private SecureString get_password()
{
SecureString passWord = new SecureString();
foreach (char c in TB_Password.Text.ToCharArray()) passWord.AppendChar(c);
return passWord;
}

[/code]

Nun werden (neben dem Aufbau und Ausgabe der Tabelle) eigentlich nur noch eine wichtige Routine benötigt:  Sie führt die Powershell Skripte aus…

 

[code language=”csharp”]

/// <summary>
/// Execute PowerShell Skripts. Übergeben wird ein Array mit PowerShell Befehlen
/// </summary>
/// <param name=”psCommand“></param>
/// <return value=”Collection”></return>
private Collection<PSObject> execute_ps(List<Command> psCommand)
{
UserCredential.UserName = TB_User.Text;
UserCredential.Password = get_password();
 // Anlegen der Initialen Session.
InitialSessionState initialSession = InitialSessionState.CreateDefault();
 initialSession.ImportPSModule(new[] { “MSOnline” });
using (Runspace psRunSpace = RunspaceFactory.CreateRunspace(initialSession))
{
Collection<PSObject> results = null;
// runspace öffnen.
psRunSpace.Open();
//Durchlaufen der Liste mit den Befehlen – und Ausführung der Befehle.
 
foreach (var com in psCommand) // new Command[] { connectCommand, getUserCommand, setUserPName }
{

    var pipe = psRunSpace.CreatePipeline();
pipe.Commands.Add(com);

    // Ausführen des Befehls – Analyse etwaiger Fehler.
results = pipe.Invoke();

   var error = pipe.Error.ReadToEnd();
if (error.Count > 0) //&& com == connectCommand)
{

        MessageBox.Show(error[0].ToString(), “Problem beim login”);
return results;
}

   }

  // Runspace schließen.
   psRunSpace.Close();

   return results;
}

}

[/code]

Der Rest der Anwendung besteht darin, die Tabelle zu füllen, die Änderungen dann wieder aus der Tabelle auszulesen und als Skript wieder an execute_ps zu übergeben.

Als Zielpunkte der Skripte werden folgende Powershell-Skripte genutzt:

  • Connect-MsolService
  • Set-MsolUser (um die Änderungen am Benutzer durchzuführen)
  • Set-MsolUserPrincipalName
  • Set-MsolUserPassword

Wichtig ist, dass bei der Übergabe der Skript-Befehle weitergehende Parameter als “Parameters” übergeben werden, beispielhaft hier mit Set-MsolUserPrincipalname dargestellt.

[code language=”csharp”]

psCommand.Add(new Command(“Set-MsolUserPrincipalName”));  // Powershell – Befehl
psCommand[2].Parameters.Add((new CommandParameter(“-UserPrincipalName”, old_cUserName + “@” + domains[1]))); // Parameter -UserPrincipalName
psCommand[2].Parameters.Add((new CommandParameter(“-NewUserPrincipalName”, new_UserPrincipalName))); // Parameter -NewUserPrincipalName

[/code]

Der entsprechende Powershell – Befehl hierzu lautet:

[code language=”powershell”]

Set-MsolUserPrincipalName
-NewUserPrincipalName <String>
[-ImmutableId <String>]
[-NewPassword <String>]
-UserPrincipalName <String>
[-TenantId <Guid>]
[<CommonParameters>]

[/code]

Ich hoffe, das Beispiel hilft, um vergleichbare Themen schneller lösen zu können. Ich danke allen, die im Web so viel interessanten Beispielcode veröffentlicht haben. Das gesamte Projekt setzt sich aus einzelnen Teilen aus den oben genannten Beispielen zusammen.