Is it possible in Powershell to dot-source or re-use somehow script functions without it being executed? I'm trying to reuse the functions of a script, without executing the script itself. I could factor out the functions into a functions only file but I'm trying to avoid doing that.
Example dot-sourced file:
function doA
{
Write-Host "DoAMethod"
}
Write-Host "reuseme.ps1 main."
Example consuming file:
. ".\reuseme.ps1"
Write-Host "consume.ps1 main."
doA
Execution results:
reuseme.ps1 main.
consume.ps1 main.
DoAMethod
Desired result:
consume.ps1 main.
DoAMethod
You have to execute the function definitions to make them available. There is no way around it.
You could try throwing the PowerShell parser at the file and only executing function definitions and nothing else, but I guess the far easier approach would be to structure your reusable portions as modules or simply as scripts that don't do anything besides declaring functions.
For the record, a rough test script that would do exactly that:
$file = 'foo.ps1'
$tokens = @()
$errors = @()
$result = [System.Management.Automation.Language.Parser]::ParseFile($file, [ref]$tokens, [ref]$errors)
$tokens | %{$s=''; $braces = 0}{
if ($_.TokenFlags -eq 'Keyword' -and $_.Kind -eq 'Function') {
$inFunction = $true
}
if ($inFunction) { $s += $_.Text + ' ' }
if ($_.TokenFlags -eq 'ParseModeInvariant' -and $_.Kind -eq 'LCurly') {
$braces++
}
if ($_.TokenFlags -eq 'ParseModeInvariant' -and $_.Kind -eq 'RCurly') {
$braces--
if ($braces -eq 0) {
$inFunction = $false;
}
}
if (!$inFunction -and $s -ne '') {
$s
$s = ''
}
} | iex
You will have problems if functions declared in the script reference script parameters (as the parameter block of the script isn't included). And there are probably a whole host of other problems that can occur that I cannot think of right now. My best advice is still to distinguish between reusable library scripts and scripts intended to be invoked.
After your function, the line Write-Host "reuseme.ps1 main." is known as "procedure code" (i.e., it is not within the function). You can tell the script not to run this procedure code by wrapping it in an IF statement that evaluates $MyInvocation.InvocationName -ne "."
$MyInvocation.InvocationName looks at how the script was invoked and if you used the dot (.) to dot-source the script, it will ignore the procedure code. If you run/invoke the script without the dot (.) then it will execute the procedure code. Example below:
function doA
{
Write-Host "DoAMethod"
}
If ($MyInvocation.InvocationName -ne ".")
{
Write-Host "reuseme.ps1 main."
}
Thus, when you run the script normally, you will see the output. When you dot-source the script, you will NOT see the output; however, the function (but not the procedure code) will be added to the current scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With