Powershell Plugin System

We wrote a powershell script that processes images from the internal system and sends them to another system. Now another part of the business would like to connect to this and do their own indat processing and push it to yet another system. Having asked around, around the company there are several stakeholders, so I would just like to add these new systems.

The first simple prototype opens all the .ps1files in a folder and launches a specially named function there and hopes for the best, basically. However, it seems that this could be improved. Is there any definite best practice for any plugin system? If not, given that this is done in a fairly secure environment, and the new modules will be checked by administrators, are there any problems with my approach above?

+3
source share
1 answer

Why don't you use the configuration file for your main script, explicitly indicating which script and which function to call? Something like this (warning: this is the copied / pasted and adapted code from what I wrote. Maybe a few crashes, but this gives you a general idea):

<?xml version="1.0"?>
<configuration>
  <Plugins>
    <Plugin Path="c:\blah\plugin1.ps1" PowerShellFunction="My-Plugin-Function" />
  </Plugins>
</configuration>

In the main script:

function Load-Plugins
{
    param (
        [parameter(Mandatory = $true)][xml] $config,
        [parameter(Mandatory = $true)][string] $nodeType
    )

    $plugins = @{}

    foreach ($pluginNode in $config.SelectNodes($nodeType))
    {
        if ($pluginNode)
        {
            $Path = $pluginNode.Path
            $powerShellFunction = $pluginNode.PowerShellFunction

            $plugin = New-Object Object |
                Add-Member -MemberType NoteProperty -Name "Path" -Value $Path -PassThru |
                Add-Member -MemberType NoteProperty -Name "PowerShellFunction" -Value $powerShellFunction -PassThru

            $plugins[$Path] = $plugin
        }
    }

    return $plugins
}


function Execute-Plugins
{
    param (
        [parameter(Mandatory = $true)][hashtable] $plugins
    )

    $Error.Clear()

    if (!$plugins.Values)
        { return }

    foreach ($plugin in $plugins.Values)
    {
        & .\$plugin.Path
        Invoke-Expression "$($plugin.PowerShellFunction)"
    }
}


function Load-Script-Config  
{
    param (
        [parameter(Mandatory = $false)][string] $configFile
    )

    if (!$configFile)
        { $configFile = (Get-PSCallStack)[1].Location.Split(':')[0].Replace(".ps1", ".config") }

        return [xml](Get-Content $configFile)
}

$pluginConfig = Load-Script-Config
$plugins = Load-Plugins $config "configuration/Plugins/Plugin"
Execute-Plugins $plugins
+3
source

All Articles