Windows Script Component (WSC) goes a long way back. This technique is almost 15 years old, dating from Windows 2000.
But you can still use it, even by the latest Powershell version.
Find here more information about what WSC is.
In short WSC gives you the possibility to create COM objects on the fly. Which you can register as normal COM objects exposing you methods and properties.
As you can see the WSC files show up with different Icon. If you right click it you see extra shortcut menu’s.
Register will register you COM object in the registry if you filled up the WSC file with the proper XML sections. The same as you would use the regsvr32.exe command line tool.
Or you can just run functions as is, without registering.
WSC supports VBScript / JScript and PerlScript.
Let’s give an example on how to access the object from within PS.
1. Create a simple WSC file.
This simple example will display a Message Box with a text as parameter, when invoked using PS.
You need to use the .Net [system.runtime.interopservices.marshal]::BindToMoniker to connect to the WSC object.
As you can see I use the following prefix syntax “script:…” in order to call the WSC object on the fly.
This will avoid you to register the COM object on your system. Which makes it extremely flexible. You can now adjust the WSC code on the fly and run it. As well as copy it on multiple machines without any admin overhead.
The InvokeMember has 5 parameters, which explain themselves :
1. “Test” is the name of the WSC VBScript function to call.
2. $im holds the BindingFlags method
3. Not used
4. Variable that holds the references to the WSC Object
5. Used to send across the Parameter(s) to the WSC function.
Here is the full code with some helper calls in between.
CLS $test = [system.runtime.interopservices.marshal]::BindToMoniker("script:C:\_\Apps\_PowerShell\_Advanced Examples\_WSC Examples\Test.wsc") $isObj = [system.runtime.interopservices.marshal]::IsComObject($test) write-host $isObj Write-host " " Write-host "Get-Type" $test.GetType() $param = "Hello World ! -> From PowerShell to WSC" $im = [System.Reflection.BindingFlags]::InvokeMethod $test.GetType().psobject.BaseObject.InvokeMember("test", $im, $null, $test, $param) $ret1 = [System.Runtime.InteropServices.Marshal]::GetIDispatchForObject($test) $ret2 = [System.Runtime.InteropServices.Marshal]::GetIUnknownForObject($test) $uObj = [System.Runtime.InteropServices.Marshal]::GetUniqueObjectForIUnknown($ret2) $Obj = [System.Runtime.InteropServices.Marshal]::GetObjectForIUnknown($ret2) # refers back to $WSC COM object returns the GUID write-host " " #[System.Runtime.InteropServices.Marshal]::Release($test) [System.Runtime.Interopservices.Marshal]::ReleaseComObject($test) write-host "5. " $ret1 $ret2 $uObj $obj write-host " " [System.Runtime.InteropServices.Marshal]::AreComObjectsAvailableForCleanup() write-host " " [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() rv test, im, param, isObj, ret1, ret2, uobj, obj [System.GC]::Collect()