LOGO

Configure Windows for PowerShell Scripts - Easy Setup

December 3, 2014
Configure Windows for PowerShell Scripts - Easy Setup

Adjusting PowerShell Execution Policies for Scripting

Both Windows and PowerShell incorporate security mechanisms and default settings designed to safeguard users from inadvertently executing scripts during typical computer use.

However, for individuals who frequently develop and run PowerShell scripts as part of their workflow, these protections can become inconvenient.

This guide details methods to modify these features, striking a balance between usability and maintaining a secure computing environment.

Understanding Execution Policies

PowerShell utilizes execution policies to determine which scripts are permitted to run on a system. These policies control script behavior based on factors like origin and digital signatures.

The default policy, often 'Restricted', prevents any scripts from running. Other policies include 'AllSigned', 'RemoteSigned', and 'Unrestricted', each offering varying levels of script execution permission.

Modifying Execution Policies

To change the current execution policy, you must open PowerShell as an administrator.

Use the Set-ExecutionPolicy cmdlet, followed by the desired policy name.

For example, to set the policy to 'RemoteSigned', allowing locally created scripts to run without a signature while requiring signed scripts from the internet, execute: Set-ExecutionPolicy RemoteSigned.

Bypassing Execution Policies Temporarily

Instead of permanently altering the execution policy, you can bypass it for a single script execution.

This is achieved by using the -ExecutionPolicy Bypass parameter when launching the script.

For instance: powershell.exe -ExecutionPolicy Bypass -File "C:\Scripts\MyScript.ps1".

Using the 'Unblock' Attribute

Downloaded scripts may have a blocked state, preventing execution even with a permissive execution policy.

To remove this block, right-click the script file in File Explorer, select 'Properties', and check the 'Unblock' box at the bottom of the 'General' tab.

Security Considerations

While adjusting execution policies can streamline scripting tasks, it's crucial to understand the security implications.

Loosening restrictions increases the risk of executing malicious scripts.

Always verify the source and content of scripts before running them, and consider using digital signatures to ensure authenticity.

Summary

PowerShell's execution policies provide a valuable security layer, but can hinder scripting workflows.

By understanding these policies and utilizing techniques like temporary bypassing or the 'Unblock' attribute, users can effectively manage script execution while maintaining a reasonable level of security.

Remember to prioritize security best practices and exercise caution when running scripts from untrusted sources.

Understanding Windows and PowerShell Script Execution Restrictions

PowerShell functions as the modern command shell and scripting language for Windows, designed to supersede CMD and batch scripts. A PowerShell script possesses the capability to execute virtually any task achievable manually through the command line. This broad functionality extends to making nearly any system modification, constrained only by the permissions of the user account in use.

Consequently, the ability to simply double-click a PowerShell script and execute it with full Administrator privileges presents a significant security risk. A concise script, such as the example below, could potentially cause substantial damage:

Get-ChildItem "$env:SystemDrive\" -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue

It is strongly advised not to execute the command provided above.

This command recursively traverses the file system, deleting accessible files. Surprisingly, the system may not immediately become unusable, even when run with elevated privileges. However, if a user experiences data loss or program malfunctions after running this script, a simple reboot may lead to Windows Startup Repair, indicating an unrecoverable system state. A more concerning scenario involves a script that installs malicious software, such as a keylogger or remote access tool, potentially leading to financial fraud and legal repercussions.

It's clear that protective measures are necessary to safeguard users from unintentional harm. However, experienced users, system administrators, and technical professionals generally possess the knowledge to identify and avoid these threats, prioritizing efficient task completion. To achieve this, they may need to disable or circumvent certain restrictions.

  • PowerShell restricts external script execution by default. The ExecutionPolicy setting in PowerShell prevents the execution of scripts from untrusted sources by default across all Windows versions. In certain Windows iterations, the default policy entirely prohibits script execution. We previously detailed how to modify this setting in How to Allow the Execution of PowerShell Scripts on Windows 7, and will revisit the topic with greater detail.
  • The .PS1 file extension is not natively associated with PowerShell. As initially discussed in our PowerShell Geek School series, Windows defaults to opening .PS1 files in Notepad, rather than invoking the PowerShell interpreter. This prevents accidental execution of potentially harmful scripts when double-clicked.
  • Administrator permissions are required for some PowerShell scripts. Even with an Administrator-level account, User Account Control (UAC) prompts are necessary for certain actions. This can be inconvenient when working from the command line. While disabling UAC is not recommended, streamlining the process is desirable.

These challenges are also addressed in How to Use a Batch File to Make PowerShell Scripts Easier to Run, which demonstrates using a batch file as a temporary workaround. Now, we will explore a more permanent solution. It's important to note that these modifications should generally be limited to systems used exclusively by you, to avoid increasing the risk for other users.

Modifying the .PS1 File Association

A common initial challenge encountered when working with PowerShell scripts is the default file association for .PS1 files. For security reasons, associating these files with anything other than PowerShell.exe is a prudent measure to prevent the unintentional execution of potentially harmful scripts. However, given that PowerShell includes the Integrated Scripting Environment (ISE), specifically designed for script editing, defaulting to Notepad seems counterintuitive. Even if immediate enablement of double-click execution isn't desired, adjusting these settings is often beneficial.

While the Default Programs control panel offers a method for altering the .PS1 file association, direct manipulation of the Registry provides finer-grained control over how files are opened. This approach also allows for the setting or modification of additional options available within the .PS1 file context menu. It is crucial to create a registry backup before proceeding with any changes.

The Registry settings governing the opening of PowerShell scripts are located at:

HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell

Before making alterations, it's advisable to examine these settings and their sub-keys using Regedit. The Shell key contains a single value, "(Default)", which is currently set to "Open". This value designates the default action triggered by double-clicking the file, as detailed in the sub-keys.

Expanding the Shell key reveals three sub-keys, each representing a distinct action applicable to PowerShell scripts.

how-to-configure-windows-to-work-with-powershell-scripts-more-easily-1.jpg

Exploring the values within each key reveals the following default behaviors:

  • 0 - Run with PowerShell. This option is already present in the context menu for PowerShell scripts, with the text sourced from another location rather than the key name itself. It is not, however, the default double-click action.
  • Edit - Open in PowerShell ISE. This is a more logical default than Notepad, but requires a right-click to initiate.
  • Open - Open in Notepad. The key name corresponds to the string stored in the "(Default)" value of the Shell key, meaning a double-click will "Open" the file using Notepad.

If you prefer to utilize the existing command strings, simply modify the "(Default)" value within the Shell key to match the key name corresponding to your desired double-click action. This can be accomplished directly within Regedit, or by leveraging techniques from our registry exploration tutorial with PowerShell (along with a minor PSDrive adjustment) to construct a reusable script for system configuration. The following commands require execution from an elevated PowerShell session, similar to running CMD as Administrator.

Initially, a PSDrive for HKEY_CLASSES_ROOT must be configured, as it is not established by default. The command to achieve this is:

New-PSDrive HKCR Registry HKEY_CLASSES_ROOT

This allows navigation and editing of registry keys and values within HKEY_CLASSES_ROOT, mirroring the functionality available in HKCU and HKLM PSDrives.

To configure double-clicking to directly launch PowerShell scripts:

Set-ItemProperty HKCR:\Microsoft.PowerShellScript.1\Shell '(Default)' 0

To configure double-clicking to open PowerShell scripts in the PowerShell ISE:

Set-ItemProperty HKCR:\Microsoft.PowerShellScript.1\Shell '(Default)' 'Edit'

To revert to the default behavior (opening PowerShell scripts in Notepad upon double-click):

Set-ItemProperty HKCR:\Microsoft.PowerShellScript.1\Shell '(Default)' 'Open'

These commands address only the basic modification of the default double-click action. Further customization of how PowerShell scripts are handled when opened from Explorer will be discussed in the subsequent section. Remember that PSDrives do not persist across sessions; therefore, including the New-PSDrive command within any configuration script or adding it to your PowerShell profile is recommended. Otherwise, manual execution will be necessary before making changes in this manner.

Adjusting the PowerShell ExecutionPolicy Configuration

The PowerShell ExecutionPolicy serves as an important security measure, preventing the execution of potentially harmful scripts. Several options are available for configuring this policy, each offering a different level of security. These options range from the most secure to the least, and can be implemented in various ways.

  • Restricted – Scripts are entirely prohibited from running. This is the standard setting on most systems and even prevents the execution of your profile script.
  • AllSigned – All scripts must possess a digital signature from a trusted publisher to execute without prompting the user. Unsigned or explicitly untrusted scripts will not run. PowerShell will request confirmation if a script is signed by a publisher whose trust status is undefined.
  • RemoteSigned – Scripts downloaded from the internet are treated as if the "AllSigned" policy were in effect. However, locally created or imported scripts are permitted to run without prompting.
  • Unrestricted – All scripts are allowed to run, though a confirmation prompt will appear for scripts originating from the internet.
  • Bypass – All scripts execute without any warnings. Exercise extreme caution when using this setting.
  • Undefined – No policy is defined for the current scope, allowing fallback to policies defined in lower scopes or the OS defaults.

As the description of Undefined suggests, the aforementioned policies can be applied at multiple scopes. The Get-ExecutionPolicy cmdlet, used with the -List parameter, displays all scopes and their current configurations.

how-to-configure-windows-to-work-with-powershell-scripts-more-easily-2.jpg

The scopes are prioritized in the order listed, with higher-level scopes overriding those below. If no policies are defined, the system defaults to its standard setting, typically Restricted.

  • MachinePolicy represents a Group Policy applied at the computer level. This is generally used in domain environments, but can also be configured locally.
  • UserPolicy represents a Group Policy applied to the user. This is also commonly found in enterprise settings.
  • Process applies to the current PowerShell instance. Changes made at this scope do not affect other PowerShell processes and are lost when the session ends.
  • CurrentUser is configured in the local registry and applies to the user account launching PowerShell. It can be modified using Set-ExecutionPolicy.
  • LocalMachine is configured in the local registry and applies to all users on the system. This is the default scope modified by Set-ExecutionPolicy when no -Scope parameter is specified.

For the purpose of enhancing usability while balancing security, we will focus on the lower three scopes. MachinePolicy and UserPolicy are most useful for enforcing restrictive policies that are difficult to circumvent.

Changes limited to the Process level or below allow for flexible policy adjustments as needed. A configuration similar to the one shown in the screenshot provides a good balance. Setting the LocalMachine policy to Restricted generally prevents script execution by users other than the administrator.

While this can be bypassed by knowledgeable users, it offers protection against accidental script execution by less experienced individuals. Setting the CurrentUser policy to Unrestricted allows manual script execution from the command line, while still prompting caution for downloaded scripts. The RemoteSigned setting at the Process level can be configured in a shortcut to PowerShell.exe or, as demonstrated below, in the Registry.

This enables easy double-click execution of self-written scripts while adding a stronger barrier against unintentional execution of potentially malicious scripts from external sources. To configure the CurrentUser and LocalMachine policies as shown in the screenshot, execute the following commands from an elevated PowerShell session:

Set-ExecutionPolicy Restricted

Set-ExecutionPolicy Unrestricted -Scope CurrentUser

To enforce the RemoteSigned policy for scripts launched from Explorer, a registry value must be modified. This is crucial because, depending on your PowerShell or Windows version, the default configuration may bypass all ExecutionPolicy settings except AllSigned. To determine the current configuration, run this command (ensuring the HKCR PSDrive is mapped):

Get-ItemProperty HKCR:\Microsoft.PowerShellScript.1\Shell\Command | Select-Object '(Default)'

The default configuration will likely be one of the following strings, or something similar:

(Observed on Windows 7 SP1 x64, with PowerShell 2.0)

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-file" "%1"

(Observed on Windows 8.1 x64, with PowerShell 4.0)

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'"

The first option is relatively benign, simply executing the script under the existing ExecutionPolicy settings. While it could be improved by enforcing stricter restrictions, it wasn't originally designed for double-click execution. The second option, however, completely bypasses the ExecutionPolicy, even Restricted.

This bypass applies only to sessions launched from Explorer, but it could result in launching scripts that your policy would otherwise prohibit. To align the Process-level ExecutionPolicy for scripts launched from Explorer with the screenshot, modify the same registry value:

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-ExecutionPolicy" "RemoteSigned" "-file" "%1"

how-to-configure-windows-to-work-with-powershell-scripts-more-easily-3.jpg

Alternatively, you can modify the setting from within PowerShell, from an elevated session with the HKCR PSDrive mapped:

Set-ItemProperty HKCR:\Microsoft.PowerShellScript.1\Shell\Command '(Default)' '"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-ExecutionPolicy" "RemoteSigned" "-file" "%1"'

Executing PowerShell Scripts with Administrative Privileges

While disabling User Account Control (UAC) entirely is discouraged for security reasons, consistently running scripts and programs with elevated permissions is also not advisable. It's best to only grant Administrator access when absolutely necessary for specific operations. Therefore, establishing a default behavior that automatically prompts for UAC elevation for all PowerShell scripts isn't recommended. However, a convenient solution is to introduce a new context menu option, enabling easy execution of scripts in elevated sessions when required.

This approach mirrors the technique used to add "Open with Notepad" to the context menu for all file types, but in this case, we will specifically target PowerShell scripts. We will also leverage methods previously discussed, utilizing a batch file instead of direct registry modifications to initiate our PowerShell script.

Registry Modification for Context Menu

To implement this change within the Registry Editor (Regedit), navigate to the following key:

HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell

Within this key, create a new subkey named "Run with PowerShell (Admin)". Subsequently, create another subkey under "Run with PowerShell (Admin)" called "Command". Finally, set the "(Default)" value under the "Command" key to the following:

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" ""& {Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy RemoteSigned -File \"%1\"' -Verb RunAs}"

This configuration will add the desired context menu entry.

PowerShell Implementation

Achieving the same result using PowerShell requires three distinct commands. One for each new key creation, and another to define the "(Default)" value for the "Command" key. Remember to account for elevation and the HKCR mapping.

New-Item 'HKCR:\Microsoft.PowerShellScript.1\Shell\Run with PowerShell (Admin)'

New-Item 'HKCR:\Microsoft.PowerShellScript.1\Shell\Run with PowerShell (Admin)\Command'

Set-ItemProperty 'HKCR:\Microsoft.PowerShellScript.1\Shell\Run with PowerShell (Admin)\Command' '(Default)' '"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" ""& {Start-Process PowerShell.exe -ArgumentList ''-ExecutionPolicy RemoteSigned -File \"%1\"'' -Verb RunAs}"'

It's crucial to observe the distinctions between the string used in PowerShell and the actual value written to the Registry. Specifically, the entire command must be enclosed in single quotes, and internal single quotes need to be doubled to prevent parsing errors.

Verification and Functionality

After applying these changes, a new context menu entry labeled "Run with PowerShell (Admin)" will appear when you right-click on a PowerShell script.

how-to-configure-windows-to-work-with-powershell-scripts-more-easily-5.jpg

Selecting this option will initiate two successive PowerShell instances. The initial instance serves as a launcher for the second, which utilizes the Start-Process cmdlet with the "-Verb RunAs" parameter to request administrative privileges for the new session. Upon confirming the UAC prompt, your script will execute with the necessary elevated permissions.

Final Adjustments for Enhanced PowerShell Experience

A few additional refinements can significantly streamline your workflow. Consider removing the Notepad association altogether. This can be achieved by copying the "(Default)" value found under the Command key within the Edit section, and pasting it into the corresponding location under Open.

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell_ise.exe" "%1"

Alternatively, the following PowerShell script, executed with Administrative privileges and access to HKCR, can accomplish the same result:

Set-ItemProperty HKCR:\Microsoft.PowerShellScript.1\Shell\Open\Command '(Default)' '"C:\Windows\System32\WindowsPowerShell\v1.0\powershell_ise.exe" "%1"'

Another common issue is the console window closing immediately after script execution. This prevents review of output, which is crucial for identifying errors or confirming successful operation. A simple solution is to include a pause command at the end of each script.

However, a more permanent fix involves modifying the "(Default)" values for the Command keys to incorporate the "-NoExit" parameter. The modified values are presented below.

(For systems without Administrative access)

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-NoExit" "-ExecutionPolicy" "RemoteSigned" "-file" "%1"

(For systems with Administrative access)

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" ""& {Start-Process PowerShell.exe -ArgumentList '-NoExit -ExecutionPolicy RemoteSigned -File \"%1\"' -Verb RunAs}"

These adjustments can also be implemented using PowerShell commands. Remember, elevation and HKCR access are prerequisites for these changes.

(Non-Administrative users)

Set-ItemProperty HKCR:\Microsoft.PowerShellScript.1\Shell\Command '(Default)' '"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-NoExit" "-ExecutionPolicy" "RemoteSigned" "-file" "%1"'

(Administrative users)

Set-ItemProperty 'HKCR:\Microsoft.PowerShellScript.1\Shell\Run with PowerShell (Admin)\Command' '(Default)' '"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" ""& {Start-Process PowerShell.exe -ArgumentList ''-NoExit -ExecutionPolicy RemoteSigned -File \"%1\"'' -Verb RunAs}"'

Examining PowerShell Script Execution

For testing purposes, a script will be utilized to display the current ExecutionPolicy settings and confirm whether the script is running with elevated Administrator privileges. This script, named "MyScript.ps1", will be located in the "D:\Script Lab" directory on the test system. The script's code is provided below for reference.

if(([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))

{Write-Output 'Running as Administrator!'}

else

{Write-Output 'Running Limited!'}

Get-ExecutionPolicy -List

The following illustrates the outcome when using the "Run with PowerShell" action.

how-to-configure-windows-to-work-with-powershell-scripts-more-easily-6.jpg

Conversely, utilizing the "Run with PowerShell (Admin)" action, following User Account Control (UAC) confirmation, produces this result:

how-to-configure-windows-to-work-with-powershell-scripts-more-easily-7.jpg

To demonstrate the impact of the ExecutionPolicy at the Process level, the system can be made to perceive the file as originating from the Internet through the following PowerShell command.

Add-Content -Path 'D:\Script Lab\MyScript.ps1' -Value "[ZoneTransfer]`nZoneId=3" -Stream 'Zone.Identifier'

how-to-configure-windows-to-work-with-powershell-scripts-more-easily-8.jpg

Thankfully, the -NoExit parameter was enabled. Without it, the error message would have flashed briefly and potentially gone unnoticed!

The 'Zone.Identifier' can be removed using this command:

Clear-Content -Path 'D:\Script Lab\MyScript.ps1' -Stream 'Zone.Identifier'

Helpful Resources

  • Running PowerShell scripts from a batch file - Daniel Schroeder's Programming Blog
  • Checking for Administrator permissions in PowerShell - Hey, Scripting Guy! Blog
#PowerShell#Windows#configuration#scripts#automation#scripting