Is it possible to start Powershell ISE with specified (not default) profile? - powershell

I want to have several (more than one) PowerShell profiles which will create different environments.
More specifically I need way for start separate PowerShell ISE for work with TFS and other PowerShell ISE instance for regular work. 'TFS' environment require loading some additional snappins, modules, modify prompt and so on. I do not want all this stuff will be executed for regular PowerShell ISE sessions but only when I want to.
I found that I can automatically load arbitrary script through command line parameter -File, but it does not executed automatically..

I do it by creating a shortcut for PowerShell ISE with a default directory :
In the default Directory (here called D:\TFS) I create a .PS1 file called local_profile.ps1.
In the beginning of the current profile file (C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1) I add :
# Try to load local profile
Get-ChildItem "local_profile.ps1" -ErrorAction SilentlyContinue | %{.$_}
You just have to add your initialization code to D:\TFS\local_profile.ps1.

powershell ISE has a profile too.
Probably is something like:
E:\Users\UserName\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
Or you can open powershell ise and look at $profile variable.
After locate your profile file, write your modules import and custom scripts in it.

Related

Powershell function call causes missing function error using powershell v7 on windows 10

I wrote a script to build all .net projects in a folder.
Issue
The issue is I am getting a missing function error when I call Build-Sollution.
What I tried
I made sure that function was declared before I used it so I am not really sure why it saids that it is not defined.
I am new to powershell but I would think a function calling another functions should work like this?
Thanks in advance!
Please see below for the error message and code.
Error Message
Line |
3 | Build-Sollution $_
| ~~~~~~~~~~~~~~~
The term 'Build-Sollution' 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.
Build-Sollution:
Code
param (
#[Parameter(Mandatory=$true)][string]$plugin_path,
[string]$depth = 5
)
$plugin_path = 'path/to/sollutions/'
function Get-Sollutions {
Get-ChildItem -File -Path $plugin_path -Include *.sln -Recurse
}
function Build-Sollution($solution) {
dotnet build $solution.fullname
}
function Build-Sollutions($solutions) {
$solutions | ForEach-Object -Parallel {
Build-Sollution $_
}
}
$solutions_temp = Get-Sollutions
Build-Sollutions $solutions_temp
From PowerShell ForEach-Object Parallel Feature | PowerShell
Script blocks run in a context called a PowerShell runspace. The runspace context contains all of the defined variables, functions and loaded modules.
...
And each runspace must load whatever module is needed and have any variable be explicitly passed in from the calling script.
So in this case, the easiest solution is to define Build-Sollution inside Build-Sollutions
As for this...
I am new to powershell but I would think a function calling another
functions should work like this?
... you cannot use the functions until you load your code into memory. You need to run the code before the functions are available.
If you are in the ISE or VSCode, if the script is not saved, Select All and hit use the key to run. In the ISE use F8 Selected, F5 run all. In VSCode, F8 run selected, crtl+F5 run all. YOu can just click the menu options as well.
If you are doing this from the consolehost, the run the script using dot sourcing.
. .\UncToYourScript.ps1
It's ok to be new, we all started somewhere, but it's vital that you get ramped up first. so, beyond what I address here, be sure to spend time on Youtube and search for Beginning, Intermediate, Advanced PowerShell for videos to consume. There are tons of free training resources all over the web and using the built-in help files would have given you the answer as well.
about_Scripts
SCRIPT SCOPE AND DOT SOURCING Each script runs in its own scope. The
functions, variables, aliases, and drives that are created in the
script exist only in the script scope. You cannot access these items
or their values in the scope in which the script runs.
To run a script in a different scope, you can specify a scope, such as
Global or Local, or you can dot source the script.
The dot sourcing feature lets you run a script in the current scope
instead of in the script scope. When you run a script that is dot
sourced, the commands in the script run as though you had typed them
at the command prompt. The functions, variables, aliases, and drives
that the script creates are created in the scope in which you are
working. After the script runs, you can use the created items and
access their values in your session.
To dot source a script, type a dot (.) and a space before the script
path.
See also:
'powershell .net projects build run scripts'
'powershell build all .net projects in a folder'
Simple build script using Power Shell
Update
As per your comments below:
Sure the script should be saved, using whatever editor you choose.
The ISE does not use PSv7 by design, it uses WPSv5x and earlier.
The editor for PSv7 is VSCode. If you run a function that contains another function, you have explicitly loaded everything in that call, and as such it's available.
However, you are saying, you are using PSv7, so, you need to run your code in the PSv7 consolehost or VSCode, not the ISE.
Windows PowerShell (powershell.exe and powershell_ise.exe) and PowerShell Core (pwsh.exe) are two different environments, with two different executables, designed to run side-by-side on Windows, but you do have to explicitly choose which to use or write your code to branch to a code segment to execute relative to the host you started.
For example, let's say I wanted to run a console command and I am in the ISE, but I need to run that in Pwsh. I use a function like this that I have in a custom module autoloaded via my PowerShell profiles:
# Call code by console executable
Function Start-ConsoleCommand
{
[CmdletBinding(SupportsShouldProcess)]
[Alias('scc')]
Param
(
[string]$ConsoleCommand,
[switch]$PoSHCore
)
If ($PoSHCore)
{Start-Process pwsh -ArgumentList "-NoExit","-Command &{ $ConsoleCommand }" -PassThru -Wait}
Else {Start-Process powershell -ArgumentList "-NoExit","-Command &{ $ConsoleCommand }" -PassThru -Wait}
}
All this code is doing is taking whatever command I send it and if I use the PoSHCore switch...
scc -ConsoleCommand 'SomeCommand' -PoSHCore
... it will shell out to PSCore, run the code, otherwise, it just runs from the ISE>
If you want to use the ISE with PSv7 adn not do the shell out thing, you need to force the ISE to use PSv7 to run code. See:
Using PowerShell Core 6 and 7 in the Windows PowerShell ISE

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.

PowerShell ISE not recognizing $profile variables

In my $profile directory, I have a few custom variables, as well as the default variables, such as $root (which equals "C:\"), etc. One custom variable I have holds the filepath to my desktop, so I can easily reference the path, and also not have to create the variable every time I start up PS. If I attempt to resolve any variable value from the $profile path within ISE(both the script pane and console) it does not work. However, if I use the regular PS terminal, it works no problem. Any suggestions or explanations?
PowerShell ISE uses a different host profile than a standard PowerShell session. The $profile variable actually displays the profile for the CurrentUserCurrentHost profile by default, but there are four profile locations stored in this variable. Each of these locations are dot-sourced by default when you load PowerShell. You can see this by typing $profile | Get-Member -MemberType NoteProperty to see the total profiles configured:
AllUsersAllHosts
AllUsersCurrentHost
CurrentUserAllHosts
CurrentUserCurrentHost
Before we continue, let's talk about what a PowerShell Host really is. From Microsoft:
The host application can define the runspace where commands are run, open sessions on a local or remote computer, and invoke the commands either synchronously or asynchronously based on the needs of the application.
So what this means is that a PowerShell Host implements a PowerShell session. This can be powershell.exe for a basic, standard host, but there could be any number of alternative applications or development tools that may implement their own PowerShell Host as well, for a number of reasons.
The AllHosts profile locations should remain standard regardless of your PowerShell host, but different PowerShell hosts will typically set their own CurrentHost profile locations for their host. For example, powershell.exe is its own PowerShell host, and will have its own host-specific profiles, named Microsoft.PowerShell_profile.ps1. PowerShell ISE implements its own PowerShell host, and has different host-specific profiles named Microsoft.PowerShellISE_profile.ps1.
If you want code in your profile to be host-agnostic, you should make sure to place your profile code in one of the AllHosts profiles. Host-specific code, such as things you only want to be available in the context of the ISE PowerShell host, or a VSCode PowerShell host, should go into that host-specific profile.
$profile is different in the ISE:
$profile
C:\Users\js\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
console:
$profile
C:\Users\js\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

Execute Batch in Powershell (Win 10) does not affect Parent Shell

just for understanding this.
I want to open my Powershell in a certain folder. As I didn´t find out how, I tried to put a batch file with just "cd ....." in it in the default folder where PowerShell opens.
When I execute the batch, though, I end up where I started from.
It seems that the batch gets excuted in a subshell which doesn´t affect the Parentshell.
How can I execute the stuff in the batchfile in parentshell ?
Thanks in advance!
You cannot. Batch files are executed by cmd, not PowerShell, so there will always be a new process for them.
With a PowerShell script you can use dot-sourcing
. Script.ps1
To execute the script in your current scope, which is most similar to how batch files are executed by cmd by default.
If you want to open your Powershell in a certain folder, you can set that up in your Powershell profile. In Powershell, type $profile and that will give you the location of your profile file. Edit that file and use Set-Location:
Set-Location 'C:\Some\Place'
Powershell will execute whatever is in your profile script every time you open a new Powershell session.

Load script from PowerShell ISE's command environment

Is there a way to open a script file ($profile or otherwise) from within the IDE's command environment (PS> prompt), such that it loads in the IDE itself?
# loads the current user/current host profile in Notepad (probably because .PS1 is associated w/ Notepad.exe)
PS > ii $profile
# same for any random script file
PS > ii .\Foo.ps1
Instead of Invoke-Item, just use ise. When run from the ISE, it will load the file.
PS> ise myscript.ps1
To make Invoke-Item behave like you want (as well as double-clicking from Explorer), you can associate .ps1 files with powershell_ise.exe. Here is a blog post explaining how to do this if you need it.