How to use powershell.exe with -Command using a scriptblock and parameters
Asked Answered
F

3

15

For reasons that should not impact the current question I need to run a script, with the definition and parameters outside the command, inside a different PowerShell instance, without using PSSessions, background jobs or files (I have working examples for PSSession, background jobs and .ps1 files and I'm aware they can replace what I'm trying to do, but I need a working example with powershell.exe -Command as well).

I looked at the help for powershell.exe, and it should support what I am trying to do, but I can't get it working with all that I need (script definition and parameters outside the command).

As a working example I have:

$abc = powershell.exe -WindowStyle Hidden -NonInteractive -Command {Invoke-Command -ScriptBlock {
    param($a1,$a2)
    $a1*6
    $a2*5} -Argumentlist @(8,'abc')}

I need to be able to at least move the -ArgumentList outside the command, like:

$abc = powershell.exe -WindowStyle Hidden -NonInteractive -Command {Invoke-Command -ScriptBlock {
param($a1,$a2)
$a1*6
$a2*5} -Argumentlist @($args[0],$args[1])} -args @(8,'abc')

and even better have:

$script={
param($a1,$a2)
$a1*6
$a2*5}
$args=@(8,'abc')
$abc = powershell.exe -WindowStyle Hidden -NonInteractive -Command $script -args $args

I already looked at the following similar questions, but couldn't find what I needed:

Folkway answered 31/10, 2016 at 12:55 Comment(7)
What's your use case?Cuticula
Remove -WindowStyle Hidden.Khotan
Looks to me like you're running this from within PowerShell, so why do you think you need powershell.exe -Command instead of simply using Invoke-Command?Multitudinous
@Cuticula I'm testing an API and I need to execute a command multiple times, but due to some legacy code no developer wants to touch, I can only execute the command once per instance, hence the need for executing a command/script in a new instance.Folkway
@Ansgar Wiechers Thank you for making the question more readable. Yes, I'm running this from PowerShell, but Invoke-Command is executed in the same instance, and as stated before, for reasons outside my ability to control, I need to execute some commands multiple time.Folkway
@PetSerAl Removing -WindowStyle Hidden did the trick. Thanks a lot.Folkway
@PetSerAl Can you post your comment as answer so the can mark it as answer?Artifice
T
3

Not sure if this helps I added a few things to your original script and changed $args to $z and it seemed to work.

$script={
param($a1 =1 ,$a2 = 2)
$a1*6
$a2*5
test-connection -Count 2 www.google.com
Write-Output $a1
Write-Output $a2
}
$z=@(8,'abc')
$abc = powershell.exe -WindowStyle Hidden -NonInteractive -Command $script -args $z 

$abc

48
abcabcabcabcabc

PSComputerName                 : ok
IPV4Address                    :1.1.1.4
IPV6Address                    : 
__GENUS                        : 2
__CLASS                        : Win32_PingStatus
__SUPERCLASS                   : 
__DYNASTY                      : Win32_PingStatus
__RELPATH                      : Win32_PingStatus.Address="www.google.com",BufferSize=32,NoFragmentation=FALSE,RecordRoute=0,ResolveAddressNames=FALSE,SourceRou
                                 te="",SourceRouteType=0,Timeout=4000,TimestampRoute=0,TimeToLive=80,TypeofService=0
__PROPERTY_COUNT               : 24
__DERIVATION                   : {}
__SERVER                       : ok
__NAMESPACE                    : root\cimv2
__PATH                         : \\ok\root\cimv2:Win32_PingStatus.Address="www.google.com",BufferSize=32,NoFragmentation=FALSE,RecordRoute=0,ResolveAddressName
                                 s=FALSE,SourceRoute="",SourceRouteType=0,Timeout=4000,TimestampRoute=0,TimeToLive=80,TypeofService=0
Address                        : www.google.com
BufferSize                     : 32
NoFragmentation                : False
PrimaryAddressResolutionStatus : 0
ProtocolAddress                :1.1.1.4
ProtocolAddressResolved        : 
RecordRoute                    : 0
ReplyInconsistency             : False
ReplySize                      : 32
ResolveAddressNames            : False
ResponseTime                   : 19
ResponseTimeToLive             : 252
RouteRecord                    : 
RouteRecordResolved            : 
SourceRoute                    : 
SourceRouteType                : 0
StatusCode                     : 0
Timeout                        : 4000
TimeStampRecord                : 
TimeStampRecordAddress         : 
TimeStampRecordAddressResolved : 
TimestampRoute                 : 0
TimeToLive                     : 80
TypeofService                  : 0


PSComputerName                 : ok
IPV4Address                    :1.1.1.4
IPV6Address                    : 
__GENUS                        : 2
__CLASS                        : Win32_PingStatus
__SUPERCLASS                   : 
__DYNASTY                      : Win32_PingStatus
__RELPATH                      : Win32_PingStatus.Address="www.google.com",BufferSize=32,NoFragmentation=FALSE,RecordRoute=0,ResolveAddressNames=FALSE,SourceRou
                                 te="",SourceRouteType=0,Timeout=4000,TimestampRoute=0,TimeToLive=80,TypeofService=0
__PROPERTY_COUNT               : 24
__DERIVATION                   : {}
__SERVER                       : ok
__NAMESPACE                    : root\cimv2
__PATH                         : \\ok\root\cimv2:Win32_PingStatus.Address="www.google.com",BufferSize=32,NoFragmentation=FALSE,RecordRoute=0,ResolveAddressName
                                 s=FALSE,SourceRoute="",SourceRouteType=0,Timeout=4000,TimestampRoute=0,TimeToLive=80,TypeofService=0
Address                        : www.google.com
BufferSize                     : 32
NoFragmentation                : False
PrimaryAddressResolutionStatus : 0
ProtocolAddress                :1.1.1.4
ProtocolAddressResolved        : 
RecordRoute                    : 0
ReplyInconsistency             : False
ReplySize                      : 32
ResolveAddressNames            : False
ResponseTime                   : 21
ResponseTimeToLive             : 252
RouteRecord                    : 
RouteRecordResolved            : 
SourceRoute                    : 
SourceRouteType                : 0
StatusCode                     : 0
Timeout                        : 4000
TimeStampRecord                : 
TimeStampRecordAddress         : 
TimeStampRecordAddressResolved : 
TimestampRoute                 : 0
TimeToLive                     : 80
TypeofService                  : 0

8
abc
Tensive answered 2/3, 2018 at 22:31 Comment(0)
T
1

user4003407 has provided the crucial pointer:

  • Remove -WindowStyle Hidden from your call.

    • By using it, you're hiding the current console window, i.e. you're making the caller's window disappear, which is clearly not the intent.

    • If you're concerned about unwanted output from the CLI call:

      • By using $abc = , due to capturing success output, you're effectively hiding it.
      • If you need to silence other output streams, use redirections as needed, such as 2>$null to silence (non-terminating) errors.
      • *>$null would silence all streams (including the success output stream, which precludes capturing).
  • Apart from that, the last call in your question uses the correct syntax, whose overall form is, using powershell.exe, the Windows PowerShell CLI (the same applies analogously to pwsh, the PowerShell (Core) CLI):

    # Note: Works only from INSIDE PowerShell      
    powershell.exe -Command { ... } -args arg1, ...
    

Note:

  • -Command may be preceded by other parameters, such as -NoProfile - see the linked help topics for details.

  • -args must be a ,-separated list of positional arguments - named arguments (e.g., -foo bar) are not supported.

    • In your script block, you may declare parameters with a param(...) block, as in your attempt, or you can simply use the automatic $args variable to access the parameters by index ($args[0] for the first, ...).
  • Unlike with string-based CLI calls - which are the only option when calling from outside PowerShell - script block-based calls offer rich type support, within the type-fidelity limitations of PowerShell's XML-based serialization infrastructure - see this answer - and support for all output streams.

Tights answered 24/4, 2023 at 21:0 Comment(0)
P
0

This answer isn't 100% relevant to the original poster, because they are trying to run PowerShell from within PowerShell. I am trying to run it PowerShell from either a command prompt, or specifically WMI. A little background: the reason I'm trying to do this is because PowerShell remoting is not enabled on my target machine and I want to enable it. I can't use winrm because it requires user input. So, this works:

$x=Get-WmiObject -ComputerName "<computer name>" -Namespace "root\cimv2" -Class "Win32_Process" -List
$x.Create('C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command "& C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command {Enable-PSRemoting}"',$null,$null)

Results:

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     : 
__DYNASTY        : __PARAMETERS
__RELPATH        : 
__PROPERTY_COUNT : 2
__DERIVATION     : {}
__SERVER         : 
__NAMESPACE      : 
__PATH           : 
ProcessId        : 12508
ReturnValue      : 0
PSComputerName   : 

I should probably post this in a different question, but this one came up on a google search for "how to pass scriptblock to powershell.exe", so I thought it would be useful here.

Portfire answered 22/5, 2020 at 18:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.