C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Service && ADOConnection
Gedeon
Отправлено: 26.07.2004, 19:37


Ветеран

Группа: Модератор
Сообщений: 1742



Вот появилась необходимость сделать службу, которая бы по таймеру кое чего делала с базой. Итак создаем новое Service Application На Service1(Созданный по умолчанию DataModule) ляпаем таймер, ставим интервал 60000 и Enabled=true; в OnTimer пока Beep(). ляпаем TADOConnection, connected = true;
CODE

   while(!Terminated){
       ServiceThread->ProcessRequests(true);
   }

Компилим, регистрирум службу, пытаемся запустить и ... получаем:
QUOTE

Служба не была, запущена, т.к. вовремя не ответила на запрос.

Ладно, я тупой, читаем хэлп по аналогии пишем
CODE

   try{
       ADOC->Open();
           while(!Terminated){
               ServiceThread->ProcessRequests(true);
           }
       }
   __finally{
       ADOC->Close();
   }

Клмпилим, регистрим пытаемся запустить и ... получаем вообще суперсообщения, от которого случается истерика
QUOTE

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

Млин, че за ######? Че не так я сделал или как сделать правильно?
Gedeon
Отправлено: 30.07.2004, 20:48


Ветеран

Группа: Модератор
Сообщений: 1742



QUOTE (Gedeon @ 26/07/2004, 20:39)
Ладно, я тупой

Вот на самом деле так и есть biggrin.gif .
Если ADOConnection изначально поставить в Connected = true; то все нормально запускается, просто я не того провайдера поставил.
Если открывать при запуске сервиса надо вставить перед ореn еще следующую строку
CODE

    CoInitialize();

Все нормально запускается и работает, только появилась другая проблема, этому сервису нужно еще кое-какие файлы в сети смотреть, а если он стартует под локальной учетной записью, то его понятно никто никуда не пустит, так вот надо запустить сервис от имени своей учетной записи, чего ну никак сделать не получается, он долго колбасится, а потом пишет, что служба вовремя не ответила на запрос, в состоянии сервиса остается запуск аж до самой перезагрузки компа.
Вот код сервиса, может кто-то подскажет чего он не запускается от моей учетной записи(SQL Server, стоящий на этой же тачке нормально стартует).
СРР
CODE

//---------------------------------------------------------------------------
#include "UTest.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

#include "stdio.h"
TMAIl_SQL *MAIl_SQL;
//---------------------------------------------------------------------------
__fastcall TMAIl_SQL::TMAIl_SQL(TComponent* Owner)
       : TService(Owner)
{
   Updating = false;
}
//---------------------------------------------------------------------------
TServiceController __fastcall TMAIl_SQL::GetServiceController(void)
{
       return (TServiceController) ServiceController;
}
//---------------------------------------------------------------------------
void __stdcall ServiceController(unsigned CtrlCode)
{
       MAIl_SQL->Controller(CtrlCode);
}
//---------------------------------------------------------------------------
void __fastcall TMAIl_SQL::ServiceExecute(TService *Sender)
{
   while(!Terminated){
       ServiceThread->ProcessRequests(true);
   }
}
//---------------------------------------------------------------------------
void __fastcall TMAIl_SQL::ServiceStart(TService *Sender, bool &Started)
{
   try{
       CoInitialize(NULL);
       ADOC->Open();
       QSettings->Open();
       for(QSettings->First();!QSettings->Eof;QSettings->Next()){
           if(QSettings->FieldByName("Parameter")->AsString=="NBU_LOG_PATH"){
               NBU_LOG_PATH = QSettings->FieldByName("Value")->AsString;
           }
           else if(QSettings->FieldByName("Parameter")->AsString=="NBU_TCPFOSS_LOG_PATH"){
               NBU_TCPFOSS_LOG_PATH = QSettings->FieldByName("Value")->AsString;
           }
           else if(QSettings->FieldByName("Parameter")->AsString=="KYIV_LOG_PATH"){
               KYIV_LOG_PATH = QSettings->FieldByName("Value")->AsString;
           }
           else if(QSettings->FieldByName("Parameter")->AsString=="SERVICE_ERROR_LOG_FILE"){
               SERVICE_ERROR_LOG_FILE = QSettings->FieldByName("Value")->AsString;
           }
       }
       QSettings->Close();
       Timer1->Enabled = true;
       Timer1Timer(this);
   }
   catch(Exception &E){
       AnsiString ErrMsg = Now().FormatString("dd.mm.yyyy hh:nn:ss ") + E.Message
        + " function = \"" + "TMAIl_SQL::ServiceStart" + "\" \n";
       WriteToFileMsg("C:\\ServiceError.txt", ErrMsg);
   }
}
//---------------------------------------------------------------------------

void __fastcall TMAIl_SQL::ServiceStop(TService *Sender, bool &Stopped)
{
   if(ADOC->Connected)
       ADOC->Close();
}
//---------------------------------------------------------------------------


void __fastcall TMAIl_SQL::Timer1Timer(TObject *Sender)
{
   if(Updating) return;
   Updating = true;
   //проверка почты НБУ
   AnsiString NBU_Log_File_Name = NBU_LOG_PATH + "d" +
    Date().FormatString("ddmmyy") + ".sta";


   if(FileExists(NBU_Log_File_Name)){

       try{
           TStringList *NBUSL = new TStringList();
           NBUSL->LoadFromFile(NBU_Log_File_Name);
           for(int Str=0; Str<NBUSL->Count; Str++){

               WorkWithNBULetter(NBUSL->Strings[Str],Date());
           }
       }
       catch(Exception &E){
           ShowMessage(E.Message);
           return;
       }

   }

   Updating = false;
}
//---------------------------------------------------------------------------


bool __fastcall TMAIl_SQL::WriteToFileMsg(AnsiString FileName, AnsiString Msg)
{
   if(!FileExists(FileName)){
       HANDLE File = CreateFile(FileName.c_str(),NULL,NULL,NULL,
        CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
       CloseHandle(File);
   }
   char* WriteFileName = FileName.c_str();
   char* WriteMessage = Msg.c_str();

   FILE *file = fopen(WriteFileName,"a+");
   if(!file) return false;


   for(unsigned int i=0; i<strlen(WriteMessage); i++){
       if(fputc(WriteMessage[i],file)==EOF) return false;
   }
   if(fclose(file)==EOF) return false;
   return true;
}
//---------------------------------------------------------------------------

void __fastcall TMAIl_SQL::WorkWithNBULetter(AnsiString LetterString, TDateTime LetterDate)
{

   struct NBULetter{
       AnsiString LetterName, LetterPath, SenderMail, RecieverMail, CryptName;
       TDateTime LetterDate, PrepareConv, RecieveConv;
       int LetterStatus, AbonentId;
   } Letter;
   Letter.LetterName = LetterString.SubString(119,12).Trim();
   Letter.SenderMail = LetterString.SubString(18,8).Trim() + "@" +
    LetterString.SubString(27,8).Trim();
   Letter.RecieverMail = LetterString.SubString(36,8).Trim() + "@" +
    LetterString.SubString(45,8).Trim();
   Letter.AbonentId = 2;
   Letter.CryptName = LetterString.SubString(132,12).Trim();
   Letter.LetterDate = TDateTime(LetterDate.FormatString("dd.mm.yyyy ") +
   LetterString.SubString(60,2) + ":" + LetterString.SubString(62,2) + ":" +
    LetterString.SubString(64,2));
   #define LSS LetterString.SubString
   Letter.PrepareConv = TDateTime(LSS(54,2) + "." + LSS(56,2) + "." + LSS(58,2)
    + " " + LSS(60,2) + ":" +LSS(62,2) + ":" + LSS(64,2));
   try{
       Letter.RecieveConv = TDateTime(LSS(67,2) + "." + LSS(69,2) + "." + LSS(71,2)
        + " " + LSS(73,2) + ":" +LSS(75,2) + ":" + LSS(77,2));
   }
   catch(Exception &E){
       if(AnsiString(E.ClassName()) == "EConvertError")
           Letter.RecieveConv = NULL;
   }
   #undef LSS
   AnsiString InOut = LetterString.SubString(154,1);
   if(InOut == "I"){
       Letter.LetterStatus = 1;
   }
   else{
       if(Letter.RecieveConv.operator int() != NULL){
           Letter.LetterStatus = 2;
       }
       else{
           //тут проверка отправлено ли письмо
           AnsiString SendNBULog = NBU_TCPFOSS_LOG_PATH +
            LetterDate.FormatString("yyyymmdd") + "T0.log";
           if(FileExists(SendNBULog)){
               TStringList *SL = new TStringList();
               SL->LoadFromFile(SendNBULog);
               if(SL->Text.AnsiPos(Letter.CryptName)!=0){
                   Letter.LetterStatus = 3;
               }
               else{
                   Letter.LetterStatus = 4;
               }
               delete SL;
           }
           else{
               Letter.LetterStatus = 4;
           }
       }
   }
   if(Letter.LetterStatus==1){
       Letter.LetterDate = Letter.RecieveConv;
   }
   else{
       Letter.LetterDate = Letter.PrepareConv;
   }
   Letter.LetterPath = "M:\\NBUMAIL\\USERD\\" + LetterString.SubString(36,8).Trim()
    + "\\APPL";

   SQLC->CommandText = "EXEC SP_INSERT_MAIL '" + Letter.LetterName + "' ,'" +
    Letter.LetterPath + "' ,'" + Letter.SenderMail, + "' ,'" + Letter.RecieverMail
    + "' ," + AnsiString(Letter.LetterDate) + " ," + AnsiString(Letter.AbonentId);
   SQLC->Execute();

}
//---------------------------------------------------------------------------

Н
CODE


//---------------------------------------------------------------------------
#ifndef UTestH
#define UTestH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <SvcMgr.hpp>
#include <vcl.h>
#include <ADODB.hpp>
#include <DB.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TMAIl_SQL : public TService
{
__published:    // IDE-managed Components
   TADOConnection *ADOC;
   TTimer *Timer1;
   TADOCommand *SQLC;
   TADOQuery *QSettings;
   void __fastcall ServiceExecute(TService *Sender);
   void __fastcall ServiceStart(TService *Sender, bool &Started);
   void __fastcall ServiceStop(TService *Sender, bool &Stopped);
   void __fastcall Timer1Timer(TObject *Sender);
private:        // User declarations
   bool Updating;
   AnsiString NBU_LOG_PATH, NBU_TCPFOSS_LOG_PATH, KYIV_LOG_PATH, SERVICE_ERROR_LOG_FILE;
   bool __fastcall WriteToFileMsg(AnsiString FileName, AnsiString Msg);
   void __fastcall WorkWithNBULetter(AnsiString LetterString, TDateTime LetterDate);
public:         // User declarations
       __fastcall TMAIl_SQL(TComponent* Owner);
       TServiceController __fastcall GetServiceController(void);

       friend void __stdcall ServiceController(unsigned CtrlCode);
};
//---------------------------------------------------------------------------
extern PACKAGE TMAIl_SQL *MAIl_SQL;
//---------------------------------------------------------------------------
#endif

FoxVID
Отправлено: 03.08.2004, 08:39


Ученик-кочегар

Группа: Участник
Сообщений: 29



Скорее всего проблема заключается в том, что ADOConnection стартует с пользователем по умолчанию и у Вас стоит Use Windows NT integrated security в настройках сервера и в настройках ADOConnection. В настройках сервера выберите Autentication for SQL Server and Windows, а в настройках ADOConnection укажите пользователя, от имени которого будет стартовать это соединение.
Bcbsql
Gedeon
Отправлено: 03.08.2004, 11:11


Ветеран

Группа: Модератор
Сообщений: 1742



Да нет, тут дело не в этом, все так и стоит, как Вы сказали. Под локальной учетной записью сервис стартует, и нормально с SQL Server связывается, а вот под записью админ не хочет (так сказать зависает), под специально созданной учетной записью для запуска SQL Server с административными правами вообще получаю сообщение "Отказано в доступе. Ошибка 5." Кстати тоже самое и со встроенной записью администратор. Блин бред какой-то.
FoxVID
Отправлено: 03.08.2004, 12:54


Ученик-кочегар

Группа: Участник
Сообщений: 29



Если у Вас стоит Autentication: SQL Server and Windows, попробуйте ввести пользователя sa и его пароль. Если все сработает (по идее должно biggrin.gif ), то значит Ваши учетные записи не имеют достаточно прав.
Gedeon
Отправлено: 03.08.2004, 13:13


Ветеран

Группа: Модератор
Сообщений: 1742



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

Вернуться в Работа с базами данных в C++Builder