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:

Community
  • 1
  • 1
Mircea
  • 178
  • 1
  • 1
  • 6
  • What's your use case? – Bill_Stewart Oct 31 '16 at 15:21
  • 1
    Remove `-WindowStyle Hidden`. – user4003407 Oct 31 '16 at 15:45
  • 1
    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`? – Ansgar Wiechers Oct 31 '16 at 18:55
  • @Bill_Stewart 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. – Mircea Nov 01 '16 at 12:55
  • @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. – Mircea Nov 01 '16 at 12:56
  • @PetSerAl Removing -WindowStyle Hidden did the trick. Thanks a lot. – Mircea Nov 01 '16 at 13:19
  • @PetSerAl Can you post your comment as answer so the can mark it as answer? – jumbo Jan 18 '18 at 12:45

3 Answers3

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
Thom Schumacher
  • 1,469
  • 13
  • 24
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.

0

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.

mklement0
  • 382,024
  • 64
  • 607
  • 775