1

In linux environment we can disable alias and call original command with ".\ls", is it possible also powershell?

function Get-WmiObject { 
    # In here How Can I Use original "Get-WmiObject" command?
    Get-WmiObject "win32_bios" | select Manufacturer
}
New-Alias -Name "Get-WmiObject" -Value Get-WmiObject -Force
  • Current session when I type "Get-WmiObject", it will be return me Get-WmiObject "win32_bios" | select Manufacturer

  • But first of all, it has to run "Get-WmiObject" original command inside my function

Error

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
+ ~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-WmiObject:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
Ichigo Kurosaki
  • 135
  • 1
  • 6
  • 3
    wouldnt it be simpler to name your function `Get-Manufacturer` ? then you would be able to keep using `Get-WmiObject` in the same session if needed? in any case you can use `Microsoft.PowerShell.Management\Get-WmiObject` inside the function and no `New-Alias` – Santiago Squarzon Aug 21 '23 at 22:58
  • Simple. Create a function with alias name that has one instruction that call the original function. – jdweng Aug 21 '23 at 23:28
  • Microsoft.PowerShell.Management ... solved my problem thank u @SantiagoSquarzon – Ichigo Kurosaki Aug 21 '23 at 23:58

1 Answers1

1

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.)

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thank u, by the way WMI command does not work on "PowerShell (Core) v6+" and above right? – Ichigo Kurosaki Aug 22 '23 at 07:51
  • @IchigoKurosaki, indeed they are not part of PowerShell (Core) anymore - though in recent versions you can call them via the Windows Compatibility feature, which is best avoided, however; see the 2nd footnote I've added to the answer. – mklement0 Aug 22 '23 at 12:17
  • 1
    I'm doing my best to make it work on older systems as well. That's my only purpose. For this reason, I will add the feature of adding my features by comparing the ps version in my next coding. Thanks for this good information. – Ichigo Kurosaki Aug 22 '23 at 13:37
  • By the way, I think there is one problem, but I not sure, I cannot forward my pipeline output to the my function "@args" is it normal? `function Get-WmiObject { Get-WmiObject -Class "win32_bios" @args }; Get-WmiObject | select Manufacturer | Remove-WmiObject`, **Remove-WmiObject** not finding class in here, is it normal? – Ichigo Kurosaki Aug 22 '23 at 19:49
  • 1
    @IchigoKurosaki, extra effort is needed if you want to support pipeline input - see [this answer](https://stackoverflow.com/a/67842481/45375). – mklement0 Aug 22 '23 at 21:06