4

I'm using Windows PowerShell and it is configured using doskey macros. I have a file named Macros.doskey.

105=code E:\static5\105
135=code E:\static5\135
static5=code E:\static5

How can I get the command corresponding to alias name ?

For example, when I type 105 in PowerShell it will execute the command code E:\static5\105

Now I want to know how to get the command from the alias name.

briantist
  • 45,546
  • 6
  • 82
  • 127
Sanjay Raz
  • 135
  • 6
  • 1
    this `doskey /macros` will list out the current set of doskey macros. you can parse the resulting text fairly easily. [*grin*] – Lee_Dailey Mar 10 '19 at 18:09
  • @Lee_Dailey that looks promising. How cool would it be if `Get-Command` and/or `Get-Alias` could be extended to list those?! – briantist Mar 10 '19 at 18:10
  • @briantist - i would not do it that way. i prefer to leave the builtin stuff unchanged. however, it is fairly easy to write a wrapper for those if desired. i would make a function that called `doskey` with a filter to match against a parameter value. [*grin*] – Lee_Dailey Mar 10 '19 at 18:17
  • @Lee_Dailey, `doskey /macros` command list out the complete set of doskey macros. How can I show only one command? – Sanjay Raz Mar 10 '19 at 18:18
  • @SanjayRaz - use something like `doskey /macros | Where-Object {$_ -match $Var}` in a custom function. use the basic function template from the ISE to make it really easy. [*grin*] – Lee_Dailey Mar 10 '19 at 18:30

3 Answers3

3
  • doskey is a utility primarily designed to work with cmd.exe, not PowerShell.

    • PowerShell has better functionality built in, in the form of aliases and functions, and in Windows 10 you must even deactivate PowerShell's own command-line editing to even get doskey to work (see below).
  • If you still want to use doskey in PowerShell, there are two prerequisites:

    • The PSReadLine module - which handles command-line editing since Windows 10 by default - must not be loaded, as it takes precedence over doskey definitions[1]; that is, you may need to unload it explicitly with Remove-Module PSReadLine, but that means that you'll lose all of its benefits.

    • You must invoke any doskey.exe macro definitions with /exename=powershell.exe (Windows PowerShell) or /exename=pwsh.exe (PowerShell Core) for them to be usable from PowerShell.

      • Note that it is then doskey that expands a macro name typed by the user, which means that PowerShell only sees the expanded command and therefore has no knowledge of macro names. Therefore, trying to inspect doskey macros with
        Get-Command won't work; inspect the output from doskey /macros instead, as in Lee Dailey's answer.

      • Additionally, doskey also resolves macros when soliciting arbitrary user input via Read-Host[1], which is undesired.


To summarize the reasons for not using doskey in PowerShell:

  • It cannot be used with the PSReadLine module, which by default handles command-line editing since Windows 10 and provides invaluable functionality.

  • doskey macro expansion invariably also occurs when scripts solicit arbitrary user input via Read-Host, which is undesired.


Therefore, I suggest you abandon doskey in favor of PowerShell functions, and add them to your $PROFILE file so that they're available in every session:

  • While you can define functions named for numbers such as 105in PowerShell, you'll have to invoke them with & so as to disambiguate from actual numbers, e.g., & 105.

  • Therefore, I suggest refactoring your approach to define a single function named, say, c, that takes an optional argument to identify which file(s) to open:

function c { pushd E:/static5; code $(if ($Args) { $Args } else { '.' }); popd }

Your original doskey macros then map onto this function as follows:

  • 105 -> c 105
  • 135 -> c 135
  • static5 -> c

Note that this not only allows you to pass an arbitrary file name (of a file located in E:/static5/) to function c, but even multiple ones; e.g., c 105 135 would open both files for editing.

To inspect the definition of function c later, you can simply call $function:c or, more verbosely, (Get-Command c).Definition.


[1] As PetSerAl notes: "doskey performs translations on the console input buffer. [...]. It does not work if the console is not in line input mode, thus it is not compatible with PSReadline, although Read-Host will be affected.
https://i.stack.imgur.com/HpYzq.png"

mklement0
  • 382,024
  • 64
  • 607
  • 775
1

I've never used doskey with PowerShell, so I'm not sure how they appear. My best guess is that PowerShell sees them as commands of type "Application" which usually means external executables.

To start, check what PowerShell sees:

Get-Command 105 | Format-List *
# or
gcm 105 | fl *

From there, you might see just some exe like doskey.exe or maybe you'll see additional info too.

If it's just listed as an executable then I'm not sure you'll be able to get the info out of doskey.

PowerShell has its own versions of aliases which would have let you do full discovery, but PowerShell aliases can't take parameters, they just alias one command to another.

You could simulate doskey functionality in PowerShell by writing functions instead:

function static5 {
    code.exe 'E:\static5'
}
briantist
  • 45,546
  • 6
  • 82
  • 127
  • Thank you for the quick reply. Your solution works when I use functions to simulate doskey functionalities but in my case, PowerShell give me some error like this Get-Command : The term '105' 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-Command 105 | Format-List * – Sanjay Raz Mar 10 '19 at 18:03
  • @SanjayRaz that's very interesting, I don't know how the command could work in PowerShell while not being discoverable through `Get-Command`. Unfortunately I can't really take the time right now to do a doskey setup and investigate, but maybe someone else will be able to take that on. If possible I recommend moving on from doskey. – briantist Mar 10 '19 at 18:09
  • 2
    `doskey` do translation of console input buffer. PowerShell never see original line. It does not work if console is not in line input mode, thus it is not compatible with `PSReadline`, although `Read-Host` will be affected. https://i.stack.imgur.com/HpYzq.png – user4003407 Mar 10 '19 at 18:42
  • @briantist: PetSerAl's comment implies that you'll never be able to inspect `doskey` macros with `Get-Command`, because `doskey` macros, _if_ they're actually in effect (they won't be with `PSReadLine` loaded, except when you use `Read-Host`, which is where you _don't_ want them), get expanded _before_ PowerShell ever sees the _already expanded_ command. – mklement0 Mar 11 '19 at 14:48
1

this will do the job fairly well. [grin] note that it just gives the text matching the macro. i did not test with multiline macros, nor do i know if that is even possible.

if you want the result to be just the macro instead of the full line, you can add a | ForEach-Object {$_.Split('=')[1]} to get the part after the =.

@"
404=echo '404'
666=echo '666'
dwd=echo 'Doo Wa Diddy'
"@ | Set-Content "$env:TEMP\Doskey-Macros.txt" -Force

doskey /macrofile=c:\temp\doskey-macros.txt

function DKA ($Macro)
    {
    doskey /macros |
        Where-Object {
            $_ -match $Macro
            }
    }

testing & output ...

dka -Macro dwd
dwd=echo 'Doo Wa Diddy'

dka -Macro adg
# nothing at all since there was no match

dka 404
404=echo '404'
Lee_Dailey
  • 7,292
  • 2
  • 22
  • 26