VCF Automation Blog

from Stefan Schnell

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 net8. It contains a namespace with the name ExampleLibrary and a class with the name ExampleClass with one static method and one instance method.

using System;
using System.Reflection;

[assembly: AssemblyVersion ("1.1.1.1")]
[assembly: AssemblyFileVersion ("1.1.1.1")]
[assembly: AssemblyCopyrightAttribute("Stefan Schnell")]
[assembly: AssemblyCompanyAttribute("Stefan Schnell")]
[assembly: AssemblyProductAttribute("ExampleLibrary with ExampleClass")]

namespace ExampleLibrary {

  public class ExampleClass {

    public string InstanceMethod(string Name = "World") {
      return "Hello " + Name;
    }

    public static string StaticMethod(string Name = "World") {
      return "Hello " + Name;
    }

  }

}

Unfortunately 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 code.

[Byte[]]$global:helloWorldAssembly = `
0x4D,0x5A,0x90, ... 0x00,0x00,0x00,0x00,0x00

Function Main {

  [System.Reflection.Assembly]$helloWorld = `
    [System.Reflection.Assembly]::Load($global:helloWorldAssembly)

  $class = $helloWorld.GetType("ExampleLibrary.ExampleClass")

  # [String]$Result = [ExampleLibrary.ExampleClass]::StaticMethod("Stefan");
  $staticMethod = $class.GetMethod("StaticMethod")
  [String]$Result = $staticMethod.Invoke($null, @("Stefan"))
  Write-Host $Result;

  # $instance = [ExampleLibrary.ExampleClass]::new()
  [System.Object]$instance = [System.Activator]::CreateInstance($class)
  # [String]$Result = $instance.InstanceMethod("Michael")
  $instanceMethod = $class.GetMethod("InstanceMethod")
  $Result = $instanceMethod.Invoke($instance, @("Michael"))
  Write-Host $Result;

}

# Main
Main

But it works.

vcf automation powershell action with embeded dotnet assembly

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. 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.