Начал делать самодельную "Оболочку для оболочки" Shell2Shell
(Пока пишу сугубо под винду но в принципе "это неточно" (поживем увидим ) )
Суть идеи в написании "универсального лаунчера"(Пускателя ) для проектов подобных "Автоматике 1111 Stable Diffusion".
(Возможно с плагинами, доступом АПИ и разной "гибридной технологии", которую лучше делать в виде обычной программы вместо того чтобы, лепить все подряд в веб-интерфейс (и питон-скрипты) (по сути это будет гибрид "NMKD Stable Diffusion GUI " и "Автоматики 1111") )
>>>Что даст это приложение,кроме вывода окна терминала? В чем отличие от обычной веб версии Автоматика ?
1 Выбор вариантов запуска (Причем одна программа сможет запускать множество разных оболочек с разными настройками)
2 Строго говоря пока что этот проект не имеет особой привязки ни к "Автоматике 1111" ни к SD
(можно запустить что угодно включая чисто онлайновые сервисы или на против сугубо консольные проекты)
3 Дико надоело то что нужно постоянно запускать браузер
("автоматический" пуск еще хуже так как вываливает все открытые окна, закладки и т.д.)
4 В ближайшем будущем сделаю парсинг консоли (терминала ) .
5 Часть вещей которых нет в веб-оболочке (или они сделаны очень неуклюже ) гораздо проще сделать в виде классической "монолитной" программы
(но с встроенными скриптами и плагинами).
6 Такую "оболочку для оболочки" по идее ничего не стоит научить полностью автоматической установке моделей и самой SD+""Автоматики 1111""
7 В дальнейшем можно сделать дополнительный "прямой доступ к API" что может вообще делать почти любые вещи на которые хватит фантазии.
Добавлено спустя 6 минут 23 секунды:
>>S2S_bin0_4_1.7z
Это разумеется не более чем ранняя альфа версия .
Но интересна идеей "инкапсуляции гибридных API" и созданием "интегральных" сборок разнородных сервисов .
"Захват консоли" идет в двух режимах "виртуальном"(в нем можно парсить консольный вывод ) и "реальном" ( обычная консоль "удочеренная" через SetParent )
"Экстренная остановка" выполняется через KillProcessTree (Все-бы хорошо да работает только в 32-х разрядном режиме )
Зы
"Виртуальная консоль" RunDosInMemo (Консольный вывод из "Автоматики 1111" изрядно наворочен и "обычный мемо" для него не слишком годится так что буду переделывать)
- Код: Выделить всё
Procedure RunDosInMemo(CmdLine: String; AMemo: TMemo);
Const
ReadBuffer = 1023;
Var
Security: TSecurityAttributes;
OutReadPipe, OutWritePipe: tHandle; // труба для output'a консольной проги.
InReadPipe, InWritePipe: tHandle; // труба для input'a консольной проги.
ErrReadPipe, ErrWritePipe: tHandle; // труба для error's консольной проги.
// InReadPipe, ErrReadPipe и объявлены для полноты картины,но не создаются и не используются.
start: TStartUpInfo;
ProcessInfo: TProcessInformation;
Buffer: Pchar;
BytesRead: DWord;
Apprunning: DWord;
avail : dword;
notread:dword;
stop:boolean;
Begin
stop := false;
With Security Do Begin // инициализация структуры
nlength := SizeOf(TSecurityAttributes);
binherithandle := true;
lpsecuritydescriptor := Nil;
End;
Createpipe(InReadPipe, InWritePipe, @Security, 0);
Createpipe(ErrReadPipe, ErrWritePipe, @Security, 0);
If Createpipe(OutReadPipe, OutWritePipe, @Security, 0) Then Begin
// создали трубу для выхлопа бэкграунд-приложения
Buffer := AllocMem(ReadBuffer + 1);
// создали буфер для чтения
FillChar(Start, Sizeof(Start), #0);
// заполнили содержимое стартовой структуры #0
start.cb := SizeOf(start);
start.hStdOutput := OutWritePipe;
start.hStdError := OutWritePipe;
start.hStdInput := InReadPipe;
(*************************************************************
такой себе опширненьний комментарий...
Оказывается, мать их так, если сделать перенаправление
вывода в трубы, но не читать его, то если он(вывод)
будет достаточно длинный и сможет переполнить буфер,
который изначально отводится под трубу, то пишущий поток
остановится и будет ждать пока не освободится место в
буфере трубы. Как только оно освободилось, он сможет
продолжать работу и писать дальше.
start.hStdOutput := OutWritePipe;
start.hStdError := OutWritePipe;
почему собственно такой странный код: два потока
перенаправлены в одну трубу?
Потому что некоторые замечательные проги типа 7zip свой
вывод направляют не в StdOut, а почему то в StdErr...
и если для этих двух потоков назначить две разных трубы,
а читать только одну, то произойдет то, что описано выше.
РРРРРРРРРРРРРРРРРРРРРРРРР!!!!!!!!! сопли, слюни, ярость и
буйное помешательство на почве программирования под винду.
Может стоит сделать две трубы и читать каждую в отдельное
мемо???
**************************************************************)
start.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
start.wShowWindow := SW_HIDE;
// окно прячем
If CreateProcess(Nil, PChar(CmdLine), @Security, @Security, true, NORMAL_PRIORITY_CLASS,
Nil, Nil, start, ProcessInfo) Then Begin
// создали процесс
Repeat
Apprunning := WaitForSingleObject(ProcessInfo.hProcess, 100);
PeekNamedPipe(OutReadPipe, @Buffer[0], ReadBuffer, @BytesRead, @avail, @notread);
// PeekNamedPipe копирует из буфера трубы и оставляет его в первоначальном состоянии
// в то время как ReadFile читая из трубы - опустошает ее.
// PeekNamedPipe можно использовать для того чтобы узнать сколько данных есть в трубе
// и если в PeekNamedPipe передать 2 и 3 параметры пустыми, то она просто скажет
// сколько данных есть в трубе
if avail > 0 then begin
ReadFile(OutReadPipe, Buffer[0], BytesRead, BytesRead, Nil); // *******
// ReadFile при чтении из трубы опустошает ее(трубы) буфер.
end
else begin
if Apprunning <> 258 then
stop := true;
end;
// читаем через читающий конец трубы из вывода консоли
Buffer[BytesRead] := #0;
// последний символ #0 - конец буфера
OemToAnsi(Buffer, Buffer);
// перевели из кодировки DOS в кодировку WIN
AMemo.Text := AMemo.text + String(Buffer);
// то что прочитали приписали к тексту в мемо
Application.ProcessMessages;
// обработали очередь сообщений
// Until ((Apprunning <> WAIT_TIMEOUT) or (avail < 0));
Until stop;
// прервемся когда процесс завершится
End;
FreeMem(Buffer); // освободили буфер
CloseHandle(ProcessInfo.hProcess); // закрыли все хендлы
CloseHandle(ProcessInfo.hThread);
CloseHandle(OutReadPipe);
CloseHandle(OutWritePipe);
CloseHandle(InReadPipe);
CloseHandle(InWritePipe);
CloseHandle(ErrReadPipe);
CloseHandle(ErrWritePipe);
End;
// конец.
End;
Зы Зы
В качестве "браузерного движка" для веб-интерфейсов использован WebView4Delphi + Microsoft Edge WebView 2