Search code examples
powershellwebclientdownloadstring

Powershell IEX not importing module


I'm writing a small powershell script that allows users to pull down a list of powershell ps1 files stored on a local webserver. Browsing to the URL would show a directory listing.

The script has 2 switches: (1) "-i" will use some simple regex to display a list of ps1 files found at the given URL, (2) if "-m" is supplied the script should pull down the desired ps1 and "import" it so it becomes available in the current terminal session.

Examples:

PS C:> Demo-Module -i http://10.1.1.1/repo/

PS C:> Demo-Module -i http://10.1.1.1/repo/ -m ShareEnum.ps1

Code:

  if($i){
    if(-Not ($m)){
        $webClient = new-object System.Net.WebClient
        $webClient.DownloadString($i) -split "`n" | Select-String -Pattern '[-A-Z0-9.]+\.ps1' | % { $_.Matches | % { $_.Value } }
    }
    if($m){
        if($i.EndsWith("/") -eq "True"){
            $url = echo $i$m
            IEX (New-Object System.Net.Webclient).DownloadString($url)
        }
        else{
            $url = echo $i'/'$m
            IEX (New-Object System.Net.Webclient).DownloadString($url)
        }
    }
  }

Keep in mind this is just some demo code. The logic here runs without any errors however afterwards the ps1 file (eg: ShareEnum) is not available on the commandline.

Running the following from the commandline does work:

PS C:> IEX (New-Object System.Net.Webclient).DownloadString('http://10.1.1.1/ShareEnum.ps1')
PS C:> Get-Help ShareEnum   # The script is loaded in the current terminal session

Any help is appreciated.

Clarification:

I just want to clarify the issue as there seems to be some confusion about what I want to achieve. This question is not about how to run a ps1 script locally, the idea is that ps1 scripts can be hosted on a webserver and loaded directly into the current powershell terminal session.

Both of the following have exactly the same effect.

Remotely loading ShareEnum:

PS C:> IEX (New-Object System.Net.Webclient).DownloadString('http://10.1.1.1/ShareEnum.ps1')

Locally dot-sourcing ShareEnum:

PS C:> . .\ShareEnum.ps1

The examples above work perfectly. The issue, I think, is that the $url variable is not being interpreted correctly by WebClient in my demo code. The script exits without displaying any error but after it runs, ShareEnum can not be called within the current powershell terminal session.


Solution

  • Well.. I have figured out what the problem actually is but it leaves me with a new issue. The code above works as intended however the "imported" remote script is tied to the script scope and when the code finishes running and the script exits the imported script gets removed.

    There is a dirty solution to this issue. The remote ps1 needs to be edited so that the function is set as a global function. This way when the script exits the remote ps1 file is still loaded in the current session.

    function global:ShareEnum
    {
    ...
    }
    

    This is not great, ideally the Demo-Module should handle this by itself. I will leave this question open for a while to see if anyone can find a better way to solve this issue.