npocmaka_ wrote:Nice feature and pretty useful in this case.
Definitely, this (script-block) could be better solution than invoke-expression. But there are more lacks than I expected.
--------------------------------------
Consider the following powershell script. It will be used further. Let's call it script.ps1.
Code: Select all
param(
[string]$str
);
$VAR = "Hello, world!";
function F1() {
$str;
$script:VAR;
}
F1;
There are:
-- param block describing the parameter $str
-- variable accessible via scope
Run it and find that both param block and variable scope are working
Code: Select all
>powershell -f script.ps1 "came from cmdline"
came from cmdline
Hello, world!
--------------------------------------
Let's make hybrid with invoke-expressions
Code: Select all
<# :
@echo off
setlocal
set "POWERSHELL_BAT_ARGS=%*"
if defined POWERSHELL_BAT_ARGS set "POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%"
endlocal & powershell -NoLogo -NoProfile -Command "$_ = $input; Invoke-Expression $( '$input = $_; $_ = \"\"; $args = @( &{ $args } %POWERSHELL_BAT_ARGS% );' + [String]::Join( [char]10, $( Get-Content \"%~f0\" ) ) )"
goto :EOF
#>
param(
[string]$str
);
$VAR = "Hello, world!";
function F1() {
$str;
$script:VAR;
}
F1;
and run it:
Code: Select all
>script.0.bat "came from cmdline"
The term 'param' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:10 char:6
+ param <<<< (
+ CategoryInfo : ObjectNotFound: (param:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Hello, world!
The param block doesn't work and throws exception when called in invoke-expression.
Let's fix it (the param block is commented):
Code: Select all
<# :
@echo off
setlocal
set "POWERSHELL_BAT_ARGS=%*"
if defined POWERSHELL_BAT_ARGS set "POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%"
endlocal & powershell -NoLogo -NoProfile -Command "$_ = $input; Invoke-Expression $( '$input = $_; $_ = \"\"; $args = @( &{ $args } %POWERSHELL_BAT_ARGS% );' + [String]::Join( [char]10, $( Get-Content \"%~f0\" ) ) )"
goto :EOF
#>
#param(
# [string]$str
#);
$VAR = "Hello, world!";
function F1() {
$str;
$script:VAR;
}
F1;
and run it:
Code: Select all
>script.0.bat "came from cmdline"
Hello, world!
We can see from the examples above that using invoke-expression, we loose the possibility to declare input parameters within param blocks.
--------------------------------------
Let's consider script-block:
Code: Select all
<# :
@echo off
setlocal
set "POWERSHELL_BAT_ARGS=%*"
if defined POWERSHELL_BAT_ARGS set "POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%"
endlocal & powershell -NoLogo -NoProfile -Command "$input | &{ [ScriptBlock]::Create( ( Get-Content \"%~f0\" ) -join [char]10 ).Invoke( @( &{ $args } %POWERSHELL_BAT_ARGS% ) ) }"
goto :EOF
#>
param(
[string]$str
);
$VAR = "Hello, world!";
function F1() {
$str;
$script:VAR;
}
F1;
Run it and find that we are still able to declare input parameters but have lost the variable scope:
Code: Select all
>script.1.bat "came from cmdline"
came from cmdline