Have you ever found yourself writing the same PowerShell code over and over, thinking “there should be a built-in function for this”. Here is my trick for an even better PowerShell day! First I’ll show you how to create a PowerShell profile where you can define all of our favorite methods, and then I’ll show you how to use it on many computers, as you will probably want this on your servers as well as your desktop.
Start by opening a PowerShell and type $profile. This default variable contains a path to your PowerShell profile, usually located in the Documents\WindowsPowerShell, which does not exist by default. Run the following two lines to create the folder, and create an empty file.
mkdir (Split-Path $profile) -ErrorAction SilentlyContinue;
if(!(Test-Path $profile))
{
Set-Content -Path $profile -Value ""
}
After running these you have an empty profile. Use your favorite editor to edit the file.
# PS> ise $profile
The code inside this file will run each time your start a new PowerShell. Here you can define your own methods. What makes this very usefull is the possibility to create a method to download your PowerShell profile from the internet. Here is an example of such a function:
# Function to update the powershellprofile from the internet
function Update-PowerShellProfile() {
[CmdletBinding()]
Param()
Write-Verbose "Updating PowerShell profile"
if(!(Test-Path (Split-Path $profile))) {
Write-Verbose ("Profile path did not exist, creating {0}" -f (Split-Path $profile))
mkdir (Split-Path $profile)
}
Write-Debug "Creating System.Net.WebClient"
$wc = New-Object System.Net.WebClient
Write-Debug "Downloading file http://pastebin.com/raw.php?i=tdySrDgz"
$wc.DownloadFile("http://pastebin.com/raw.php?i=tdySrDgz", $profile)
Write-Output "Reload profile with the cmdlet: . `$profile"
}
Basically it downloads a some stuff from pastebin and puts into the PowerShell profile. After this, you can either open a new PowerShell to run the profile again, or you can type “. $profile” to re-load the profile.
Here is an example of a full profile (a subset of methods I have in mine). I have my own PowerShell profile hosted in my Dropbox folder, but you choose wherever you want, just change the Update-PowerShellProfile method.
function Connect-ExchangeOnline{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=0)]
[System.Management.Automation.PSCredential]$Credentials
)
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Authentication Basic -AllowRedirection -Credential $Credentials
Import-PSSession $session -DisableNameChecking
}
function Disconnect-ExchangeOnline {
[CmdletBinding()]
Param()
Get-PSSession | ?{$_.ComputerName -like "*outlook.com"} | Remove-PSSession
}
# Function to update the powershellprofile from the internet
function Update-PowerShellProfile() {
[CmdletBinding()]
Param()
Write-Verbose "Updating PowerShell profile"
if(!(Test-Path (Split-Path $profile))) {
Write-Verbose ("Profile path did not exist, creating {0}" -f (Split-Path $profile))
mkdir (Split-Path $profile)
}
Write-Debug "Creating System.Net.WebClient"
$wc = New-Object System.Net.WebClient
Write-Debug "Downloading file http://pastebin.com/raw.php?i=tdySrDgz"
$wc.DownloadFile("http://pastebin.com/raw.php?i=tdySrDgz", $profile)
Write-Output "Reload profile with the cmdlet: . `$profile"
}
# Set the PowerShell prompt to PS>
function prompt{
Write-Host -ForegroundColor Red "PS" -NoNewline
Write-Host -ForegroundColor White -NoNewline ">"
return " "
}
function ConvertTo-Base64
{
[CmdletBinding(DefaultParameterSetName='String')]
[OutputType([String])]
Param
(
# String to convert to base64
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromRemainingArguments=$false,
Position=0,
ParameterSetName='String')]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[string]
$String,
# Param2 help description
[Parameter(ParameterSetName='ByteArray')]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[byte[]]
$ByteArray
)
if($String) {
return [System.Convert]::ToBase64String(([System.Text.Encoding]::UTF8.GetBytes($String)));
} else {
return [System.Convert]::ToBase64String($ByteArray);
}
}
function ConvertFrom-Base64 {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,
Position=0,
ValueFromPipeline=$true)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[string]
$Base64String
)
return [System.Text.Encoding]::UTF8.GetString(([System.Convert]::FromBase64String($Base64String)));
}
function Split-String
{
[CmdletBinding()]
[OutputType([string[]])]
Param
(
# The input string object
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
Position=0)]
[String] $InputObject,
# Split delimiter
[Parameter(Mandatory=$false,
ValueFromPipeline=$false,
Position=1)]
[String] $Delimiter = "`n",
# Do trimming or not
[Parameter(Mandatory=$false,
ValueFromPipeline=$false,
Position=2)]
[Boolean] $Trim = $true
)
if($Trim) {
return $InputObject -split $Delimiter | foreach{$_.Trim()}
} else {
return $InputObject -split $Delimiter
}
}
function ConvertFrom-ImmutableID
{
[CmdletBinding()]
[OutputType([GUID])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$false,
ValueFromPipeline=$true,
Position=0)]
$ImmutableID
)
return [guid]([system.convert]::frombase64string($ImmutableID) )
}
function New-ObjectFromHashmap
{
[CmdletBinding()]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
Position=0)]
$Hashmap
)
Begin
{
}
Process
{
New-Object -TypeName PSCustomObject -Property $Hashmap
}
End
{
}
}
Then for each new server you are working on, just find a way to bring the Update-PowerShellProfile method, run it and you have the same profile everywhere, such as my Connect-ExchangeOnline method or the Split-String method.
Have fun!