40

How can I execute PowerShell ps1 scripts from package.json "scripts"?

I know how to set up a basic script in package.json "scripts". For example with the following configuration, I can exec npm run test which will output "this is only a test" to the console:

"scripts": {
  "test": "echo \"this is only a test\""
}

However, I have a more advanced scenario where I'd like to execute a PowerShell script. Something like this:

"scripts": {
  "buildAngular": "buildAngular.ps1"
}

Can I exec a ps1 script like this via the scripts object? Is any special setup/config required? Are there any additional constraints?

4 Answers 4

79

Assuming powershell is in you PATH you can call it like this:

"scripts": {
    "test": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command ./test.ps1"
}

Tested on Windows 7 with Powershell v4.

Limitations are that you need Powershell installed and in your PATH. I didn't test it with Powershell for Linux, so not sure if this solution will be portable to other platform for now.

Sign up to request clarification or add additional context in comments.

3 Comments

It works on Linux / Mac OS X with Powershell Core if you replace @powershell with pwsh and -Command with -File (see What's New in PowerShell Core 6.0). Do not use the the @ symbol before pwsh because it's a batch syntax. The complete working example is: "test": "pwsh ./Do-Stuff.ps1 -ExecutionPolicy Unrestricted -NoProfile".
great answer, works on my Windows 10
Personally, I favour calling a .bat script, passing the ps1 file to execute as an argument. Then inside the batch script, perform checks on whether PowerShell Core exists before falling back to 'native' PowerShell for Windows users. You can also put your -NoProfile -ExecutionPolicy... code in the batch script as well so it's a bit cleaner.
9

Prepend the PowerShell command with "powershell", e.g.,

"command": "powershell Remove-Item ..\\folder\\file; Copy-Item -Path folder\\* -Destination ..\\other-folder -Recurse",
"buildAngular": "powershell buildAngular.ps1"

Comments

7

You might set the script-shell config - either via npm config set script-shell "powershell" or environment variable $env:npm_config_script_shell="powershell"

Then you could use

"scripts": {
    "test": "Write-Host 'this is only a test'"
}

or

"scripts": {
    "buildAngular": ".\\buildAngular.ps1"
}

I'm not sure whether you can supply parameters like -NoProfile though.

Comments

0

Personally, I favour calling a .bat script and passing the .ps1 filename to execute as an argument. Obviously this will only work in Windows, so YMMV.

Inside the batch script, you can perform checks on whether PowerShell Core exists before falling back to 'native' PowerShell. You can also put your -NoProfile -ExecutionPolicy code in the batch script as well so it's a bit cleaner in the package.json file.

Package.json:

"scripts": {
  "test": "build-scripts\RunBuildScript.bat test"
}

RunBuildScript.bat:

@ECHO OFF

REM Check the argument passed in. You could also check if the file actually exists.
SET "NpmBuildScriptName=%1"
IF ["%NpmBuildScriptName%"] == [""] (
    ECHO "Could not find the name of the script."
    GOTO :TidyUp
)

REM Perform some checks for PowerShell Core in the file system.
FOR %%s IN ("PowerShell\pwsh.exe" "\PowerShellCore\pwsh.exe") DO (
    IF EXIST %%s (
        ECHO "PowerShell found at %%s"
        SET "PowerShellPath=%%s"
        GOTO :ExecuteScript
    )
)

REM If you can't find PowerShell, use the default.
IF ["%PowerShellPath%"] == [""] (
    ECHO "PowerShell Core was not found. Defaulting to native PowerShell"
    SET "PowerShellPath=powershell"
    GOTO :ExecuteScript
)

:ExecuteScript
    %PowerShellPath% -NoProfile -ExecutionPolicy Unrestricted -Command "%NpmBuildScriptName%.ps1"
    GOTO :TidyUp

:TidyUp
    REM Wipe after using.
    SET "NpmBuildScriptName="

ECHO 0

test.ps1

Write-Host "this is only a test"

Obviously a lot of hoops to jump through just to output some text, but this approach makes it a bit more extensible.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.