2016-11-20 1 views
1

J'ai besoin de savoir si stdin ou stdout a été réorienté pour une application de la console en utilisant la dernière CPF (v3.0.0)Comment détecter si stdin ou stdout est redirigé dans FreePascal sous Windows?

Dans l'ancien temps Turbo Pascal, j'avais une fonction écrite en assemblée qui a fait cela. Voir ci-dessous:

{ ************************************************************** 
    * Routine : RedirectedStd         * 
    * Purpose : Return Yes (True) if standard handle is being * 
    *   : redirected.         * 
    * Note(s) : Even though handle can take any handle value, * 
    *   : the function will be meaningful only for the * 
    *   : standard input, standard output, and standard * 
    *   : error. It will, however, be True for any  * 
    *   : handle that does NOT point to the console.  * 
    *   : (Besides, this is what it actually checks for.)* 
    *   : Make sure handle belongs to an open file or * 
    *   : you will get wrong answer (check IOResult). * 
    ************************************************************** } 
function RedirectedStd(handle: Word): Boolean; assembler; 
const 
    DEVICE  = $0080; 
    FASTCONSOLE = $0010; 
    CONSOUT  = $0002; 
    CONSIN  = $0001; 
asm 
    mov  InOutRes,0 
    mov  ax,$4400  { IOCTL svc, get device information } 
    mov  bx,handle 
    int  $21   { result in DX } 
    mov  ax,1   { assume function is True } 
    jc  @Error   { got error with code in AX } 
    test dx,DEVICE 
    jz  @Out 
    test dx,FASTCONSOLE 
    jz  @Out 
    test dx,CONSOUT 
    jz  @Out 
    test dx,CONSIN 
    jz  @Out 
    xor  ax,ax   { function is False } 
    jmp  @Out 
@Error: 
    mov  InOutRes,ax 
@Out: 
end; { RedirectedStd } 

Cette syntaxe n'est pas valide pour l'assembleur FPC. J'ai essayé ma chance avec la variante suivante qui, bien que se compile bien, il se bloque: (. Je ne sais pas si ma conversion est équivalente)

function RedirectedStd(handle: Word): Boolean; assembler; 
label Error,Done; 
const DEVICE  = $0080; 
     FASTCONSOLE = $0010; 
     CONSOUT  = $0002; 
     CONSIN  = $0001; 
asm 
      movw  $0,InOutRes 
      movw  $4400,%ax   { IOCTL svc, get device information } 
      movw  handle,%bx 
      int  $21     { result in DX } 
      movw  $1,%ax    { assume function is True } 
      jc  Error    { got error with code in AX } 
      test  DEVICE,%dx 
      jz  Done 
      test  FASTCONSOLE,%dx 
      jz  Done 
      test  CONSOUT,%dx 
      jz  Done 
      test  CONSIN,%dx 
      jz  Done 
      xor  %ax,%ax    { function is False } 
      jmp  Done 
Error: movw  %ax,InOutRes 
Done: 
end; { RedirectedStd } 

Toutes les idées?

EDIT: Sur la base acceptée réponse qui m'a donné sens assez pour comprendre la solution, je suis venu avec le remplacement sans rendez-vous suivant pour ma routine originale:

function RedirectedStd(handle: Word): Boolean; {$ifndef WINDOWS} unimplemented; {$endif} 
begin 
    RedirectedStd := False; 
    {$ifdef WINDOWS} 
    case handle of 
    0: RedirectedStd := GetFileType(GetStdHandle(STD_INPUT_HANDLE)) <> FILE_TYPE_CHAR; 
    1: RedirectedStd := GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) <> FILE_TYPE_CHAR; 
    2: RedirectedStd := GetFileType(GetStdHandle(STD_ERROR_HANDLE)) <> FILE_TYPE_CHAR; 
    end; 
    {$endif} 
end; { RedirectedStd } 

Oh, et vous devez utilise Windows;

+0

Possible duplicate of [Comment puis-je déterminer si Console.Out a été redirigé vers un fichier?] (Http://stackoverflow.com/questions/743885/how-can-i-determine-whether-console-out- has-been-redirected-to-a-file) –

+0

@DavidHeffernan: Pas vraiment. Je suis à la recherche d'une solution FreePascal. – tonypdmtr

+0

Appelez les fonctions winapi dans la première réponse. Ou trouver l'un des innombrables autres dupes qui disent la même chose. En voici un http://stackoverflow.com/questions/9021916/how-do-i-check-if-my-delphi-console-app-is-redirected-to-a-file-or-pipe il y en a beaucoup plus –

Répondre

1

Utilisez

GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); 

pour stdout. Il devrait être évident que faire pour stdin.

+0

Assez bien. J'ai dû faire un peu plus de travail pour comprendre comment les valeurs retournées sont utilisées, mais j'ai réussi. J'ai mis à jour ma question pour inclure la fonction de travail. – tonypdmtr

+1

Tout est documenté, vous le savez. Devrait être clair à partir de cela. N'utilisez pas de constantes magiques. –