Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Безопасный код

302
28 сентября 2004 года
Sagittarius
648 / / 12.04.2003
Ситуация следующая:
Код:
Var Excel: OleVariant;
. . .
try
  . . .
  // Создаем объект - приложение Excel
  Excel := CreateOleObject('Excel.Application');
  . . .
  // Делаем приложение Excel видимым
  Excel.Visible := true;
finally
  // Удаляем связь с объектом Excel
  Excel := Unassigned;
end;

Все работает нормально, но, если у меня в промежутке между созданием Excel И его отображеним вылетит какая-либо ошибка, сгенерированная Excel-ом (например, OLE error xxxxxx), то секция finally игнорируется, т.е. объект Excel не освобождается, а в процессах остается висеть EXCEL невидимый.
Как отловить эту ошибку? Или как сделать, чтобы Excel сам удалялся при первой же ошибке?
10
29 сентября 2004 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Sagittarius
Как отловить эту ошибку? Или как сделать, чтобы Excel сам удалялся при первой же ошибке?


Обычно пишут так:

Код:
var Excel: OleVariant;
. . .
Excel := CreateOleObject('Excel.Application');
try
  . . .
  // Создаем объект - приложение Excel
  . . .
  // Делаем приложение Excel видимым
  Excel.Visible := true;
finally
  // Удаляем связь с объектом Excel
  Excel := Unassigned;
end;
302
30 сентября 2004 года
Sagittarius
648 / / 12.04.2003
Цитата:
Originally posted by smartsoft

Обычно пишут так:
Код:
var Excel: OleVariant;
. . .
Excel := CreateOleObject('Excel.Application');
try
  . . .
  // Создаем объект - приложение Excel
  . . .
  // Делаем приложение Excel видимым
  Excel.Visible := true;
finally
  // Удаляем связь с объектом Excel
  Excel := Unassigned;
end;


Чем этот вариант лучше?
Неважно как пишут, суть вопроса в другом. Читай внимательней.

1.8K
03 октября 2004 года
Sanya DLR
123 / / 03.03.2004
А у меня вот никак не вылетает подобная ошибка. :( Как ты это делаешь? :)
Появляется ли проблемма если код содержит только те строки что ты вынес в вопрос?
10
04 октября 2004 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Sagittarius
Чем этот вариант лучше?


Дело в том, что ошибка может возникнуть и в процессе создания объекта Excel. Если такое произойдет, блок finally вызываться не будет.

Цитата:
Originally posted by Sagittarius
Неважно как пишут, суть вопроса в другом. Читай внимательней.


Таким образом, в моем образце кода в блоке finally существует гарантия, что объект Excel определен.

302
04 октября 2004 года
Sagittarius
648 / / 12.04.2003
Цитата:
Originally posted by Sanya DLR
А у меня вот никак не вылетает подобная ошибка. :( Как ты это делаешь? :)
Появляется ли проблемма если код содержит только те строки что ты вынес в вопрос?


Чтобы вылетела ошибка, вызови несуществующий метод. Например, Excel.Foo

302
04 октября 2004 года
Sagittarius
648 / / 12.04.2003
Цитата:
Originally posted by smartsoft

Дело в том, что ошибка может возникнуть и в процессе создания объекта Excel. Если такое произойдет, блок finally вызываться не будет.

Таким образом, в моем образце кода в блоке finally существует гарантия, что объект Excel определен.


В том и дело, что при создании объекта Excel может вылететь ошибка. В реальном коду, у меня еще создаются и инициализируются другие объекты, которые необходимо будет освободить в любом случае, независимо от того, создался объект Excel или нет.

10
04 октября 2004 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Sagittarius
В реальном коду, у меня еще создаются и инициализируются другие объекты, которые необходимо будет освободить в любом случае, независимо от того, создался объект Excel или нет.


Ну, значит, процесс работы с каждым проблемным объектом нужно заключить в собственный блок try-finally.

302
04 октября 2004 года
Sagittarius
648 / / 12.04.2003
Цитата:
Originally posted by smartsoft

Ну, значит, процесс работы с каждым проблемным объектом нужно заключить в собственный блок try-finally.


Ты предлагаешь делать вложенные блоки try...finally?

10
04 октября 2004 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Sagittarius
Ты предлагаешь делать вложенные блоки try...finally?


Так всегда так делают. А как по-другому?

Код:
var
  Excel, Workbook, Sheet: OleVariant;
begin
  Excel := CreateOleObject('Excel.Application');
  try
    Workbook := OlePropertyGet(Excel, <параметры>);
    try
      Sheet := Workbook[0]; // или как там еще - не помню уже ;)
      try
        <...код работы с Sheet...>
      finally
        Sheet := Null;
      end;
      Sheet := Workbook[1]; // аналогично предыдущему
      try
        <...код работы с Sheet...>
      finally
        Sheet := Null;
      end;
    finally
      Workbook := Null;  // принудительное "отпускание" объекта Workbook
    end;
  finally
    Excel.Quit(<не знаю, какие тут должны быть параметры>);
    // кстати, присваивать Unassigned или Null необязательно,
    // Дельфи автоматом вызывает для всех автоматических переменных типа String, Record или Variant
    // процедуру Finalize, которая освобождает всю дополнительно выделенную память
  end;
end;
302
04 октября 2004 года
Sagittarius
648 / / 12.04.2003
Цитата:
Originally posted by smartsoft
Так всегда так делают.


Я с тобой совершенно согласен.
Насчет автоматического удаления переменных...
Случаем не в курсе, если у меня функция возвращает инициализированный TStringList, его удалять обязательно?

ИМХО. Все же лучше самому удалять все переменные. Это будет правильный тон программирования.

10
04 октября 2004 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Sagittarius
Случаем не в курсе, если у меня функция возвращает инициализированный TStringList, его удалять обязательно?


Естественно.

Кстати, борец за хороший тон программирования, - создавать и возвращать некоторый объект внутри функции - моветон. ;)

1.8K
04 октября 2004 года
Sanya DLR
123 / / 03.03.2004
Цитата:
Originally posted by Sagittarius

Чтобы вылетела ошибка, вызови несуществующий метод. Например, Excel.Foo


Ну вызвал я несуществующий метод... Он мне сказал про это. А потом таки выполнил секцию finally. Чего еще не хватило?
Кстати, обратил внимание, что сама Excel:=unassigned мгновенного эффекта не дала. Пока вся секция не выполнилась, Excel в процессах висел, а потом исчез (я объявлял его глобально, так что речь не об уничтожении локальной переменной при выходе из процедуры).
И ты засунь в эту finally какой-нибудь showmessage('labuda') чтобы убедиться, что он точно не выполняется.

302
05 октября 2004 года
Sagittarius
648 / / 12.04.2003
Цитата:
Originally posted by Sanya DLR

Ну вызвал я несуществующий метод... Он мне сказал про это. А потом таки выполнил секцию finally. Чего еще не хватило?
Кстати, обратил внимание, что сама Excel:=unassigned мгновенного эффекта не дала. Пока вся секция не выполнилась, Excel в процессах висел, а потом исчез (я объявлял его глобально, так что речь не об уничтожении локальной переменной при выходе из процедуры).
И ты засунь в эту finally какой-нибудь showmessage('labuda') чтобы убедиться, что он точно не выполняется.


Я сейчас, к сожалению, точно не помню. Но были такие ситуации, когда несколько таких ошибок приводило к захломлению списка процессов, в котором через некоторое время начинало висеть процессов 20 с названием EXCEL, сильно тормозивших систему.

Насчет Unassigned...
Присвоение Execl значения Unassigned не уничтожает и не закрывает приложения Excel. Excel будет открыт до тех пор, пока пользователь не закроет его сам, главное не забыть показать приложение, а то только в процессах и можно будет найти. Чтобы закрыть приложение надо вызвать метод Quit.

302
05 октября 2004 года
Sagittarius
648 / / 12.04.2003
Цитата:
Originally posted by smartsoft
Кстати, борец за хороший тон программирования, - создавать и возвращать некоторый объект внутри функции - моветон. ;)


Ну ладно, не будем придираться к типу возвращаемых значений :) Иногда без этого никак, а объявлять глобальные переменные, как в Basic, совсем не хочется. Не в каменном веке живем ведь ;)

10
06 октября 2004 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by Sagittarius
Иногда без этого никак, а объявлять глобальные переменные, как в Basic, совсем не хочется. Не в каменном веке живем ведь ;)


Можно написать процедуру, которая будет записывать результаты в переданный ей экземпляр класса. Например, как TDataSet.GetFieldList.

302
07 октября 2004 года
Sagittarius
648 / / 12.04.2003
Цитата:
Originally posted by smartsoft

Можно написать процедуру, которая будет записывать результаты в переданный ей экземпляр класса. Например, как TDataSet.GetFieldList.


Это не вариант. У меня есть универсальная функция, которая дожна возвращать разное количество значений. TStringList для этого, как нельзя лучше, подходит. И к этой функции обращаются разные классы.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог