Консольным приложением не был создан файл

Консольным приложением не был создан файл

Есть общеизвестный пример: http://www.sources.ru/delphi/system/capturing_output_from_console.shtml

Есть также общеизвестная программа openssl.exe

Как бы доработать пример так, что сначала вызывается программа с параметрами "openssl.exe -a -b -c . ", далее она ожидает ввода с клавиатуры (если бы её запускать с cmd), нужно её подсунуть содержимое на сотню другую байт (контент), который она зашифрует и выдаст ответ, который и надо считать.

Вот считывание в примере и реализовано, но как бы сделать запись в консоль?


брат Птибурдукова ( 2013-01-14 19:40 ) [1]

Создавай два пайпа. Второй запуздыривай сюда: hStdInput := GetStdHandle(STD_INPUT_HANDLE); // стандартный ввод не перенаправляем


Rouse_ © ( 2013-01-14 19:40 ) [2]

Вон тут Пашка Голубь доделывал этот пример: http://forum.sources.ru/index.php?showtopic=83650


Игорь Шевченко © ( 2013-01-14 19:52 ) [3]

if not WasOK then
raise Exception.Create( "Ошибка выполнения или компиляции: " +
Chr( 10 ) + Chr( 13 ) + CommandLine )

Для интернетов самое то


Игорь Шевченко © ( 2013-01-14 20:01 ) [4]


ES ( 2013-01-14 21:57 ) [5]


> Вон тут Пашка Голубь доделывал этот пример

в принципе, я как-то так и делал.
Только для тестов использовал конструкцию — сначала запускал процесс "ftp", в консоль передавал

Ничего не получалось. Это приводило к тому, что консоль отображалась на экране, программа ничего не считывала (после данного кода шло считывание ReadFile).

Возможно, управление до WriteFile доходило раньше, чем консоль успевала инициализироваться или типа того. Но дело в том, что вроде бы в ответ на команда OpenSSL ничего не выдает, запускаешь — а просто курсор мигает и все. Как понять когда начать программно вводить команды.


ES ( 2013-01-15 11:10 ) [6]

Я ошибся в том, что забыл писать Enter! то есть, перевод строки: #13#10

Возник другой вопрос, почему я запускаю команду "ftp":

WasOK := CreateProcess( nil,
"ftp",
nil,
.

дальше стандартный код, подходим к считыванию данных из консоли:

>WasOK := ReadFile( StdOutPipeRead, Buffer, 255, BytesRead, nil );

на этом месте исполнение зависает навсегда. Хотя если в консоле набрать ftp, то мы видим приглашение:

Почему это приглашение "ftp>" не считывается?

Хотя писать можно, да.


ES ( 2013-01-18 20:30 ) [7]

Камрады, измучился весь с этим Openssl.exe

Есть такая команда:

> openssl.exe smime -sign -signer public.pem -inkey private.pem -nochain -nocerts -outform PEM -nodetach

Формирует криптоконтейнер PKCS#7, где:

public.pem — публичный ключ
private.pem — приватный 2048-битный ключ

После такого запроса openssl.exe переходит в режим ввода текста с консоли для упаковки в контейнер. Если эту операцию делать ручками, то набираешь текст (при этом Enter — всего лишь перевод строки), далее я знаю что можно нажать [Enter], [CTRL]+[Z], далее Enter — после чего openssl.exe набранный текст упаковывает в контейнер. Вот как это выглядит:

C:MySSL>openssl
.exe smime -sign -signer public.pem -inkey private.pem -nochain -nocerts
-outform PEM -nodetach
Loading "screen" into random state — done
Вводим любой текст типа
Только что до этого нажал Enter. сейчас еше раз нажму
вот..
^Z
——BEGIN PKCS7——
MIIC7QYJKoZIhvcNAQcCoIIC3jCCAtoCAQExCzAJBgUrDgMCGgUAMGsGCSqGSIb3
DQEHAaBeBFyCoq6kqKwgq+6hrqkg4qWq4eIg4qivoA0Kkq6r7KquIOfiriCkriDt
4q6jriCtoKagqyBFbnRlci4uLiDhpannoOEgpeilIOCgpyCtoKas4w0Koq7iLi4a
DQoNCjGCAlkwggJVAgEBMFcwSTELMAkGA1UEBhMCUlUxGDAWBgNVBAoTD1BTIFlh
bmRleC5Nb25leTEgMB4GA1UEAxMXWWFuZGV4IE1vbmV5IElzc3VpbmcgQ0ECCh4/
wpMAAAAALeYwCQYFKw4DAhoFAKCB2DAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcB
MBwGCSqGSIb3DQEJBTEPFw0xMzAxMTgxNjIxNTlaMCMGCSqGSIb3DQEJBDEWBBTy
0giOb5OyNlgHLQcU/GrIl6G4UzB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQB
KjALBglghkgBZQMEARYwCwYJYIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3
DQMCAgIAgDANBggqhkiG9w0DAgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDAN
BgkqhkiG9w0BAQEFAASCAQBTARbvY0i+2iXk/c0BuE83V7lFhXFFgu68NQ+87Xq+
eRcwoPBFp8gfuHj+QLOP4Lz9qI99Uqg0jv4i1rjUQpQ/9kSqrc6jnd/DNn4+IovZ
cVZyWFNEWC5qe8qVMRS98zhYynJfqgpQz97J7A9ZryjYedp8iud0gLwGnbT+mP7U
q9cecoJoad1kLNvDPIcn3W0PX1lzMekG7ALeaIkosE8GyNKnAlYMS1sjZPoh+6eX
lKZUuf+CAdR2XWDgETGhPt9voNAM562bLnTWUqDVxr9MUI+5gvqd3fqVlqVWw9sU
XPvUgVl/Tkv1E4RHQBP6EbEW2n3SpfMSFaado2ek5FSx
——END PKCS7——

Вот как переделать пример: http://forum.sources.ru/index.php?showtopic=83650

Чтобы все сработало? Там передается [Enter] — и для внешней программы это событие, но для openssl это нифига не событие. У меня все подвисает, что логично, видимо openssl продолжает дальше ждать ввода текста.

Я пробовал после WriteFile делать:

Но ответом идет False с кодом GetLastError = 87, что означает:
"Параметр задан неверно".

После WriteFile делать CloseHandle(StdinPipeWrite) тоже пробовал.

Что делать? Как запустить openssl и передать в него текст, сообщив о конце передачи текста?! (

Читайте также:  Как быстро выучить таблицу менделеева стихом


Игорь Шевченко © ( 2013-01-18 20:39 ) [8]

А записать в StdinPipeWrite #$1A ?


ES ( 2013-01-19 00:37 ) [9]


> А записать в StdinPipeWrite #$1A ?

попробовал. ничего не вышло, такое же зависание.


ES ( 2013-01-19 00:38 ) [10]

от безысходности писал также:

тоже не получилось.


брат Птибурдукова ( 2013-01-19 00:43 ) [11]

Попробуй в командной строке выполнить openssl.exe smime -sign -signer public.pem -inkey private.pem -nochain -nocerts -outform PEM -nodetach


ES ( 2013-01-19 11:51 ) [12]


> Попробуй в командной строке выполнить openssl.exe smime
> -sign -signer public.pem -inkey private.pem -nochain -nocerts
> -outform PEM -nodetach -in InFile.content


брат Птибурдукова ( 2013-01-19 13:21 ) [13]


> Только в openssl это указывается доп. командой
Так ты уверен, что с перенаправлением вывода всё работает так же корректно, как с дополнительным параметром?


ES ( 2013-01-20 23:55 ) [14]


> Так ты уверен, что с перенаправлением вывода всё работает
> так же корректно, как с дополнительным параметром?

да, попробовал сейчас команду:

> openssl.exe smime -sign -signer public.pem -inkey private.pem -nochain -nocerts -outform PEM -nodetach

отработало просто на ура, тут же выдало ответ и вышло из программы openssl.


ES ( 2013-01-21 00:07 ) [15]

Причем, для openssl вроде как есть оттестированный рабочий код для PHP, его структура вроде бы понятна и на дельфи нечто такое же получается:

$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w")); // stderr is a file to write to

$process = proc_open(
"openssl smime -sign -signer " . $certificate .
" -inkey " . $privkey .
" -nochain -nocerts -outform PEM -nodetach",
$descriptorspec, $pipes);

if (is_resource($process)) <
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout

fwrite($pipes[0], $source);
fclose($pipes[0]);

но тем не менее на дельфи изобразить не получается ((


Игорь Шевченко © ( 2013-01-21 00:21 ) [16]

уже код пора выкладывать


ES ( 2013-01-21 11:35 ) [17]

procedure TExternalProgRunner.Execute;
var
CommandLine: string;
StdOutPipeRead, StdOutPipeWrite, StdInPipeRead, StdInPipeWrite: THandle;
SA : TSecurityAttributes;
SI : TStartupInfo;
PI : TProcessInformation;
WasOK : BOOL;
Buffer : array[0..255] of Char;
BytesRead, Written : Cardinal;
WaitRes: Cardinal;
hArray: array[0..1] of THandle;
sCurDir: string;
aaa: integer;
begin
With SA do
Begin
nLength := SizeOf( SA );
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
// создаём пайп для перенаправления стандартного вывода
CreatePipe( StdOutPipeRead, // дескриптор чтения
StdOutPipeWrite, // дескриптор записи
@SA, // аттрибуты безопасности
0 // количество байт принятых для пайпа — 0 по умолчанию
);
// создаём пайп для перенаправления стандартного ввода
CreatePipe( StdInPipeRead, // дескриптор чтения
StdInPipeWrite, // дескриптор записи
@SA, // аттрибуты безопасности
0 // количество байт принятых для пайпа — 0 по умолчанию
);

try
// Создаём дочерний процесс, используя StdOutPipeWrite в качестве стандартного вывода,
// а так же проверяем, чтобы он не показывался на экране.
with SI do
Begin
FillChar( SI, SizeOf( SI ), 0 );
cb := SizeOf( SI );
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
wShowWindow := SW_HIDE or SW_SHOWMINNOACTIVE;
hStdInput := StdInPipeRead; //GetStdHandle(STD_INPUT_HANDLE);
hStdOutput := StdOutPipeWrite;
hStdError := StdOutPipeWrite;
end;

CommandLine := """ + FAppPath + "" " + FParam ;
sCurDir := ExtractFileDir(FAppPath);
WasOK := CreateProcess( nil,
PChar( CommandLine ),
nil,
nil,
True,
0,
nil,
PChar(sCurDir),
SI,
PI );
FhProcess := PI.hProcess ;

// если процесс может быть создан, то дескриптор, это его вывод
CloseHandle( StdOutPipeWrite );
if not WasOK then
begin
FStatus := prsEnd ;
end
else
begin
FStatus := prsRun ;
FisSuccessRun := true ;
try
// если указано — пишем в консоль текст
if FConsoleInput <> "" then
begin
WriteFile(StdinPipeWrite, FConsoleInput[1], length(FConsoleInput),
Written, nil);
end;
// получаем весь вывод до тех пор, пока DOS-приложение не будет завершено
Repeat
// читаем блок символов (могут содержать возвраты каретки и переводы строки)
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil );
// есть ли что-нибудь ещё для чтения?
if BytesRead > 0 then
Begin
// завершаем буфер PChar-ом
Buffer[BytesRead] := #0;
// добавляем буфер в общий вывод
FcsData.Enter;
try
FAllRead := FAllRead + Buffer;
finally
FcsData.Leave;
end;
end;
Until not WasOK or ( BytesRead = 0 ) or (Terminated);

Читайте также:  Печатные буквы в ворде

if Line <> "" then
OemToChar(PChar(Line), PChar(FAllRead)) ;>

SetEvent(FeventFinishRead) ;
// ждём, пока завершится консольное приложение
hArray[0] := pi.hProcess;
hArray[1] := FeventTerminate ;
WaitRes := WaitForMultipleObjects(2, @hArray, false, INFINITE);
if WaitRes = WAIT_OBJECT_0 then // значит, терминировался именно процесс запущенный
FStatus := prsEnd ;
FExitCode := 0;
GetExitCodeProcess( pi.hProcess, FExitCode );
finally
// Закрываем все оставшиеся дескрипторы
CloseHandle( PI.hThread );
CloseHandle( pi.hProcess );
end;
end;
finally
SetEvent(FeventFinishRead) ;
CloseHandle( StdOutPipeRead );
if StdInPipeWrite <> 0 then
CloseHandle( StdInPipeWrite );
if StdInPipeRead <> 0 then
CloseHandle(StdInPipeRead);
end;
end;

> WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil );


Игорь Шевченко © ( 2013-01-21 15:34 ) [18]

WaitForInputIdle вставить не поможет перед началом работы с вводом-выводом?


Юрий Зотов © ( 2013-01-21 17:47 ) [19]

Я делал иначе, без пайпов. В своей программе создаю консоль и запускаю чужое консольное приложение, как дочерний процесс с наследуемыми дескрипторами ввода-вывода. В результате чужая программа разделяет с моей одну и ту же консоль — то есть, моя программа может в консоль писать, а та читает.


ES ( 2013-01-22 11:28 ) [20]


> WaitForInputIdle вставить не поможет перед началом работы
> с вводом-выводом?

вставил перед WriteFile.
WaitForInputIdle(pi.hProcess, INFINITE) возвращает 0xFFFFFFFF.
GetLastError = 18: "Больше файлов не осталось"

Результата не дало.


Игорь Шевченко © ( 2013-01-22 14:41 ) [21]


> // если процесс может быть создан, то дескриптор, это его
> вывод
> CloseHandle( StdOutPipeWrite );

Зачем этот вызов ?


Игорь Шевченко © ( 2013-01-22 14:57 ) [22]

надо закрыть описатели записи в stdout и чтения stdin

Для того чтобы создать консольное приложение, надо в меню File выбрать команду New Project , в появившемся окне New Project выбрать CLR Console Application , в поле Name ввести имя проекта (рис. 6.2) и нажать кнопку OK . В результате этих действий станет доступным окно редактора кода, в котором можно набирать текст программы.

Рис. 6.2. Начало работы над консольным приложением

В качестве примера в листинге 6.2 приведен текст консольного приложения — утилиты clear, которая удаляет из каталога, указанного при запуске утилиты, и всех его подкаталогов tmp-файлы. Также, если при запуске утилиты указан ключ –CLEARDEBUG , утилита удаляет все файлы из всех подкаталогов Debug. Так как операция удаления является потенциально опасной, то утилита запрашивает у пользователя подтверждение на выполнение. Причем, чтобы операция очистки была начата, необходимо ввести Y , ввод любого другого символа, в том числе y , отменяет операцию. Основную работу — удаление файлов выполняет рекурсивная функция сlear. Сначала она обрабатывает (удаляет tmp-файлы) текущий каталог, затем формирует список подкаталогов

Часть II. Практикум программирования

текущего каталога, делает текущим первый (по номеру элементов списка) подкаталог и вызывает себя (рекурсия) для обработки этого подкаталога.

Листинг 6.2. Очистка диска (консольное приложение)

// clear.cpp : main project file.

Читайте также:  Как прошить телефон без потери данных

using namespace System;

using namespace System::IO;

кол-во удаленных файлов

bool debug = true ;

true — только сообщение о выполнении

bool clearDebug = false ; //

очистка каталогов Debug

// Очистка текущего каталога и всех его подкаталогов.

// подкаталоги текущего каталога

// файлы, которые надо удалить

int p = System::IO::Directory::GetCurrentDirectory()->

ToString()->LastIndexOf(‘\’); String^ aFolder =

if (aFolder == "Debug")

// удалить все файлы из каталога Debug

Files = Directory::GetFiles (System::IO::Directory::GetCurrentDirectory(),"*.*");

Глава 6. Консольное приложение

Files = Directory::GetFiles (System::IO::Directory::GetCurrentDirectory(),"*.tmp");

// удалить tmp-файлы из текущего каталога

Files = Directory::GetFiles (System::IO::Directory::GetCurrentDirectory(),"*.tmp");

int nf = Files->Length; for (i = 0; i if (! debug)

Console::WriteLine(Files[i] + " — удален"); nDel = nDel +1;

// обработать подкаталоги if (debug)

n = Directories->Length; for (i = 0; i if (debug) Console::WriteLine(Directories[i]);

Часть II. Практикум программирования

int main( array ^args)

char r; // ответ пользователя: Y или N

// проверим, указано ли имя файла теста if (args->Length == 0)

Console::WriteLine("Ошибка: Надо задать каталог."); Console::WriteLine("Команда: clear [-CLEARDEBUG]"); Console::WriteLine("-CLEARDEBUG — очистка каталогов Debug
");

Console::ReadLine(); return -1;

// проверим, существует ли указанный каталог try

catch (System::IO::DirectoryNotFoundException^ ex)

Console::WriteLine("Каталог " + path +" не найден");

Console::ReadLine(); return -1;

("Программа удалит все файлы из подкаталогов Debug");

Глава 6. Консольное приложение

Console::WriteLine("каталога "+ path+ " и всех его подкаталогов.");

Console::WriteLine("Программа удалит tmp-файлы");

Console::WriteLine("из каталога "+ path+

" и всех его подкаталогов.");

Console::ReadLine(); // дочитать из буфера ввода if (r != ‘Y’)

Console::ReadLine(); return -1;

Console::WriteLine("Удалено файлов: "+ nDel.ToString()); Console::WriteLine("Работа выполнена!"); Console::Write("Нажмите ");

Console::ReadLine(); return 0;

Построение консольного приложения выполняется обычным образом, т. е. выбором в меню Build команды Build Solution .

После успешной компиляции программу можно запустить. Для этого надо в меню Debug выбрать команду Start Debugging или Start Without Debugging .

Если программа должна получать параметры из командной строки, то при ее запуске из среды разработки параметры надо ввести в поле Command Arguments раздела Configuration Properties Debugging окна Property Page

(рис. 6.3), которое становится доступным в результате выбора в меню Project команды Properties . Следует обратить внимание: если в строке-параметре есть пробелы, то ее надо заключить в двойные кавычки.

У меня есть решение, которое имеет 3 проектов. Одним из них является консольным приложением и другие 2 являются окно приложения. Оба окна приложение использует консольное приложение, поэтому я добавил ссылку на консольном приложении в обеих окнах приложений проектов. Теперь, когда я строю окна проектов, консольное приложение копируется в выходной каталог, но проблема в том, что его конфигурационный файл «consoleapp.exe.config» не копируется!

Если бы я использовал библиотеку (сборки) вместо консольного приложения, он будет создан конфигурационный файл этой сборки в папке вывода.

Как решить эту проблему?

Выберите consoleapp.exe.config в дереве решений.

Выберите « Содержимое » для сборки Действие опции в собственности сетки.

Выберите Копировать всегда для копирования в каталог вывода опции.

Надеюсь, что это помогает 🙂

Быстрое создание консольного проекта в VS2008 и добавив « App.config », он имеет параметры:

Строить Действие: Нет
Скопировать в каталог Ouput: Не копировать
пользовательский инструмент:
Пользовательский инструмент Пространство имен:

Однако я не уверен, что эффект добавление ссылки на проект консоли будет иметь, как проект консоли представляет собой приложение, а не библиотеки классов.

Если вы хотите, чтобы консольное приложение для запуска с приложениями Windows, для отладки, то лучше, чем подход ссылок проекта будет установить решение для запуска нескольких приложений. Щелкните правой кнопкой мыши на решения, выберите свойства и на узле Start Project, выберите несколько проектов. (И удалить ссылки на консольное приложение.)

Ваши приложения используют значение по умолчанию для параметров из скомпилированного кода ссылочного проекта.

Ссылка на основную публикацию
Количество дней в текущем месяце excel
Определим число дней в заданном месяце с помощью функции КОНМЕСЯЦА() . Если ячейка А1 содержит дату, то число дней месяца,...
Камера мвк 16 схема подключения
Вы сможете задать интересующий Вас вопрос, заполнив ниже приведенную форму. Мы обязательно ответим Вам и предоставим всю необходимую информацию. Видеокамеры...
Клавиатура с пластмассовыми штырями преимущества и недостатки
электронный почта сканер клавиатура Клавиатура является одним из важнейших устройств, определяющим условия комфортабельной работы на РС. Главным элементом в клавиатуре...
Команда 102 на теле2 что это такое
Ниже представлены полезные команды Теле2 Казахстан, разбитые по категориям. Они бесплатны, но часть услуг, которыми они управляют могут быть платными....
Adblock detector