Thursday, December 28, 2006

Restart your engine - The PowerShell way


Frequently, I have the need to change the content of the PowerShell profile file Microsoft.PowerShell_profile.ps1) to reflect my needs. Any change to the profile requires me to exit PowerShell and re-launch it for changes to take place.

After making a lot of changes this can be very annoying. Well, this task definitely deserves a function!. The function will restart the console And will be stored in the profile for fast execution whenever you call it. But how? Can you restart any application from within itself ? After some experiments I came up with a solution that uses WScript.

Before delving into the solution, you must ensure the existence of a PowerShell profile file. PowerShell maintains a variable called $profile. Typing it into the console will reveal the file path. Note: although $profile will show you a path including the file name, this doesn’t mean that The profile really exists. Here are some commands you can use to find more info:

• test-path $profile # test if your profile exists
• if it returns false you should create it
• New-Item -path $profile -itemtype file -force

Now, The basic idea is to write a function in PowerShell that writes a .vbs file With some commands in it, to the temp directory. The file will use the WScript.Sleep function for a period of time and will then launch PowerShell.exe So lets start coding:

1. Launch PowerShell
2. type: notepad $profile to open your profile file
3. Copy and paste the following code and save changes:

# restarting PowerShell function res{
   $cmd = "Set oShell = CreateObject(""WScript.Shell"") `n"
   $cmd += "WScript.Sleep 1000 `n"
   $cmd += "oShell.Run ""PowerShell.exe""" | Out-File -filePath $env:temp"\ps.vbs" -inputobject  
   $cmd -encoding ASCII -force WScript.exe $env:temp"\ps.vbs"
   exit
}

4. Exit PowerShell From now on, for any change to the profile , and whenever you want to restart PowerShell just type res and watch it happen.

Shay

15 comments:

Jeffrey Snover said...

Howdy $hay!

Cool stuff!
I just added your restart function to my profile file. I changed it to:
1) use the standard VERB name (RESTART) and then defined an alias to make it easy to type.
2) used a here-string to make the script a little more readable.

function Restart-PowerShell {
$cmd = @"
'This is a temporary script to Restart a PowerShell Session
'Created $(Get-Date)
Set oShell = CreateObject("WScript.Shell")
WScript.Sleep 1000
oShell.Run "PowerShell.exe"
"@
Out-File -filePath $env:temp"\Restart-PowerShell.vbs" -inputobject $cmd -encoding ASCII -force
WScript.exe $env:temp"\Restart-PowerShell.vbs"
exit
}
Set-Alias rsps Restart-PowerShell

Cheers!

Jeffrey Snover [MSFT]
Windows PowerShell/MMC Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Shay said...

Thank you Jeffry. I couldn't ask for more (my jaw hearts, it wont close). Certainly learned something new from your post.

PowerShell is realy powerfull as its name suggests, a whole new world to explore from the VBScript side of things. Its amazing what a one-liner command can do, and there is many more.

Cheers

aleksandar said...

When I want to restart PowerShell session, I type:

. $profile

It looks to me like a totally PowerShell way to restart PS engine. :-)

Cheers,
Aleksandar
http://powershellers.blogspot.com

Shay said...

well, this is even shorter.
thats the POWER of PowerShell :-)

Shay said...

aleksandar
after some expermenting there is
one exception for the .$profile
any changes to the prompt function (if exists) doesnt work, and i guess it wont work for any startup functions in the $profile.

Anonymous said...

This primitive way works fine for me:

function Restart-PowerShell {
cmd /c start powershell.exe
exit
}

Thanks,
Roman Kuzmin

aleksandar said...

My prompt function looks like this:

function prompt {
$host.ui.rawui.windowtitle = "The Shell Must Flow."
$host.ui.rawui.foregroundcolor = "Green"
$history = @(get-history)
if ($history.count -eq 0) {
$intCommandCount = 0
} else {
$intCommandCount = $history[$history.count - 1].ID
}
"PS[" + ($intCommandCount + 1).ToString() +"]>"

}

Any changes to that function are visible after typing ". $profile".


Cheers,
Aleksandar
http://powershellers.blogspot.com

Anonymous said...

Cool idea. However I changed mine to look like this:

start-process $pshome\powershell.exe | out-null

exit

thomas said...

Perhaps I am missing something here, but doesn't the following accomplish the same thing? (it works in my env)

function Restart-PowerShell {
Invoke-Item "c:\winnt\system32\WindowsPowerShell\v1.0\
powershell.exe"
exit
}

Anonymous said...

Do you can write anything else about it? Great article!

$hay@Israel said...

Actually, I did. There's an update to this post here
http://scriptolog.blogspot.com/2007/08/restart-your-engine-powershell-way.html

Lo0m said...

is there anything bad about using this?:

function resps {& "c:\prace\powershell\powershell.lnk"; exit}

$hay@Israel said...

Hi Lo0m

I have a a function in my $profile that starts a transcript for the session.

The only *bad* thing I found is having an error, when launching the shortcut, that the transcript could not be started.

Thanks for the idea!

-Shay

Caterpillar Engine Parts said...

Interesting stuff I must admit. But what I really want to know is how did you really compose all this coding?? Okay, once I get this down hopefully it will work for me because I tried a couple different ways and none of them seemed to work. No worries though, that's why Google is here! haha I can literally find anything to everything on the web nowadays but enough of that.. But then thing is, that whenever I try inserting something like this it say, "The project type is not supported by this installation" How can I solve this problem?

$hay@Israel said...

Caterpillar,

We can take it offline if you want, you can email me to scriptolog AT gmail DOT com.