0

I have a module, and script which runs simple user scripts. I want to keep user script as simple as possible, and that's why I use Import-Module with -Global flag. I have a problem with module "private" variable. In my case I have 2 copies of this variable. Can I achieve only one copy?

Below is simple example. You can run in by placing 3 files in the same folder and executing ScriptRunner.ps1.

Module.psm1

function Invoke-UserScript
{
    param($Path)

    $Script:UserScriptFailed = $false
    & $Path
    return $Script:UserScriptFailed
}

function New-Something
{
    $Script:UserScriptFailed = $true
}

function Write-Var
{
    Write-Host "Write-Var output: $Script:UserScriptFailed"
}

Export-ModuleMember -Function Invoke-UserScript
Export-ModuleMember -Function New-Something
Export-ModuleMember -Function Write-Var

ScriptRunner.ps1

Set-Location $PSScriptRoot
Import-Module -Name (Resolve-Path '.\Module.psm1') -Global
$failed = Invoke-UserScript -Path '.\UserScript.ps1'
Write-Output "ScriptRunner output: $failed"

UserScript.ps1

New-Something
Write-Var

In my example function New-Something sets UserScriptFailed to $true. But once UserScript.ps1 finishes, ScriptRunner.ps1 sees $false value.

Output:

Write-Var output: True
ScriptRunner output: False
Zergatul
  • 1,957
  • 1
  • 18
  • 28
  • This is to be expected - `$script:` refers to the module scope when called from within a module's exported function, and `ScriptRunner.ps1` is not part of the module – Mathias R. Jessen May 13 '19 at 14:11
  • @MathiasR.Jessen `ScriptRunner.ps1` is not part of the module, and it is not referring to `UserScriptFailed` variable, we are ok here. The problem is `& $Path` creates new copy of this variable. And this line is within a module. – Zergatul May 13 '19 at 14:18
  • You could maybe use `Export-ModuleMember -Variable ...`, but I'm not sure how this will work the `script:` scope. Another way could be to move `UserScriptFailed` to `global`-scope, but that's not the best joice ... – Moerwald May 13 '19 at 14:57
  • What do you want to achieve? – Moerwald May 13 '19 at 14:58
  • If you want to share a variable between multiple ps1-files you can try to inject to variable as a [ref](https://stackoverflow.com/questions/29596634/how-to-define-named-parameter-as-ref-in-powershell)-parameter – Moerwald May 13 '19 at 15:03
  • @Moerwald I want to validate user script by using my module. User creates simple script with commands from my module (I parse his script and check if he uses only allowed commands). In short I want to achieve 2 `True` values in my output. – Zergatul May 13 '19 at 15:10
  • @Moerwald global variable or exported variable is bad, since user can access it – Zergatul May 13 '19 at 15:11
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/193276/discussion-between-moerwald-and-zergatul). – Moerwald May 13 '19 at 15:19

1 Answers1

1

You could try to dot source the script you want to check:

function Invoke-UserScript
{
    param($Path)

    $Script:UserScriptFailed = $false
    # Sourcing may add the functions to the current scope
    . $Path
    & $Path
    return $Script:UserScriptFailed
}
Moerwald
  • 10,448
  • 9
  • 43
  • 83