0

I have a script like this:

 [CmdletBinding()]
 param(
    [Parameter(Mandatory=$true)]
    $Message
 )
 Write-Host "Hello, $Message!"

But I want to provide a method that allows users to dot source the script. Initially, I was just thinking I would wrap the whole script in a function to allow dot sourcing:

 function Hello
 {
    [CmdletBinding()]
    param(
       [Parameter(Mandatory=$true)]
       $Message
    )
    Write-Host "Hello, $Message!"
 }

The problem with this is that if I did this, it would break the script for some people who are using it the old way. Is it possible to return an object with the same functionality as the script, or is there a way to dot source the script as it is (the first example above)?

3 Answers 3

3

I would suggest using splatting with $PSBoundParameters:

[CmdletBinding()]
 param(
    [Parameter(Mandatory=$true)]
    $Message
 )

 function Hello
 {
    [CmdletBinding()]
    param(
       [Parameter(Mandatory=$true)]
       $Message
    )
    Write-Host "Hello, $Message!"
 }

 Hello @PSBoundParameters

Alternatively: instead of dot-sourcing just create function from existing script:

$code = Get-Content .\HelloScript.ps1
New-Item -Path function:\Hello -Value ([scriptblock]::Create($code))
3
  • Good idea with @PSBoundParameters but if no argument is passed the script will take an empty array as a valid argument and output Hello, ! rather than throw an error(which is presumably what the OP wants because of Mandatory=$true)
    – Raf
    Commented Aug 13, 2014 at 8:19
  • If you create the function using your second block of code, how do you call it? It doesn't seem to let me do anything after I create the function.
    – EGr
    Commented Aug 13, 2014 at 13:02
  • @Raf - it works exactly same as original, because on script -Message is also Mandatory. @EGr - You just call it Hello -Message YourMessage
    – BartekB
    Commented Aug 14, 2014 at 5:29
0

At the end of function Hello you must trigger it to simulate old behaviour. So if the script used to take an argument from command line, lets say c:\scripts\hello.ps1 bob, you can do it as so:

function Hello
{
   ...
}
if($args.Count -eq 0){
   Hello $null
}
else{
   Hello $args
}

$args will be an empty array if you were to run c:\scripts\newhello.ps1 without an argument, rather than $null as previously when no value was passed. Therefore we check $args.Count before triggering the function with correct parameter.

1
  • So I would need to redefine the whole function in a function block?
    – EGr
    Commented Aug 12, 2014 at 15:54
0

I know this is incredibly old but I just ran into it while doing something similar. I have a Foo.ps1 script that needs to work as a script but that I would also like available as one function exported from a module. It seems (I just started playing with it) as if putting the following (in Foo.psm1) function Foo { . "$PSScriptRoot\Foo.ps1" } works like a charm. Avoids having to write out all the arguments in two places.

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.