Where to put PowerShell profile scripts if standard locations are forbidden? - powershell

In our corporate environment, I am having difficulty with creating a PowerShell profile scripts.
To prevent users from writing documents on the local disk, the "Documents" directory is forced to be on a network drive. Commonly the "H:" (home) drive.
Likewise, users are forbidden from writing under C:\Windows\System32.
Where can I put the ISE profile script if these two are not available?
PSVersion 5.0.10586.117
PS C:\Windows\System32\WindowsPowerShell\v1.0> $HOME, $PSHOME
C:\Users\pwatson
C:\Windows\System32\WindowsPowerShell\v1.0
See also: Help-About about_Profiles
When I am not connected to the network, these are the $profile settings. I still cannot write under C:\Windows\System32 and the CurrentUser values are invalid.
PS C:\Windows\System32\WindowsPowerShell\v1.0> $profile | Get-Member -Type NoteProperty | ForEach-Object {$_.ToString
()}
string AllUsersAllHosts=C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
string AllUsersCurrentHost=C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1
string CurrentUserAllHosts=WindowsPowerShell\profile.ps1
string CurrentUserCurrentHost=WindowsPowerShell\Microsoft.PowerShell_profile.ps1
PS C:\Windows\System32\WindowsPowerShell\v1.0>

One option is to create a shortcut with a target like this:
%systemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoExit -file C:\somewhere\myprofile.ps1
and then always use this shortcut to start PowerShell.
This is not actually using the built-in PowerShell profile concept but it is dot-sourcing a ps1 file that behaves pretty much like a profile file.
If you like to start PowerShell from cmd.exe, create a batch-file with the same content as above and put it somewhere in your path (if you have permissions to do so)

Related

How to set intellisense permanently in windows powershell v-7.2.3 [duplicate]

I am looking to define a set of custom aliases/variables for use every time I launch PowerShell. I am looking for the PowerShell alternative to the .bashrc file.
I have tried putting a file named Profile.ps1 in the home directory, but it never runs. What do I need to do to get this file to run?
I am using Windows 10.
I'd start by reading through Microsoft's documentation about_Profiles. I've linked to the 5.1 version of the documentation since that's likely what you have on Windows 10, though I doubt it has changed much from version to version. It includes instructions on how to actually create the file and details about when it runs.
For your use case, you probably want to do the following from your session:
if (!(Test-Path -Path $PROFILE)) {
New-Item -ItemType File -Path $PROFILE -Force
}
which will generate the profile. Then once that is generated you can open it with notepad directly with the same example from there:
notepad $PROFILE
You can substitute your favorite editor for notepad. VSCode for instance would be:
code $PROFILE
You can also just get the path to the your profile by simply typing $PROFILE into the shell and it will output it, and then use that information to navigate to it from your favorite editor.
Per the documentation:
A PowerShell profile is a script that runs when PowerShell starts.
It's more complicated than that since there are multiple profile files as the documentation explains, but for your story it's accurate enough.
You can always also 'dotsource' your profile to make it run manually by executing:
. $Profile
However you should note that objects previously defined by prior invocations of your profile might not be removed. So while developing your profile that's a useful technique, be sure to only trust how it behaves when run by opening a completely new session.
I have tried putting a file named Profile.ps1 in the home
directory, but it never runs.
Profile.ps1 will work, though not in the $Home directory, but rather in the $Home\[My ]Documents\[Windows]PowerShell\Profile.ps1. The actual combination between [My ]Documents and [Windows]PowerShell depends on the versions of Windows and PowerShell, as documented here.
On my Windows 10 with PS 5.1 the right place for profile.ps1 is $home\Documents\WindowsPowerShell.
The candidate locations for profile files can also be checked via PowerShell itself.
PS C:\etc> $profile | get-member -name *user*
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
AllUsersAllHosts NoteProperty string AllUsersAllHosts=C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
AllUsersCurrentHost NoteProperty string AllUsersCurrentHost=C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1
CurrentUserAllHosts NoteProperty string CurrentUserAllHosts=C:\Users\XXXXXXXX\Documents\WindowsPowerShell\profile.ps1
CurrentUserCurrentHost NoteProperty string CurrentUserCurrentHost=C:\Users\XXXXXXXX\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

Loading different PowerShell profiles on startup? [Powershell 7]

Is there a way to specify which PowerShell profile to load when initializing PowerShell?
For instance, I'd like to be able to load a Python Conda profile when working in Python, or load a profile with bash command aliases when working with cross-platform scripts.
Note: I'm on the same machine, on the same user. So machine/user-specific profiles would not work in my case.
As PowerShell profiles are just PowerShell scripts loaded on startup of the PowerShell terminal, there are multiple ways to load them. Assuming you have two profile files:
conda_profile.ps1
bash_profile.ps1
Calling the profile scripts directly
You can just execute them after you open a PowerShell window, e. g.:
.\conda_profile.ps1
Calling the profile scripts by aliases
If the names or paths are too long or too complicated, you can create aliases for them, e. g.:
# Put the following two lines into the file stored in $PROFILE. You probably have to create it.
Set-Alias -Name condap -Value "C:\path\to\conda_profile.ps1"
Set-Alias -Name bashp -Value "C:\path\to\bash_profile.ps1"
After that, you can load a profile by typing condap or bashp.
Calling a profile by shortcut
You can also create different shortcuts to open a PowerShell with a certain profile:
Copy the shortcut from %APPDATA%\Microsoft\Windows\Start Menu\Programs\Windows PowerShell\Windows PowerShell.lnk
Rename it to condap for example.
Edit its target from %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe to %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoExit -File "C:\path\to\conda_profile.ps1".
Do it for other profiles respectively.
Choosing a profile by being prompted at startup
You can also write a profile that asks you to choose between different profiles, when you start PowerShell. Make sure you have a profile for your current host and current user:
if (!(Test-Path -Path $PROFILE)) {
New-Item -Type File -Path $PROFILE -Force
}
After that, add some lines to this file to ask for input and execute the desired profile script based on that input. It will work, but keep in mind that a user interaction inside the profile will probably be a bad design in the most cases.
Just to be more concise for command line (and non-windows) users:
pwsh -NoExit -File <your_profile_script>
Will start a powershell session with the specified profile.

How do I call a DOSkey Alias from Powershell?

I have DOSKey Alias that I setup like so (Aliases in Windows command prompt) calling it from the registry, and I'd like to be able to run it from powershell; is there some way to do this? All it really does is add something to the %PATH% environment variable.
If you don't have to use DOSKey and would just like to alias a command, you can use the built-in Set-Alias command like so:
Set-Alias -Name np -Value notepad++
That will, while the current powershell window is open, alias np to notepad++. Which also lets you open files with np temp.txt.
If you'd like to persist that, you could add it to your profile. You can do that by editing your Microsoft.PowerShell_profile.ps1, a shorthand is:
notepad $profile
Feel free to use notepad++ or any other editor you might have in your PATH. You can add the Set-Alias line to the bottom of the file and save and close it.
When you then open another powershell instance, it will have the example np alias available.
Below is code that will copy your DOSKEY macros into PowerShell aliases. This might or might not make sense for some commands which already have PowerShell aliases or do not work in the same way in PowerShell.
Note that you must source the command into the current shell.
PS C:\src\t> type .\Get-DoskeyMacros.ps1
& doskey /MACROS |
ForEach-Object {
if ($_ -match '(.*)=(.*)') {
Set-Alias -Name $Matches[1] -Value $Matches[2]
}
}
PS C:\src\t> . .\Get-DoskeyMacros.ps1
NOTES: (ht mklement0)
This code presumes that the doskey aliases have already been defined, which is not likely in a normal PowerShell session. However, you can start the PowerShell session from a cmd session that has them defined or run a batch file from PowerShell that defines them.
A potential translation-to-alias problem is that doskey macros support parameters (e.g., $*), whereas PowerShell aliases do not.
#lit's script didn't work for me.
Below is a script that worked. It copies the generated Set-Alias commands to the $profile script.
doskey /MACROS |
ForEach-Object {
if ($_ -match '(.*)=(.*)') {
echo ('Set-Alias -Name '+$Matches[1]+' -Value '+$Matches[2])
}
} > $profile
Notes:
Like the original script, this must be executed in a PowerShell session started from a cmd session.
The $profile file didn't exist for me. I first had to create it, along with the containing folder.

Powershell - shortened the directory prompt, but how to save the change?

Using Powershell in Windows 10. To change the prompt from:
PS C:\Users\b.HQ\Desktop\tsdev\my_folder>
PS my_folder> tsc
I used the following command in Powershell:
function prompt {'PS ' + $(Get-Location | Split-Path -Leaf) + ">"}
But, each time I restart Powershell, I have to reenter this. Is there any way to persist this change?
P.S. I know nothing about the config of Powershell, and I have looked for a solution, but apart from the prompt I am using, I did not see a way of saving it.
Run powershell as administrator, then run the following:
Test-Path $Profile
if it returns false then no you don’t have a profile file yet, so create it:
New-Item –Path $Profile –Type File –Force
(this will create profile file, or will overwrite the existing one)
Then, edit your profile file:
notepad $Profile
put your function in the file and save.
I created this neat prompt to that shows the drive and last folder.
For you example it would render as
PS C:\Users\b.HQ\Desktop\tsdev\my_folder>
as
PS C:\...\my_folder>
The prompt function is:
function prompt {"PS " + (get-location).drive.name+":\...\"+ $( ( get-item $pwd ).Name ) +">"}

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