Closed Tadas closed 5 years ago
Good idea @Tadas. Thanks!
@Tadas I'm trying to repro your issue but can't get the problem to occur. This is what I'm trying:
function Start {
[cmdletbinding()]
param()
'Start your engines'
}
or
function Start-Engine {
[PoshBot.BotCommand(
CommandName = 'start'
)]
[cmdletbinding()]
param()
'Start your engines'
}
or
function Start-Engine {
[PoshBot.BotCommand(
Aliases = 'start'
)]
[cmdletbinding()]
param()
'Start your engines'
}
All of these seem to work fine.
What does your plugin command look like that triggers this?
It can only happen when you have an alias defined
> Get-Alias -Name start
CommandType Name Version Source
----------- ---- ------- ------
Alias start -> Start-Process
> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.18262.1000
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.18262.1000
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
Only your first example triggers the bug, that function is pretty much identical to what I have.
Sorry still can't repro this, and I'm not sure why you're getting a problem either. 🤷♂️
PoshBot is already executing the actual command from the module, not the module-qualified name, but the actual function/cmdlet object returned from Get-Command
.
When it loads the module, it gets all the module's public commands via Get-Command here.
It then stores each object in either the .FunctionInfo
or .CmdletInfo
property of the [Command]
instance depending on if the command is of type Function
or Cmdlet
here. When it comes time to execute a command in a job, it adds either the .FunctionInfo
or .CmdletInfo
property to the hashtable that will be sent to the job here. Inside the job, it executes the actual command object here and here.
It never executes the command by name only which I can see would cause a problem with aliases of the same name.
Below is effectively what PoshBot does and even though I've added an alias for start
, it still executes the module command because it's not being executed by name.
New-Alias -Name start -Value Start-Process
$c = Get-Command -Module PoshBot.PSSummit -Name start
& $c
I'd like to understand more about how you're running into this.
Ok I think we're running into serialization nuances. Is your plugin begin executed as job?
Just before Start-Job
call:
https://github.com/poshbotio/PoshBot/blob/5cadba893fe9191634d6e8d23a802f7229917dd2/PoshBot/Classes/Command.ps1#L133-L138
[DBG]: PS D:\Dev\_PoshBot>> $jobParams.ArgumentList.Function.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False FunctionInfo System.Management.Automation.CommandInfo
and inside of the job:
[DBG]: [Job14]: PS D:\Documents>> l
26: ParsedCommand = $options.ParsedCommand | Select-Object -ExcludeProperty $parsedCommandExcludes
27: OriginalMessage = $options.OriginalMessage
28: BackendType = $options.BackendType
29: }
30: Wait-Debugger
31:* & $cmd @namedParameters @positionalParameters
32:
[DBG]: [Job14]: PS D:\Documents>> $cmd.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True PSObject System.Object
[DBG]: [Job14]: PS D:\Documents>> $cmd | gm
TypeName: Deserialized.System.Management.Automation.FunctionInfo
Name MemberType Definition
---- ---------- ----------
GetType Method type GetType()
ToString Method string ToString(), string ToString(string format, System.IFormatProvider ...
Namespace NoteProperty string Namespace=ReproModule
CmdletBinding Property System.Boolean {get;set;}
CommandType Property System.String {get;set;}
DefaultParameterSet Property {get;set;}
Definition Property System.String {get;set;}
Description Property {get;set;}
HelpFile Property {get;set;}
Module Property System.String {get;set;}
ModuleName Property System.String {get;set;}
Name Property System.String {get;set;}
Noun Property System.String {get;set;}
Options Property System.String {get;set;}
OutputType Property Deserialized.System.Collections.ObjectModel.ReadOnlyCollection`1[[System....
Parameters Property Deserialized.System.Collections.Generic.Dictionary`2[[System.String, msco...
ParameterSets Property Deserialized.System.Collections.ObjectModel.ReadOnlyCollection`1[[System....
RemotingCapability Property System.String {get;set;}
ScriptBlock Property System.String {get;set;}
Source Property System.String {get;set;}
Verb Property System.String {get;set;}
Version Property System.Version {get;set;}
Visibility Property System.String {get;set;}
Ahh. That makes sense.
I'm OK with this change to use the module qualified name.
Description
I wanted to use
start
cmdlet name in a plugin but discovered that command execution jobs never finish executing. Turns out thatstart
was being resolved asStart-Process
by PowerShell. PoshBot should use module-qualified cmdlet names when invoking plugin commands to ensure that the right cmdlet is called regardless of aliases.https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_command_precedence?view=powershell-6#qualified-names
Related Issue
Motivation and Context
Enables usage of cmdlet names in plugins which might be hidden by an alias e.g.
start
(a default alias forStart-Process
)How Has This Been Tested?
Types of changes
Checklist: