Source a PowerShell script on each new shell - powershell

I have a script called Restart-Audio.ps1
Stop-Process -Confirm -Name musicapp*
Stop-Service audiosrv
Stop-Service AudioEndpointBuilder
Start-Service audiosrv
Invoke-Item C:\path\to\music\app.exe
Every time I start a new PowerShell session, I want this script to run when I type "Restart-Audio" like a normal cmdlet. When I tried to add this to my PowerShell profile, it tried to run the script, asking for the confirmation to stop the processes. I don't want it to run as soon as a PowerShell session starts; I want the command to run when I tell it to.
Thanks.

This can be done using Powershell profiles, see here for details.
You basically create (if the file doesn't already exist) C:\Users\<<UserName>>\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 and that can contain your above script.
I'd construct the file as:
Function Restart-Audio{
Stop-Process -Confirm -Name musicapp*
Stop-Service audiosrv
Stop-Service AudioEndpointBuilder
Start-Service audiosrv
Invoke-Item C:\path\to\music\app.exe
}
Then you just open Powershell and type Restart-Audio to run that function.
Additionally, if you save the script to any folder in your $env:PATH you can just type the first few characters of the script name and TAB complete to run the script.

Related

PowerShell function not running as expected

I have a curious case that I cannot fathom the reason for...
Please know I am a novice to PowerShell.
I am working on a PowerShell menu system to help automate building out new computers in my environment. I have a PS1 file that holds the script for an app install. When I use the script to reference this I am able to run it and have no issue. However, when I try inserting this into a function and referencing it does not.
This works:
4 # Microsoft Office 32-bit
{
Write-Host "`nMicrosoft Office 32-bit..." -ForegroundColor Yellow
# {installMS32Bit}
Invoke-Expression "cmd /c start powershell -NoExit -File '\\**SERVERPATH**\menuItems\ms_office\32-bit\install.ps1'"
Start-Sleep -seconds 2
}
This does not:
function installMS32Bit(){
Invoke-Expression "cmd /c start powershell -NoExit -File '\\**SERVERPATH**\menuItems\ms_office\32-bit\install.ps1'"
}
}
4 # Microsoft Office 32-bit
{
Write-Host "`nMicrosoft Office 32-bit..." -ForegroundColor Yellow
{installMS32Bit}
Start-Sleep -seconds 2}
install.ps1 file:
# Copy MS Office uninstall and setup to local then run and install 32-bit Office
Copy-Item -Path '\\**SERVERPATH**\menuItems\ms_office\setup.exe' -Destination 'C:\temp\' -Force
Copy-Item -Path '\\**SERVERPATH**\menuItems\ms_office\uninstall.xml' -Destination 'C:\temp\' -Force
Copy-Item -Path '\\**SERVERPATH**\menuItems\ms_office\32-bit\Setup.exe' -Destination 'C:\temp' -Force
Invoke-Expression ("cmd /c 'C:\temp\setup.exe' /configure 'C:\temp\uninstall.xml'")
Start-Process -FilePath 'C:\temp\Setup.exe'
Secondary question and a little explanation for Invoke-Expression...
I like to see progress and like to have secondary windows open to monitor the new process being run. I was unable to find a solution with a persistent window that worked for me to do this without Invoke-Expression.
If there is a better way to do this in PowerShell I am all ears!
{installMS32Bit}
As Mathias points out in a comment on the question, this statement doesn't call your function, it wraps it in a script block ({ ... })[1], which is a piece of reusable code (like a function pointer, loosely speaking), for later execution via &, the call (execute) operator.
To call your function, just use its name (by itself here, given that there are no arguments to pass): installMS32Bit
Invoke-Expression should generally be avoided; definitely don't use it to invoke an external program, as in your attempts.
Additionally, there's generally no need to call an external program via cmd.exe (cmd /c ...), just invoke it directly.
For instance, replace the last Invoke-Epression call from your question with:
# If the EXE path weren't quoted, you wouldn't need the &
& 'C:\temp\setup.exe' /configure 'C:\temp\uninstall.xml'
I like to see progress and like to have secondary windows open to monitor the new process being run. I was unable to find a solution with a persistent window that worked for me to do this without Invoke-Expression.
(On Windows), Start-Process by default executes a console application in a new window (unless you specify -NoNewWindow), asynchronously (unless you specify -Wait).
You cannot pass a .ps1 script directly to Start-Process (it will be treated like a document to open rather than an executable to call), but you can pass it to PowerShell's CLI via the -File parameter:
Start-Process powershell.exe '-File install.ps1'
The above is short for:
Start-Process -FilePath powershell.exe -ArgumentList '-File install.ps1'
That is, PowerShell will execute the following in a new window:
powershell.exe -File install.ps1
[1] Since you're not assigning the script block being created to a variable, it is implicitly output (printed to the display, in the absence of a redirection); a script block stringifies by its literal contents, excluding the enclosing { and }, so string installMS32Bit will print to the display.

Powershell file won't work with double-click [duplicate]

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?
Create a shortcut with something like this as the "Target":
powershell.exe -command "& 'C:\A path with spaces\MyScript.ps1' -MyArguments blah"
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 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
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.
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.
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 {}
}
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'
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"'
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
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.
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.
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.
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
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.
there is my solution 2022
Install "PowerShell-7.2.2-win-x64.msi"
Right click on file.ps1 and change to exec with "pwsh"
Powershell registry hacks and policy bypass never worked for me.
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.
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"""''}"')
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.
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
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.
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.
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

how do I make it easy for my parents to run this Powershell command?

I am not a programmer and my parents' Windows 10 PC tends to loose its start menu and cortana processes, resulting in start menu not showing up at all when the start icon is clicked.
I made a quick search and found + tested this Powershell command and it worked:
Get-AppxPackage | % { Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppxManifest.xml" -verbose }
I wish to turn this command into a shortcut/batchfile that executes the command and restarts the PC whenever the desktop icon is double clicked, in order to avoid explaining to my parents what to do to fix the problem. Can any one help me out please?
Thank you in Advance.
you can encode the command and put the whole thing into a single batch file (no .ps1 necessary)
details here
https://blogs.msdn.microsoft.com/timid/2014/03/26/powershell-encodedcommand-and-round-trips/
or you can use this function
https://github.com/gangstanthony/PowerShell/blob/master/Encode-Text.ps1
first, either use Get-Content or Get-Clipboard (copy your whole script to the clipboard) to encode your desired script
PS> Encode-Text (Get-Clipboard | out-string)
RwBlAHQALQBBAHAAcAB4AFAAYQBjAGsAYQBnAGUAIAB8ACAAJQAgAHsAIABBAGQAZAAtAEEAcABwAHgAUABhAGMAawBhAGcAZQAgAC0ARABpAHMAYQBiAGwAZQBEAGUAdgBlAGwAbwBwAG0AZQBuAHQATQBvAGQAZQAgAC0AUgBlAGcAaQBzAHQAZQByACAAIgAkACgAJABfAC4ASQBuAHMAdABhAGwAbABMAG8AYwBhAHQAaQBvAG4AKQBcAEEAcABwAHgATQBhAG4AaQBmAGUAcwB0AC4AeABtAGwAIgAgAC0AdgBlAHIAYgBvAHMAZQAgAH0ADQAKAA==
then you can use that in your batch file like so
powershell -encodedcommand RwBlAHQALQBBAHAAcAB4AFAAYQBjAGsAYQBnAGUAIAB8ACAAJQAgAHsAIABBAGQAZAAtAEEAcABwAHgAUABhAGMAawBhAGcAZQAgAC0ARABpAHMAYQBiAGwAZQBEAGUAdgBlAGwAbwBwAG0AZQBuAHQATQBvAGQAZQAgAC0AUgBlAGcAaQBzAHQAZQByACAAIgAkACgAJABfAC4ASQBuAHMAdABhAGwAbABMAG8AYwBhAHQAaQBvAG4AKQBcAEEAcABwAHgATQBhAG4AaQBmAGUAcwB0AC4AeABtAGwAIgAgAC0AdgBlAHIAYgBvAHMAZQAgAH0ADQAKAA==
You could execute the PowerShell script via a batch file.
Batch file:
set powerscriptPath=C:\Example.ps1
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%powerscriptPath%""' -Verb RunAs}"
This will bypass the execution policies on the computer allowing the script to run in Administrator mode too. NOTE: You will need to edit the powerscriptPath to point to your PowerShell script location, I just used C:\Example.ps1 as an example.
You will want to add Restart-Computer -Force to the end of your PowerShell script to restart the computer
Get-AppxPackage | % { Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppxManifest.xml" -verbose }
Restart-Computer -Force
Make a bat file which executes powershell with that file. Then add a shortcut to the bat file
I am really unsure why you would run a batch file just to call a powershell script! Talk about hokey approaches to a non-problem.
To call a powershell script is really no different than calling a batch script:
It's simply path to PowerShell, and the script path as a parameter:
"%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe" "C:\users\austinfrench\desktop\example.ps1"
You can also use the exact same format as the target for a desktop shortcut.

Run a PowerShell method from cmd and don't wait for its return

In cmd I'm trying to run Method1 which is in a PowerShell script, script1.
Method1 is a method that takes a few hours, and I simply want to fire and forget.
The following is working for me:
c:\temp> powershell
PS c:\temp> . .\script1.ps1;Method1
When I do the lines above, everything is working fine as long as I keep the CMD of PS opened. once I close the PS window, it kills Method1.
So actually I want that from cmd, in one line, to somehow make Method1 work without the dependency of the PowerShell window, maybe create a new process.. I am not really sure.
I've tried:
c:\temp> cmd /c powershell . .\script1.ps1;Method1
It is running for a few seconds, but when the cmd gets closed, then Method1 also terminates.
I also tried
c:\temp>cmd /c powershell -noexit "& { . .\script.ps1;Method1 }"
Again, once I do this, it is working. However, a PowerShell window is opened and if I close it then it terminates Method1.
From you help, I've tried:
c:\temp> cmd /c powershell start-process cmd /c powershell . .\script1.ps1;Method1
But I get an exception:
Start-Process : A positional parameter cannot be found that accepts
argument 'powershell'.
But still, I am not able to make it work.
Alternatively if you want a pure PowerShell solution (note this needs to be running as Admin):
Invoke-Command LocalHost -Scriptblock $script -InDisconnectedSession
The InDisconnectedSession switch runs it in a separate PowerShell session that will not be terminated when you close the PowerShell window. You can also use Get-PSSession and pass the session to Enter-PSSession to interact with it during or after execution. Remember in this state if you close the window it -will- kill it, so you'll want to use Exit-PSSession to keep it alive.
There is however a problem - you can't do any remoting tasks, at least not easily. This incurs the wrath of the "double hop" where you remote to one computer (your own in this case), then to another, and for security PowerShell refuses to pass any credentials to the second remoting session so it can't connect, even if you put the credentials in manually. If you do need to do remoting I recommend sticking with launching a hidden PowerShell process.
You can use PowerShell jobs for that, so just:
Start-Job -FilePath somepath
And add a method call at the end of the script, or pass in a Scriptblock like:
Start-Job -ScriptBlock {. .\path_to_ps1; Method1}
Or perhaps use the hackish:
start-process cmd -WindowStyle Hidden -ArgumentList "'/c powershell . .\script1.ps1;Method1'"
Actually, you can just launch PowerShell, without CMD, and I am not sure why I was using a cmd approach:
start-process powershell -WindowStyle Hidden -ArgumentList ". .\script1.ps1;Method1"
Easy answer ya'll; Just paste "start" command into your PS window (whether in a remote session or not) and it works fine:
Start C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -file 'driverletter:\path\yourpowershellscript.ps1'

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?
Create a shortcut with something like this as the "Target":
powershell.exe -command "& 'C:\A path with spaces\MyScript.ps1' -MyArguments blah"
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 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
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.
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.
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 {}
}
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'
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"'
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
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.
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.
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.
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
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.
there is my solution 2022
Install "PowerShell-7.2.2-win-x64.msi"
Right click on file.ps1 and change to exec with "pwsh"
Powershell registry hacks and policy bypass never worked for me.
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.
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"""''}"')
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.
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
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.
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.
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