Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Компоненты ADO в сервисе Win32 [D6, IB6.x, MSSQL]


Страницы:   1 2 3

iZEN ©   (2002-11-15 15:23:00) 

Компоненты ADO в консольном приложении. :[
Возможно ли такое в принципе?

Пробую создать сервисное приложение под Windows2000/XP, где в run-time инстанцируются компоненты TADOConnection и TADOQuery.
Создаются нити на основе TThread, в которые передаются экземпляры этих компонентов и они начинают работу (должны начать - в оконном тестовом приложении всё работает).

...
{$APPTYPE CONSOLE}

uses
ActiveX,...;
...
var
Connection: TADOConnection;
Query: TADOQuery;
Writer: TWriterTask;//Дочерняя нить
...
procedure TConverter.ServiceStart(Sender: TService; var Started: Boolean);
begin
OLEInitialize(nil);
Connection := TADOConnection.Create(nil);
Query := TADOQuery.Create(nil);
Query.Connection := Connection;
Writer := TWriterTask.Create();
Writer.FreeOnTerminate := True;
Writer.SetConnection(Connection);
...
//---Стартуем нить
Writer.Resume();
end;

procedure TConverter.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
//Очистка и завершение работы сервиса
...
OLEUninitialize();
end.

Компиляция происходит нормально.
Инсталляции сервиса происходит нормально (среди сервисов присутствует).
Как только пытаюсь запустить, выдаётся сообщение: "сервис был запущен и остановлен. Некоторые службы автоматически останавливаются, если им нечего делать".
Но как раз делать-то есть чего!!!

Как это побороть?


ЮЮ   (2002-11-28 09:09:00) [1]

>Под отладчиком в окне "Локальные переменные" видим:
AllNames: ();
НИЧЕГО НЕТ!
Хотя AllNames <> nil;

А AllNames[0], AllNames[AllNames.Count - 1] ??
Это у динамического массива в отладчике видно (("1")("2")), а StringList так не посмотришь


iZEN   (2002-11-28 08:07:00) [2]

Для Zelius © (27.11.02 17:04).

Ну естественно, я же уже не мальчик.
В секцию finally переход осуществляется только после прочтения всего файла и "якобы-занесения" всех строк в AllNames.Add(s). То есть всё происходит без исключений и всё читается (это я вижу при пошаговой отладке), но AllNames оказывается пустым всегда, даже не nil!

Предположение: в Delphi в конструкторе объектов исключения не могут выбрасываться до завершения конструирования (проглатываются? тихие исключения?).

Вы-то сами можете попробовать: обычный текстовый файл, в котором число символов кратно 20. Есть собственная функция ANSI() (очень простая), переводящая чимвол кодировки DOS866 в WIN1251, но она Вам не нужна для эксперимента.

P.S. Задача вообще-то решена с использованием дин.массива. Так что проехали?


Zelius   (2002-11-27 17:04:00) [3]

а ты ставил на AllNames.Add(s) брякпойнт? Ты заходил в дебагере внутрь этого метода? если нет, то попробуй... и поставь брякпойнт в секции finally! Если код сразу перейдет туда, значит был эксепшн... Мне кажется, что возможное объяснение происходящего это эксепшн при открытии файла... Больше мыслей нет... Все должно работать...


iZEN   (2002-11-27 16:14:00) [4]

Попробовал бы я так в Java поставить вопрос - меня бы на смех подняли.
Ну нет там таких заморочек! Всё прозрачно, если используешь стандартные библиотечные объекты (да и свои тоже).


iZEN   (2002-11-27 16:11:00) [5]

На Zelius © (27.11.02 15:50).

И это пробовал. Думаете я первый раз попадаю в "передряги"?
Непонятно одно: почему AllNames.Add(s); не отрабатывает, даже исключений нет.
Странно. Весма странно.

На Zelius © (27.11.02 15:51).
/**Должен заявить, что данный когд не имеет никакого отношения к консольности!!! Если что-то не работает, то надо искать причину в другом...*/

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


iZEN   (2002-11-27 15:55:00) [6]

Дополнение к iZEN © (27.11.02 15:34).
sимеет допустимое значение на всех стадиях функции.


Zelius   (2002-11-27 15:51:00) [7]

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


Zelius   (2002-11-27 15:50:00) [8]

Остается только одно, по Станиславскому - НЕ ВЕРЮ :))
Попробуй вставь в код дополнительные переменные простого типа и присвой их в интересующих тебя местах, типа после заполнения массива перед SetLength( Names, AllNames.Count); поставь k := AllNames.Count и s := Allnames.CommaText и помотри, что они буду значить...


iZEN   (2002-11-27 15:46:00) [9]

Дополнение к iZEN © (27.11.02 15:34).
sимеет допустимое значение на всех стадиях функции.


iZEN   (2002-11-27 15:38:00) [10]

Вот такие чудеса...однако.


iZEN   (2002-11-27 15:34:00) [11]

Для Zelius © (27.11.02 15:21).

Спасибо за код.
НО!
В консольном приложении: строчка sне заносится в AllNames.Add(s);. ХОТЬ ТРЕСНИ!!!
Под отладчиком в окне "Локальные переменные" видим:

...
AllNames: ();

НИЧЕГО НЕТ!
Хотя AllNames <> nil;


iZEN   (2002-11-27 15:24:00) [12]

Вот так вернее (ошибся насчёт "задание длины массива на 2 элемента больше"):

...
finally
if (Assigned(AllNames)) then begin
SetLength(Names, j);
for i := Low(Names) to High(Names) do
Names[i] := AllNames[i];
...

Массив AllNames имеет длину, превышающую число значимых строк (j - счётчик строк).


Zelius   (2002-11-27 15:21:00) [13]

Попробуй, пожалуйста, такой код, в нем я постарался исключть по максимуму возможные подводные камни, хотя один там еще остался:

constructor TTSArchiv.Create(const NamesFileName, ValuesFileName: TFileName);
procedure FillNames();
//Запонение массива Именами ТС
var fis: TFileStream;
k: Integer;
s: AnsiString;
c: Byte;
AllNames: TStringList;
begin
fis := nil;
AllNames := nil;
try
fis := TFileStream.Create(NamesFileName, fmOpenRead or fmShareDenyNone);
AllNames := TStringList.Create();
fis.Position := 0;
while fis.Position < fis.Size do
begin
fis.Read( c, 1);
Inc(k);
if (c >= 32) then s := s + ANSI(c);
if (k = 20) and (s <> "") then
begin
AllNames.Add(s);
s := "";
k := 0;
end;
end;
if s <> "" then AllNames.Add(s);
SetLength( Names, AllNames.Count);
for i := 0 to AllNames.Count-1 do
Names[i] := AllNames[i];
finally
FreeAndNil(AllNames);
FreeAndNil(fis);
end;
end;
begin
inherited Create();
FillNames();
end;


iZEN   (2002-11-27 15:09:00) [14]

Вы имеете ввиду строчку SetLength(Names, j+1);?
Здесь происходит задание длины массива на 2 элемента больше (! т.к. j увеличивается 2 раза: после Inc(j);и в этом месте).
Хотя действительно можно обойтись SetLength(Names, j-1);- по длине массива AllNames.
Или даже так:
SetLength(Names, High(AllNames) - Low(AllNames) + 1);
(Кстати, спасибо за намёк на уловку:), лишние два элемента массива надо бы исключить)
В любом случае, выход за границы не происходит, но количество элементов, естественно, выходит больше чем есть. "Лишние" элементы пустые. Я по шагам всё проверил.


Zelius   (2002-11-27 14:58:00) [15]

Такой вопрос, тебе удалось полноценно пройтись отладчиком по этому коду? То есть я хочу сказать, что есть шанс, что какое-то исключение ты просто не увидел, иногда отладчик сразу убегает в другой кусок кода. Например, в первом варианте кода, ты забывал передать в AllNames тот кусок строки, который был последним в файле и не был кратным 20! Однако j у тебя указывал на то что она есть и при присвоенни в Names это последней строки вылезал эксепшн! Этот кусок кода я смоделировал у себя.


iZEN   (2002-11-27 14:51:00) [16]

Этот конструктор использует локальную функцию, которая читает файл в буфер. Представляет его как байтовый поток (Stream), из которого берутся строки длиной 20 символов (константа lenName = 20;).
Переполнения никакого быть не может: изначально вычисляется и устанавливается длина массива с "хвостиком" ( SetLength(AllNames, mis.Size div lenName + lenName);).
Это решает проблему выхода за границы массива.
Переменная jслужит для подсчёта "полноценных" строк.


iZEN   (2002-11-27 14:45:00) [17]

/**Zelius © (27.11.02 14:15)
А у тебя не выскакивает ошибка типа "List index out of bounds" ?
*/
Нет. Всё глухо. Отладчик не жалуется...


Zelius   (2002-11-27 14:15:00) [18]

А у тебя не выскакивает ошибка типа "List index out of bounds" ?
Судя по коду, у тебя есть несколько потенциальных мест для возникновения ошибок.


BlackTiger   (2002-11-27 13:09:00) [19]

Что-то странное в компонентах VCL все-таки есть. И это не глюки программиста. Я подозреваю, что Делфа проводит какую-то НЕЯВНУЮ инициализацию чего-то внутри и этой инициализации не происходит в таких специфичных приложениях как консольные и сервисы. При этом хелпы просто умалчивают про это (впрочем много о чем еще).
В книгах про ТАКИЕ вещи тоже не пишут, так как авторы зачастую сами ничего в этом не понимают. Ответ знают только борландовцы и люди, которые сами бились (и успешно!) с такими проблемами. Подход, который подходит (калабурчик-с) для разработки стандартных (оконных) приложений, абсолютно не применим при создании сервисов и консолей - тут надо копать глубже, но не всегда понятно в какую сторону.
Вот! Мое личное мнение.


iZEN   (2002-11-27 13:07:00) [20]

Было: AllNames: TStringList;
Стало: AllNames: array of String;


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо