Meet the Scripting Guy Ed Wilson in Munich!

Hallo Community,

Es hat wieder geklappt. Ed “the scripting guy” Wilson kommt wieder nach München.
Ok, nicht ganz nach München aber zu Microsoft in Unterschleissheim.

Wann?
28. März 2014 ab 17:30 Uhr

Wo?
Microsoft Deutschland
Konrad-Zuse-Str 1
85716 Unterschleissheim

Thema?
Das Thema ist natürlich PowerShell aber genauer geht es hauptsächlich um Desired State Configuration (DSC)

Anmeldung?
Ja bitte. Da wir uns in in den Firmenräumen von Microsoft treffen ist eine Anmeldung erforderlich.
Bitte nutzt dafür unsere Xing-Seite . (Xing Anmeldung erforderlich das sonst der Event nicht angezeigt wird)
https://www.xing.com/events/meet-scripting-guy-ed-wilson-munich-1372939?creation=true
P.S. MS Mitarbeiter schreiben bitte direkt an Rolf Masuch

Dateien drucken mit OneDrive

Wir werden immer mobiler, überall Dokumente bearbeiten, eMails lesen und beantworten. Was ist aber z.B. mit den Rechnungen die per eMails als PDF kommen. Am Desktop zu Hause kein Problem ausdrucken und abheften. Am Handy oder Tablet am Flughafen schon etwas schwieriger. Damit müssen diese eMails dann zweimal angesehen/bearbeitet werden. Mir ist es mehr als einmal passiert, dass ich den Ausdruck eines Dokuments vergessen habe. Es musste also eine Lösung her.

Drucken über Internet ist zu komplex und nicht sicher genug. Also musste eine Lösung her die von allen Geräten stabil bedient werden kann. Dabei ist der OneDrive (ehemals SkyDrive) das Mittel meiner Wahl. Die Idee ist, das die Dateien die gedruckt werden sollen in einem Ordner, in meinem Beispiel „ONEDRIVE:\-drucken\“, abgelegt werden und dort von einem Job auf dem Desktop verarbeitet werden. Hier das Script für die Verarbeitung auf dem Desktop.

cls
## Environment Variable SKYDRIVE anlegen
## http://web.powershell-ag.de/skydrive-mit-powershell-nutzen/

## Wichtig !
## Die Dateien müssen aus dem System von dem gedruckt 
## wird OFFLINE verfügbar sein.
$strDir = $env:SKYDRIVE+"\- Drucken\"

## Dateitpen z.B. PDF und DOCX die gedruckt werden
$Dateityp = @( "*.pdf","*.docx") 

## Ausdrucken der Dateien
$Dateityp | Foreach-Object {
    $strVerzeichnis = $strDir + $_
    Dir $strVerzeichnis | Foreach-Object {
        Start-Process -FilePath $_.FullName Verb Print`
       -WindowStyle Minimized -wait

## Datei löschen
Remove-Item $_.FullName
    }
} 

Bei mir auf dem Desktop wird der Ausdruck der Dateien über Aufgabenplanung 30 Min. nach dem Start des Systems ausgeführt. Damit ist genug Zeit für die Synchronisierung  der Dateien im Druckverzeichnis vom OneDrive auf das lokale System.

SkyDrive aus PowerShell nutzen

Auf jedem Rechner auf den in Zugriff habe liegt der SkyDrive Ordner
in einem anderem Pfad.
Um z.B. Daten von SkyDrive lesen oder dort ablegen, muss das Script
jedes Mal angepasst werden. Natürlich kann man im Script über
Rechnername, IP Adresse oder ähnlich automatisch darauf reagieren,
aber das ist sehr aufwendig und muss in jedem Script wieder erfolgen.

Meine Lösung hierfür ist eine neue Environment Variable in der der
Wert des SkyDrive Pfads abgelegt ist. Danach kann dann über diese
Variable auf die SkyDrive Ordner mit einem einheitlichen Pfad
zugegriffen werden.

Zuerst eine Environment Variable anlegen.

$SkyDrivePath="D:\SkyDrive"
New-Itemproperty -path "hkcu:\Environment" -Name "SKYDRIVE"´
-value $SkyDrivePath -type ExpandString

Nach einem Neustart des Rechners steht die neue Environment Variable
%SKYDRIVE%  dann zur Verfügung.

Bei Windows 8.1 liegt der SkyDrive Ordner übrigens im %USERPROFILE%

Fehler in “GetSyncedObjectCount”

Beim Anwenden des Scripts „GetSyncedObjectCount“ aus den Office 365 Helper Scripts ist mir aufgefallen, dass das Ergebnis nicht so ok ist. In der Umgebung mit der ich getestet habe, gibt es Gruppen die mit dem AD synchronisiert und welche die Lokal im Office 365 erstellt wurden. Das Script hat aber immer die gesamte Anzahl der Gruppen als Synchronisiert zurückgegeben.

Der Fehler steckt in den Zeilen 56-58, dort wird die Variable „LastDirSyncTime“ nur auf einen leeren String abgeprüft und nicht auf $NULL.

Hier die korrekten Zeilen:

$users|%{if(($_.LastDirSyncTime -ne $Null) -or ´
        ($_.LastDirSyncTime-ne"")) {$ucount=$ucount+1}}
$groups|%{if(($_.LastDirSyncTime -ne $Null) -or ´
       ($_.LastDirSyncTime-ne"")){$gcount=$gcount+1}}
$contacts|%{if(($_.LastDirSyncTime -ne $Null) -or ´
       ($_.LastDirSyncTime-ne"")){$ccount=$ccount+1}}

Werte im Array gruppieren

Mal wieder ein paar Zeilen Code aus der täglichen Praxis. Ich habe heute Morgen eine Lösung benötigt, die mir die Anzahl gleicher Zeilen in einem Array zurückliefert.
Meine Lösung sieht dabei wie folgt aus:

Function Get-ArrayValueCount {
  param($array)
  begin {
    $hash=@{}
  }
  process {
    $Array | %{ $hash[$_] =$hash[$_] +1 }
    $hash.GetEnumerator() |?{$_.value-gt0} |%{
       New-ObjectPSObject-Property@{
         Value=$_.keyCount=$_.value
       }
     }
   }
 }

Hier ein kleines Beispiel für die Benutzung:

cls
$Vorname=@()
$Vorname+="Anna"
$Vorname+="Willi"
$Vorname+="Anna"
$Vorname+="Werner"
$Vorname+="Willi"
$Vorname+="Anna"

Get-ArrayValueCount $Vorname | sortCount

18. PowerShell Community Treffen am 25.09.2013

Hallo Community,

wir werden uns am 25.09.2013 im Microsoft Campus in Unterschleißheim treffen.
Der Beginn ist auf 18:00 Uhr festgelegt und nachfolgend findet ihr die Agenda des Abends:

  • PS 4.0, Desired State Configuration
  • ca. 1 Std. Basics

Über eine rege Teilnahme freuen wir uns!

Achtung, Achtung, Achtung!

Leider muss der Termin abgesagt werden. Ein neuer Termin wird bekannt gegeben.

-> zur Anmeldung

Neue Termine für Anwendertreffen online

Die Termine für die kommenden vier Anwendertreffen sind unter Termine nun online. Das nächste Treffen findet am 25.09.2013 ab 18 Uhr statt. Hier ist bereits eine Anmeldung via XING möglich. Die jeweilige Agenda wird kurz vor der Veranstaltung veröffentlicht.

Dirsync und Office 365

Heute mal etwas weniger PowerShell dafür aber eine wichtige Informationen, für alle die beabsichtigen mit dem neuen Dirsync und der neuen Passwortreplikation Office 365 zu betreiben. Bei der Suche nach dem Fehler sind aber doch einige KByte an Script gegen die Office365 Umgebung gelaufen.

Grundsätzlich sind die Grundlagen in dem folgenden TechNet Artikel recht gut und vollständig beschrieben.
http://technet.microsoft.com/en-us/library/hh967629.aspx

http://blogs.technet.com/b/educloud/archive/2013/06/03/new-azure-active-directory-sync-tool-with-password-sync-is-now-available.aspx

Zu erwähnen ist hier, dass die Passwörter in der Domain sicher sein müssen und nicht älter als 90 Tage sein dürfen. Das ist aber glaube ich kein Thema, da wir ja alle ein gut gepflegtes AD betreiben. J

Wenn man das alles zum Laufen bekommen hat und die AD-User dann bei Office 365 zu sehen sind kommt der Interessante Teil.
Allen Usern eine Lizenz zuweisen. — Ok hier doch mal eine Beispielzeile PS:
get-Msoluser | where {$_.IsLicensed -eq $False} |´

Set-MsolUserLicense -AddLicenses “Test:ENTERPRISEPACK”

 

Nun kann dann über Office 365 der Migrationsassistent für die Mehrstufige Migration gestartet werden.
Hier gibt es die Möglichkeit mit einer CSV-Datei die User die Migriert werden sollen zu übergeben.

Die Anleitung dazu findet sich hier:

http://technet.microsoft.com/de-DE/library/ms.exch.eac.LearnMoreMigrationCSVStaged(EXCHG.150).aspx?v=15.0.731.0&l=1&s=BPOS_S_E15_0

Achtung Falle:
Im Abschnitt Password findet sich der folgende Test:

Password ist das Kennwort, das für das neue Exchange Online-Postfach festgelegt wird. Alle Kennworteinschränkungen, die auf die Office 365-Organisation angewendet wurden, gelten für die in der CSV-Datei enthaltenen Kennwörter. Ein Kennwort muss eine Mindestlänge von acht Zeichen haben. Dieses Attribut ist optional.

WICHTIG:
Bei der Dirsync mit Passwort Anbindung ist es zwingend notwendig, dass das Passwort LEER ist, sonst wird das AD Passwort überschrieben und der User muss sich mit dem Password aus der CSV-Datei anmelden.

Die Datei muss also so aussehen:

EmailAddress,Password,ForceChangePassword
pilarp@tailspintoys.com,,False

WPF Form aus Visual Studio als Formular mit der PowerShell nutzen

Hallo Community,

die Verwendung von Formularen als kleine Eingabemasken ist auch in Zeiten der PowerShell immer wieder ein Thema.
Heute möchte ich euch eine Methode beschreiben, mit der ihr eure Formulare in Visual Studio (http://msdn.microsoft.com/de-de/vstudio/) erstellt und mit eurem Skript ansprecht. Zuerst müsst ihr in Visual Studio ein neues Projekt vom Typ Windows / WPF Applikation erstellen. Dabei ist es unerheblich ob dies mit C# oder Visual Basic erstellt wird. Als nächstes entwerft ihr das Formular wie ihr es benötigt. Also Buttons, Label, Listen hinzufügen und, das ist ganz wichtig, jedem der Controls einen Namen geben. Speichert das Projekt ab und merkt euch den Pfad in dem die XAML Datei abgelegt wird.

Aber jetzt genug mit den Vorbereitungen und los geht es mit dem Skripten in der PowerShell. In dem Skript sind zuerst die Assemblies für das Presentation Framework und System als Typ hinzuzufügen. Dies geschieht mit den folgenden Zeilen:
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName
System

Danach wird der Inhalt er XAML Datei mittels Get-Content in eine [XML] typisierte Variable eingelesen.
[XML]$XAML = Get-Content D:\ps\WPF\PS_WPF_Sample.xaml

Der nächste Schritt ist ein kleiner Kunstgriff um das native Visual Studio Format in der PowerShell einbinden zu können. Es geht darum das Attribut x:class zu entfernen. Visual Studio benötigt diese Klasse aber die PowerShell kann auch wunderbar ohne dieses Attribut auskommen. Also weg damit…
$XAML.Window.RemoveAttribute(“x:Class”)

 Jetzt kann es mit nativer PowerShell und XML weiter gehen. Das Formular wird als Reader eingelesen und danach geladen.
$Reader = New-Object System.Xml.XmlNodeReader $XAML
$Form = [Windows.Markup.XamlReader]::Load($Reader)

Über die Variable $Form habt ihr jetzt den vollen Zugriff auf das WPF Formular. Jetzt gilt es die einzelnen Controls direkt ansprechen zu können.
Da die einzelnen Controls innerhalb von Visual Studio mit Namen versehen wurden können wir jetzt mit der PowerShell danach suchen und das Ergebnis in eine Variable pro Control packen.
$PSBtnOK = $Form.FindName(‘PSBtnOK’)

Jetzt gilt es den gefundenen Controls bzw. ihren Variablen die gleichen Tricks beizubringen wie Ihren Verwandten in Visual Studio d.h. es müssen Events zu den jeweiligen Variablen hinzugefügt werden. Welche dies sind hängt natürlich von dem jeweiligen Control ab und bei einem Button ist das natürlich der Click Event. Und so wird er in der PowerShell hinzugefügt:
$PSBtnOK.Add_Click($btnOKClick)

Als vorletzter Schritt muss der hinterlegte Skript-Block noch mit Leben gefüllt werden.  Das kann z.B. so aussehen:
$btnOKClick = {$PSLabel.Content = $PSText.Text}

Zu guter Letzt ist das Ganze noch in eine Funktion zu packen und diese muss als letztes aufgerufen werden. Die eigentliche Anzeige des Formulars erfolgt mit der Methode
$Form.ShowDialog() | Out-Null

Für den Aufruf kann entweder die ISE oder die PowerShell.exe mit dem Schalter -STA verwendet werden da WPF diese Option benötigt.

Anbei findet ihr in dem Artikel auch das beschriebe Skript sowie die XAML Datei. Die Pfade müsst ihr natürlich auf eure Gegebenheiten anpassen.

Viel Spaß mit dieser Art Formulare bereit zu stellen.
C:\PS> Get-Help -Name Rolf

WPF Sample 001

PS_WPF_Sample.ps1

PS_WPF_Sample.xaml

Outlook an Office 365 (WAVE 15) von Hand anbinden

Sollte es mal nötig sein, Outlook ohne einen autodiscover Eintrag im DNS mit Office365 (WAVE 15) anbinden zu müssen, so ist das möglich. Dabei ist die PowerShell sehr hilfreich, da man die ExchangeGUID des Postfaches benötig, das angebunden werden soll.

Als erstes stellt bitte eine Remote Powershell Verbindung zu dem entsprechenden Office 365 System her.

Jedes Benutzer Konto hat übrigens eine eigene ExchangeGUID, was man nach der Ausführung des folgenden Befehls sehr leicht feststellen kann.

Get-Recipient | select Identity, ExchangeGUID  | ft

In größeren Organisationen kann man die Abfrage auch auf einen Benutzer begrenzen.

Get-Recipient -Identity “test.user@deinefirma.de” | select ExchangeGUID | fl

Die ExchangeGUID zusammen mit dem Domainnamen bildet dann den Servernamen:

Beispiel:   fd957759-8091-4e9e-ab4c-eb5e7a242740@deinefirma.de

In der Anlage findet Ihr noch ein PDF in dem die Einbindung in Outlook beschrieben ist.

PDF: Outlook an Office 365