OberonCore
https://forum.oberoncore.ru/

Подсистема Ctl.
https://forum.oberoncore.ru/viewtopic.php?f=2&t=540
Страница 1 из 1

Автор:  Евгений Темиргалеев [ Пятница, 29 Июнь, 2007 15:54 ]
Заголовок сообщения:  Подсистема Ctl.

Вот такая проблема. Создаем новое приложение (сервер автоматизации). Выполняем обработку данных. После сборщик мусора должно все подобрать, а сервер по идее выгрузиться. Однако, он выгружаться и не думает. Попробуйте просто эти строки - потыкал по коммандеру - и получил кучу процессов Excel.
Код:
   IMPORT   CtlExcel := CtlExcel9;

   PROCEDURE ...
   VAR
      excel: CtlExcel.Application;
   BEGIN
      excel := CtlExcel.NewApplication();
      ...
У кого есть какие идеи? Проблема в ББ реализации COM/Ctl?

Автор:  Axcel [ Пятница, 29 Июнь, 2007 17:30 ]
Заголовок сообщения:  Re: Подсистема Ctl.

А Вы после обработки сделали excel.quit?

Автор:  Евгений Темиргалеев [ Понедельник, 02 Июль, 2007 11:41 ]
Заголовок сообщения: 

Угу. Даже excel.Quit; excel := NIL; Kernel.Collect....
Если сделать окно ёкзеля видимым, то Quit видимость убирает, а процесс остается. Может в ББ что-то его держит. Вот только что?

Автор:  Евгений Темиргалеев [ Понедельник, 02 Июль, 2007 11:46 ]
Заголовок сообщения:  Против лома нет приема

Пока выкручиваюсь прибиванием процесса:
Код:
   PROCEDURE KillExcel;
      VAR
         h, ph: WinApi.HANDLE;
         res: WinApi.BOOL;
         entry: WinTlhelp.PROCESSENTRY32W;
   BEGIN
      h := WinTlhelp.CreateToolhelp32Snapshot(WinTlhelp.TH32CS_SNAPPROCESS, 0);
      ASSERT(h # -1, 100);   (* Получили снимок процессов *)
      entry.dwSize := SIZE(WinTlhelp.PROCESSENTRY32W); res := WinTlhelp.Process32FirstW(h, entry);
      IF res = WinApi.TRUE THEN
         ASSERT(entry.dwSize = SIZE(WinTlhelp.PROCESSENTRY32W), 101)   (* Можем читать имя *)
      END;
      WHILE res = WinApi.TRUE DO
         (* StdLog.String(entry.szExeFile); StdLog.Ln; *)
         MtStrings.ToUpper(entry.szExeFile, entry.szExeFile);
         IF entry.szExeFile = "EXCEL.EXE" THEN
            ph := WinApi.OpenProcess(WinApi.PROCESS_TERMINATE, WinApi.FALSE, entry.th32ProcessID);
            ASSERT(ph # 0, 102);   (* Процесс "открылся" *)
            res := WinApi.TerminateProcess(ph, 0);
            ASSERT(res # 0, 103);   (* Процесс убился *)
            res := WinApi.CloseHandle(ph);
            ASSERT(res # 0, 104);   (* Дескриптор удалился *)
         END;
         res := WinTlhelp.Process32NextW(h, entry)
      END;
      ASSERT(WinApi.GetLastError() = WinApi.ERROR_NO_MORE_FILES, 105);   (* Чтение списка процессов завершилось успешно *)
      res := WinApi.CloseHandle(h);
      ASSERT(res # 0)   (* Дескриптор удалился *)
   END KillExcel;

Надо только юзерам сообщать, что во время работы екзелем пользоваться запрещается :lol:

Автор:  Кривохатько С.А. [ Понедельник, 02 Июль, 2007 19:36 ]
Заголовок сообщения: 

Евгений Темиргалеев писал(а):
Угу. Даже excel.Quit; excel := NIL; Kernel.Collect....
Если сделать окно ёкзеля видимым, то Quit видимость убирает, а процесс остается. Может в ББ что-то его держит. Вот только что?


Проблема точно не в BB. Очень давно сталкивался с подобным и под .NET. Правда там эти процессы сами отмирали через некоторое (довольно большое) время. Решилось обертыванием работы с Excel в класс, экземпляр которого создавался локально в теле процедуры:
Код:
//код вне класса ExcelWork
bool result = false;
ExcelWork ew = new ExcelWork(this);
result = ew.GenExcel(gr, ods, GenPaged);
ew = null;
GC.Collect();
return result;


Кроме этого в этом классе был метод:
Код:
//метод класса ExcelWork
private void NAR(Object o)
{
        try{
              System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
        }
        finally{
                o = null;
        }
}


С помощью которого "добивались" объекты Excel:
Код:
//метод класса ExcelWork
Excel.Application excelApp = null;
Excel.Workbook wbk = null;

try
{
        excelApp = new Excel.Application();
        excelApp.UserControl = false;
        excelApp.DisplayAlerts = false;
        wbk = excelApp.Workbooks.Add(Missing.Value);
...............

        wbk.Close(false,Missing.Value,Missing.Value);
        NAR(wbk);
        excelApp.Quit();
        NAR(excelApp);
        GC.Collect();
        GC.WaitForPendingFinalizers();
}
catch(Exception e)
{
...............


Возможно обертывание в класс или NAR были лишними, точно уже не помню. Таже обратите внимание на UserControl и DisplayAlerts.

Автор:  Кривохатько С.А. [ Понедельник, 02 Июль, 2007 23:24 ]
Заголовок сообщения: 

Мда, попробовал переложить выше-написанное в BB. Оказалось, что всё работает как должно, висящих в памяти процессов Excel не наблюдается. Исходный код:

Код:
MODULE ExamplesExcel;

IMPORT   CtlExcel := CtlExcel9, Kernel;

PROCEDURE OpenClose*;
VAR
   excel: CtlExcel.Application;
BEGIN
   excel := CtlExcel.NewApplication();
   excel.PUTVisible(TRUE);
   excel.Quit;
   excel:=NIL;
   Kernel.Collect;
END OpenClose;

END ExamplesExcel.

^QExamplesExcel.OpenClose


Версия BB - 1.6, Excel - 11(2003).
Видимо это был глюк самого Excel 9-10, который исправили в 11ой версии. Как вариант - какой-нибудь некорректно написанный плагин может мешать закрываться Excel'у.

Автор:  Евгений Темиргалеев [ Вторник, 03 Июль, 2007 09:14 ]
Заголовок сообщения: 

У меня BB 1.5, Excel 11. Этот пример работает также. Однако, когда между Quit и NewApplication стоит обработка - открытие книги и т.п, то процесс остается.

Попробуйте (у меня excel остается):
Код:
   PROCEDURE OpenClose*;
      VAR
         excel: CtlExcel.Application;
         wb: CtlExcel.Workbook;
   BEGIN
      excel := CtlExcel.NewApplication();
      excel.PUTVisible(TRUE);
      wb := excel.Workbooks().Open("E:\workbook.xls", NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL);
      excel.Quit;
      wb := NIL; excel:=NIL;
      Kernel.Collect;
   END OpenClose;

Автор:  Кривохатько С.А. [ Среда, 04 Июль, 2007 01:22 ]
Заголовок сообщения: 

Евгений Темиргалеев писал(а):
У меня BB 1.5, Excel 11. Этот пример работает также. Однако, когда между Quit и NewApplication стоит обработка - открытие книги и т.п, то процесс остается.

Подтверждаю. Как пишут здесь:
http://support.microsoft.com/Default.aspx?kbid=317109

"This behavior is by design."

Даже если заменить код на элементарный:
Код:
wbks: CtlExcel.Workbooks;
.....................
wbks := excel.Workbooks();
wbks.Close();
wbks := NIL;
.....................


получаем аналогичный результат. Остаётся либо изобретать Marshal.ReleaseComObject в BB, либо убивать процессы.

Автор:  Вячеслав Бойко [ Суббота, 14 Июнь, 2008 12:16 ]
Заголовок сообщения:  Re: Подсистема Ctl.

В меню "COM" есть пункт "Collect", который вызывает процедуру HostMenus.Collect, которая и прибивает Excel.
Код:
VAR
  app: CtlExcel.Application;
  .....

   PROCEDURE Exit*;
   BEGIN
      app:= NIL;
      HostMenus.Collect;
   END Exit;


Автор:  Вячеслав Бойко [ Среда, 18 Июнь, 2008 11:05 ]
Заголовок сообщения:  Re: Подсистема Ctl.

Куда утекает память?
Код:
MODULE TestExcel;

   IMPORT
      CtlT, Excel := CtlExcel9, StdLog, Services;

   TYPE

      Action = POINTER TO RECORD (Services.Action) END;

   VAR
      app: Excel.Application;
      ws: Excel.Worksheet;
      wb: Excel.Workbook;
      action: Action;
      range: Excel.Range;
      N: INTEGER;

   PROCEDURE (action: Action) Do;
   BEGIN
      N:= ws.Range(CtlT.Str("A1"), CtlT.Str("A1")).Value().Int();
      Services.DoLater(action, Services.Ticks() + 1000)
   END Do;

   PROCEDURE Start*;
   BEGIN
      app := Excel.NewApplication();
      app.PUTVisible(TRUE);
      app.PUTDisplayAlerts(FALSE);
      wb := app.Workbooks().Add(NIL);
      ws := Excel.This_Worksheet(wb.Worksheets().Item(CtlT.Int(1)));
      range := ws.Range(CtlT.Str("A1"), NIL);
      range.PUTValue(CtlT.Int(12345));
      NEW(action);
      Services.DoLater(action, Services.now)
   END Start;

   PROCEDURE Stop*;
   BEGIN
      Services.RemoveAction(action);
      action := NIL;
      app.Workbooks().Close();
      ws := NIL;
      wb := NIL;
      app.Quit;
      app := NIL;
   END Stop;
   

END TestExcel.


В диспетчере задач наюлюдаю как BB и Excel потихоньку отъедают память (BB съел 100 Мб и на этом не остановился). И такая картина наблюдается при чтении данных из различных объектов при использовании подсистемы Ctl.

Автор:  Вячеслав Бойко [ Пятница, 04 Июль, 2008 18:14 ]
Заголовок сообщения:  Re: Подсистема Ctl.

:?:
Господа, может кто-то сможет объяснить: куда утекает память при чтении из СОМ-объекта (см. сообщение выше)?
Сам не могу сообразить...

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/