РефератыИнформатика, программированиеПрПрограммируем под IIS на Visual C++

Программируем под IIS на Visual C++

Одной из распространенных задач администрирования web-сайтов является анализ log-файлов и сбор данных из них. Поговорим об этой задаче на примере IIS 5.0 (Internet Information Service). В связи с тем, что данный HTTP сервер поддерживает несколько форматов таких файлов (формат W3C, формат NCSA, а также свой формат IIS), анализ log-файлов превращается в довольно трудоемкую задачу. Кроме того для формата W3C список полей может конфигурироваться, что задачу не облегчает.


Но к счастью вместе с IIS 5.0 в составе прочих компонентов, поставляется компонент MSWC.IISLog, который предназначен для получения данных из log-файлов и предоставляет для этой цели интерфейс ILogScripting. Находится он в файле %windir%system32inetsrvlogscrpt.dll. С помощью этого интерфейса можно читать данные из log-файла, записывать прочтенные данные в другой файл.


Перед тем как начать работу с какими-либо log-файлом, его нужно открыть. Дляэтогослужитметод OpenLogFile:


HRESULT OpenLogFile( [in] BSTR szLogFileName,


[in] IOMode Mode,


[in] BSTR szServiceName,


[in] long iServiceInstance,


[in] BSTR szOutputLogFileFormat),


где в параметре szLogFileName задается полный путь к файлу; параметр Mode может принимать следующие значения:


ForReading - файл будет открыт для чтения


ForWriting - файл будет открыт для записи;


в параметре szServiceName задается название службы, которой был создан данный файл (например "W3SVC"); парметр iServiceInstance указывает номер экземпляра сервера данной службы (напр. 1); в параметре szOutputLogFileFormat задается название формата, в котором будут читаться или записываться данные (например "W3C"). Если метод выполнился успешно то возвращается 0.


Для чтения данных из файла служит метод ReadLogRecord:


HRESULT ReadLogRecord(),


который читает строку из текущей файловой позиции и перемещает позиционер файла дальше. Мы можем получить эти данные в виде значений конкретных полей с помощью множества методов, которые возвращают эти значения:






























































get_DateTime Отображение даты и времени по Гринвичу (GMT)
get_ServiceName Отображение имени службы
get_ServerName Отображение имени сервера
get_ClientIP Отображение имени узла клиента
get_UserName Отображение имени пользователя
get_ServerIP Отображение IP-адреса сервера
get_Method Отображение типа операции
get_URIStem Отображение адреса URL
get_URIQuery Отображение всех параметров, передаваемых с запросом
get_TimeTaken Отображение общего времени обработки
get_BytesSent Отображение числа переданных байтов
get_BytesReceived Отображение числа полученных байтов
get_Win32Status Отображение кода состояния Win32
get_ProtocolStatus Отображение состояния протокола
get_ServerPort Отображение номера порта
get_ProtocolVersion Отображение строки версии
get_UserAgent Отображение строки агента пользователя
get_Cookie Отображение имени Cookie клиента
get_Referer Отображение страницы источника ссылки
get_CustomFields Отображение массива специальных заголовков

Всеэтиметодыимеютодинформат: HRESULT get_MethodName(VARIANT *pValue). В параметре pValue будет возвращено интересующее нас значение. Если значение запрашиваемого параметра равно "-", то тип pValue будет VT_EMPTY. Если же по каким-то причинам параметр не будет найден в log-файле (напр. параметр отключен, или текущая строка - незначащая), то тип pValue будет VT_NULL.


Для того, чтобы мы сильно не увлеклись существует метод AtEndOfLog, который подобно привычному feof возвращает (или не возвращает :)) признак достижения конца файла и выглядит приблизительно так:


HRESULT AtEndOfLog([out, retval] VARIANT_BOOL* pfEndOfRead)


В параметре pfEndOfRead, собственно, и возвращается интересующий нас признак, что позволяет нам все таки когда-нибудь завершить обработку log-файла.


Помимо всего этого имеется еще метод WriteLogRecord, который позволяет записывать данные, полученные из одного log-файла в другой. Формат его следующий:


HRESULT WriteLogRecord([in] ILogScripting* pILogScripting),


где


pILogScripting - это указатель на экземпляр ILogScripting, в котором содержатся прочитанные данные. Этот метод похож на ReadLogRecord тем, что записывает в файл одну строку (напомню, что ReadLogRecord читает одну строку).


Для закрытия открытых файлов служит метод CloseLogFiles:


HRESULT CloseLogFiles([in] IOMode Mode),


в котором параметр Mode может принимать следующие значения:


ForReading - будут закрыты файлы, открытые для чтения


ForWriting - будут закрыты файлы, открытые для записи


AllOpenFiles - будут закрыты все открытые файлы


Чтобы доступиться к компоненту MSWC.IISLog из C++ надо иметь .h

файл, описывающий интерфейс ILogScripting. Сделать его нам поможет утилита OLEViewer, которая входит в состав Visual Studio. В меню "File" этой утилиты выберем пункт "View TypeLib" и укажем файл logscrpt.dll (естественно полный путь к нему). В новом окне откроется библиотека типов нашего объекта, которую мы сохраним в качестве .idl файла.


Для этого в меню "File" выберем пункт "Save as", укажем тип файла "idl", и сохраним его в некое место (например туда, где находится проект), к примеру, назвав его "logscrpt.idl". Все бы хорошо, да только в новоиспеченном файле придется сделать косметические изменения. Во-первых в самое начало файла надо вставить следующие строчки:


cpp_quote("DEFINE_GUID(CLSID_LogScripting, 0x26B9ED02, 0xA3D8, 0x11D1, 0x8B, 0x9C, 0x08, 0x00, 0x09, 0xDC, 0xC2, 0xFA);")


cpp_quote("DEFINE_GUID(IID_ILogScripting, 0x26B9ECFF, 0xA3D8, 0x11D1, 0x8B, 0x9C, 0x08, 0x00, 0x09, 0xDC, 0xC2, 0xFA);")


Во-вторых строчки


typedef enum {


ForReading = 1,


ForWriting = 2,


AllOpenFiles = 32


} IOMode;


надо перенести так, чтобы они находились до определения ILogScripting интерфейса.


Теперь осталось только сгенерировать файл logscrpt.h с помощью команды midl.exe logscrpt.idl /h logscrpt.h (проверьте путь к компилятору midl).


В заключение приведу пример программы работы с интерфейсом, которая получает в качестве параметров командной строки путь к log-файлу, название службы, название формата файла, номер экземпляра сервера и выдает на экран список всех URL адресов, к которым были зафиксированы обращения в этом файле. Вот пример вызова этой программы:


logging.exe d:logsw3svc2ex01060515.log W3SVC W3C 2


#include


#include


#include


#include


#include "logscrpt.h"


#define SOME_ERROR(lpszErrorText, nErrorNum)


printf("%s: %X


", lpszErrorText, nErrorNum);


throw nErrorNum;


int main(int argc, char *argv[])


{


HRESULT hres;


VARIANT vParam;


short nEndOfFile;


_bstr_t bstrLogFile;


_bstr_t bstrServiceName;


_bstr_t bstrLogFormat;


long nServerInstance;


_bstr_t bstrUriStem;


// проверка наличия параметров


if (argc < 5)


{


printf("Usage: %s LogFileName ServiceNa


me LogFormatName ServerInstance


", argv[0]);


return 0;


}


// получаем параметры из коммандной строки


try {


bstrLogFile = argv[1];


bstrServiceName = argv[2];


bstrLogFormat = argv[3];


if (!(nServerInstance = atol(argv[4])))


// экземплярсерверанеможетбыть 0


nServerInstance = 1;


}


catch (...) {


printf("Something wrong in parameters!


");


return 0;


}


// это будет ссылка на интерфейс


ILogScripting *pLogScripting = NULL;


try {


// инициализируем COM


if (!SUCCEEDED(hres = CoInitialize(NULL)))


{


SOME_ERROR("CoInitialize error", hres);


}


// теперьсоздадимэкзепляринтерфейса


if (!SUCCEEDED(hres = CoCreateInstance(CLSID_LogScripting,


NULL, CLSCTX_ALL, IID_ILogScripting,


(void **)&pLogScripting)))


{


SOME_ERROR("CoCreateInstance error", hres);


}


// открываем log-файл bstrLogFile для чтения, указывая, что этот


// файл относится к первому экземляру сервера службы W3SVC, а //


// форматунего W3C


if (!SUCCEEDED(hres =


pLogScripting-OpenLogFile(BSTR(bstrLogFile), ForReading,


BSTR(bstrServiceName), 1, BSTR(bstrLogFormat))))


{


SOME_ERROR("OpenLogFile error", hres);


}


// теперь можно приступить к анализу содержимого файла


for ( ;; ) {


// проверим на достижение конца файла


if (!SUCCEEDED(hres =


pLogScripting-AtEndOfLog(&nEndOfFile)))


{


SOME_ERROR("AtEndOfLog error", hres);


}


if (nEndOfFile)


// счастливо выходим


break;


// читаемследующуюзаписьфайла


if (!SUCCEEDED(hres = pLogScripting-ReadLogRecord()))


{


SOME_ERROR("ReadLogRecord error", hres);


}


// получаем из нее параметр адрес URL


if (!SUCCEEDED(hres = pLogScripting-get_URIStem(&vParam)))


{


SOME_ERROR("ReadLogRecord error", hres);


}


if (vParam.vt == VT_BSTR)


{


// если параметр не пуст распечатаем его на экране


bstrUriStem = vParam.bstrVal;


printf("Uri-stem: %s


", LPSTR(bstrUriStem));


}


}


// закрываемфайл


if (!SUCCEEDED(hres = pLogScripting-CloseLogFiles(ForReading)))


{


SOME_ERROR("CloseLogFiles error", hres);


}


}


catch (...) {}


// последние действия по деинициализации


if (pLogScripting != NULL)


pLogScripting-Release();


CoUninitialize();


return hres;


}


Dima Mukalov

Сохранить в соц. сетях:
Обсуждение:
comments powered by Disqus

Название реферата: Программируем под IIS на Visual C++

Слов:1159
Символов:11809
Размер:23.06 Кб.