Showing posts with label Profiles. Show all posts
Showing posts with label Profiles. Show all posts

Sunday, July 6, 2008

UPDATE: Importing Scripts as Libraries, Part Deux

I forgot to mention that the most convenient place to put this function is in your profile. What's that? You don't have a profile? Well What are you watiing for?

Make a folder inside your Documents folder called WindowsPowerShell. Inside that folder create a script called Microsoft.PowerShell_profile.ps1. Think of it as .bashrc for PowerShell.

I've uploaded my profile as an example here.

Also, note that I'm searching under the path pointed to by the PSPATH environment variable. I have it set to C:\PSLibs in my profile.

Importing Scripts as Libraries, Part Deux

In this post I showed how using the dotsource operator lets us run a script and import all of its named objects from the script scope into the global scope. The effect is as if instead of calling a script you just typed its contents at the prompt.

This set off a lightbulb in my head, and gave me the solution to something I'd been pondering for a while: how to import scripts as libraries (modules, etc, whatever we're calling them these days). You see, if I come up with a really neat function I don't want to have to cut and paste it into every script that uses it, and if I come up with a lot of content, I'd like to be able to share them with people.

This is what I came up with, and it incorporates a few new tricks I picked up along the way to trying to solve this problem. The desired result: I can type in 'import-script scriptname.ps1' and it is automatically imported without having to know the full path to the file.

Some highlights:
  • Test-Path is a nice cmdlet for checking the existence of a path on any PSDrive, so that means any Enviornment variable, registry key, file object, etc.
  • Exceptions work, but are really hard to get straight. Check out this link for some details.
  • The (, (command)) syntax is how I'm forcing the variable to be an array. I might get rid of it later, I think now that I'm using boolean comparison instead of looking for the length of the array to check if any files were found.
  • In most examples people use Write-Error instead of echo to print error messages, but I wanted to have the error show up clearly without all of the red words and extra garbage.
  • Note that I'm searching everything under the folder pointed to by the PSPATH environment variable. I point mine to C:\PSLibs by default.

function Import-Script ([string]$script) {
  $local:ReportErrorShowSource = 0

  # Clean up the Exception messages a bit
  trap [Exception] {
    $errmsg = "`n`tError importing '$script': "
    $errmsg += ($_.Exception.Message + "`n")
echo $errmsg
break
  }

  # Check PSPATH
  if (-not (Test-Path "Env:pspath")) {
    throw "PSPath environment variable not set."
  }elseif (-not (Test-Path $env:pspath)) {
    throw "PSPATH environment variable points to invalid path." 
  }

  $files = (, (dir $env:pspath $script -Recurse))

  # Make sure we find a single matching file
  if ($files.Length -gt 1) {
    throw ([string]$files.Length + " files of name '$script' found in PSPATH.")
  }elseif (-not $files) {
    throw "No files named '$script' found in PSPATH."
  }

  # Do the needful
  . $files[0].FullName
}

Setting up a Profile in PowerShell

Profiles in PowerShell are like "rc files" for Linux commands. The profile is a PowerShell script that is run every time you invoke the interpreter. You can use it to set up aliases, create default variables, or anything else that you can do in a PowerShell Script.

Profiles can be per-machine, per-user, or per-shell. See this website for the full details.

To set up your personalized profile for your user account, create the following file:

$env:userprofile\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

Here's the profile I set up for myself:

# PROFILE START ###########################

# ALIASES
set-alias subst 'subst-output.ps1'
set-alias match 'get-match.ps1'
set-alias ex 'explorer.exe'

# ENVIRONMENT
$env:pathext = (".PS1;" + $env:pathext)

# PATH
cd "$env:userprofile\Documents"

# PROFILE END #############################