1.   Arbeiten mit COM-Klassen
1.1 COM-Klassen des Windows Scripting Hosts
      Beispiel 1a) Erstellen eines Shortcuts mit VBS (WshShortcut_Object)
      Beispiel 1b) Erstellen eines Shortcuts mit Powershell
1.2 COM-Klassen der Script Runtime
      Beispiel 1a: Erstelldatum eines Ordners über die Eigenschaft "datecreated" aus dem FileSystemObject feststellen
      Beispiel 1b: Erstelldatum eines Ordners über die Eigenschaft "creationtime" der [DirectoryInfo]-Klasse feststellen
1.3 Auflisten aller registrierten COM-Klassen
1.4 Mit COM-Klassen Office automatisieren
      Beispiel 1: Neue Excelmappe öffnen und eine Zelle beschreiben
      Beispiel 2: Neue Excelmappe öffnen unter  Einsatz des CultureInfo-Klasse

2.   System.__ComObject


1 Arbeiten mit COM-Klassen

Die COM Automation ist seit langer Zeit ein Standard zum Skripten von Aufgaben in der Systemadministration. Jeder VBS-Programmierer hat mehr oder weniger unbewusst schon intensiv mit dieser Schnittstelle gearbeitet.
Selbstverständlich stehen die COM-Klassen auch in der Powershell zur Verfügung, wobei viele Aufgaben hier üblicherweise mittels cmdlets und .Net-Klassen erledigt werden. Viele Anwendungen wie das MS-Office Paket bringen ihre eigenen COM-Objekte mit, die man nach wie vor für deren Automation verwenden muss.

Hat man sich ein COM-Objekt aus einer Klasse erstellt, so kann man genauso mit dessen Methoden und Eigenschaften arbeiten, wie mit jedem anderen Powershellobjekt.
Die COM-Klassen sind nicht ganz so einheitlich aufgebaut wie .Net-Klassen, dennoch spricht aus meiner Sicht nichts gegen die Verwendung dieses Automation Interfaces.

Wichtige COM-Klassen befinden sich im Windows Script Host (z.B. WSHShell, WshNetwork) und in der Script Runtime (z.B. FileSystemObject, Dictionary Object)
 

1.1 COM-Klassen des Windows Scripting Hosts

Eine Auflistung der COM-Objekte mit VBS-Beispielen des WSHs findet man unter MSDN: Objects (Windows Script Host)

Scripting.Signer Object

Enables an author to sign a script with a digital signature and a recipient to verify the signature's authenticity and trustworthiness.

WScript Object

Provides access to most of the objects, methods, and properties in the WSH object model.

WshArguments Object

Gives you access to the entire collection of command-line parameters — in the order in which they were originally entered.

WshController Object

Exposes the method CreateScript() that creates a remote script process.

WshEnvironment Object

Gives you access to the collection of Microsoft Windows system environment variables.

WshNamed Object

Provides access to the named command-line script arguments within the WshArguments object.

WshNetwork Object

Gives you access to the shared resources on the network to which your computer is connected.

WshRemote Object

Provides access to the remote script process.

WshRemoteError Object

Exposes the error information available when a remote script (a WshRemote object) terminates as a result of a script error.

WshScriptExec Object

Provides status and error information about a script run with Exec, along with access to the stdIn, stdOut, and stdErr channels.

WshShell Object

Gives you access to the native Windows shell functionality.

WshShortcut Object

Allows you to create a shortcut programmatically.

WshSpecialFolders Object

Allows you to access the Windows Special Folders.

WshUnnamed Object

Provides access to the unnamed command-line script arguments within the WshArguments object.

WshUrlShortcut Object

Allows you to create a shortcut to an Internet resource, programmatically.

 

Beispiel 1a) Erstellen eines Shortcuts mit VBS (WshShortcut_Object)

'VBS-Script
'msdn.microsoft.com/en-us/library/xk6kst2k(VS.85).aspx

set WshShell = WScript.CreateObject("WScript.Shell")
strDesktop = WshShell.SpecialFolders("Desktop")
set oShellLink = WshShell.CreateShortcut(strDesktop & "\Shortcut Script.lnk")
oShellLink.TargetPath = WScript.ScriptFullName
oShellLink.WindowStyle = 1
oShellLink.Hotkey = "CTRL+SHIFT+F"
oShellLink.IconLocation = "notepad.exe, 0"
oShellLink.Description = "Shortcut Script"
oShellLink.WorkingDirectory = strDesktop
oShellLink.Save


Beispiel 1b) Erstellen eines Shortcuts mit Powershell

Set-StrictMode -Version "2.0"
Clear-Host

 
$Shell = New-Object -com "Wscript.Shell"
$Desktop=$Shell.SpecialFolders.Item("Desktop")

$ShellLink=$Shell.CreateShortcut("$Desktop\Shortcut Powershell2.lnk")
$ShellLink.Targetpath = "powershell.exe"
$ShellLink.WindowStyle=1
$ShellLink.Hotkey ="CTRL+SHIFT+P"
$ShellLink.IconLocation = 'powershell.exe,1'
$ShellLink.Description="Shortcut Powershell"
$ShellLink.WorkingDirectory=$Desktop
$ShellLink.Save()

 

 

1.2 COM-Objekte der Script Runtime

Eine Auflistung der COM-Objekte der "Script Runtime" mit VBS-Beispielen des WSHs findet man unter: MSDN: Script Runtime

Dictionary Object

Explains the concept of the Dictionary object and links to its methods and properties.

FileSystemObject

Links to the FileSystemObject basics and FileSystemObject reference sections.

Script Encoder

Provides an overview of the Script Encoder command-line tool and links to topics that explain how to use it.


Beispiel 1a: Erstelldatum eines Ordners über die Eigenschaft "datecreated" aus dem FileSystemObject feststellen

Set-StrictMode -Version "2.0"
Clear-Host
 
$FolderName="C:\Temp"
$Fso=New-Object -com "Scripting.FileSystemObject"
$Folder=$Fso.GetFolder($FolderName)
$Folder.DateCreated
#Ausgabe

Donnerstag, 14. Januar 2010 12:01:05

 
Beispiel 1b: Erstelldatum eines Ordners über die Eigenschaft "creationtime" der [DirectoryInfo]-Klasse feststellen

Set-StrictMode -Version "2.0"
Clear-Host

 
$FolderName="C:\Temp"
$a=New-Object System.Io.DirectoryInfo("$Foldername")
$a.Creationtime
#Ausgabe

Donnerstag, 14. Januar 2010 12:01:05

 

1.3 Auflisten aller registrierten COM-Klassen

Windows PowerShell Blog: Listing all the COM automation PROGIDs

Set-StrictMode -Version "2.0"
Clear-Host

 
$a = dir  REGISTRY::HKEY_CLASSES_ROOT\CLSID -include PROGID -recurse | foreach {$_.GetValue("")}
$a | Where{$_ -like "*Scripting*"}  #Wscript ist eine andere interessante Bibliothek für VBSler
#Ausgabe

Scripting.Dictionary
Scripting.Encoder
Scripting.FileSystemObject
Scripting.Signer

die Ausführung des Skripts dauert einige Sekunden

 
Mit Get-Member kann man sehr schön die verfügbaren Methoden und Eigenschaften  von Filesystemobject erforschen

New-Object -com Scripting.Filesystemobject | Get-Member
#gekürzte Ausgabe

TypeName: System.__ComObject#{2a0b9d10-4b87-11d3-a97a-00104b365c9f}

Name                MemberType Definition                                              
----                ---------- ----------                                              
...      
CreateFolder        Method     IFolder CreateFolder (string)                           
CreateTextFile      Method     ITextStream CreateTextFile (string, bool, bool)         
DeleteFile          Method     void DeleteFile (string, bool)                          
DeleteFolder        Method     void DeleteFolder (string, bool)                        
DriveExists         Method     bool DriveExists (string)                               
FileExists          Method     bool FileExists (string)            

 

1.4 Mit COM-Klassen Office automatisieren

Hier folgt nur ein kurzer Abschnitt über Powershell und Office, um in erster Linie die Verwendung von COM-Klassen zu demonstrieren. Eine ausführlichere Beschreibung der Steuerung besonders von Excel findet man im Kapitel Microsoft Office -> Excel


Beispiel 1: Neue Excelmappe öffnen und eine Zelle beschreiben

#deutsches Excel auf deutschem OS

Set-StrictMode -Version "2.0"
Clear-Host

 
$Excel = New-Object -com Excel.Application
$Excel.Visible=$True
$Excel.Workbooks.Add()
$Excel.Cells.Item(1,1)="4711"

Öffnet entweder eine neue Excelinstanz und schreibt "4711" in die obere, linke Zelle, oder wirft folgenden Fehler aus, wenn ein englisches Excelpaket auf einem deutschem Betriebssystem installiert ist

#Fehler

Ausnahme beim Aufrufen von "Add" mit 0 Argument(en):  "Altes Format oder ungültige Typbibliothek. (Ausnahme von HRESULT: 0x80028018 (TYPE_E_INVDATAREAD))"
Bei Zeile:3 Zeichen:21

+ $excel.workbooks.add <<<< ()
   
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ComMethodTargetInvocation

Abhilfe bringt die CultureInfo-Klasse, wie im nächsten Beispiel gezeigt wird.


Beispiel 2: Neue Excelmappe öffnen unter Einsatz des CultureInfo-Klasse

# Englisches Office auf deutschem OS

Set-StrictMode -Version "2.0"
Clear-Host
 
$Excel = New-object -com Excel.Application
$CI = [System.Globalization.CultureInfo]'en-Us'
$excel.Workbooks.PsBase.GetType().InvokeMember("Add", [Reflection.BindingFlags]::InvokeMethod, `
           $null, $Excel.Workbooks, $null, $ci)


$Workbook.Name

#Ausgabe

Book1

 

Um in Excel Objekte weiter zu erforschen, bietet sich der Objektkatalog an, den man in Excel über die VBA -Umgebung ("Alt-F11") und dort mit F2 öffnen kann. Eine nähere Beschreibung findet sich im Microsoft Office -> Excel

 

2 System.__ComObject

(Lesen und lesbar machen von bestimmten LDAP-Attributen)

Bei LDAP-Queries gegen das ActiveDirectory erhält man bei einigen Eigenschaften nicht direkt einen verwertbaren Wert zurück, sondern den auf den ersten Blick ziemlich wertlosen Eintrag "System.__ComObject"

$DomRoot=[ADSI]"" #gleichwertig zu [ADSI]"LDAP://DC=testdom,DC=intern"
$DomRoot | select *pwd*, lock*, *time*

#Ausgabe

maxPwdAge                : {System.__ComObject}
minPwdAge                : {System.__ComObject}
minPwdLength             : {7}
pwdProperties            : {1}
pwdHistoryLength         : {24}
lockoutDuration          : {System.__ComObject}
lockOutObservationWindow : {System.__ComObject}
lockoutThreshold         : {0}
creationTime             : {System.__ComObject}

von einigen Properties wie minPwdLength erhält man direkt aussagefähige Werte, einige muss man zu interpretieren wissen wie die pwdProperties MSDN: DOMAIN_PASSWORD_INFORMATION Structure und einige Eingenschaften wie midPwdAge oder creationTime verstecken wiegesagt ihr Geheimnis hinter dem Wert System.__ComObject.

Hier jetzt das Skript, das einige dieser Properties meiner Testdomäne bestimmt hat. Der entscheidende Teil des Skripts, nämlich die Funktion ConvertADSLargeInteger, stammt von der Site  bsonposh.com 

Set-StrictMode -Version "2.0"
Clear-Host
 
$DomRoot=[ADSI]""
$DomRoot | Select *pwd*,lock*, *time* #oberer Teil der Ausgabe

function ConvertADSLargeInteger([object] $adsLargeInteger)
{
    $highPart = $adsLargeInteger.GetType().InvokeMember("HighPart", `

     [System.Reflection.BindingFlags]::GetProperty, $null, $adsLargeInteger, $null)
    $lowPart  = $adsLargeInteger.GetType().InvokeMember("LowPart",  `

      [System.Reflection.BindingFlags]::GetProperty, $null, $adsLargeInteger, $null)

    $bytes = [System.BitConverter]::GetBytes($highPart)
    $tmp   = [System.Byte[]]@(0,0,0,0,0,0,0,0)
    [System.Array]::Copy($bytes, 0, $tmp, 4, 4)
    $highPart = [System.BitConverter]::ToInt64($tmp, 0)

    $bytes = [System.BitConverter]::GetBytes($lowPart)
    $lowPart = [System.BitConverter]::ToUInt32($bytes, 0)
 
    return $lowPart + $highPart
    # Funktion von bsonposh.com
}

"maxPwdAge: $((ConvertADSLargeInteger $DomRoot.maxpwdage.value)/-864000000000)"
"minPwdAge: $((ConvertADSLargeInteger $domRoot.minpwdage.value)/-864000000000)"
"lockoutduration: $((ConvertADSLargeInteger $DomRoot.lockoutduration.value)/-864000000000*24*60)"

$Ticks=ConvertADSLargeInteger $DomRoot.CreationTime.Value
$Datum=[DateTime]::FromFileTime($ticks)
"CreationTime: $($Datum.Datetime)"

#Ausgabe

maxPwdAge                : {System.__ComObject}
minPwdAge                : {System.__ComObject}
minPwdLength             : {7}
pwdProperties            : {1}
pwdHistoryLength         : {24}
lockoutDuration          : {System.__ComObject}
lockOutObservationWindow : {System.__ComObject}
lockoutThreshold         : {0}
creationTime             : {System.__ComObject}

maxPwdAge: 42
minPwdAge: 2
lockoutduration: 30
CreationTime: Freitag, 9. Juli 2010 11:49:27

Leider sind nicht alle {System.__Object} Werte LargeIntegerwerte. Beispielsweise ist die Eigenschaft "wellknownproperties" ist vom Typ "ADSTYPE_DN_WITH_BINARY". 

Für die Konvertierung solcher {System.__Object} -Werte muss man eigene Funktionen erstellen. Ich habe zumindest keine gefunden.