preloader
12 October 2011 / #Powercli

OneLiner or Not OneLiner, that is the question !

post-thumb

It’s been a while we wanted to write this post, there was just a draft, and each time we’re passing by, we’re still thinking Damn, yes, still have to finish it !! Here it is today :p This post ask good question : OneLiner or Not OneLiner ?

In some case (our friend and co-worker hypervisor.fr will sure confirm it), OneLiner is more than just a piece of code, it’s almost an Art of coding :p It’s true it’s convenient, we just have to run the line of code, there’s no need to call a filescript, fill some arguments, etc !

ps1loader_oneliner

In that case, we got all the awesome scripts from LucD or Alan Renouf, but they usually are *.ps1 files, so we have to load them in our PowerCLI session, and if we accidentally close it or open a new session, we have to reload them all each time! So we have been told that if we could take full advantage of both sides and gain OneLiner ease with *.ps1 scripts.

What we’re trying to do is :

  1. get a repository where we’ll put all *.ps1 scripts
  2. a function in order to load on demand theses cmdlets/functions
  3. an automatic load of theses cmdlets/functions at PowerCLI console launch

For the repository, it’s easy, we just need to create a folder which will host all the *.ps1 files with all the functions/cmdlet we wanted to use. For example, soon as we get the last PowerCLI Man script : straight to the magic folder !

ps1loader_folder

For the second point, we’ll create a Load-KickAssScripts.ps1 file in the repository seen before and which will contain the following code :

# PowerCLI Scripts loader and reloader
# www.vmdude.fr

Function global:Load-KickAssScripts([switch]$Silent = $false) {
    # Repository path of all *.ps1 scripts
    $path4Source = "C:\PowerCLI Scripts"

    ForEach ($Script2Source in (Get-Childitem $path4Source\* -Include *.ps1 -Exclude Load-KickAssScripts.ps1)) {
        # Sourcing of all ps1 scripts in directory
        . $Script2Source.FullName
        if (!$Silent) {
            Write-Host -Foregroundcolor green "Source of" $Script2Source.FullName
        }
    }
}

This will allow us to load new *.ps1 scripts hosted in our repository without the need for restart our PowerCLI console.

Then for the point 3. we’ll edit the C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1 file in order to add the following piece of code just before the script signature (end of file) :

...
. "C:\PowerCLI Scripts\Load-KickAssScripts.ps1"
Load-KickAssScripts -Silent

# SIG # Begin signature block
...

In our example, we have a Get-HelloWorldByVMdude.ps1 file with the following basic test code :

# Sample Hello World for testing automatic sourcing on PowerCLI profiles
# www.vmdude.fr

Function global:Get-HelloWorldByVMdude {
    Write-Host -ForegroundColor red "Hello World !"
}

Once we put it in place, we have the desired behavior :

ps1loader_details

  • Step n°1 : we check the automatic load of Get-HelloWorldByVMdude.ps1 file
  • Step n°2 : we check the execution of the function
  • Step n°3 : we copy into the repository a new script file named Get-YellowHelloWorldByVMdude.ps1 with the following code :
# Sample Hello World for testing automatic sourcing on PowerCLI profiles
# www.vmdude.fr

Function global:Get-YellowHelloWorldByVMdude {
    Write-Host -ForegroundColor yellow "Hello World !"
}
  • Step n°4 : we call back the repository files loader
  • Step n°5 : we check if the new file was well-loaded
  • Step n°6 : we check the execution of the new function

Finally, this will allow to have best of the 2 worlds and the automatic loader allow us to load new scripts without having to close/restart PowerCLI console.

So to the question OneLiner or Not OneLiner, the answer is : both !

You can download the tests scripts used here :

Note : It’s important that function defined in the scripts hosted into the repository are in the global PowerCLI context (more information about scopes are available with the cmdlet Get-Help about_Scopes)

In order to verify this, you just have to check the function declaration which have to be defined like :

Function global:FUNCTION_NAME() {}

and not like :

Function FUNCTION_NAME() {}

> Frederic MARTIN