Loading PowerShell Profiles from Other Script Files

by Donn Felker 29. October 2008 09:47

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:

powershell

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.

    • %windir%\system32\WindowsPowerShell\v1.0\profile.ps1

      This profile applies to all users and all shells.

    • %windir%\system32\WindowsPowerShell\v1.0\ Microsoft.PowerShell_profile.ps1

      This profile applies to all users, but only to the Microsoft.PowerShell shell.

    • %UserProfile%\My Documents\WindowsPowerShell\profile.ps1

      This profile applies only to the current user, but affects all shells.

    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

    1. (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.
    2. [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.
    3. $fileContents =  ... - Now we just set it to a local variable.
    4. 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.

     

    Downloads

    profile.ps1

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    PowerShell | Productivity

    Custom Google Maps Geocode Powershell CmdLet

    by Donn Felker 18. September 2008 09:43

    This may look like a repeat... well.. because it is... BUT.. you cannot find the old post. Why? Because, well ... it no longer exists. My old host decided to accidentally delete my account. Yeah. Oops. After that nightmare, I've moved to a new host where the grass is greener, the hippies wear deodorant and well ... wait ... never mind... onto the good stuff...Here's the old post, reposted again.

    ---------------------------------

    Ok, I admit ... I have a fascination with maps. Why? Who knows. I just love knowing where I'm at, where I'm going, not being lost, etc etc etc. Last year I wrote a C# class that would connect to Google Maps and return the latitude and longitude of an address by utilizing the Google Maps API. Get that class

    Awhile back I also wrote about the complexity of our industry and about how staying up to speed is quite difficult. Jeffrey Snover (PowerShel/Windows Management Architect) commented on that post and recommend learning PowerShell. I completely agree with what he said. However - I've only scratched the surface of PowerShell and its capabilities and just recently I picked up a copy of Bruce Payettes "Windows PowerShell in Action". So far, its a great book. I'll post a review when I'm done. But as I was reading I got into thinking about how I would like to Geocode addresses from the command line in certain instances. A custom PowerShell cmdlet was in fashion. 

     

    The Get-GoogleGeocode CmdLet

    At that point, the Get-GoogleGeocode cmdlet was born. I took my code from the C# Google Maps Geocoding class I wrote, added a new property "Address" (which is what I needed to store the address the user supplied) as a simple string and then wrapped it in a cmdlet. 

    The result? An awesome cmdlet. 

    The cmdlet will take your Google Maps API Key and a list of addresses and it will Geocode them for you. Very simple, yet very powerful. 

    Lets take a look at what it can do: 

    Examples

     

    Note: My Google Maps API key has been hidden in the examples below ... SO YOU DONT STEAL IT! ;)

     

    Script Explanation

    Click the pictures for full resolution images.

     

     

    Example 1:  Gets  the longitude and latitude for one single address and outputs it to the screen.

    ps1

    PS C:\Development\DF.PowerShell.Cmdlets\bin\Release> Get-GoogleGeocode -apiKey <YourAPIKeyGoesHere> -addresses "2203 E. Empire St. Bloomington, IL 61704"

    Address Latitude Longitude
    ------- -------- ---------
    2203 E. Empire St. Bloomington, IL 6... 40.488283 -88.945315

     

    Example 2:  Gets the longitude and latitude for multiple addresses and outputs them to the screen. 

    ps2

    PS C:\Development\DF.PowerShell.Cmdlets\bin\Release> Get-GoogleGeocode -apiKey <YourAPIKeyGoesHere> -addresses "2203 E. Empire St. Bloomington, IL 61704", "8300 Norman Center Dr., Suite 950 Bloomington, MN 55437"

    Address Latitude Longitude
    ------- -------- ---------
    2203 E. Empire St. Bloomington, IL 6... 40.488283 -88.945315
    8300 Norman Center Dr., Suite 950 Bl... 44.853079 -93.352194

     

    Example 3:  (I think this is the REALLY cool one) Opens a file, reads each line and gets the longitude and latitude for each address in the file.

    ps3

    PS C:\Development\DF.PowerShell.Cmdlets\bin\Release> Get-Content c:\temp\MicrosoftOffices.txt | Foreach-Object {Get-Goog
    leGeocode -apikey <YourAPIKeyGoesHere> -addresses $_ }

    Address Latitude Longitude
    ------- -------- ---------
    2203 E. Empire St. Bloomington, IL 6... 40.488283 -88.945315
    77 W. Wacker Dr., Suite 2300 Chicago... 41.886499 -87.630526
    3025 Highland Pkwy., Suite 300 Downe... 41.831445 -88.010731
    500 E. 96th St., Suite 460 Indianapo... 39.928171 -86.150754
    N19 W24133 Riverwood Dr., Suite 150 ... 43.056940 -88.229463
    4601 Westtown Parkway, Suite 136 Wes... 41.610376 -93.711712
    10801 Mastin Blvd., Suite 620 Overla... 38.932978 -94.702328
    8300 Norman Center Dr., Suite 950 Bl... 44.853079 -93.352194
    3 City Place Dr., Suite 1100 St. Lou... 38.670381 -90.433552
    13815 FNB Parkway Omaha NE 68154 41.266103 -96.130733

     

    Script HELP

    If you ever forget about how to run this command, I have included the help files as well. 

    Access help by typing: Get-Help Get-GoogleGeocode. This will give you very basic help. For detailed or full help type: Get-Help Get-GoogleGeocode -detailed or  Get-Help Get-GoogleGeocode -full

    To use this script, execute the command Get-GoogleGeocode and supply a api key and a list of addresses separated by a comma. 

    From help:

    PS C:\Development\DF.PowerShell.Cmdlets\bin\Release> get-help get-googlegeocode
    NAME
        Get-GoogleGeocode
    SYNOPSIS
        This cmdlet will return the latitude and longitude of the addresses that are passed into the cmdlet.
    SYNTAX
        Get-GoogleGeocode -ApiKey <String> -Addresses <String[]> [<CommonParameters>]
    DETAILED DESCRIPTION
        This cmdlet will return the latitude and longitude of the addresses that are passed into the cmdlet. The apikey is
        required for this to work. Also, you may encounter proxy issues if you require a proxy for access to the internet.
        This cmdlet utilizes the System.Net.WebClient class to access the internet. This cmdlet will connect with the Googl
        e Maps API, ask for the geocoding information and then return it.
        You will need a Google Maps API Key for this. Sign up for one here: http://code.google.com/apis/maps/
        If the latitude and longitude are both ZEROS, this means the address could not be geocoded.
    RELATED LINKS
    REMARKS
        For more information, type: "get-help Get-GoogleGeocode -detailed".
        For technical information, type: "get-help Get-GoogleGeocode -full".

     

    How to Install

    Start powershell and navigate to the Release directory run the "install.ps1" script from the command line. It should look like this when you run it: 

    install

     

    How to uninstall?

    Run the uninstall.ps1 script. Running that script should result in something that resembles this:  

    uninstall

     

    Downloads

    C# Solution & Binaries: DF.PowerShell.zip (44.51 kb)

    Note: Text File with Addresses from Example 3 is included in solution download.


    Currently rated 5.0 by 1 people

    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    .NET | PowerShell

    Creating .NET Event Sources with PowerShell

    by Donn Felker 25. February 2008 12:42

    I use Enterprise Library for Logging and I use different event sources for each app. I've noticed that creating event sources is kind of a pain sometimes. Either you have to write an app that does it for you, or you have to write some logic in your code that checks for the event source. Either way, I think that's too bloated for in-house software. Now for software that has to be deployed, then ok, no problem I see the use. But we're talking bout non-released code here. Code that is used on an internal site or externally facing site.

    Or you can use PowerShell, simple as pie. :)

    This one liner will check for the Event Source and if it does not exist, it will create it for you. Real easy. Gotta love PowerShell.

     

    if (![System.Diagnostics.EventLog]::SourceExists("MySourceName")) { [System.Diagnostics.EventLog]::CreateEventSource("MySourceName", "Application") }

    Now if we write an event to the event log, it will show up because the source now exists. :)

    You HAVE TO love one liners that can replace entire applications. :) Albeit, not a big app, but an app, none the less.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    PowerShell

    Notepad? THE PowerShell IDE? Please, Save Me - Give Me Some IntelliSense

    by Donn Felker 21. February 2008 21:12

    As of lately I've been tasked with more and more work with process automation. As usual, automation is usually found to be best suited for a scripting language and therefore I've been working with PowerShell a lot lately.

    I'll admit - I have a problem with scripting languages the IDE's for Scripting Languages. What's the problem? The problem is that the IDE is usually Notepad. Don't get me wrong, I LOVE Notepad, so much that I use Notepad++ as my primary text editor. Adding it to the context menu has been one of the productivity boosters in my day to day work.

    The real issue comes down to productivity. I don't write a .NET Enterprise app in Notepad, I use Visual Studio. Could I? Yes. I don't write a Professional Letter in Notepad, I do it in Word. Could I write it in Notepad? Yes. This list could go on and on. I could use MS Paint to create a nice 3D Image, but I wont. But why? Simple... its not productive to. Its not productive to write letters, enterprise applications, or create a billion dollar proposal in Notepad.

    Millions of dollars have been put into productivity tools. The industry has put a bounty on productivity so high that entire companies are based around developer productivity. Tools and libraries such as ReSharper, DevExpress, Telerik, Infragistics, etc. help forge the way for developers to increase productivity in their day to day work. In this instance I'm talking about Windows development, there are MANY other companies that create productivity tools for many different industries, such as - graphic design, engineering, medial, etc. The point here is that time is money.

    Tools, are exactly that - tools. We've come from the stone age where a wheel was an innovational tool to help move items easier. So please, this is 2008 , and in computer years that puts Notepad into the stone age. So, please don't code in Notepad if you don't have to. Using Notepad as a tool to edit files on the fly is priceless, but using the tool as a primary editor, is, well... ludicrous and crazy. There are many IDE's for almost any environment out there. As new languages are developed, new IDE's soon follow. Unfortunately, one of the worst parts about being bleeding-edge/an-early-adopter and using a new language is waiting for the tool support. Look at VS 2008, the third party companies couldn't even keep up with VS2008 release date. When PowerShell came out, the only IDE was Notepad. Unfortunately, most IT folks still seem to use Notepad for most of there PowerShell scripts. This drives me nuts. This is like driving across country when  you could fly. But hey, if you're into long, over drawn out processes, maybe driving across the country will suit you. I'll see you in NYC when you get there, I'll already have gone sight-seeing for 3 days prior to your arrival.

    powerguibig This brings me back to PowerShell. There are many IDE's out there, some free, some not. The one I've seem to use on a regular basis is PowerGUI. Its simple, yet effective. Features include, IntellSense, built in help, debugging, watch window. You can also get more libraries from the downloads as well. For me, being able to debug into a script is worth its weight in gold. I don't know how many times back in ASP Classic I wrote:

    Response.Write "In The If"

    Man, I don't miss those days at all.

    So let me say it again... if you're walking around in the stone age, its time to step out, get a IDE and start enjoying life again. Not reliving the "Response.Write" memoirs. :)

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    PowerShell

    Podcast for PowerShell - PowerScripting.net

    by Donn Felker 8. February 2008 18:17

    In a previous post I wrote about staying up to date and how I do it. I included Blogs, Podcasts, Screencasts, etc.

    This is one more Podcast to add to the list. The podcast covers all things PowerShell and I must say, its pretty good!

    If there is one thing to add to your toolbelt this year, its PowerShell - even Jeffrey Snover agrees. I guess he doesn't count though ... he is one of the architects of it. :)

    Apple ITunes Link For Podcast

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    PowerShell

    Powered by BlogEngine.NET 1.4.5.0
    Theme by Mads Kristensen

    About the author

    Donn Felker

    Senior Consultant
    MCTS
    ScrumMaster
    Agile Practitioner

    About Me | Books I Recommend

    Gotta Pay The Bills


    Tag cloud

      Popular Posts

      RecentComments

      Comment RSS

      Calendar

      <<  December 2008  >>
      MoTuWeThFrSaSu
      24252627282930
      1234567
      891011121314
      15161718192021
      22232425262728
      2930311234

      View posts in large calendar