ChatGPT解决这个技术问题 Extra ChatGPT

Is there a way to make a PowerShell script work by double clicking a .ps1 file?

I am distributing a PowerShell script to my team. The script is to fetch an IP address from the Vsphere client, make an mstsc connection, and log it in a shared file.

The moment they used the script they got to know the IP address of machine. After that, they always tend to use mstsc directly instead of running the PowerShell script. (As they are using mstsc I am not able to know whether they are using the VM frequently or not.)

Mainly they are telling me that running PowerShell is not straightforward.

I am sick by their laziness.

Is there a way to make a PowerShell script work by double clicking a .ps1 file?

How about using logs on the server? "Don't trust the user" may mean you can't trust him with your data, but more often it means don't trust him to not be lazy.
Compiling a PS script by using Powershell studio sapien.com/software/powershell_studio
I prefer to run it through vscode (so I can see the consol, and debug it)
I am also sick by the user's laziness, plus one..

D
David Brabant

Create a shortcut with something like this as the "Target":

powershell.exe -command "& 'C:\A path with spaces\MyScript.ps1' -MyArguments blah"

As Jeffery Hicks(He is an authoritative resource in powershell) advised that it is not recommended to change the settings, I would vote your answer is the best answer and JPBlanc answer as useful answer.
use this with: ` -noLogo -ExecutionPolicy unrestricted -file ` as answered by: @user3071883
@UjjwalSingh: -NoProfile is also helpful, since the profile can do all kinds of things that the script doesn't expect.
For future readers: There is a registry hack in the answers below that accomplishes what OP asked for. The accepted answer does not.
Is there a way to do this but using a relative / the current path?
M
Mansuro

Or if you want all PS1 files to work the way VBS files do, you can edit the registry like this:

HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\open\command

Edit the Default value to be something like so...

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

Then you can just double click all your .PS1 files like you would like to. in my humble opinion, be able to out of the box.

I'm going to call this "The Powershell De-castration Hack". LOL enjoy!


This is the only one that worked for me in this list of answers. I'm not prepared to accept "It's not advised" as an answer - I tell the PC what to do, the PC does not tell me.
This is actually a double-bypass. Removes the restriction against double-click-to-run, and gets around PowerShell's ExecutionPolicy which is meant to prevent running of untrusted scripts even from the console.
This is the wrong way to do it. You're changing what the "Open" command does instead of setting the "Run with PowerShell" as the default. See itgala.xyz answer below.
If you do want do use this method, the correct default value for the registry key is actually"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -File "%1"%* where you can optionally include the -ExecutionPolicy unrestricted. Note the change at the end of the command which allows zero or more parameters to be passed to the PowerShell script. Quotation marks and spacing around the percent signs should be exactly as shown.
For a command-line solution rather than editing the registry, you can type ftype Microsoft.PowerShellScript.1=^"^%SystemRoot^%\System32\WindowsPowerShell\v1.0\powershell.exe^" -NoLogo -ExecutionPolicy Unrestricted -File ^"%1^" %* which will accomplish the same.
v
vizmi

This worked for me on Windows 10 and powershell 5.1:

right click on the .ps1 file

Open with...

Choose another app

Copy the location of powershell.exe to the address bar (by default it won't show windows folder) i.e. C:\Windows\System32\WindowsPowerShell\v1.0

select powershell.exe

select "Always use this app to open .ps1 files"

click OK


Probably you need to set execution policy on the host machine to something reasonable i.e. RemoteSigned
This is several years old and nobody has thought of this until half a year ago? -- I did this as well and it works perfectly, though you have to do some more configuration or powershell will refuse to run any .ps1 scripts at all (see Set-ExecutionPolicy).
Seems like the script name needs to contain no spaces if you want this to work. Other than that it appears to work perfectly.
How is this not the highest-voted answer? Why would we edit the registry directly or use batch files when you can just do it the way Windows intended, via file associations?
Excellent answer. If you need to set the execution policy -- this worked for me Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
J
Jeffery Hicks

Be aware that one of PowerShell's security features is that users can NOT launch script with a double click. Use great care if you modify this setting. An alternative might be to package your script. Some editors like PrimalScript can do that. The users still need PowerShell installed but then they can double-click the exe. And it sounds like your team needs a little education.


It's a security feature because it delays hackers by at least a few minutes until they find an alternative!
It's a stupid and useless security feature. Can you run a batch by double ckicling on it? Yes, An exe? Yes. A VBScript? Yes. I fail to realize why a poweshell script would be considered more dangrous than all the others
I don't know about you guys, but I've definitely ran a bat file on the wrong computer before with an accidental double-click. With something meant to automate administration, it makes perfect sense to restrict that.
You can double-click an EXE file so I don't see how this helps. But surely the Powershell team is aware of this basic argument. There must be more to it.
If you write scripts that are "dangerous" to execute, and you don't add a basic confirmation process... I reckon you like to live dangerously.
P
Peter Mortensen

I wrote this a few years ago (run it with administrator rights):

<#
.SYNOPSIS
    Change the registry key in order that double-clicking on a file with .PS1 extension
    start its execution with PowerShell.
.DESCRIPTION
    This operation bring (partly) .PS1 files to the level of .VBS as far as execution
    through Explorer.exe is concern.
    This operation is not advised by Microsoft.
.NOTES
    File Name   : ModifyExplorer.ps1
    Author      : J.P. Blanc - jean-paul_blanc@silogix-fr.com
    Prerequisite: PowerShell V2 on Vista and later versions.
    Copyright 2010 - Jean Paul Blanc/Silogix
.LINK
    Script posted on:
    http://www.silogix.fr
.EXAMPLE
    PS C:\silogix> Set-PowAsDefault -On
    Call Powershell for .PS1 files.
    Done!
.EXAMPLE
    PS C:\silogix> Set-PowAsDefault
    Tries to go back
    Done!
#>
function Set-PowAsDefault
{
  [CmdletBinding()]
  Param
  (
    [Parameter(mandatory=$false, ValueFromPipeline=$false)]
    [Alias("Active")]
    [switch]
    [bool]$On
  )

  begin
  {
    if ($On.IsPresent)
    {
      Write-Host "Call PowerShell for .PS1 files."
    }
    else
    {
      Write-Host "Try to go back."
    }
  }

  Process
  {
    # Text Menu
    [string]$TexteMenu = "Go inside PowerShell"

    # Text of the program to create
    [string] $TexteCommande = "%systemroot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command ""&'%1'"""

    # Key to create
    [String] $clefAModifier = "HKLM:\SOFTWARE\Classes\Microsoft.PowerShellScript.1\Shell\Open\Command"

    try
    {
      $oldCmdKey = $null
      $oldCmdKey = Get-Item $clefAModifier -ErrorAction SilentlyContinue
      $oldCmdValue = $oldCmdKey.getvalue("")

      if ($oldCmdValue -ne $null)
      {
        if ($On.IsPresent)
        {
          $slxOldValue = $null
          $slxOldValue = Get-ItemProperty $clefAModifier -Name "slxOldValue" -ErrorAction SilentlyContinue
          if ($slxOldValue -eq $null)
          {
            New-ItemProperty $clefAModifier -Name "slxOldValue" -Value $oldCmdValue  -PropertyType "String" | Out-Null
            New-ItemProperty $clefAModifier -Name "(default)" -Value $TexteCommande  -PropertyType "ExpandString" | Out-Null
            Write-Host "Done !"
          }
          else
          {
            Write-Host "Already done!"
          }
        }
        else
        {
          $slxOldValue = $null
          $slxOldValue = Get-ItemProperty $clefAModifier -Name "slxOldValue" -ErrorAction SilentlyContinue
          if ($slxOldValue -ne $null)
          {
            New-ItemProperty $clefAModifier -Name "(default)" -Value $slxOldValue."slxOldValue"  -PropertyType "String" | Out-Null
            Remove-ItemProperty $clefAModifier -Name "slxOldValue"
            Write-Host "Done!"
          }
          else
          {
            Write-Host "No former value!"
          }
        }
      }
    }
    catch
    {
      $_.exception.message
    }
  }
  end {}
}

I've had to change it at this location for it to work: Computer\HKEY_CLASSES_ROOT\Applications\powershell.exe\Shell\Open\Command. I don't understand the registry enough to explain why this is. Maybe because i'm running Powershell 3.0? Anyway, thanks for the script.
R
Rick

I agree that setting a system setting may be a bit much, but the shortcut requiring a hardcoded path is not ideal. A bat file actually solves the problem nicely

RunMyPowershellScript.bat

 start powershell -command "& '.\MyPowershellScript.ps1' -MyArguments blah"

This batch file can now be double clicked on, shortcuts can be easily created to the batch file, and the script can be deployed to any folder.


Note you need the ps1 script in same folder as the bat file. You gain copy paste ability at the cost of maintaining 2 files.
@rick, Did not work for me, nothing happens except a black window popping up for some milliseconds: start powershell -command "& 'C:\Users\skripte\arbeitstage.ps1'"
@Timo Try running your command in a regular command prompt window so you can see what the output is before the window disappears.
@Timo use -file instead of -command, also remove the &
A
Alex Langer

You'll need to tweak registry. First, configure a PSDrive for HKEY_CLASSES_ROOT since this isn’t set up by default. The command for this is:

New-PSDrive HKCR Registry HKEY_CLASSES_ROOT

Now you can navigate and edit registry keys and values in HKEY_CLASSES_ROOT just like you would in the regular HKCU and HKLM PSDrives.

To configure double-clicking to launch PowerShell scripts directly:

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 restore the default value (sets double-click to open PowerShell scripts in Notepad):

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

I tried restoring the default value using the last line from an Elevated PowerShell ISE, but apparently if you have used a command like Thermionix described it replaces the Default, so you have to reset the Shell.command explicitly (but I haven't found the correct syntax for that so I had to go through the Control Panel> Programs> File Associations).
P
Peter Mortensen

Simple PowerShell commands to set this in the registry;

New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT
Set-ItemProperty -Path "HKCR:\Microsoft.PowerShellScript.1\Shell\open\command" -name '(Default)' -Value '"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -noLogo -ExecutionPolicy unrestricted -file "%1"'

For a bit more security I would suggest using ExecutionPolicy RemoteSigned so that a random script downloaded from the network/internet (with the metadata denoting it wasn't created locally) won't execute from a double click, but any file you have created by copy and pasting code into a .ps1 file will execute because it doesn't have that metadata associated with it.
It worked in Windows 10. Now in Windows 11 it says: Set-ItemProperty: Cannot find path 'HKCR:\Microsoft.PowerShellScript.1\Shell\open\command' because it does not exist.
doesn't work in Windows 11
F
Francis

I tried the top-most answers to this question, but encountered error messages. Then I found the answer here:

PowerShell says "execution of scripts is disabled on this system."

What worked well for me was to use this solution:

powershell -ExecutionPolicy Bypass -File script.ps1

You can paste that into a .bat file and double-click on it.


This works for me and I think this is better than the short cut method.
K
KoZm0kNoT

put a simple .cmd file in my subfolder with my .ps1 file with the same name, so, for example, a script named "foobar" would have "foobar.ps1" and "foobar.cmd". So to run the .ps1, all I have to do is click the .cmd file from explorer or run the .cmd from a command prompt. I use the same base name because the .cmd file will automatically look for the .ps1 using its own name.

::====================================================================
:: Powershell script launcher
::=====================================================================
:MAIN
    @echo off
    for /f "tokens=*" %%p in ("%~p0") do set SCRIPT_PATH=%%p
    pushd "%SCRIPT_PATH%"

    powershell.exe -sta -c "& {.\%~n0.ps1 %*}"

    popd
    set SCRIPT_PATH=
    pause

The pushd/popd allows you to launch the .cmd file from a command prompt without having to change to the specific directory where the scripts are located. It will change to the script directory then when complete go back to the original directory.

You can also take the pause off if you want the command window to disappear when the script finishes.

If my .ps1 script has parameters, I prompt for them with GUI prompts using .NET Forms, but also make the scripts flexible enough to accept parameters if I want to pass them instead. This way I can just double-click it from Explorer and not have to know the details of the parameters since it will ask me for what I need, with list boxes or other forms.


Thanks for the batch file. Just so you know, you can replace the "for" statement with just: "set SCRIPT_PATH=%~p0" (without quotes). In fact, I would use ~dp0 instead of ~p0 so it will work across drives. I'll use this myself.
g
gth

Navigate REGEDIT to HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Microsoft.PowerShellScript.1\Shell On the right pane, double-click "(Default)" Delete existing value of "Open" (which launches Notepad) and type "0" (being zero, which launches Powershell directly).

Revert the value if you wish to use Notepad as the default again.


d
datu-puti

You may set the default file association of ps1 files to be powershell.exe which will allow you to execute a powershell script by double clicking on it.

In Windows 10,

Right click on a ps1 file Click Open with Click Choose another app In the popup window, select More apps Scroll to the bottom and select Look for another app on this PC. Browse to and select C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe. List item

That will change the file association and ps1 files will execute by double-clicking them. You may change it back to its default behavior by setting notepad.exe to the default app.

Source


This works fine but pretty much duplicates the answer of vizmi.
J
Johan Boulé

A solution in the same spirit as UNIX shar (shell archive).

You can put your powershell script in a file with the .cmd extension (instead of .ps1), and put this at the start:

@echo off
Rem Make powershell read this file, skip a number of lines, and execute it.
Rem This works around .ps1 bad file association as non executables.
PowerShell -Command "Get-Content '%~dpnx0' | Select-Object -Skip 5 | Out-String | Invoke-Expression"
goto :eof
# Start of PowerShell script here

P
Peter Mortensen

If you are familiar with advanced Windows administration, then you can use this ADM package (instructions are included on that page) and allow running PowerShell scripts after double click via this template and Local GPO. After this you can simply change default program associated to .ps1 filetype to powershell.exe (use search, it's quite stashed) and you're ready to run PowerShell scripts with double click.

Otherwise, I would recommend to stick with other suggestions as you can mess up the whole system with these administrations tools.

I think that the default settings are too strict. If someone manages to put some malicious code on your computer then he/she is also able to bypass this restriction (wrap it into .cmd file or .exe, or trick with shortcut) and all that it in the end accomplishes is just to prevent you from easy way of running the script you've written.


Once installed you can find this setting in the "Local Group Policy Editor" under: Local Computer Policy -> Computer Configuration -> Administrative Templates -> Windows Components. There, you can enable it, and make sure to select a policy in the drop-down list that becomes enabled then.
z
zumalifeguard

This is based on KoZm0kNoT's answer. I modified it to work across drives.

@echo off
pushd "%~d0"
pushd "%~dp0"
powershell.exe -sta -c "& {.\%~n0.ps1 %*}"
popd
popd

The two pushd/popds are necessary in case the user's cwd is on a different drive. Without the outer set, the cwd on the drive with the script will get lost.


M
Mica

This is what I use to have scrips run as admin by default:

Powershell.exe -Command "& {Start-Process PowerShell.exe -Verb RunAs -ArgumentList '-File """%1"""'}"

You'll need to paste that into regedit as the default value for:

HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Open\Command

Or here's a script that will do it for you:

$hive = [Microsoft.Win32.RegistryKey]::OpenBaseKey('ClassesRoot', 'Default')
$key = $hive.CreateSubKey('Microsoft.PowerShellScript.1\Shell\Open\Command')
$key.SetValue($null, 'Powershell.exe -Command "& {Start-Process PowerShell.exe -Verb RunAs -ArgumentList ''-File """%1"""''}"')

T
TylerH

I used this (need to run it only once); also make sure you have rights to execute:

from PowerShell with elevated rights:

Set-ExecutionPolicy=RemoteSigned

then from a bat file:

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

 ftype Microsoft.PowerShellScript.1="C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe" -noexit ^&'%%1'

 assoc .ps1=Microsoft.PowerShellScript.1

-----------------------------------------
auto exit: remove -noexit 

and voila; double-clicking a *.ps1 will execute it.


The term '%1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Only the combination of the accepted answer with this answer worked for me, once I used the command from the accepted answer in the registry key. Apparently running assoc is required.
@ajeh (sorry for bieng leet to the party. If you get that error, its because you have thw wrong single quotes. make sure you use UTF-8. (use notepad++; drop the two strings, save as a runme.cmd file)
For the batch file part, I executed the first two lines ftype and assoc directly on the cmd line with admin privs. Had to remove one % to get it to work.
C
Chris Xue

In Windows 10 you might also want to delete Windows Explorer's override for file extension association:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\UserChoice

in addition to the HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\open\command change mentioned in other answers.

See https://stackoverflow.com/a/2697804/1360907


M
MrRobot

You can use the Windows 'SendTo' functionality to make running PS1 scripts easier. Using this method you can right click on a PS1 script and execute. This is doesn't exactly answer the OP question but it is close. Hopefully, this is useful to others. BTW.. this is helpful for a variety of other tasks.

Locate / Search for Powershell.exe

Right click on Powershell.exe and choose Open File Location

Right click on Powershell.exe and choose Create Shortcut. Temporarily save some place like your desktop

You might want to open as Admin by default. Select Shortcut > Properties > Advanced > Open As Admin

Open the Sendto folder. Start > Run > Shell:Sendto

Move the Powershell.exe shortcut to the Sendto folder

You should now be able to right click on a PS1 script.

Right Click on a PS1 file, Select the SendTo context option > Select the Powershell shortcut

Your PS1 script should execute.


How is this better than the default 'Run with Powershell' context menu option?
E
Epirocks

You may not want to but an easy way is just to create a .BAT file and put your command in:

powershell ./generate-strings-table-en.ps1
powershell ./generate-conjoined-tables-it.ps1

Then double-click said BAT file.


D
Dmitry K.

there is my solution 2022

Install "PowerShell-7.2.2-win-x64.msi"

Right click on file.ps1 and change to exec with "pwsh"

https://i.stack.imgur.com/u1Wyd.png


I didn't even know Win 10 users can access the PS in Win 11, the version 7+ so thanks for this. It was much easier to associate the .ps1 files while keeping a reasonable policy, as it should be.
m
mstone

From http://www.howtogeek.com/204166/how-to-configure-windows-to-work-with-powershell-scripts-more-easily:

Set the default value for the HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell to 0