In linux environment we can disable alias and call original command with ".\ls"
I think you meant \ls
, which would bypass an alias named ls
in POSIX-compatible shells such as Bash; however, it would not bypass a function of the same name.
To bypass both functions and aliases, you need to selectively use:
the builtin
builtin for shadowed builtins (built-in commands), such as cd
(e.g., builtin cd
)
which
for external utilities, such as ls
(e.g, "$(which ls)" -l
)
In PowerShell, by contrast, you can use the Get-Command
cmdlet with its -Type
(-CommandType
) parameter to obtain the command form of interest, and invoke the result with &
, the call operator:
Obtaining a specific command form this way and invoking it bypasses the precedence of command forms that applies when invoking commands by name, as detailed in the conceptual about_Command_Precedence help topic
Thus, using Get-Command -Type
is a single mechanism that allows you to invoke the desired form of any command, and therefore works equally with cmdlets (-Type Cmdlet
) and external programs (-Type Application
), for instance.
Applied to your case:
function Get-WmiObject {
& (Get-Command -Type Cmdlet Get-WmiObject) "win32_bios" |
Select-Object Manufacturer
}
Note:
You do not also have to define an alias in addition to your custom Get-WmiObject
function - the latter is enough.
- In fact, trying to define an alias with the same name as an existing command not only doesn't make any sense, it shouldn't even be allowed - yet as of PowerShell 7.3.6 such a definition is accepted and then fails on invocation, as you've experienced - see GitHub issue #20153.
In the case of invoking cmdlets and module-originated functions, specifically, you can alternatively - and less unambiguously[1] - use a module-qualified command name, as Santiago suggests: that is, you can qualify the cmdlet/function name with the name of its originating module, by placing the module name before the command name, separate with \
; e.g.:
Microsoft.PowerShell.Management\Get-WmiObject
To discover which module a given cmdlet or function (if any) originates from, you can again use Get-Command
:
# -> 'Microsoft.PowerShell.Management'
(Get-Command -Type Cmdlet Get-WmiObject).Module.Name
As an aside: The CIM cmdlets (e.g., Get-CimInstance
) superseded the WMI cmdlets (e.g., Get-WmiObject
) in PowerShell v3 (released in September 2012). Therefore, the WMI cmdlets should be avoided, not least because PowerShell (Core) 7+, where all future effort will go, doesn't even have them anymore.[2] Note that WMI still underlies the CIM cmdlets, however. For more information, see this answer.
[1] Although atypical, it is possible for multiple versions of a given module to be have been loaded side by side. To distinguish between those versions, you need to know the specific module version whose command you're trying to invoke, which requires using Get-Command
's -FullyQualifiedModule
parameter. You can find the module names and versions of all forms of a command with a given name with, e.g. Get-Command Get-WmiObject -All | Select Module, Version
. Once you know the desired version number, use something like:
& (Get-Command -FullyQualifiedModule @{ ModuleName = 'Microsoft.PowerShell.Management'; RequiredVersion = '3.1.0.0' } Get-WmiObject) -?
[2] The WMI cmdlets can now be called, namely via a hidden Windows PowerShell process used by the Windows PowerShell Compatibility feature, but that is best avoided, as you both pay a performance penalty and lose type fidelity, which notably includes loss of the methods of WMI objects. (Though note that CIM objects fundamentally lack methods and require use of Invoke-CimMethod
.)