Mark Robbins
Mark Robbins

Reputation: 2457

Create powershell alias for . $profile

I want to create a set of aliases in a file that I can update, then invoke an alias aa so that the file executes and I am provided with the new aliases in the current session. Ultimately I wanted these aliases available automatically on PS startup so I am using C:\Users\Administrator\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 to put them in. Right now it looks like:

$psdir="C:\Users\Administrator\Documents\WindowsPowerShell"  

function Reload-Profile{
  # . ${profile} DOES NOT WORK
  # Write-Host ${profile}
  # Write-Host $profile
  # powershell $profile DOES NOT WORK      
  # Get-ChildItem "${psdir}\*.ps1" | %{.$_} DOES NOT WORK
  Write-Host "Custom PowerShell Environment Loaded" 
}
function Edit-Profile
{
  powershell_ise.exe $profile
}
Set-Alias show Get-ChildItem
Set-Alias show2 Get-ChildItem
Set-Alias aa Reload-Profile
Set-Alias ep Edit-Profile

How can I do this so that the aliases are loaded on startup, yet I can also update them with an aa alias and have them brought into the current session?

Upvotes: 2

Views: 903

Answers (2)

user4003407
user4003407

Reputation: 22132

The problem with your code is, that Reload-Profile is a function and when you invoke it, it will create new scope for itself. When you then invoke . $profile, it will not create new scope for profile, but it still be invoked inside Reload-Profile scope. Thus, when Reload-Profile ends, the scope will be discarded. So, you need to invoke Reload-Profile with dot invoke operator as well: . Reload-Profile or . aa, if you use alias.

I assume, your real question is "How to make aa command in a way, which does not require to use dot invoke operator?"

The answer will be to use compiled cmdlet instead of PowerShell function, because PowerShell does not create new scope for cmdlet invocation. That cmdlet can then invoke . $profile in current scope.

Add-Type @‘
    using System.Management.Automation;
    using System.Management.Automation.Runspaces;
    [Cmdlet("Reload", "Profile")]
    public class ReloadProfileCmdlet : PSCmdlet {
        protected override void EndProcessing() {
            InvokeCommand.InvokeScript(
                ". $profile",
                false,
                PipelineResultTypes.Output | PipelineResultTypes.Error,
                null
            );
        }
    }
’@ -PassThru | Select -First 1 -ExpandProperty Assembly | Import-Module
Set-Alias aa Reload-Profile

P.S.
I recommend you to use different verb instead of Reload, because Reload is not included in a list of recommended verbs, thus Import-Module will issue warning, when you import Reload-Profile into your session.

Upvotes: 1

Seth
Seth

Reputation: 1255

If the original author of the comment that contained the following code decides to post it as an answer, just add a comment to this answer and I will remove it. As it has been two days I don't really expect him to. Meanwhile this should give people a better idea of what is actually happening.

# https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.utility/add-type
# Create a new cmdlet Reload-Profile using C# code and import it
Add-Type '
using System.Management.Automation;
using System.Management.Automation.Runspaces;

// https://msdn.microsoft.com/en-us/library/dd878294(v=vs.85).aspx
[Cmdlet("Reload", "Profile")]
public class ReloadProfileCmdlet : PSCmdlet {
    protected override void EndProcessing()
    {
        // https://msdn.microsoft.com/en-us/library/ms568378(v=vs.85).aspx
        // Runs $profile without parameters in the current context and displays the output and error
        InvokeCommand.InvokeScript(". $profile", false, PipelineResultTypes.Output | PipelineResultTypes.Error, null);
    }
}' -PassThru | Select -First 1 -ExpandProperty Assembly | Import-Module;
# Setup an alias for the new cmdlet
Set-Alias aa Reload-Profile

For better readability/highlighting the C# code standalone:

using System.Management.Automation;
using System.Management.Automation.Runspaces;

// https://msdn.microsoft.com/en-us/library/dd878294(v=vs.85).aspx
[Cmdlet("Reload", "Profile")]
public class ReloadProfileCmdlet : PSCmdlet {
    protected override void EndProcessing()
    {
        // https://msdn.microsoft.com/en-us/library/ms568378(v=vs.85).aspx
        // Runs $profile without parameters in the current context and displays the output and error
        InvokeCommand.InvokeScript(". $profile", false, PipelineResultTypes.Output | PipelineResultTypes.Error, null);
    }
}

Upvotes: 2

Related Questions