powershellpipestdinshortcut-file

Pipe into executable through .lnk file


I have an executable at C:\Very\Long\Path\StreamToClipboard.exe
The file C:\InPath\StreamToClipboard.lnk points to that executable.
The directory C:\InPath is in my PATH variable, and .lnk is in my PATHEXT variable.

In regular cmd, I can execute any of these commands:
echo Hello | C:\Very\Long\Path\StreamToClipboard.exe
echo Hello | C:\InPath\StreamToClipboard.lnk
echo Hello | StreamToClipboard.lnk
echo Hello | StreamToClipboard
and the the executable is started, the text "Hello" is correctly piped into that process.

In PowerShell, I can execute echo Hello | C:\Very\Long\Path\StreamToClipboard.exe and it works too. But all of the other commands don't work:

Fehler beim Ausführen des Programms "StreamToClipboard.lnk": Die angegebene ausführbare Datei ist keine gültige
Anwendung für diese Betriebssystemplattform.In Zeile:1 Zeichen:12
+ echo foo | C:\InPath\StreamToClipboard.lnk
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.
In Zeile:1 Zeichen:1
+ echo foo | C:\InPath\StreamToClipboard.lnk
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [], ApplicationFailedException
    + FullyQualifiedErrorId : NativeCommandFailed

(and respective paths)
Which roughly translates to Error while executing "StreamToClipboard.lnk": The specified executable file is not a valid application for this operating system plattform.

Note that echo Hello | "C:\Very\Long\Path\StreamToClipboard.exe" also does not work, with a different error message:

In Zeile:1 Zeichen:14
+ ... cho Hello | "C:\Very\Long\Path\StreamToClipboard.exe"
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ausdrücke sind nur als erstes Element einer Pipeline zulässig.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ExpressionsMustBeFirstInPipeline

Roughly translates to Expressions are only valid as the first element in a pipeline.

If I, instead of creating the .lnk file, copy the entire executable to C:\InPath\StreamToClipboard.exe, then these commands:
echo Hello | C:\InPath\StreamToClipboard.exe
echo Hello | StreamToClipboard.exe
echo Hello | StreamToClipboard
work fine.

How can I get PowerShell to accept echo Hello | StreamToClipboard (where it's an .lnk file), or at least echo Hello | StreamToClipboard.lnk?


Solution


  • Workarounds:

    # & is required, because the executable path is quoted.
    # Note: 'Hello' is the PowerShell-idiomatic equivalent of
    #        echo Hello
    'Hello' | & "C:\Very\Long\Path\StreamToClipboard.exe"
    

    Note: For simplicity, you may choose to always use & when invoking external programs, but it is only required in the cases mentioned above, discussed in more detail in this answer.

    'Hello' | cmd /c C:\InPath\StreamToClipboard.lnk
    

    Note that, in both workarounds, character encoding issues may arise, given that data is being sent to an external program:


    [1] Note that (temporarily) appending ";.LNK" to the value of $env:PATHEXT, the environment variable that lists all filename extensions that belong to executables, does not help.

    [2] The reason is that these parameters cause Start-Process to switch from the ShellExecute WinAPI function to CreateProcess, and the latter only works with actual executables.