Powershell: Foeach-Object -Parallel problems with functions imported by WindowsCompatibility module

Created on 23 Aug 2019  路  4Comments  路  Source: PowerShell/PowerShell

Foreach-Object -Parallel doesn't recognize available commands when imported using the WindowsCompatibility module. This likely has to do with how those commands are imported using local remoting, but I haven't dug into the -Parallel implementation yet to see where the failure is.

Steps to reproduce

# Import a windows module, doesn't matter which one. Here I'm importing WMI commands
Import-WinModule Microsoft.Powershell.Management -Force
# Can validate that commands imported with 'Get-Command Get-WMIObject'
Get-Command Get-WMIObject
CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Get-WmiObject                                      1.0        Microsoft.PowerShell.Management.WinModule
# Set a variable to iterate through
$service = 'W32Time','WManSvc','PlugPlay'
# Attempt to use new -Parallel flag
$service | ForEach-Object -Parallel {Get-WmiObject -Class win32_service -Filter ("Name = '{0}'" -f $_)}

# Output error (repeated 3 times)
Get-WmiObject : The term 'Get-WmiObject' 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:1 char:1
+ Get-WmiObject -Class win32_service -Filter ("Name = '{0}'" -f $_)
+ ~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Get-WmiObject:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

Expected behavior

# Should work like it does with the -Process flag:
$service | ForEach-Object -Process {Get-WmiObject -Class win32_service -Filter ("Name = '{0}'" -f $_)} 

ExitCode  : 0
Name      : W32Time
ProcessId : 1736
StartMode : Manual
State     : Running
Status    : OK

ExitCode  : 1077
Name      : WManSvc
ProcessId : 0
StartMode : Manual
State     : Stopped
Status    : OK

ExitCode  : 0
Name      : PlugPlay
ProcessId : 1036
StartMode : Manual
State     : Running
Status    : OK

Actual behavior

# Returns an error stating the command doesn't exist-
Get-WmiObject : The term 'Get-WmiObject' 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:1 char:1
+ Get-WmiObject -Class win32_service -Filter ("Name = '{0}'" -f $_)
+ ~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Get-WmiObject:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

Environment data

Name                           Value
----                           -----
PSVersion                      7.0.0-preview.3
PSEdition                      Core
GitCommitId                    7.0.0-preview.3
OS                             Microsoft Windows 10.0.18362
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Area-Cmdlets-Core Issue-Question Resolution-Answered

Most helpful comment

ForEach-Object -Parallel is akin to using Start-Job to run the commands - it's run in a totally separate process. You'll need to run the import command _inside_ the -Parallel scriptblock; the module being available in the parent session is not sufficient for -Parallel 馃檪

All 4 comments

ForEach-Object -Parallel is akin to using Start-Job to run the commands - it's run in a totally separate process. You'll need to run the import command _inside_ the -Parallel scriptblock; the module being available in the parent session is not sufficient for -Parallel 馃檪

/cc @PaulHigin for information.

Perhaps we could add this in the cmdlet docs..

@iSazonov Thanks, yes I agree this needs to be documented. We can also think about adding common initialization for the parallel script blocks including module import. I actually thought about adding it but decided it was something we could add later as needed.

BTW I will publish a blog article soon on this feature, and will use some of the information for cmdlet documentation.

This issue has been marked as answered and has not had any activity for 1 day. It has been closed for housekeeping purposes.

Was this page helpful?
0 / 5 - 0 ratings