Как сказать, “владеет” ли приложение Delphi своей консолью?

Вот пример передачи обратно PDF.

header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
header('Content-Transfer-Encoding: binary');
readfile($filename);

@Swish я не находил тип контента применения, чтобы сделать что-либо различное (протестированный в IE и Firefox). Существует ли причина того, что не был передан фактический тип MIME обратно?

Также в руководстве PHP Hayley Watson отправленный:

, Если Вы хотите вынудить файл быть загруженным и сохраненным вместо того, чтобы быть представленным, помнят, что нет такого типа MIME как "application/force-download". Корректный тип для использования в этой ситуации является "application/octet-stream", и использование чего-либо еще просто полагается на то, что клиенты, как предполагается, игнорируют нераспознанные типы MIME и используют "application/octet-stream" вместо этого (ссылка: Разделы 4.1.4 и 4.5.1 из RFC 2046).

Также соответственно IANA там является не зарегистрированным типом application/force-download.

7
задан Incredulous Monk 27 September 2009 в 02:02
поделиться

5 ответов

В основном вам нужно проверить две вещи:

  1. Совместно ли консоль приложения между процессами? Если вы используете cmd.exe для запуска консольного приложения, оно по умолчанию будет совместно использовать консоль, поэтому вам не нужно будет отображать сообщение «Нажмите Enter, чтобы закрыть окно».

  2. Является ли вывод перенаправили в файл? Если это так, то сообщение также необязательно отображать.

Для первого существует простое решение в виде функции Windows API GetConsoleProcessList () . К сожалению, он доступен только в Windows XP и более поздних версиях, но, возможно, вам этого достаточно. Его нет в модуле Delphi 2009 Windows , поэтому вам придется импортировать его самостоятельно:

function GetConsoleProcessList(lpdwProcessList: PDWORD;
  dwProcessCount: DWORD): DWORD; stdcall; external 'kernel32.dll';

Конечно,

8
ответ дан 6 December 2019 в 10:01
поделиться

Раньше я использовал что-то вроде следующего:


program ConsoleTest;
{$APPTYPE CONSOLE}
uses Windows;
function GetConsoleWindow: HWND; stdcall; external kernel32 name 'GetConsoleWindow';
function IsOwnConsoleWindow: Boolean;
//ONLY POSSIBLE FOR CONSOLE APPS!!!
//If False, we're being called from the console;
//If True, we have our own console (we weren't called from console)
var pPID: DWORD;
begin
  GetWindowThreadProcessId (GetConsoleWindow,pPID);
  Result:= (pPID = GetCurrentProcessId);
end;

begin writeln ('Hello '); if IsOwnConsoleWindow then begin writeln ('Press enter to close console'); readln; end; end.

4
ответ дан 6 December 2019 в 10:01
поделиться

Для программы foo.exe создайте пакетный файл с именем foo_runner.bat . Не документируйте эту команду, поскольку она не предназначена для использования кем-либо по имени, но используйте ее в качестве цели для любых ярлыков, созданных вашим установщиком. Его содержимое будет простым:

@echo off
%~dp0\foo.exe %*
pause

Эта часть % ~ dp0 указывает каталог, в котором находится командный файл, поэтому вы гарантированно запускаете foo.exe в папке командного файла. каталог вместо того, чтобы брать его из другого места на пути поиска.

1
ответ дан 6 December 2019 в 10:01
поделиться

Я использую (не помню, где я это нашел):

function WasRanFromConsole() : Boolean;
var
  SI: TStartupInfo;
begin
  SI.cb := SizeOf(TStartupInfo);
  GetStartupInfo(SI);

  Result := ((SI.dwFlags and STARTF_USESHOWWINDOW) = 0);
end;

И затем использую как таковое:

  if (not WasRanFromConsole()) then
  begin
    Writeln('');
    Writeln('Press ENTER to continue');
    Readln;
  end;
2
ответ дан 6 December 2019 в 10:01
поделиться

Вау, Ник, это действительно впечатляет! Я протестировал ваше решение и отлично работает.

Итак, вы можете сделать что-то вроде этого:

function isOutputRedirected() : boolean;
var
  StdOutHandle     : THandle;
  bIsNotRedirected : boolean;
  FileInfo         : TByHandleFileInformation;

begin
  StdOutHandle:= GetStdHandle(STD_OUTPUT_HANDLE);
  bIsNotRedirected:=( NOT GetFileInformationByHandle(StdOutHandle, FileInfo)
    and (GetLastError = ERROR_INVALID_HANDLE));
  Result:=( NOT bIsNotRedirected );
end;

function isStartedFromConsole() : boolean;
var
  SI: TStartupInfo;
begin
  SI.cb := SizeOf(TStartupInfo);
  GetStartupInfo(SI);
  Result := ((SI.dwFlags and STARTF_USESHOWWINDOW) = 0);
end;

function GetConsoleSize() : _COORD;
var
  BufferInfo: TConsoleScreenBufferInfo;
begin
  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), BufferInfo);
  Result.x:=BufferInfo.srWindow.Right - BufferInfo.srWindow.Left + 1;
  Result.y:=BufferInfo.srWindow.Bottom - BufferInfo.srWindow.Top + 1;
end;

И наконец:

var
 cKey : Char;
 fCursorPos  : _COORD;

    if( NOT isOutputRedirected() ) and( NOT isStartedFromConsole() ) then
           begin
             // Windows app starts console.
             // Show message in yellow (highlight) and at the bottom of the window
            writeln;
            fCursorPos:=getConsoleSize();
            Dec( fCursorPos.y );
            Dec( fCursorPos.x, 40 );
            SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 14 );
            SetConsoleCursorPosition( GetStdHandle(STD_OUTPUT_HANDLE), fCursorPos );
            write( '<< Press ENTER to close this window >>' );
            read(cKey);
           end;

Ура, приятель!

Эрвин Хантьес

2
ответ дан 6 December 2019 в 10:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: