DEV Community

Jeremy Lanssiers
Jeremy Lanssiers

Posted on Originally published at Medium

Set up a reusable Powershell environment for all your Windows machines

Set up a reusable Powershell environment for all your Windows machines

Tired of manually copying your favorite PowerShell aliases and functions to every new machine? I solved the sync problem! I show you how to set up your $profile to pull configurations from a centralized Git repository. I'll organize a setup into neat aliases.ps1, functions.ps1, and prompt.ps1 files.

Set up a Git Repo

Create or login to github.com, go to Repositories and create your GitHub repo. In this example, we'll create a repo called powershell.

On your machine, create a Repos directory in your home folder and change directory to that path. If you want to use another filename or location for your Repos dir, change to that path.

mkdir ~/Repos; cd ~/Repos;
Enter fullscreen mode Exit fullscreen mode

Inside your Repos directory, git clone the powershell repo you made on GitHub.

git clone https://github.com/<username>/powershell.git
Enter fullscreen mode Exit fullscreen mode

Set up environment variables

Go to Control Panel > System.

Control panel > System

Go to Advanced System Settings.

Advanced System Settings

Go to Environment Variables.

Environment Variables

Add a new variable REPOS_DIR and set the location of the Repos directory.

Add a new variable POWERSHELL_UTILS_DIR and set the location of the powershell repo directory.

Set up profile.ps1

Run echo $profile to see where your Powershell profile is defined.

Open your favorite text editor (Sublime Text Editor, Atom, Notepad …) and add the following lines:

$init = [string]::join([environment]::newline, (get-content -path $env:POWERSHELL_UTILS_DIR\init.ps1))
invoke-expression $init

$OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
Enter fullscreen mode Exit fullscreen mode

These lines reference init.ps1, we will create inside the powershell repo. This is the only setup step you have to repeat on all your machines.

You can set different locations for your Repos directory on each machine. The reusability of POWERSHELL_UTILS_DIR and REPOS_DIR is practical because you may want to set aliases to files or scripts inside your "powershell" repo. They will work on each machine, if you reuse $env: POWERSHELL_UTILS_DIR or $env:REPOS_DIR in your aliases or functions.

Set up Powershell configurations & functions

Inside init.ps1, add a loop to load all files with Powershell customizations (files ending in .ps1) in both the base directory and the functions subdirectory, e.g.

$baseDir = $env: POWERSHELL_UTILS_DIR 

$targetFolders = @(
    "$baseDir",
    "$baseDir\functions"
)

foreach ($folder in $targetFolders) {
    if (Test-Path $folder) {
        $files = Get-ChildItem -Path $folder -Filter *.ps1 -File
        foreach ($file in $files) {
            if ($file.FullName -ne $PSCommandPath) {
                . $file.FullName
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Inside aliases.ps1 inside the base directory, add useful aliases you want to reuse on every machine, e.g.

Set-Alias -Name cat -Value Get-Content -Option AllScope

Set-Alias -Name clr -Value clear

Set-Alias -Name echo -Value Write-Output -Option AllScope

Set-Alias -Name grep -Value findstr -Option AllScope
Enter fullscreen mode Exit fullscreen mode

Inside a functions.ps1 inside the functions subdirectory, add useful functions you want to reuse on every machine, e.g.

function Restart-Powershell { & $profile }
Enter fullscreen mode Exit fullscreen mode

Inside prompt.ps1 inside the base directory, customize your command prompt, e.g.

# Prompt format

function prompt {

    Write-Host ""

    # PS
    Write-Host "PS " -NoNewline -ForegroundColor "white" -BackgroundColor "black"

    # Working Directory
    $path ="$($executionContext.SessionState.Path.CurrentLocation) "
    Write-Host $path -NoNewline -ForegroundColor "blue" -BackgroundColor "black"

    #Git branch
    if (Test-Path .git) { 
        try {
            $branch = git rev-parse --abbrev-ref HEAD
            Write-Host "($branch) " -NoNewline -ForegroundColor "cyan" -BackgroundColor "black"
        } catch { }
    }

    # Prompt
    $userPrompt = ">"
    Write-Host $userPrompt -NoNewline -ForegroundColor "white"

    return " "
}
Enter fullscreen mode Exit fullscreen mode

Prompt

Prompt

Set up a cleanup function that can be executed on each machine

Create a Function inside utils.ps1 inside the functions subdirectory:

function Remove-Clutter { 
    $targets = @(
        "$env:USERPROFILE\Downloads\",
        "$env:USERPROFILE\OneDrive\OneDrive - Federal Public Service - Finance\Afbeeldingen"
    )

    $shell = New-Object -ComObject Shell.Application

    foreach ($target in $targets) {
        if (Test-Path $target) {
            Write-Host "Cleaning files at $target" -ForegroundColor Yellow

            Get-ChildItem -Path $target -File -Recurse | ForEach-Object {
                Write-Host "Cleaning file $($_.FullName)"

                $item = $shell.Namespace(0).ParseName($_.FullName)
                $item.InvokeVerb("delete")
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, we set an array of general file paths that need to be cleaned. Then, we iterate over the array and recursively remove all the files and directories nested under that file path. Notice the * after each file path, which makes sure only the children of that directory are deleted.

Top comments (0)