The Windows Command Processor cmd.exe features a built-in pseudo-variable called CmdCmdLine that holds the original command line that invoked it.
Given that the Command Prompt is opened just by cmd.exe (without any arguments!), CmdCmdLine holds the (quoted) value of ComSpec, usually "C:\Windows\system32\cmd.exe".
When a batch file is run from such a Command Prompt window by typing its path/name, the value of CmdCmdLine does not change (because the already open cmd.exe instance remains the same).
However, when the script is involved in a pipe, which initiates new cmd.exe instances for either side, CmdCmdLine changes to something like C:\Windows\system32\cmd.exe  /S /D /c" …", where … stands for the batch file together with its arguments just as provided.
We can now make use of that and check CmdCmdLine whether it just contains a single item (the ComSpec value) or multiple ones (ComSpec plus some arguments), and if the second one equals /S.
Here is an sample script (named program.bat) to demonstrate what I mean (although this will unfortunately fail when the original Command Prompt window has been invoked by something like %ComSpec% /S …):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Enable delayed expansion to safely return `CmdCmdLine`:
setlocal EnableDelayedExpansion
>&2 setlocal DisableDelayedExpansion
>&2 echo/
>&2 echo BatFile = ^<%0^>
>&2 echo BatArgs = ^<%*^>
>&2 endlocal
>&2 echo/
>&2 echo ComSpec = ^<!ComSpec!^>
>&2 echo CmdLine = ^<!CmdCmdLine!^>
for %%L in (!CmdCmdLine!) do (
    rem /* `!!` are consumed by delayed expansion, hence the following condition
    rem    is only true for the first iteration because of the `endlocal`: */
    if "!!"=="" (
        endlocal
    ) else (
        rem /* This point is only reached when there are more than one items in
        rem    `CmdCmdLine`, which is the case when the script was involved in
        rem    a pipe (though it does not matter on which side it stood);
        rem    for this to work we assume that the second item, hence the first
        rem    argument, is `/S` as usual for pipes; the hosting Console Window
        rem    must not have been invoked by `cmd.exe /S ...` then though: */
        >&2 echo CmdSwit = ^<%%~L^>
        >&2 set "CmdSwit=%%~L"
        if /I "%%~L"=="/S" (
            >&2 echo/
            >&2 set "CmdSwit="
           rem /* `timeout` does not accept redirected input, which can be used
           rem    to distinguish between the sides of the pipe: */
           > nul 2>&1 timeout /T 0 || call :PIPE
        )
        goto :ARGS
    )
)
:ARGS
>&2 echo/
rem // Parsing each argument individually is more robust as parsing `%*`:
:ARGS_LOOP
if "%~1"=="" goto :NEXT
rem // Do something with `%1` here...
>&2 echo BatArg# = ^<%1^>
shift /1
goto :ARGS_LOOP
:NEXT
>&2 (if defined CmdSwit echo/& pause)
rem // ...
endlocal
exit /B
:PIPE
    setlocal DisableDelayedExpansion
    rem /* The `for /F` loop awaits the whole input text before iterating!
    rem    `more` hangs when there are more than about 64K lines and it converts
    rem    tabs to spaces (a tab becomes one space here due to switch `/T1`);
    rem    use `findstr "^"` instead when you expect more than about 64K lines;
    rem    regard that line lengths are limited to about 8K characters: */
    for /F delims^=^ eol^= %%I in ('more /S /T1') do (
        rem // Do something with `%%I` here...
        >&2 echo PipLin# = ^<%%I^>
    )
    endlocal
    exit /B
Note that lines beginning with >&2 are nothing but debugging lines for illustration.
Here are some usage examples (debugging output):
- Script invoked by command line - program.bat(no pipe, no arguments):
 - 
- BatFile = <program.bat>
BatArgs = <>
ComSpec = <C:\Windows\system32\cmd.exe>
CmdLine = <"C:\Windows\system32\cmd.exe" >
 
 
- Script invoked by command line - program.bat arg1 arg2(no pipe, some arguments):
 - 
- BatFile = <program.bat>
BatArgs = <arg1 arg2>
ComSpec = <C:\Windows\system32\cmd.exe>
CmdLine = <"C:\Windows\system32\cmd.exe" >
BatArg# = <arg1>
BatArg# = <arg2>
 
 
- Script invoked by command line - (echo pip1^&echo pip2^&rem/) | program.bat(pipe with some lines, no arguments):
 - 
- BatFile = <program.bat>
BatArgs = <>
ComSpec = <C:\Windows\system32\cmd.exe>
CmdLine = <C:\Windows\system32\cmd.exe  /S /D /c" program.bat">
CmdSwit = </S>
PipLin# = <pip1>
PipLin# = <pip2>
 
 
- Script invoked by command line - (echo pip1^&echo pip2^&rem/) | program.bat arg1 arg2(pipe with some lines, some arguments):
 - 
- BatFile = <program.bat>
BatArgs = <arg1 arg2>
ComSpec = <C:\Windows\system32\cmd.exe>
CmdLine = <C:\Windows\system32\cmd.exe  /S /D /c" program.bat arg1 arg2">
CmdSwit = </S>
PipLin# = <pip1>
PipLin# = <pip2>
BatArg# = <arg1>
BatArg# = <arg2>