dotNET Assemblies are a deployment units in form of a dynamic link libraries (DLL). They contain classes, methods etc. to use it with dotNET applications. With the
Add-Type cmdlet and the -Path parameter it is possible to load an assembly DLL in the context of PowerShell. But how can we bring a dotNET Assembly DLL into a container of the PowerCLI runtime environment (RTE)?
Embed and use dotNET Assemblies
in PowerCLI RTE
There is a simple trick for this: We transform the binary file into an array of bytes. As simple text file, with the content "This is a test." and a length of 15 bytes, looks after the transformation like this:
[Byte[]]$FileContent = `
0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,`
0x61,0x20,0x74,0x65,0x73,0x74,0x2E
|
It is possible to perform the same procedure with any file, including dotNET assemblies.
Now to load a dotNET assembly into the PowerShell context of the PowerCLI RTE we use the System.Reflection namespace, with the Assembly class and the Load method. This method allows us to load an array of bytes, which contains the assembly.
[System.Reflection.Assembly]$assembly = `
[System.Reflection.Assembly]::Load($FileContent);
|
With this step are the methods etc. in the assembly available to use.
To try that I build my own test assembly with the targetframework netcoreapp3.1. It contains a class with the name Test with one static method and three instance methods.
public class Test {
public static void staticOut() { ... }
public void instanceOut() { ... }
public void instanceOutWithParams(string Name) { ... }
public string instanceOutWithParamsAndReturn(string Name) { ... }
}
|
Unfortunately, I found out that a method call is only possible via the dotNET Reflection namespace. This makes the call (a bit) more complicated, as you can see in the following example with the static method.
# [Test]::staticOut();
$assembly.GetType("Test").GetMethod("staticOut").Invoke($null, $null);
|
But it works.
Conclusion
Basically, it can be stated that the use of dotNET assemblies in the PowerCLI RTE is possible. On this way we can use assemblies whose source code is not available to us. But where there is light, there is also shadow.
- The size of a PowerShell script increases rapidly. If one byte is necessary in a file, four bytes are necessary in the PowerShell script, with separators even five bytes. Thus, 15 bytes, of the example above, turn into 74 bytes.
- The handling of the reflection namespace is not very comfortable with unknown classes. The necessary development effort is rather higher, maintenance and support are not made easier by the complexity here.
- From a security perspective, this mapping of classes, methods, etc. could also be seen as obfuscation. Here surely procedures would be necessary to guarantee the integrity.
As far as I can say seems this approach be certainly a viable way in a few exceptional cases. Good to know, but let's go around it.