Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Script organization (all my functions are cluttering my script)

I have a large script which I'm now cleaning up with the use of functions. But, I've found that it gets kinda messy to put them all at the top of the script.. I have to scroll past hundreds of lines of codes to get to the script itself..

How do you guys keep your scripts tidy? Do you have your functions in a separate file?

like image 738
Sune Avatar asked Feb 20 '12 14:02

Sune


People also ask

How do you organize your PowerShell scripts?

What to Do: Create multiple folders for each different module or set of scripts under the same project. Splitting these into their own folders means they can be built and versioned separately from one another. Possible Issues: The problem with project organization is it's difficult to organize at a very granular level.

Should PowerShell functions be at the top?

PowerShell is a script, not a compiled language. Therefore, it goes through the script line-by-line, top to bottom, (after tokenizing the script) and evaluates each command along the way.

Where are functions defined in PowerShell?

A function in PowerShell is declared with the function keyword followed by the function name and then an open and closing curly brace. The code that the function will execute is contained within those curly braces. The function shown is a simple example that returns the version of PowerShell.

How do you exit a function in PowerShell?

Open a PowerShell console session, type exit , and press the Enter key. The PowerShell console will immediately close. This keyword can also exit a script rather than the console session.


2 Answers

Try #Region and #EndRegion

If you use PowerGUI script editor you can use regions like this:

#region Set of functions A

function foo {
    Write-Host "Just a function"
}

function bar {
    return "Just another function"
}

#endregion

When you open the script in PowerGUI script editor the regions will be collapsed so you don't have to scroll to get to the main logic. This also works in Microsoft ISE. Not all script editors honor the region tags though.

Try dot-sourcing or importing as module

Another way is to externalize your functions either into another script and do what is called dot sourcing . C:\myfunctions.ps1 or put them in a module file named with a .psm1 extension and use Import-Module.

like image 122
Andy Arismendi Avatar answered Oct 10 '22 02:10

Andy Arismendi


Try Modules

The technique that we have adopted is to make all of our functions loaded via a script module. We created a folder to hold all of the individual function files and further subdivided them into their appropriate categories. Once we have done that we create a .psm1 file to tell the module what to load and then add the module path to our PowerShell profile (if not in the default Module location).

Folder structure

Module-Name\
    Subfolder1\
    Subfolder2\
    ...
    Module-Name.psm1

.psm1 file

Module-Name.psm1 (located underneath a folder with the same name - Required)

# Script Module for Company Functions
Function Get-ScriptDirectory {
    # $MyInvocation is an Automatic variable that contains runtime details and
    # we can use this to get information about where the file is run from.
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    Split-Path $Invocation.MyCommand.Path
}

Get-ChildItem (Get-ScriptDirectory) -Recurse `
    | Where-Object { $_.Name -like "func_*" } `
| %{
    . $_.FullName
}

Profile file

Microsoft.PowershellISE_profile.ps1 / Microsoft.Powershell_profile.ps1

$LocalLibraries = "C:\Local\Path\On\Disk\"
$env:PSModulePath = $env:PSModulePath + ";$LocalLibraries"

The above code means that you don't have to store the module in the same location as the rest (useful in our case since we use SVN to version and share our stuff with our team).

Recap

To recap:

  • Name function files as "func_{Verb}-{Namespace}{Noun}.ps1"
  • Create a top level folder to hold the module psm1 file
  • Create subfolders to categorize and hold the functions, i.e. Utilities, Active Directory, Exchange, etc.
  • Create your "psm1" file
  • Optional: Add additional module location to your profile

We prefix the "ps1" files with "func_" so that when tab-completing the function name, if in the same directory as the file, it will not get confused. In addition, we add the Namespace (company initials, etc) in front so that our function names will not collide with any other added functions.

Handy reload function

One additional, useful tip, that might come in handy during development is to define an alias, "reload" in our case, that will force the module to reload. This means that once you have changed a file, all you have to do is type that and it will be dot-sourced into memory again with your changes.

# Function to reload Module
Function int_ModuleNameModuleLoad {
    Import-Module Module-Name -Force -WarningAction SilentlyContinue
    Write-Host "Module-Name Reloaded"
}

# Set Aliases
If (-not(Get-Alias "reload" -ErrorAction SilentlyContinue)) {
    New-Alias -Name reload -Value int_ModuleNameModuleLoad -Force
}

The reason I use "int_" instead of our normal naming structure is that, this function is located within our profile and I consider it internal and not a full blown function.

I hope this gives you some good ideas, it has worked out great for us so far!

-Adam

like image 36
alistek Avatar answered Oct 10 '22 01:10

alistek