How to use Powershell to download a script file then execute it with passing in arguments?
Asked Answered
E

2

8

I usually have this command to run some powershell script:

& ".\NuGet\NuGet Package and Publish.ps1" -Version $env:appveyor_build_version -NuGet "C:\Tools\NuGet\nuget.exe" -apiKey $env:apiKey

works fine but the script is found locally on my server.

I'm hoping to say: run this script with arguments, etc.. fine .. but the script is located as a GIST or in some GitHub public repo.

Is this possible?

Eyelid answered 19/10, 2015 at 1:33 Comment(4)
You download it from your online source and then run? What am I missing?Mamiemamma
@zespri i have no idea how to do that in powershell? or even if that can be possible?Eyelid
So the question amounts to "how download a file from internet with powershell?"Mamiemamma
... and then execute the contents of the file (the contents are a script) -- AND --- pass args to that (downloaded) script. (also happy to rename the question subject :) )Eyelid
A
16

In the linux world, this is commonly referred to as 'piping to bash'

Here is an example that installs chef taken from the chef documentation

curl -L https://omnitruck.chef.io/install.sh | sudo bash

The same thing can be done with powershell

. { iwr -useb https://omnitruck.chef.io/install.ps1 } | iex; install

iwr is shorthand for Invoke-WebRequest and iex is short for Invoke-Expression

Since you specifically asked about passing in arguments, here is an example with args.

. { iwr -useb https://omnitruck.chef.io/install.ps1 } | iex; install -channel current -project chefdk

You can look at the powershell script for a clearer understanding how it works.

Basically host your powershell script as a github gist, then in the script wrap everything in a module

new-module -name foobar -scriptblock {


  Function Foo() {

  }
  Function Bar() {

  }
  Function Install-Project() {
    param (
      [string]$project = 'chef',
      [string]$channel = 'stable'
    )
    Foo
    Bar
  }

  set-alias install -value Install-Project

  export-modulemember -function 'Foo','Bar' -alias 'install'
}

Best practices

'Piping to bash' is controversial because it is theoretically possible for attacker to intercept and replace your script with their own if you aren't careful.

  • Only install scripts you control or fully trust
  • Use permalinks or verify hashes of file you download
  • Only download from https
Advent answered 8/11, 2016 at 16:4 Comment(1)
This was really useful! But if I use exit in my script instead of exiting the program it closes PowerShell. Is there a way to only exit the program and leave PowerShell open?Sudarium
M
4

If I understood the question correctly, this is what worked for me:

(new-object net.webclient).DownloadFile('https://gist.githubusercontent.com/AndrewSav/c4fb71ae1b379901ad90/raw/23f2d8d5fb8c9c50342ac431cc0360ce44465308/SO33205298','local.ps1')
./local.ps1 "parameter title"

Output:

Called with parameter: parameter title

This is downloading and executing this gist: https://gist.github.com/AndrewSav/c4fb71ae1b379901ad90

Mamiemamma answered 19/10, 2015 at 2:38 Comment(5)
can you download that gist to an inmemory object, then execute that (with providing args to it) ? Eg - we don't have file access.Eyelid
Yes, you can with Invoke-Expression but you will need to fiddle with parameter passing. It may be not very trivial getting it right - depending on parameters. Look at Chocloatey download/install script. You can do something similar, you will just need to figure out how to pass the parameters, because chocolatey has none.Mamiemamma
yeah. i was hoping you might say "use iex .. but i've never had that working when I tried to pass args to that...Eyelid
Sorry. Add absence of file system access to the question, as this is the crucial piece of information.Mamiemamma
Np. it's not absent. I was just seeing if the answer could also be done using iex in the case of file-system access was denied.Eyelid

© 2022 - 2024 — McMap. All rights reserved.