45

Is it possible to run a Powershell script when you run Powershell? As in, double click the Powershell icon and open the window. Is there some type of "auto-run" setting somewhere?

user9993
  • 627

6 Answers6

53

There is a PowerShell script that runs on ps startup, if it exists. The filespec for this script is in the variable $profile.

You can use PowerShell commands to check to see if this script file exists, to create it if it doesn't, and to edit it with notepad. Here's the how-to guide.

Note that in recent (~2020 and later) versions, PowerShell will no longer run unsigned scripts (not even $profile!) by default. If you just follow the old instructions such as in that how-to guide, when you open a new PowerShell, you'll see an error message like:

. : File C:\[..]\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 cannot be loaded
because running scripts is disabled on this system. For more information,
see about_Execution_Policies at
https:/go.microsoft.com/fwlink/?LinkID=135170.

Signing your profile once — let alone every time you change it — is probably not realistic, so you must change the Execution Policy to allow it.

To do this, you can either:

  1. Run the following command as Administrator:

    Set-ExecutionPolicy RemoteSigned -Scope LocalMachine

  2. or, use RegEdit to modify Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell, adding a new REG_SZ with the name ExecutionPolicy and the value RemoteSigned.

Both have exactly the same effect and will persist across sessions.

The RemoteSigned policy requires that scripts downloaded from elsewhere be signed, but scripts you create locally on your machine (such as $profile) can run without a signature. (You could also set the policy to Unrestricted to enable unsigned downloaded scripts as well, but this isn't recommended security practice.)

Trey
  • 312
16

Type the following command:

New-item –type file –force $profile

A file Microsoft.PowerShell_profile.ps1 will be created in C:\Users\<username>\Documents\WindowsPowerShell\ for PowerShell 5 and older or C:\Users\<username>\Documents\PowerShell\ for PowerShell 6 Core (this folder will be automatically created).

Then edit this file and you can add personalized PowerShell functions or load modules or snap-ins...

Now when you run your powershell console, Microsoft.PowerShell_profile.ps1 will be triggered.

N P
  • 161
4

To run an arbitrary script on PowerShell session startup, use the following command:

PowerShell -NoExit -File PathToScript.ps1
3

There are many ways to do this. A straight forward way is to a profile script in your default powershell home path.

  1. Navigate to $env:UserProfile\Documents\WindowsPowerShell.
    Typically, this expands to C:\Users\<username>\Documents\WindowsPowerShell.
    Create the folders if they do not exist.
  2. Create a file named profile.ps1. You can write your script in this file, and this file will be executed each time you start powershell as the user. If you have the script somewhere else, you can have profile.ps1 call those scripts.

As a side note, the default profile name should be Microsoft.PowerShell_profile.ps1.
But profile.ps1 also works.

1

Update the Default $Profile Variable Edit the Default .PS1 file (if not exist, Create it) Add your Script to the .PS1 File

0

I wanted to provide an expanded answer to the OP's question that includes a more robust, and decidedly more secure, solution to the problem where PowerShell, by default, will not execute PowerShell scripts, even your own PowerShell profile script (insert facepalm meme here).

First, the rest of this answer assumes that you are using a Windows OS (since PowerShell Core now supports Linux & MacOS). Second, much credit due to the other users who have clarified where the "profile" script is expected to be found by PowerShell, which is in the $profile environment variable in PowerShell. This defaults to <PROFILE DIRECTORY>\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 where <PROFILE DIRECTORY> will be unique to your system and Windows profile name. As the accepted answer by Walter Mitty demonstrates, by PowerShell default, if you create this file, you will receive an error that executing scripts is disabled. This is because the PowerShell default execution policy is Restricted, meaning that no scripts can be executed. Many examples in articles suggest changing your execution policy to RemoteUnsigned, but this may leave some unsettled in that it allows any script on your local system to be run whether signed or not. A better default choice would be to set your execution policy to AllSigned, which only allows signed scripts to run regardless of them being located on the local machine or a remote resource (e.g. network file share). To sign your profile script, or any other script for that matter, you'll need to follow some additional steps to generate a code signing certificate and set it up to have a proper trust chain.

  1. Open a PowerShell terminal

NOTE: if you are coming back to these instructions to sign a PowerShell script (and you already have your script signing certificate installed), you may skip down to step 10.

  1. Set some variables for the new code signing certificate with values you deem appropriate (just type or paste & copy the lines not starting with a #):
# Define the certificate subject name
$subject = 'PowerShell Script Signing';

Define the date on which the certificate will expire (I recommend VERY far in the

future so your OS will "expire" before your scripts do!

NOTE: this date is local to your system, not UTC, and you may need to alter the format

if you use a different culture than en-US

$notAfterDate = '12/31/2099 23:59:59';

Define the size of the RSA key in bits

NOTE: the current default of 2048 is plenty for the purposes of local script signing

$keyLength = 2048;

  1. Create a new self-signed certificate:
$certificate = New-SelfSignedCertificate -CertStoreLocation Cert:\CurrentUser\My -Subject "CN=$subject" -KeySpec Signature -Type CodeSigningCert -NotAfter (Get-Date $notAfterDate) -KeyLength $keyLength -HashAlgorithm 'SHA256';

NOTE: the New-SelfSignedCertificate cmdlet will default to the current date, minus 10 minutes, for the "Not Before Date" value, so you do not need to specify it unless you wanted to [1]. The hash algorithm is specified as SHA256 as SHA1 (the default) has long been deprecated for security certificates.

  1. Your new certificate will be in the current user's certificate store in the "Personal" folder. To double-check, open your Start menu and type "user certificate". Select the option "Manage user certificates" to open the MMC plugin for the Certificate Manager using your current user's certificate store. Under "Certificates - Current User", expand the "Personal" folder to select the "Certificates" sub-folder. In here you should see your newly created certificate having the same value as you set for the $subject variable for the "Issued To" property. Keep this MMC window open as we'll come back to it later.
  2. Export the certificate to a file in your "My Documents" folder. The location is not important, so you may change $certificatePath to an absolute or relative path of your preference (e.g. "C:\Certificates\$subject.cer"):
$certificatePath = [Environment]::GetFolderPath("MyDocuments") + "\$subject.cer";
Export-Certificate -Cert $certificate -FilePath $certificatePath;
  1. Import the certificate into the "Trusted Root Certification Authorities" folder of the current user certificate store:
Get-Item $certificatePath | Import-Certificate -CertStoreLocation "Cert:\CurrentUser\Root";

NOTE: You will receive a "Security Warning" prompt because Windows cannot automatically verify the authenticity of the certificate (because it is self-signed). Since you created the certificate, you can trust yourself and click "Yes" to install the certificate.

  1. In the MMC window, expand "Trusted Root Certification Authorities" folder and select the "Certificates" sub-folder. If you don't see the code signing certificate in the list, you may need to right-click on the "Certificates" sub-folder and select "Refresh". Verify the certificate has been imported into this store location.
  2. Move the original certificate from the "Personal" folder to the "Trusted Publishers" folder. In my experience, having the certificate in the "Trusted Root Certification Authorities" folder only completes the trust chain for the certificate (as a self-signed certificate authority). PowerShell, however, still won't trust the script when signed by the certificate because it apparently only checks the "Trusted Publishers" location in your certificate store. Hence the need for moving the certificate to this folder.
    1. Expand the "Trusted Publishers" folder so that you can see the "Certificates" sub-folder.
    2. Drag the certificate from the "Personal\Certificates" folder into the "Trusted Publishers\Certificates" folder.
    3. Double-check the "Trusted Publishers\Certificates" folder to ensure the certificate is now found in that location.
  3. Close the MMC window and return to your PowerShell terminal.
  4. This step would normally have a shortcut to the certificate's thumbprint since you just created it. But for completeness we will assume you are returning here in the future to sign a different PowerShell script. Find your PowerShell script signing certificate[2]:
Get-ChildItem -Path Cert:\ -CodeSigningCert -Recurse

You should get at least one result, your newly created script signing certificate having the subject you specified in step 2. Copy the value for the matching certificate's Thumbprint to use as the <THUMBPRINT> value in the next step.

  1. Retrieve the certificate object:
$certificate = Get-ChildItem -Path Cert:\CurrentUser\TrustedPublisher | Where-Object { $_.Thumbprint -eq '<THUMBPRINT>' };
  1. Sign the PowerShell script:
Set-AuthenticodeSignature -FilePath 'C:\Users\example\Documents\myPowerShellScript.ps1' -Certificate $certificate;

TIP: if, at this point, you are trying to sign your PowerShell profile script, you could use $profile for the -FilePath parameter.

  1. Modify your default PowerShell script execution policy:
Set-ExecutionPolicy -ExecutionPolicy 'AllSigned' -Scope 'CurrentUser';
  1. Test your newly signed PowerShell profile script by opening a new instance of the PowerShell terminal. If successful, you should receive no error messages (unless there is a problem with your profile script itself). Close this new instance of PowerShell and return to the original.

  2. Clean up by removing the certificate file in your Documents folder:

Remove-Item ([Environment]::GetFolderPath("MyDocuments") + "\$subject.cer");

Further Notes

  • As mentioned in step 8, in my experience using PowerShell version 5.1.19041.5129, leaving the certificate in the "Personal\Certificates" location did not allow PowerShell to verify and trust the signed script. Moving the certificate to the "Trusted Publishers\Certificates" location resolved this issue. Your version of PowerShell may behave differently.
  • These instructions only apply to the current user. I intentionally did not mention performing this action for all users because:
    1. You would still have to make the certificate available in the "Trusted Publishers" folder in each user's certificate store OR create a unique certificate for each user.
    2. Other users on the system may have a different setting for the PowerShell script execution policy. As an example, if another user already switched to RemoteSigned, signing the scripts on the local machine becomes an unneeded step for that user.

References