Environment

This section describes ways to customize your environment. Quite likely, you will need to configure the system to suit better your needs. That includes scripting common tasks, installing useful modules, etc. You do not need to start from scratch for that. There are a few starting points, such as mine which are available at https://github.com/gkantsidis/WindowsPowerShell. It is quite useful to put your customizations and scripts into a version control system. That will allow you to use the same settings on many machines and keep track of the evolution of your scripts.

For most scripts and common uses, you should not have to bother with the information towards the end of this section. Standard commands and modules should work ok. However, if PowerShell gains traction in other operating systems and in different environments, or if you want to script non-standard PowerShell hosts, you need to keep in mind the variety of versions, editions, and hosts; not all features are available to all of them; you may experience variability even on the same machine. As a script writer, you may need to restrict the use of your scripts to specific PowerShell configurations to avoid creating problems for your users.

Profile

The user profile is typically stored in %UserProfile%\Documents\WindowsPowerShell(from cmd), or $Env:UserProfile\Documents\WindowsPowerShell (from PowerShell). That directory does not need to exist. If it does, upon invoking PowerShell, the system will first try to locate there a file named profile.ps1 and execute it. It will also try to locate a file whose name is given in variable $profile, and it will execute it after. That second file depends on the PowerShell Host (see note later in this section); for example, for the standard PowerShell shell it is called Microsoft.PowerShell_profile.ps1.

In the next version of PowerShell (v6.0 --- currently in beta), the directory is now called %UserProfile%\Documents\PowerShell. (Creating a junction between the two directory works --- however, traditional profiles may not work very well with the new PowerShell.) In Unix, it is ~/.config/powershell.

The system also looks for configuration info in %windir%\system32\WindowsPowerShell\v1.0\ (cmd) or $Env:windir\system32\WindowsPowerShell\v1.0\ (PowerShell). Again, it will search for profile.ps1 in that directory and Microsoft.PowerShell_profile.ps1 or similar.

See Windows PowerShell Profiles for an old description of the profiles (this page used the old location of the user Documents directory, My Documents, which does not exist any more --- the rest of the instructions are still valid).

Modules

You can organize code in modules. Later, I give some notes on writing modules (see Modules). By default, the system will search in the set of directories stored in $Env:PSModulePath (or, %PSModulePath% from cmd) variable for the list of available modules. You can see the list of available modules using:

Get-Module -ListAvailable

and

Get-Module

to get a list of the loaded modules.

In the recent versions, PowerShell has better capabilities for automatically loading modules on request (i.e. when trying to execute an instruction). When you want to explicitly load a modules use:

Import-Module -Name <ModuleName>

(You can also use the -Verbose parameter to debug loading issues.)

If the module resides in a non-standard location use:

Import-Module -Name <Path>

Observe that in the <Path> you should not include the trailing \ and if it is in the current directory you should prefix with .\:

Import-Module -Name .\<LocalPath>

For more information see Importing a PowerShell Module page at MSDN.

External Modules

There are plenty of ready modules that you can use to improve your PowerShell experience. Many of them can be found in PowerShell Gallery. There are other sources as well, such as repos in GitHub. To find modules and scripts in the PowerShell Gallery, you can use the commands Find-Module, Find-Script, Install-Module, and Install-Script; these are available from the PowerShellGet module. The module also provides support for management of the install modules, e.g. to update them with Update-Module and its short version upmo, and to delete modules Uninstall-Module.

For modules from GitHub, you should clone to a local directory, and make sure that the (parent) directory is included in $Env:PSModulePath.

System wide modules are installed under $Env:windir\System32\WindowsPowerShell\v1.0\Modules whereas those installed with PowerShellGet are under $Env:ProgramFiles\WindowsPowerShell\Modules. Keep in mind that it is possibly to have multiple versions of the same module installed. By default, the latest version is loaded; you may want to periodically clean old versions.

Sources of modules and scripts

Here is a list of sources where to search for modules and scripts:

The first was also described in the previous note.

Checking for elevated permissions

There are many ways to check whether a script runs elevated. The Writing Scripts->Script Requirements note suggests using the #Requires directive to guarantee that the script will not run unless with elevated permissions. However, sometimes you just need to check whether you are running in that mode. One way to do so is the following:

If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{ 
    Write-Host "Please run this script elevated"
    exit
}

The process above is equivalent to:

$myIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$wp = New-Object Security.Principal.WindowsPrincipal($myIdentity)
$isAdmin = $wp.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)

A better way is to use the Test-AdminRights from the xUtility module.

PowerShell Version and Host

To get the version of PowerShell use $PSVersionTable.PSVersion. See the Wikipedia article for more information about the existing versions and their capabilities. In summary, it is important to keep in mind:

Version OS Interesting Features
2.0 Windows 7, Server 2008 R2, etc Remoting, modules, ISE, etc.
3.0 Windows 8, Server 2012, etc Automatic module detection, better remote sessions, etc.
4.0 Windows 8.1, Server 2012 R2, etc Desired State Configuration (DSC), better debugging, changes in remoting, etc.
5.0 Windows 10, Server 2016 Classes, enumerations, better debugging, package management with Chocolatey
6.0 (in beta) .NET Core (Windows and Linux) Transition to .NET Core, cross-platform

If you can use PowerShell 5.0, you should definitely do so. The package management improved a lot, the use of classes can improve the quality and maintainability of scripts, etc.

To get the current edition of PowerShell use $PSEdition. The default edition is Desktop; there is also the Core edition. (This corresponds to the .NET environment used; the Desktop corresponds to .NET Framework and you get all features, and Core corresponds to .NET Core and you get reduced features but more portability.) I have not had to use the Core edition, but this may become relevant if PowerShell becomes popular in more platforms (that may contain .NET Core). It may create problems later as many scripts use features that will not be available to Core, but most scripts (and I suppose existing modules) do not currently check for it.

To check the host of PowerShell use $Host. There are many available hosts, including ConsoleHost (this is what you use when starting PowerShell.exe; it is the most common), Windows PowerShell ISE Host (this is used by Windows Powershell ISE Host), Visual Studio Code Host, PowerShell Tools for Visual Studio Host, ServerRemoteHost when connecting to a remote machine (e.g. with Enter-PSSession), and many others (actually, it is not very difficult to write your own host1). Often experiences and capabilities are not available on all hosts. Most likely, you need to care about the ConsoleHostand be careful that some advanced features (from 3rd party modules) may not work well or even crash in the other hosts.

In addition, the environment also depends on the platform (Win32NT for the default Windows OS and Unix for Linux, Linux subsystem on Windows [LXSS], MacOS, etc.); you can check that with [System.Environment]::OSVersion.Platform. The processor also affects the libraries that may be available; you can check that with $Env:PROCESSOR_ARCHITECTUREin Windows and $Env:HOSTTYPE in Linux (Ubuntu). Most typically, this would be AMD64or x86(underscore)64, respectively. Another variation may arise from the type of the console host. You can retrieve that with $host.Name; in Windows it is ConsoleHost; TODO: check value for Linux.

To summarize, PowerShell may run in a large variety of environments. Currently, the most popular is Windows with .NET Framework. Use the following commands to get an idea of the capabilities of your PowerShell environment:

$PSVersionTable.PSVersion
$PSVersionTable
$PSEdition
$Host

See Script Requirements for mandating the running environment of a script.

PowerShell Core (aka PowerShell 6.0)

Starting with PowerShell Core 6.0, PowerShell will become cross-platform. Read more in this blog. PowerShell will change to .NET Core, a change that may raise compatibility problems. According to the blog, there is work to ensure binary compatibility.

Building PowerShell from Source

The source repository is hosted in GitHub. Follow the instructions on GitHub to clone and build.

Building in Windows

For Windows the instructions are here. In a nutshell, make sure that the following apply:

  • The Visual Studio 2015 toolchain is in the PATH.
  • If cmake is installed, also make sure that it is in the PATH.

Optionally:

  • Set environment variable DOTNET_CLI_TELEMETRY_OPTOUT to 1 to disable telemetry.

Then the steps are as follows:

Import-Module ./build.psm1

Start-PSBootstrap
# if there is an existing version of dotnet, you may want to try:
Start-PSBootstrap -Force
# (make sure that the right version of dotnet appears first in path)


Start-PSBuild
# for the release version, try:
Start-PSBuild -Configuration Release

The output will be in ./[project]/bin/[configuration]/[framework]/[rid]/[binary name], e.g. src\powershell-win-core\bin\Debug\netcoreapp2.0\win10-x64.

This page claims that it is possible to build a version that uses .NET Framework with:

Start-PSBuild -FullCLR

however, this does not seem to work anymore.

Building in Linux

Instructions to setup PowerShell on Linux are here. The instructions assume Ubuntu 14.04 LTS, and I believe they also assume Intel architecture (at least x64). Not sure whether (or, how) it can be built in ARM.

Roughly, the installation steps are as follows:

./tools/download.sh
powershell
Import-Module ./build.psm1
Start-PSBootstrap
# Maybe restart the process at this point (from a new shell) to get the updated path
# For debug version
Start-PSBuild
# For release version
Start-PSBuild -Configuration Release

In bash on Windows, the console host is not behaving very well (the same is true also for the cmder program). Hence, you need to be careful with changes to the prompt, etc. (TODO: Check on a proper Ubuntu machine.)

It seems that the PowerShell modules PackageManagementand PowerShellGet (GitHub) are not installed. TODO: How does module management works in Linux? Using the files from another installation (e.g. the Windows version when using bash on Windows) seems to work ok. A better approach may be to build and install from sources:

./bootstrap.ps1 netstandard1.6
./build.ps1 netstandard1.6

Then copy the folder src/out/PackageManagement to the module search directory (e.g. ~/.local/share/powershell/Modules/) and inside that directory there is a coreclr subdirectory; if empty, copy the dlls from another installation.

Also, install PowerShellGet from:

Startup behavior

With respect to startup, observe that unlike the existing PowerShell installation, the user settings are not expected to be in %USERPROFILE%\Documents\WindowsPowerShell but in %USERPROFILE%\Documents\PowerShell (in Linux it is in ~/.config/powershell). One option is to create a link between the two directories. However, you need to be careful since many modules will not work well with .NET Core.

1. See https://msdn.microsoft.com/en-us/library/ee706563

results matching ""

    No results matching ""