To get a list of the COM components available on the computer you can use this PowerShell statement:
Get-ChildItem HKLM:\Software\Classes -ErrorAction SilentlyContinue |
Where-Object {
$_.PSChildName -match '^\w+\.\w+$' -and (Test-Path -Path "$($_.PSPath)\CLSID")
} |
Select-Object -ExpandProperty PSChildName | Out-GridView
On the computer I am writing this on there are 1219 COM components…
The statement above is part of the short and fine article „Get a list of all Com objects available“ by Jaap Brasser.
On MSDN there are some nice introductions:
MSDN Library: „Creating .NET and COM Objects (New-Object)“.
A COM object is created with the PowerShell CmdLet
New-Object
using the parameter -Strict
to stabilize the script when the COM component is using an Interop Assembly.The integration between COM and .NET is based on COM Interop.
Microsoft Office
Each product in Microsoft Office has at least one COM component. Usually they are used inside a Office product with Visual Basic for Applications (VBA), but VBA code can very easy be refactored to VBScript.Excel
The central COM component when working with Excel is the „Application Object“. This is a very short and incomplete example:$Excel = New-Object -ComObject Excel.Application -Property @{Visible = $true} -Strict -ErrorAction SilentlyContinue
$Workbook = $Excel.Workbooks.Add()
$Workbook.Author = 'Niels Grove-Rasmussen'
$Workbook.Title = 'PowerShell COM sandbox'
$Workbook.Subject = 'Sandbox on using COM objects in PowerShell'
$Workbook.Sheets.Item(3).Delete()
$Workbook.Sheets.Item(2).Delete()
$Sheet1 = $Workbook.Sheets.Item(1)
$Sheet1.Name = 'COM'
$Sheet1.Range('A1:A1').Cells = 'Cell A1'
$Sheet1.Range('B1:B1').Cells = 2
$Sheet1.Range('B2:B2').Cells = 3.1
$Sheet1.Range('B3:B3').Cells.Formula = '=SUM(B1:B2)'
$Excel.Quit()
Using
-Strinct
on the CmdLet New-Object
also generates 5+ lines of output about IDispatch
. This is suppressed with -ErrorAction SilentlyContinue
.Working with Excel through COM will often - of not always - end up using
Application.Sheets
. In the example above it is used to give the sheet a custom name and add values or a formula to cells.The Excel object does not close nice. So some COM cleanup is required to reset the COM environment after a Excel object is closed.
while( [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel) ) { 'Released one Excel COM count.' | Write-Verbose }
Remove-Variable Excel
[System.GC]::Collect()
As this is a old challenge there is a Microsoft article on the more general subject: „Getting Rid of a COM Object (Once and For All)“. One interesting thing about Excel in the article is that when Excel is closed manually a EXCEL.EXE process still is active.
Word
This is another example on a COM component in Microsoft Office. The naming is similar to Excel, so the central class is the Application Class.$Word = New-Object -ComObject Word.Application -Property @{Visible = $true} -Strict -ErrorAction SilentlyContinue
…
$Word.Quit()
Internet Explorer
The old Microsoft web browser has a COM component that used to be popular for a automation GUI. Some naming is aligned with Microsoft Office COM components – or the other way. The central class is the Application Class.$IE = New-Object -ComObject InternetExplorer.Application -Strict
$IE.Visible = $true
…
$IE = $null
Windows Scripting Host
The „old“ Windows automation Windows Scripting Host (WSH) from before PowerShell. By default there is script engine for Visual Basic Scripting Edition (VBScript) and JScript. Other languages are implemented to integrate with WSH, e.g. Perl and REXX. There are many old but good books, articles and examples around. Personally I prefer JScript as it has a more robust error handling than VBScript - and other subjective benefits.WScript
In this part of WSH the central COM class is WshShell.$vbInformation = 64
$vbOKCancel = 1
$Timeout = 0
$Wsh = New-Object -ComObject WScript.Shell -Strict
[int]$Button = $Wsh.Popup('Hello from PowerShell!', $Timeout, 'PowerShell', $vbInformation + $vbOKCancel)
$Wsh = $null
''
switch($Button) {
-1 { '???' }
1 { ':-)' }
2 { ':-(' }
}
The Popup method used above is a less nice way to put a popup window in a PowerShell Script. I have elsewhere written a nicer solution for a PowerShell MessageBox.
I think that if you need GUI elements then you should look at .NET Windows Forms before WSH.
Controller
WshController…Network
WshNetwork…Windows Shell
The central COM component to Windows Shell is the Shell object.Actually the name „Windows Shell“ is somewhat misleading as Windows Shell is usually used for the Windows command line shell
cmd.exe
. So if you are talking with others about the COM class Shell.Application
you should make sure to distinguish from cmd.exe
Windows Shell.$Shell = New-Object -ComObject Shell.Application -Strict
$Shell.Open('C:\')
…
$Shell = $null
ScriptControl
.
$Script = New-Object -ComObject MSScriptControl.ScriptControl -Strict
$Script.Language = 'vbscript'
$Script.AddCode('function getInput() getInput = inputbox(...')
$Input = $Script.eval('getInput')
This is a rather poisonous way to call a piece of VBScript code as the eval method is used. The method opens up for injection attack to the script.
Disclaimer: The example above should not be used in production!
When I have a more suitable example on using
ScriptControl
this example will be replaced.History
2017-06-06 Blog entry started as placeholder for ideas and old notes. Not released.2017-07-06 Notes rewritten, restructured and released.
No comments:
Post a Comment