PowerShell profiles are used for loading common scripts, add-in’s, functions, etc into the PowerShell session at startup. There are four different locations where profiles are loaded from:
You can have four different profiles in Windows PowerShell. The profiles are listed in load order. The most specific profiles have precedence over less specific profiles where they apply.
|
The Problem
This works out just fine if you want to write your own profile.ps1 file and load it from one of those areas. For example, you could perform a Set-Alias for MSBuild if you wanted to have “msbuild” run the msbuild file of your choice (2.0, 3.5, etc). But what happens when you want to load an external function that is located in another script? For example, lets say I have a script called “Convert-Xml.ps1” on my disk – as shown below (script source):
function Convert-WithXslt($originalXmlFilePath, $xslFilePath, $outputFilePath)
{
## Simplistic error handling
$xslFilePath = resolve-path $xslFilePath
if( -not (test-path $xslFilePath) ) { throw “Can’t find the XSL file” }
$originalXmlFilePath = resolve-path $originalXmlFilePath
if( -not (test-path $originalXmlFilePath) ) { throw “Can’t find the XML file” }
$outputFilePath = resolve-path $outputFilePath
if( -not (test-path (split-path $originalXmlFilePath)) ) { throw “Can’t find the output folder” }## Get an XSL Transform object (try for the new .Net 3.5 version first)
$EAP = $ErrorActionPreference
$ErrorActionPreference = “SilentlyContinue”
$script:xslt = new-object system.xml.xsl.xslcompiledtransfrm
trap [System.Management.Automation.PSArgumentException]
{ # no 3.5, use the slower 2.0 one
$ErrorActionPreference = $EAP
$script:xslt = new-object system.xml.xsl.xsltransform
}
$ErrorActionPreference = $EAP
## load xslt file
$xslt.load( $xslFilePath )
## transform
$xslt.Transform( $originalXmlFilePath, $outputFilePath )
}
The end result is that when I start PowerShell I want to load this function inside of my profile when PowerShell starts up. If that happened I would be able to start PowerShell and type Convert-WithXslt and get the function to work no problem. How do we load an external script into the current session via the profile.ps1 script? Hmm… not so simple at first.
How To Load an External Script Into Your Profile
In your profile.ps1 file, you can script it like this (assuming that your profile.ps1 is in one of the locations above):
# Loads the script into the profile.
$fileContents = [string]::join([environment]::newline, (get-content -path C:\PowerShellScripts\Convert-Xml.ps1))
invoke-expression $fileContents
This will load the script (C:\PowerShellScripts\Convert-Xml.ps1) contents into your profile. Now the function Convert-WithXslt will be available from the shell.
Script Explained
- (get-content -path C:\PowerShellScripts\Convert-Xml.ps1) – This opens the script, reads the contents and then returns the entire file. The ( ) are necessary because get-content returns an array of lines of text. ( ) force full evaluation of the expression. Therefore the full array is returned. Each item in the array is a line of text.
- [string]::join([environment]::newline, (get-content -path C:\PowerShellScripts\Convert-Xml.ps1)) – In this script we take the array as shown above, and join it on the new line character. Therefore we have a full string of the file contents.
- $fileContents = … – Now we just set it to a local variable.
- invoke-expression $fileContents – This runs the Invoke-expression cmdlet. In a nutshell this command takes the value of whats in $fileContents and runs it in the local session. Therefore, if we have a function declaration inside of that variable, we can then invoke the shell to evaluate that function declaration which in turn will then add that function to the shell’s session. Now your profile can execute whatever is in this script. Functions, aliases, etc.
Taking it a Step Further
What if you want to have a common set of scripts that everyone on your team should be using? You wont want to have those scattered over 25 PCs. What if you have to update one of them? You’ll have to update 25 machines. No good.
So here’s a simple script that will go out to a network share, load all the files it finds in the share, and load them into the PowerShell session. Therefore we have now out-sourced our profile declaration to a centralized location. I’m sure there are 10 other ways to do this, but this is the way I stumbled upon it.
I would put this file in the “%windir%\system32\WindowsPowerShell\v1.0\profile.ps1″ location so that each person who logs onto the machine now has access to the profile.
# Loads the profile for all users.
$locationOfScriptsToLoad = “\\YourCorporateShare\PowerShell\”$files = (ls -path $locationOfScriptsToLoad -recurse | where { $_.attributes -ne “directory” })
foreach($file in $files)
{
# Load the contents of the file into the profile
$fileContents = [string]::join([environment]::newline, (get-content -path $file.fullname))
invoke-expression $fileContents
}
Basically, this script will go up to \\YourCorporateShare\PowerShell\ and find all files inside of it – excluding directories (as directories are objects in PowerShell too, I want to exclude them and this is done with the { $_.attributes -ne “directory }. Once we have the file we will loop through each file and load it into the current PowerShell session. This allows you to store all of your shared PowerShell profile needs in one location. As long as this profile.ps1 script is loaded, the person executing PowerShell will have access to all the profile info.
I hope this helps anyone who is using PowerShell and wants shared profiles.
Ken says
Dope!
1603602377 says
http://www.louisvuittonpurses-bags.net Louis Vuitton Purses
http://www.louisvuittonhandbags-lv.com LV Bags
http://www.cheaplouisvuitton-bags.net Cheap Louis Vuitton
http://www.louisvuitton0.com Louis Vuitton
http://www.louisvuittonoutletsun.net Louis Vuitton Sunglasses
http://www.louisvuittonhandbags-lv.com Louis Vuitton Handbags
http://www.coachsoutletonline.org Coach Online Outlet
http://www.coachfactorysoutletonline.org Coach Factory Online
http://www.coachsfactoryoutlet.net Coach Factory
http://www.coachsoutletstoreonline.com Coach Outlet
http://www.alouisvuittonhandbags.com Authentic Louis Vuitton
http://www.burberryscarfoutlete.net Burberry Outlet
http://www.coachsoutletonline.org Coach Factory Outlet Online
http://www.e-louisvuittonoutlet.net Louis Vuitton Outlet
http://www.burberryscarf-outlet.com Burberry Outlet
http://www.coachfactoryoutletonlinstores.net Coach Factory Outlet Online
http://www.cheapcoachsbags.net Coach Bags
http://www.louisvuittonpurses-bags.net Louis Vuitton Bags
http://www.chanelbags-max.com Chanel Bags
http://www.louisvuittonbagsonline.net Louis Vuitton Bags
http://www.louisvuittonoutletsz.com Louis Vuitton Outlet
http://www.burberrybags-sale.net Burberry Bags
http://www.coachfactorysoutletonline.org Coach Factory Outlet Online
http://www.chanelhandbags-bags.net Chanel Bags
Sir_higgins says
you can use
get-content -path C:PowerShellScriptsConvert-Xml.ps1 -raw | invoke-expression
instead of
$fileContents = [string]::join([environment]::newline, (get-content -path C:PowerShellScriptsConvert-Xml.ps1))
invoke-expression $fileContents