Drücke "Enter", um den Text zu überspringen.

Kategorie: PowerShell

Hyper-V-Server / Windows Server Core: Treiber via PowerShell installieren

Wer einen Windows Server 2012 R2 als Core-Server oder den kostenfreien Hyper-V-Server 2012 R2 einsetzt, dem könnte folgendes Problem begegnen: Auf dem Server selber gibt es bekanntlich keine GUI und demnach auch keinen Gerätemanager. Und seit 2012 R2 lässt sich dieser auch nicht remote von einem grafischen Server aus ansprechen!

Was nun also tun, wenn man Treiber installieren/aktualisieren/entfernen will? Dazu möchte ich hier einige Kommandos als Hilfestellung zusammentragen:

 

Installation aller Treiber des aktuellen Verzeichnisses in das Treiber-Repository:

Get-ChildItem -Recurse -Filter *.inf | Select-Object FullName | ForEach-Object {pnputil -a $_.FullName}

Installation eines bestimmten Treibers:

pnputil.exe -i -a C:\Pfad\zum\Treiber.inf

(ACHTUNG: Installiert diesen Treiber für alle „passenden“ Geräte!)

Auflisten aller Treiber im Repository (3rd Party):

pnputil.exe -e

Entfernen eines Treibers aus dem Repository:

pnputil.exe -d oemX.inf (Name der INF-Datei über pnputil -e)

Entfernen aller Treiber aus dem Repository:

1..40 | ForEach-Object {pnputil.exe -d „oem$_.inf“} (Die Zahl 40 muss ausgetauscht werden durch die höchste Zahl aus pnputil -e)

Ermitteln der Hardware-ID der Geräte einer bestimmten Geräteklasse (hier: Netzwerkkarten)

devcon.exe listclass net

Anzeigen des von einem Gerät benutzten Treibers:

devcon.exe driverfiles „@PCI\VEN_8086&DEV_10D3&SUBSYS_040D15D9&REV_00\4&60B4255&0&00E4“

Installation eines bestimmten Treibers für ein bestimmtes Gerät:

devcon.exe /r install C:\Pfad\zum\Treiber.inf „@PCI\VEN_8086&DEV_10D3&SUBSYS_040D15D9&REV_00\4&60B4255&0&00E4“

Entfernen eines konkreten Gerätes (nicht nur der Treiber!):

devcon.exe /r remove „@PCI\VEN_8086&DEV_10D3&SUBSYS_040D15D9&REV_00\4&60B4255&0&00E4“

Nach neuen Geräten suchen:

devcon.exe rescan

 

Für einige Varianten ist DevCon.exe nötig. Siehe dazu hier:

https://msdn.microsoft.com/de-de/library/windows/hardware/ff544707(v=vs.85).aspx

http://www.wintotal.de/tipparchiv/?id=2075

Der Artikel wird künftig weiter ergänzt…

Schreibe einen Kommentar...

Hyper-V: PowerShell-Skript um nicht benutzte bzw. verwaiste VHD / VHDX Dateien zu finden

Auf einem Hyper-V System sammeln sich über die Jahre einige virtuelle Festplatten-Dateien im VHD- bzw. VHDX-Format an. Aber werden diese wirklich noch alle gebraucht? Das ist häufig schwer zu sagen, da insbesondere durch das Löschen von VMs nur deren Beschreibungs-Dateien, nicht aber die Festplatten gelöscht werden. Ähnliches kann passieren, wenn man die Replikation einer VM beendet.

Um nun diejenigen VHDs, die von keiner VM mehr genutzt werden, zu finden, habe ich ein Skript geschrieben. Dieses berücksichtigt auch, dass sich mehrere VHD/VHDX Dateien in einer Differenzierungskette befinden könnten.

Das Skript sowie eine Beschreibung findet ihr hier:

https://gallery.technet.microsoft.com/scriptcenter/Get-AbandonedVHDs-V1-to-8bfb28d9

Dem Skript kann neben einem oder mehreren Suchordnern auch u.a. eine Option übergeben werden, die direkt die nicht benötigten Dateien löscht. Das ist aber nicht ganz ungefährlich, ggf. haben die VHDs ja eine andere Funktion und sind gar nicht für Hyper-V. Denkbar wäre z.B., dass ein iSCSI-Software-Target im Einsatz ist, oder aber auch die Windows Server Sicherung.

Schreibe einen Kommentar...

System Center Configuration Manager: Site Code eines Clients auslesen

Um den Site Code (Standortcode) eines SCCM Clients auszulesen, kann man WMI verwenden. Ich habe dafür ein kleines PowerShell Script geschrieben:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<# .Synopsis Returns the Site Code of a SCCM Client as a String .DESCRIPTION Queries a given computer using WMI and returns its site code for System Center Configuration Manager (Tested on 2012 R2 and 1511) .EXAMPLE Get-SMSSiteCode -MachineName PC1 Get's the site code of the Computer named PC1 #>
 
Function Get-SMSSiteCode
{
    Param(
        # The Computername of the machine that you want to query for it's SCCM Site Code
        [Parameter(Mandatory=$true)]
        [string]$MachineName
    )
 
    Return (Get-WmiObject -ComputerName $MachineName `
                          -Namespace "root\CCM" `
                          -Class sms_authority `
           ).Name.TrimStart("SMS:")
}

<# .Synopsis Returns the Site Code of a SCCM Client as a String .DESCRIPTION Queries a given computer using WMI and returns its site code for System Center Configuration Manager (Tested on 2012 R2 and 1511) .EXAMPLE Get-SMSSiteCode -MachineName PC1 Get's the site code of the Computer named PC1 #> Function Get-SMSSiteCode { Param( # The Computername of the machine that you want to query for it's SCCM Site Code [Parameter(Mandatory=$true)] [string]$MachineName ) Return (Get-WmiObject -ComputerName $MachineName ` -Namespace "root\CCM" ` -Class sms_authority ` ).Name.TrimStart("SMS:") }

Downloaden könnt ihr das Skript hier!

Schreibe einen Kommentar...

SCCM 2012 R2 – E-Mails für Softwareanforderungen (Umfangreicher)

In einem älteren Artikel habe ich mich schon einmal mit der Frage beschäftigt, wie man neue Genehmigungsanforderungen für Software (Anwendungen) in System Center Configuration Manager per Mail an den Admin melden kann.

Was aber, wenn nicht (nur) der Admin eine Mail erhalten soll, sondern z.B. auch der Vorgesetzte des jeweiligen Benutzers, der die Software angefordert hat? Und was ist mit dem Benutzer selbst? Es wäre doch gut, wenn dieser bei Genehmigung/Ablehnung auch informiert wird?!

Das Ganze lässt sich natürlich wunderbar per PowerShell lösen. Damit nun aber nicht ein Prozess o.ä. permanent laufen muss, wäre es sinnvoll, dieses Skript z.B. nur 1x pro Stunde (über den Taskplaner) automatisch laufen zu lassen. In sofern interessieren in jedem Durchlauf des Skriptes auch nur diejenigen Anforderungen, die

  • In der letzten Stunde neu erstellt wurden (“CurrentState” ist 1)
  • In der letzten Stunde abgelehnt wurden (“CurrentState” ist 3)
  • In der letzten Stunde genehmigt wurden (“CurrentState” ist 4)

Aus dieser Überlegung und der Tatsache, dass sich sowohl der Vorgesetzte als auch die Mailadressen aus dem AD auslesen lassen, resultierte dieses einfache Script (Es ist nicht wirklich “schön” geschrieben, aber zumindest rudimentär kommentiert. Für einen produktiven Einsatz wird man es ohnehin nochmal an die eigenen Bedürfnisse anpassen müssen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
$SiteName = "PS0"
$SiteName = "PS0"
$AdminsMail = "helpdesk@kurs.intern"
$Mailserver = "mail.kurs.intern"
$Absender = "SCCM Application Request Admin"
 
$MailAnAdmins = $True
$MailAnVorgesetzten = $True
 
function Send-MyEmail
{
 
    Param(
        [string]$Sender,
        [string]$Empfaenger,
        [string]$Mailserver,
        [string]$Betreff,
        [string]$Mailtext,
        [Switch]$TestOnly
    )
 
    try{
        If(-not $TestOnly)
        {
            Send-MailMessage -From $Sender -To $Empfaenger -Subject $Betreff -Body $Mailtext 
                -SmtpServer $Mailserver -ErrorAction Stop
        }
        else
        {
            Write-Host "E-Mail für '$Empfaenger' von '$Sender' über den Mailserver '$MailServer' `n
                        mit dem Betreff '$Betreff' und dem Text:"
            Write-Host "$Mailtext `n"
 
        }
    }
    catch{
        Write-Debug "Fehler beim Versand der E-Mail über den Mailserver $SmtpServer!"
    }
 
}
 
# PS-Modul für AD lasen
Import-Module ActiveDirectory
 
# PS-Module für SCCM laden
Import-Module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1"
Set-Location "$($SiteName):\"
 
# ApprovalRequests auslesen, die sich in der letzten Stunde geändert haben 
# (Script soll stündlich laufen)
$OffeneRequests = Get-CMApprovalRequest | Where {$_.LastModifiedDate -gt (Get-Date).AddHours(-1)}
 
ForEach($Request in $OffeneRequests)
{
    # Anfordernder Benutzer
    $Benutzer = $Request.User
    $BenutzerLogin = Get-ADUser $($Benutzer.Substring(($Benutzer.IndexOf("\")+1),
                                                       $Benutzer.Length-$Benutzer.IndexOf("\")-1))
    $BenutzerName = ($BenutzerLogin | Get-ADUser).Name
 
    # Anwendung um die es geht
    $Anwendung = $Request.Application
 
    # Neue Anforderung
    If($Request.CurrentState -eq 1)
    {
        # E-Mail an Admin / Helpdeks senden
        If($MailAnAdmins)
        {
            Send-MyEmail -Sender $Absender -Empfaenger $AdminsMail -Mailserver $Mailserver 
                -Betreff "Neue Softwareanforderung von $BenutzerName" -Mailtext "Blabla..." 
                -TestOnly
        }
 
        # E-Mail an Vorgesetzten senden
        If($MailAnVorgesetzten)
        {
            # Vorgesetzter des anfordernden Benutzers
            $Vorgesetzter =  ($BenutzerLogin | Get-ADObject -Properties Manager).Manager | Get-ADUser
            $VorgesetzterMail = (Get-ADObject $Vorgesetzter -Properties mail).Mail
 
            Send-MyEmail -Sender $Absender -Empfaenger $VorgesetzterMail -Mailserver $Mailserver 
                -Betreff "Neue Softwareanforderung von $BenutzerName" -Mailtext "Blabla..." 
                -TestOnly
        }
    }
 
    # Anforderung wurde durch einen Administrator im SCCM genehmigt
    If($Request.CurrentState -eq 4)
    {
 
        # Mail an den anfordernden User senden
        $BenutzerMail = (Get-ADObject $BenutzerLogin -Properties mail).Mail
 
        Send-MyEmail -Sender $Absender -Empfaenger $BenutzerMail -Mailserver $Mailserver 
            -Betreff "Ihre Softwareanforderung für $Anwendung wurde genehmigt" -Mailtext "Blabla..." 
            -TestOnly
    }
 
    # Anforderung wurde durch einen Administrator im SCCM abgelehnt
    If($Request.CurrentState -eq 3)
    {
 
        # Mail an den anfordernden User senden
        $BenutzerMail = (Get-ADObject $BenutzerLogin -Properties mail).Mail
 
        Send-MyEmail -Sender $Absender -Empfaenger $BenutzerMail -Mailserver $Mailserver 
            -Betreff "Ihre Softwareanforderung für $Anwendung wurde abgelehnt" -Mailtext "Blabla..." 
            -TestOnly
    }
}

$SiteName = "PS0" $SiteName = "PS0" $AdminsMail = "helpdesk@kurs.intern" $Mailserver = "mail.kurs.intern" $Absender = "SCCM Application Request Admin" $MailAnAdmins = $True $MailAnVorgesetzten = $True function Send-MyEmail { Param( [string]$Sender, [string]$Empfaenger, [string]$Mailserver, [string]$Betreff, [string]$Mailtext, [Switch]$TestOnly ) try{ If(-not $TestOnly) { Send-MailMessage -From $Sender -To $Empfaenger -Subject $Betreff -Body $Mailtext -SmtpServer $Mailserver -ErrorAction Stop } else { Write-Host "E-Mail für '$Empfaenger' von '$Sender' über den Mailserver '$MailServer' `n mit dem Betreff '$Betreff' und dem Text:" Write-Host "$Mailtext `n" } } catch{ Write-Debug "Fehler beim Versand der E-Mail über den Mailserver $SmtpServer!" } } # PS-Modul für AD lasen Import-Module ActiveDirectory # PS-Module für SCCM laden Import-Module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1" Set-Location "$($SiteName):\" # ApprovalRequests auslesen, die sich in der letzten Stunde geändert haben # (Script soll stündlich laufen) $OffeneRequests = Get-CMApprovalRequest | Where {$_.LastModifiedDate -gt (Get-Date).AddHours(-1)} ForEach($Request in $OffeneRequests) { # Anfordernder Benutzer $Benutzer = $Request.User $BenutzerLogin = Get-ADUser $($Benutzer.Substring(($Benutzer.IndexOf("\")+1), $Benutzer.Length-$Benutzer.IndexOf("\")-1)) $BenutzerName = ($BenutzerLogin | Get-ADUser).Name # Anwendung um die es geht $Anwendung = $Request.Application # Neue Anforderung If($Request.CurrentState -eq 1) { # E-Mail an Admin / Helpdeks senden If($MailAnAdmins) { Send-MyEmail -Sender $Absender -Empfaenger $AdminsMail -Mailserver $Mailserver -Betreff "Neue Softwareanforderung von $BenutzerName" -Mailtext "Blabla..." -TestOnly } # E-Mail an Vorgesetzten senden If($MailAnVorgesetzten) { # Vorgesetzter des anfordernden Benutzers $Vorgesetzter = ($BenutzerLogin | Get-ADObject -Properties Manager).Manager | Get-ADUser $VorgesetzterMail = (Get-ADObject $Vorgesetzter -Properties mail).Mail Send-MyEmail -Sender $Absender -Empfaenger $VorgesetzterMail -Mailserver $Mailserver -Betreff "Neue Softwareanforderung von $BenutzerName" -Mailtext "Blabla..." -TestOnly } } # Anforderung wurde durch einen Administrator im SCCM genehmigt If($Request.CurrentState -eq 4) { # Mail an den anfordernden User senden $BenutzerMail = (Get-ADObject $BenutzerLogin -Properties mail).Mail Send-MyEmail -Sender $Absender -Empfaenger $BenutzerMail -Mailserver $Mailserver -Betreff "Ihre Softwareanforderung für $Anwendung wurde genehmigt" -Mailtext "Blabla..." -TestOnly } # Anforderung wurde durch einen Administrator im SCCM abgelehnt If($Request.CurrentState -eq 3) { # Mail an den anfordernden User senden $BenutzerMail = (Get-ADObject $BenutzerLogin -Properties mail).Mail Send-MyEmail -Sender $Absender -Empfaenger $BenutzerMail -Mailserver $Mailserver -Betreff "Ihre Softwareanforderung für $Anwendung wurde abgelehnt" -Mailtext "Blabla..." -TestOnly } }

In der Ausführung sieht das dann so aus:

Ausführen lässt sich das Skript via Taskplaner dann beispielsweise mit:

powershell.exe -ExecutionPolicy Bypass -file „SCCMMailsFuerApprovalRequests.ps1“

Das Skript lässt sich auch hier herunterladen:

Downloadlink über OneDrive

Schreibe einen Kommentar...

Microsoft Technical Summit 2015 – Die Video-Aufzeichnungen sind verfügbar!

Wer die Sessions des Summits noch einmal in Ruhe zuhause ansehen will oder gar nicht beim Summit dabei sein konnte, aber sich für die Inhalte interessiert, hat jetzt die Möglichkeit, die Videos und Unterlagen herunterzuladen.

Unter http://www.microsoft.com/germany/technical-summit/nachlese-2015.aspx sind alle Sessions der beiden tage mit den jeweiligen Infos sowie den Unterlagen und Videos aufgelistet. Hier bekommt man die Videos in mittlerer Qualität.

Unter https://channel9.msdn.com/Events/microsoft-techncial-summit/Technical-Summit-2015-The-Next-Level stehen alle Videos in 3 Qualitätsstufen zur Verfügung – und auch als MP3 Podcast.

Ich habe ein PowerShell-Script geschrieben, was den Download aller Videos in einer benutzerdefinierten Qualitätsstufe ohne großen Aufwand erledigt:

Das komplette Script könnt ihr hier herunterladen:

http://1drv.ms/1TelkeJ

Der Aufruf erfolgt dann in etwa so:

.\Get-MSTS15Content.ps1 -OutFolder D:\MSTS15 -VideoQuality Low

Viel Spaß damit!

2 Comments

Microsoft Technical Summit 2015: Meine Session zum Thema PowerShell 4.0 und 5.0

Für all diejenigen, die in meiner Session zum Thema “Deep Dive – Neuerungen in PowerShell 4.0 und 5.0” auf dem Microsoft Technical Summit 2015 in Darmstadt gesessen haben – und auch für die, die es nicht geschafft haben – stelle ich hier meine Folien und Beispiel-Skripte bereit. Sobald die Video-Aufzeichnungen verfügbar sind, werde ich diese ebenfalls hier veröffentlichen…

Downloads:

PowerPoint-Slide-Deck

PowerShell-Skripte und Beispiele

Schreibe einen Kommentar...

PowerShell DSC meldet Fehler bzgl. MSFT_RoleResource

Wenn beim Versuch, PowerShell DSC Konfigurationen von einem Windows Server 2016 als Pull-Server auf andere Server der selben Generation zu schicken, neuere Ressourcen verwendet werden, dann kann u.U. folgender Fehler auftreten:

Fehlermeldung nochmal vollständig:

“The PowerShell DSC resource MSFT_RoleResource from module <PSDesiredStateConfiguration,1.0> does not exist at the PowerShell module path nor is it registered as a WMI DSC resource.”

Grund ist ein unterschiedlicher Patch-Stand zwischen den einzelnen Servern. Abhilfe schafft also ein einspielen der entsprechenden Patches.

Schreibe einen Kommentar...

SCVMM 2012 R2: Konsole stürzt nach dem Hinzufügen einer Benutzerdefinierten Eigenschaft (“Custom Property”) ab

Heute hatte ich folgenden Effekt:

Nach dem Erstellen einer neuen “Custom Property” mit dem Namen “HDD-Typ SSD,SAS,SATA” (Sonderzeichen wie Klammern und Schrägstriche sind nicht zulässig und werden von der GUI abgefangen) stürzt die SCVMM Konsole sofort ab und lässt sich auch nicht wieder starten.

Der erste Fehler hat den Ereignisnamen “CLR20r3” an der “VmmAdminUI.exe”. Vermutlich gibt es für dieses Problem mittlerweile einen Patch, aber die verwendete Umgebung war nicht komplett gepatcht. Also musste eine Alternative her. Naheliegend war das Löschen der neu angelegten Eigenschaft, aber dies musste ohne GUI erfolgen (diese ließ sich wegen des Crashes ja nicht starten). Also bleibt nur die PowerShell…

Zunächst habe ich mit “Get-SCCustomProperty” nach der betreffenden Eigenschaft gesucht:

Der komplette Aufruf:

Get-SCCustomProperty | Where Name -NotLike "Custom*"

Danach kann man diese mit “Remove-SCCustomProperty” löschen:

Der komplette Aufruf:

Get-SCCustomProperty -Name "HDD-Typ SSD, SAS, SATA" | Remove-SCCustomProperty

Danach startet auch die Konsole wieder!

Hinweis: Zur Nutzung der SC-Kommandos muss das entsprechende Modul geladen sein. Dies geht am einfachsten, in dem man auf dem SCVMM-Server selbst die “Virtual Maschine Manager Command Shell” startet:

Schreibe einen Kommentar...

Windows 10: VPN-Verbindungen nutzen immer Remote-Gateway

Unter früheren Windows-Versionen konnte man bei VPN-Verbindungen noch den gesamten IPv4-Teil konfigurieren. Dort gab es eine Option “Standardgateway für das Remotenetzwerk verwenden”, die man abschalten konnte:

Standardmäßig war/ist diese Option eingeschaltet und sorgt dafür, dass SÄMTLICHER Datenverkehr über das Remote-Netz geleitet wird, auch das, was eigentlich “DIREKT” ins Internet gehen könnte. Der Vorteil dabei ist, dass der Traffic vom eigenen Endgerät bis zum Firmennetzwerk verschlüsselt ist, was insbesondere dann nützlich ist, wenn man in einem Internetcafe oder Hotel-WLAN sitzt und nicht klar ist, wer den Verkehr mithören kann.

Will man nun auf einem Windows 10 Client dieses Verhalten ändern – also erreichen, dass nur Traffic, der für das Remote-Netzwerk gedacht ist, über VPN geht, der Rest direkt ins Internet, müsste man diesen Haken entfernen, was bei Windows 10 nicht mehr geht, da sich die IPv4-Optionen der VPN-Verbindung nicht mehr öffnen lassen.

Was man aber tun kann, ist dieses Verhalten mit Hilfe der PowerShell herbeizuführen, und zwar mit diesem Aufruf:

Damit wird für alle VPN-Verbindungen das “Split-Tunneling” aktiviert, was eben diesem Haken entspricht.

Hier der Aufruf nochmal zum direkt Kopieren:

1
 Get-VpnConnection | Set-VpnConnection -SplitTunneling $True

Get-VpnConnection | Set-VpnConnection -SplitTunneling $True

Schreibe einen Kommentar...

Windows Server Technical Preview / vNext: “Soft Restart” funktioniert (noch) nicht

Die aktuelle Build 9841 des kommenden Windows Server (aktuell als “vNext” bezeichnet, vermutlich später “Windows Server 2016”, da erst Mitte 2016 erscheinen wird) bringt neben einigen anderen neuen Funktionen auch ein Feature “Soft Restart” mit:

Unabhängig davon, ob es installiert ist oder nicht, stehen sowohl in der CMD via shutdown.exe als auch in der PowerShell passende Optionen zur Verfügung:

Von den Funktionen erwarte ich mir, dass sie den Server neustarten, ohne die gesamte Hardware neu starten zu müssen (verbunden mit den ganzen POST-Checks und co., RAID-Controller und alles was beim Booten eben so auf einem Server Zeit kostet). Dadurch sollte der Reboot auch deutlich schneller sein, was auch Downtimes nach Updates deutlich verkürzen würde.

Leider haben beide Schalter (“shutdown.exe /soft” und “Restart-Computer –Soft”) in der aktuellsten freien Build (9841) noch keine Auswirkung und zeigen auch keinerlei Verkürzung der Boot-Zeit.

Auch nach der Installation des Features und dem dadurch notwendigen Reboot ändert sich nichts. Schade. Also abwarten…

Schreibe einen Kommentar...