Power to the People (Windows PowerShell Logon Scripts)

It’s true that PowerShell is addictive. But it’s primarily designed for use as an *Administrative* scripting and management environment. Many people ask about doing ASP.NET web content via PowerShell and also getting script to affect users, such as the following fusion of a question from a PowerShell class I taught last week, and another from a few months ago.

“Wow. PowerShell scripts are pretty handy. We have logon scripts written in VB script now. How can we use PowerShell scripts as logon scripts?”

Excellent question. You can still use a VB script as a logon script, and have that launch PowerShell just to run a specific command or to run a PowerShell script. VBscript calls PowerShell. Consider the following example which is described in a Microsoft article here.

’ logon.vbs – brief example

set objShell = CreateObject( “Wscript.Shell” )

objShell.run( “powershell.exe -noexit c:\scripts\logon.ps1” )

With that VBscript as your logon script, assigned through either Local Users and Groups, Active Directory Users and Computers, or via AD-based Group Policy, we can effectively run PowerShell scripts as logon scripts.

Here are some requirements.

1. In order to execute the script locally, each workstation or server on which this will be run will need to have Windows PowerShell installed.

2. PowerShell’s execution policy on each computer must allow the execution of the scripts in question.

3. The scripts must be accessible at a path visible to the client.

4. Any modules and extensions (e.g. Exchange Management Shell) would need to be loaded.

Of course, normal local, site, domain, organization unit, … (L, S, D, OU…) scope for Group Policy applies to the users (for Logon/Logoff scripts), or computers (for Startup/Shutdown scripts) in Active Directory affected by the policy.

The example quoted above from the Microsoft article includes -noexit parameter when launching PowerShell. That typically would not be used when running a logon script, as it leaves the shell open for the user on the target system after executing the script. Of course there are cases where that may be the appropriate desired behavior. Simply removing the -noexit parameter from that example reverses that behavior – as soon as the script completes, the shell will exit.

Powershell.exe can be launched with several parameters. Beside not using the -NoExit parameter, it is likely that a lot of logon scripts should also run with the -NonInteractive parameter instead. There is much power in many of the other parameters, especially the ability to use XML input and output formats, yet -PSConsoleFile and -Command are the most dramatic.

Briefly, -PSConsoleFile is typically used to extend the capabilities of Windows PowerShell with new providers or cmdlets. If you don’t know a cmdlet or provider is with respect to PowerShell, just remember the words “extend the capabilities.” Details really are beyond the scope of this blog post, but again, remember to include modules or extensions that your script(s) are expecting are available.

Because this script invokes powershell.exe with an anonymous -Command parameter of simply logon.ps1 – unqualified, therefore in the local folder – that PowerShell script will run at the same location as the VBscript.

Although there is so much more to delve into on this subject, I hope that this tiny bit has helped get you started if you’ve ever had that question… Can I use Windows PowerShell for logon scripts?

-Brad Werner

In this article

Join the Conversation

2 comments

  1. PSman Reply

    Unfortunately, that sample is as useless as every time people quote it. It seems to be the standard accepted non-functional answer. The problem: c:scriptslogon.ps1
    Come on, that is such a cop out. Everyone knows that a logon script is run from the domain controller, thus a network share, from a UNC in fact. The location of the logon script is never a mapped drive. It’s something like: \%userdomain%sysvoldomain.comPolicies{AAD5280F-A3B7-4F65-B15B-27E6F92BA431}UserScriptsLogon.
    So, the .vbs script mentioned is not going to know where it is and presumably the .ps1 script will be in the same location. Now please, it would be great if you could show us how one could actually run a logon script using powershell.

  2. Brad Werner Reply

    Thanks for asking! I have recently posted another entry to this blog that goes over the details, but here’s the brief run-down. I hope this helps. Please let me know of any further questions.

    As I had mentioned in the post last year, that was a simple example, but it does indeed work and is quite functional on systems which have, as you mentioned, such a local path as C:scripts populated with such scripts. Typically we populate this path using Group Policy Preferences or Group Policy’s Software Installation Service. But you wanted another way.

    Briefly put, the reason the simple examples use the local path is PowerShell code execution policy and code signing. The magic you asked for is simple however – simply change the objShell.run parameter to include a non-absolute path, such as either logon.ps1 or .logon.ps1. Either works as shown in the new post I just submitted (which should show up within another day or two I hope). So that’s not quite as magic as you were assuming.

    Yet when you use such a relative path to run the PowerShell script out of SysVol, the code signing issue must be reckoned with. This arises because the chosen script execution policy for many is systems is typically RemoteSigned. We have three options for dealing with this, including code signing the script, adjusting trusted locations, and modifying the execution policy on the necessary client machines. Again, these are mentioned in the new updated post.

    If you still don’t find the details you want there, just let me know. Thanks!