<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ZetBlog&#187; файлы</title>
	<atom:link href="http://zetblog.ru/tag/%d1%84%d0%b0%d0%b9%d0%bb%d1%8b/feed/" rel="self" type="application/rss+xml" />
	<link>http://zetblog.ru</link>
	<description>Зеты говорят. Блог о программировании, администрировании и безопасности.</description>
	<lastBuildDate>Sat, 29 Oct 2011 18:59:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Delphi: Пишем шаблон клиент-серверного приложения.</title>
		<link>http://zetblog.ru/programming/201004/delphi-%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd-%d0%ba%d0%bb%d0%b8%d0%b5%d0%bd%d1%82-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80-%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd/</link>
		<comments>http://zetblog.ru/programming/201004/delphi-%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd-%d0%ba%d0%bb%d0%b8%d0%b5%d0%bd%d1%82-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80-%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 07:47:37 +0000</pubDate>
		<dc:creator>C0ffe1n</dc:creator>
				<category><![CDATA[прикладное]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[сетевое]]></category>
		<category><![CDATA[ClientSocket]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[ServerSocket]]></category>
		<category><![CDATA[сеть]]></category>
		<category><![CDATA[файлы]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=913</guid>
		<description><![CDATA[Продолжая тему разработки собственной утилиты администрирования, в данной статье я рассмотрю типовой шаблон программы клиент-сервер, на базе которой можно разрабатывать собственные клиент-серверные приложения. Данный типовой шаблон для простоты понимания и удобства применения будет рассмотрен на примере компонентов ClientSocket и ServerSocket. Примечание Для тех, кто не в курсе, что значит клиент-серверное приложение, поясню: это комплекс программ [...]]]></description>
			<content:encoded><![CDATA[<p>Продолжая тему разработки собственной утилиты администрирования, в данной статье я рассмотрю типовой шаблон программы клиент-сервер, на базе которой можно разрабатывать собственные клиент-серверные приложения. Данный типовой шаблон для простоты понимания и удобства применения будет рассмотрен на примере компонентов <strong>ClientSocket</strong> и <strong>ServerSocket</strong>.<br />
<span id="more-913"></span><strong></strong></p>
<p><strong>Примечание</strong></p>
<div class="codesnip-container" >Для тех, кто не в курсе, что значит клиент-серверное приложение, поясню: это комплекс программ (модулей) состоящий из двух частей &#8212; клиентской и серверной. Серверная часть является &#171;главной&#187;- так называемый командный пункт, на который возложена задача поддержания связи со всеми клиентами и раздача команд управления, соответствующих их функционалу (управление клиентами). Клиентская же часть является второстепенной, но не менее важной, так как является важным и связующим элементом, позволяющим выполнять удаленные команды (функции) на компьютере, на котором установлен.</div>
<div class="codesnip-container" >Компоненты <strong>ClientSocket</strong> и <strong>ServerSocket</strong>, которые мы будем использовать, находятся на вкладке <strong>Internet</strong>. Если на этой вкладке у Вас нет этих компонентов (а по умолчанию при установке <strong>Delphi7</strong> они не ставятся), необходимо установить их самостоятельно (пакет <strong>dclsocketsXX.bpl</strong>). Данный пакет можно найти на установочном диске<strong> Delphi7</strong> (или в папке<span style="text-decoration: underline;"> C:\Temp</span>, куда распаковывается дистрибутив перед установкой &#8212; <span style="text-decoration: underline;">C:\Temp\delphi7\install\program files\borland\delphi7\bin\</span>) или можете его скачать <a href="/forum/downloadf/components/dclsockets70.rar">отсюда</a>. Чтобы установить данный пакет, запустите <strong>Delphi7</strong>. Зайдите в меню <span style="text-decoration: underline;">Component-&gt;Install Packages</span>. В появившемся окне нажмите кнопку <strong>&#171;Add&#187;</strong> и укажите место, где расположен пакет <strong>dclsocketsXX.bpl</strong>. После этого жмите<strong> ОК</strong>. Компонент на месте. ;)</div>
<p>Надеюсь все объяснил доступно =). А теперь приступим к делу и начнем мы с серверной части. Для этого создадим проект и скинем на форму компонент <strong>ServerSocket</strong>. В настройках компонента <strong>ServerSocket</strong> укажем следующее:</p>
<div class="codesnip-container" >Active = false<br />
Name = ss<br />
Port = 4321<br />
ServerType = stNonBlocking</div>
<p>А также для удобства скинем компонент <strong>Memo</strong>, в который будем выводить всякую инфу. Дадим имя компоненту <strong>log</strong>.</p>
<p>Далее, для компонента <strong>ServerSocket</strong> определяем метод <strong>onClientConnect</strong>, чтобы определять момент подключения клиентов. Вставим следующий код:</p>
<pre class=".brush: pascal">procedure TForm1.ssClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now;
  DateTimeToString(formattedDateTime, 'c', myDate);
  log.Lines.Add(formattedDateTime+': Есть коннект c '+Socket.RemoteAddress);
  { далее вы можете вставить свой код }
end;</pre>
<p>А теперь определим метод <strong>onClientRead</strong>, в котором будем обрабатывать получаемые сообщения от клиентов:</p>
<pre class=".brush: pascal">procedure TForm1.ssClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  s:string;
begin
  s:=Socket.ReceiveText;
  log.Lines.Add(s);
end;</pre>
<p>Определим метод<strong> onClientDisconnect</strong>, чтобы фиксировать факт отключения клиента:</p>
<pre class=".brush: pascal">procedure TForm1.ssClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now;
  DateTimeToString(formattedDateTime, 'c', myDate);
  log.Lines.Add(formattedDateTime+': Клиент '+socket.RemoteAddress+' отключился.');
end;</pre>
<p>На этом с серверной частью покончено =).</p>
<p>Приступим к клиентской части. Для этого создадим новый проект, скинем на форму компонент <strong>ClientSocket</strong> и таймер. В настройках компонента укажем следующее:</p>
<div class="codesnip-container" >Active = false<br />
Name = сs<br />
Port = 4321<br />
ClientType = ctNonBlocking<br />
Address = 127.0.0.1</div>
<p>Для простоты пояснения я в <strong>Address</strong> указал <strong>&#171;петлю&#187;</strong>. Но для гибкости приложения рекомендую это поле обрабатывать программно, во время <strong>CreateForm</strong> при обработке конфигурационного файла, в котором можно указывать нужный <strong>IP-адрес сервера</strong>.</p>
<p>Здесь также для удобства скинем на форму компонент <strong>Memo</strong>, в который будем выводить техническую инфу. Имя дадим соответствующее<strong> log</strong>.</p>
<p>Для компонента <strong>ClientSocket</strong> определяем метод <strong>onError</strong> для того, чтобы обрабатывать исключения, возникшие в момент подключения клиента к серверу. Вставим следующий код:</p>
<pre class=".brush: pascal">procedure TForm1.csError(Sender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
 if ErrorEvent= eeConnect  then
  begin
    cs.Active:=false;
      {добавить запись в журнал};
    mydate:=Now;
    DateTimeToString(formattedDateTime, 'c', myDate);
    log.lines.Add(formattedDateTime+': Невозможно установить соединение с сервером - '+cs.Address);
  end;
  ErrorCode:=0;
  { далее вы можете вставить свой код }
end;</pre>
<p>Теперь определим метод <strong>onConnect</strong>. Вставим следующий код:</p>
<pre class=".brush: pascal">procedure TForm1.csConnect(Sender: TObject; Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now;
  DateTimeToString(formattedDateTime, 'c', myDate);
  log.lines.Add(formattedDateTime+': Соединение с сервером - '+socket.RemoteAddress+' установлено.');
end;</pre>
<p>И чтобы фиксировать момент потери связи с сервером, определим метод <strong>onDisconnect</strong>:</p>
<pre class=".brush: pascal">procedure TForm1.csDisconnect(Sender: TObject; Socket: TCustomWinSocket);
var
  myDate : TDateTime;
  formattedDateTime : string;
begin
  mydate:=Now; //получим текущее время
  DateTimeToString(formattedDateTime, 'c', myDate); //преобразуем в строку
  log.Lines.Add(formattedDateTime+': Соединение с сервером '+socket.RemoteAddress+' потеряно.');
end;</pre>
<p>Таймер настроим так:</p>
<div class="codesnip-container" >Enabled = true<br />
Name = te<br />
Interval = 5000</div>
<p>И определяем метод <strong>onTimer</strong>. Вставим следующий код:</p>
<pre class=".brush: pascal">procedure TForm1.Timer1Timer(Sender: TObject);
begin
if not cs.Active then
  begin
    cs.Active:=true;
  end;
  cs.Socket.SendText('ping client');
end;</pre>
<p>Данный код проверяет наличие соединения с сервером и в случае его отсутствия пытается его установить.<br />
И каждые 5 секунд отправляет серверу сообщение <strong>&#171;ping client&#187;</strong>.</p>
<p>Вот примерно так выглядит типовой шаблон приложения <strong>&#171;клиент-сервер&#187;</strong>.</p>
<p><strong>Примечание</strong></p>
<div class="codesnip-container" >Хотел бы обратить внимание на обработчик <strong>onError</strong> тех, кто ранее не знал как избавиться от злосчастного сообщения &#8212; <strong>&#171;Asynchronous socket error 10061&#8243;</strong>, возникающее при попытке осуществления подключения к серверу, который недоступен.</div>
<p>Рабочий пример можно скачать <a title="Рабочий пример" href="/forum/downloadf/simples/client-server.rar">отсюда</a>.</p>
<p>Если есть кому что добавить или задать вопрос по теме &#8212; прошу отписываться в комментах ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/201004/delphi-%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd-%d0%ba%d0%bb%d0%b8%d0%b5%d0%bd%d1%82-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80-%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Администрирование: восстановление работоспособности Windows XP &#8212; ошибка c000021a.</title>
		<link>http://zetblog.ru/administration/201002/%d0%b0%d0%b4%d0%bc%d0%b8%d0%bd%d0%b8%d1%81%d1%82%d1%80%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5%d0%b2%d0%be%d1%81%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%80%d0%b0/</link>
		<comments>http://zetblog.ru/administration/201002/%d0%b0%d0%b4%d0%bc%d0%b8%d0%bd%d0%b8%d1%81%d1%82%d1%80%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5%d0%b2%d0%be%d1%81%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%80%d0%b0/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 14:21:15 +0000</pubDate>
		<dc:creator>C0ffe1n</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[Администрирование]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Windows XP]]></category>
		<category><![CDATA[восстановление]]></category>
		<category><![CDATA[ошибки]]></category>
		<category><![CDATA[файлы]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=922</guid>
		<description><![CDATA[Поведаю Вам очередной совет по восстановлению операционной системы Windows XP из дауна в синий «экран смерти» с ошибкой с000021a. Такая ситуация с ошибкой c000021a возникает при завершении Winlogon.exe или сsrss.exe, а также при неудачном запуске smss.exe. Причиной тому может стать некорректное завершение работы операционной системы, некорректная установка софта или обновления, а также «трипачек» (то бишь [...]]]></description>
			<content:encoded><![CDATA[<p>Поведаю Вам очередной совет по восстановлению операционной системы <strong>Windows XP</strong> из дауна в синий «экран смерти» с ошибкой <strong>с000021a</strong>. </p>
<p>Такая ситуация с ошибкой <strong>c000021a</strong> возникает при завершении <strong>Winlogon.exe</strong> или <strong>сsrss.exe</strong>, а также при неудачном запуске <strong>smss.exe</strong>. Причиной тому может стать некорректное завершение работы операционной системы, некорректная установка софта или обновления, а также <strong>«трипачек»</strong> (то бишь вредоносные программы).<br />
<span id="more-922"></span><br />
Для  решения проблемы Вам потребуется загрузочный диск или <strong>Live CD/DVD</strong> и т.п., чтобы получить доступ к файлам <strong>Winlogon.exe</strong>, <strong>csrss.exe</strong>, <strong>smss.exe</strong> не блокируемым системой. Кроме того, потребуется скопировать данные файлы с работоспособной системы, которые лежат в <strong>C:\WINDOWS\system32</strong>. После того как Вы, например, загрузитесь с <strong>Live CD/DVD</strong>, просто замените данные файлы и будет Вам счастье.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/administration/201002/%d0%b0%d0%b4%d0%bc%d0%b8%d0%bd%d0%b8%d1%81%d1%82%d1%80%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5%d0%b2%d0%be%d1%81%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%80%d0%b0/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Администрирование: Восстановление загрузки Windows.</title>
		<link>http://zetblog.ru/administration/201001/%d0%b0%d0%b4%d0%bc%d0%b8%d0%bd%d0%b8%d1%81%d1%82%d1%80%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b2%d0%be%d1%81%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b7/</link>
		<comments>http://zetblog.ru/administration/201001/%d0%b0%d0%b4%d0%bc%d0%b8%d0%bd%d0%b8%d1%81%d1%82%d1%80%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b2%d0%be%d1%81%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b7/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 16:33:51 +0000</pubDate>
		<dc:creator>C0ffe1n</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[Администрирование]]></category>
		<category><![CDATA[Live CD/DVD]]></category>
		<category><![CDATA[Windows XP]]></category>
		<category><![CDATA[вирусы]]></category>
		<category><![CDATA[восстановление]]></category>
		<category><![CDATA[загрузка]]></category>
		<category><![CDATA[реестр]]></category>
		<category><![CDATA[файлы]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=892</guid>
		<description><![CDATA[Случается так, что в один прекрасный день при загрузке Windows на черном экране выводится сообщение, что по причине некорректного файла system или software операционная система (далее ОС) семейства Windows не может загрузиться. Это происходит тогда, когда ОС некорректно завершает свою работу &#8212; моргнул свет, нажатие кнопки «reset» или просто по необъяснимой причине =)… В этом [...]]]></description>
			<content:encoded><![CDATA[<p>Случается так, что в один прекрасный день при загрузке Windows на черном экране выводится сообщение, что по причине некорректного файла <strong>system</strong> или <strong>software</strong> операционная система (далее ОС) семейства Windows не может загрузиться. Это происходит тогда, когда ОС некорректно завершает свою работу &#8212; моргнул свет, нажатие кнопки <strong>«reset»</strong> или просто по необъяснимой причине =)…<br />
<span id="more-892"></span><br />
В этом случае есть два выхода. Либо переустановка ОС Windows, либо восстановить работоспособность Windows <strong>«ручками»</strong>, но с небольшим ограничением. Все программы которые зависят от реестра прийдется переустанавливать =(. Первый вариант скорее для начинающих пользователей, которые только учатся переустанавливать ось и его рассматривать я не буду, а вот второй уже для опытных и в связи с этим более интересен, о нем я расскажу поподробней. </p>
<p>Для этого понадобится либо установочный диск, либо <strong>Live CD/DVD</strong>, либо возможность подключения жесткого диска к другому компу. Рассматривать данный способ я буду на примере загрузочного диска, однако все описанные действия аналогичны и для<strong> Live CD/DVD</strong> или подключения к другому компу.</p>
<p>Приступим. Загружаемся с загрузочного (установочного) диска ОС Windows. Когда вам представится выбор действий, то нужно выбрать режим восстановления операционной системы с помощью консоли восстановления, нажатие кнопки <strong>«R»</strong>. Далее выбираем раздел операционной системы – требуется ввести нужную цифру. Далее с вас спросят пароль. Если пароль при установке Windows вы не устанавливали, просто нажмите <strong>«Enter»</strong>. После этого система восстановления переведет вас в папку Windows. Далее вам потребуются знания консольных команд ;).</p>
<p>С помощью команды <strong>cd</strong> переходим в папку <strong>repair</strong>:</p>
<div class="codesnip-container" >cd repair</div>
<p>В папке <strong>repair</strong> хранится <strong>«сырой»</strong> реестр(файлы: <strong>sam</strong>, <strong>system</strong>, <strong>software</strong>, <strong>default</strong>, <strong>security</strong>. Самыми важными файлами являются <strong>sam</strong> – в котором хранятся учетки пользователей, <strong>system</strong> – системный ключ для защиты файла <strong>sam</strong>, а так же настройки системы, <strong>software</strong> – содержит информацию об установленном ПО. Это тот самый реестр, который создался при установке операционной системы и он еще не знает ни об устройствах вашей системы, ни об установленных программах. </p>
<p>Действующий или <strong>«активный»</strong> реестр вашей системы лежит в <strong>Windows\system32\config</strong>. С помощью команды <strong>copy</strong> копируем необходимые файлы из папки <strong>repair</strong> в папку <strong>config</strong>:</p>
<div class="codesnip-container" >// так как мы находимся в папке repair команда будет выглядеть так<br />
Copy < нужный  файл> Windows\system32\config\<нужный файл></div>
<p>Будет выведено сообщение что такой файл уже существует, заменить? Жмите <strong>«Y»</strong>. Далее перезагружаем компьютер. В результате такой замены, может потребоваться замена еще пары файлов – не пугайтесь, просто проведите такую же манипуляцию с файлами. </p>
<p>Как только система соизволит загрузиться, начнется процесс установки драйверов (заново). Если этого не произойдет, придется системе помочь. </p>
<p>Если же вдруг при загрузке ОС выводится сообщение, что у вас битая какая то .dll-ка, то ее можно найти на загрузочном диске в папке <strong>«I386»</strong>. При это расширение у искомой .dll-ки  будет выглядеть как <strong>«.DL_»</strong>. Если ваш CD-ROM под буквой D, то для того чтобы сменить диск надо написать:</p>
<div class="codesnip-container" >D: //и нажать «Enter»</div>
<p>После этого просто с помощью команды<strong> «copy»</strong> скопируйте в папку <strong>C:\Windows\system32</strong> (возможно с заменой).</p>
<p>Описанные выше способы могут выручить вас в тот момент, когда нет возможности перенести данные с жесткого диска, на котором слетела ось, на другой диск или нет желания <strong>«опять»</strong> переустанавливать Windows. </p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/administration/201001/%d0%b0%d0%b4%d0%bc%d0%b8%d0%bd%d0%b8%d1%81%d1%82%d1%80%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b2%d0%be%d1%81%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b7/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WinAPI: Работа с файлами (основные функции).</title>
		<link>http://zetblog.ru/programming/200902/winapi-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0-%d1%81-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0%d0%bc%d0%b8-%d0%be%d1%81%d0%bd%d0%be%d0%b2%d0%bd%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8/</link>
		<comments>http://zetblog.ru/programming/200902/winapi-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0-%d1%81-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0%d0%bc%d0%b8-%d0%be%d1%81%d0%bd%d0%be%d0%b2%d0%bd%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 23:27:55 +0000</pubDate>
		<dc:creator>C0ffe1n</dc:creator>
				<category><![CDATA[прикладное]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[системное]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[WinAPI]]></category>
		<category><![CDATA[файлы]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=227</guid>
		<description><![CDATA[Категорически всех приветствую! На этот раз в наше поле зрения попала группа API-функций для работы с файлами. Ибо, как мне кажется, помимо меня многие программисты сталкиваются с необходимостью их использования в своих программах. Но откровенно скажу в голове все эти функции вместе с их возможными параметрами и не упомнишь, а иметь возможность &#171;вспомнить все&#187; ;) [...]]]></description>
			<content:encoded><![CDATA[<p>Категорически всех приветствую! На этот раз в наше поле зрения попала группа API-функций для работы с файлами. Ибо, как мне кажется, помимо меня многие программисты сталкиваются с необходимостью их использования в своих программах. Но откровенно скажу в голове все эти функции вместе с их возможными параметрами и не упомнишь, а иметь возможность &#171;вспомнить все&#187; ;)  прочитав эту статью &#8212; очень неплохая затея. За сим и приступаю к рассмотрению оного =).<br />
<span id="more-227"></span><br />
В этой статье мы рассмотрим следующие API-функции:</p>
<ol>
<li>CreateFile</li>
<li>OpenFile</li>
<li>ReadFile</li>
<li>WriteFile</li>
<li>CloseFile</li>
<li>DeleteFile</li>
<li>CopyFile</li>
<li>FindFirstFile</li>
<li>FindNextFile</li>
<li>GetFileSize</li>
</ol>
<p><strong>Замечание</strong></p>
<p>Но прежде чем  приступить к делу, замечу для случая, когда действия над файлами происходят удаленно.  За счет реализации в ОС Windows механизма прозрачного доступа к файлам,  данные функции работают и с удаленными файлами, отличием является задание сетевого пути к файлу, а именно для С/С++ необходимо указывать путь в следующем формате:   &#171;\\\\имя_удаленного_компа\\путь_к_ файлу\\ имя_файла&#187;.<br />
<strong>Пример:</strong></p>
<pre class=".brush: cpp">
DeleteFile("\\\\comp1\\user1\\test\\test1.txt");
</pre>
<p>Для Delphi необходимо указывать путь в следующем формате:   &#171;\\имя_удаленного_компа\путь_к_ файлу\имя_файла&#187;.</p>
<p><strong>Пример:</strong></p>
<pre class=".brush: pascal">
DeleteFile('\\comp1\user1\test\test1.txt');
</pre>
<p><strong>Функция CreateFile</strong></p>
<p>Функция создаёт указатель на новое устройство типа:</p>
<ul>
<li>Файл</li>
<li>Канал</li>
<li>mailslot (почтовый канал)</li>
<li>комуникационный ресурс (например COM порт)</li>
<li>дисковые устройства (только для Windows NT)</li>
<li>консоли</li>
<li>директории (открывает их)</li>
</ul>
<p>Все эти функции описаны в одном файле. Для С/С++ в хедере (заголовочный файл) winbase.h, для Delphi в модуле windows.pas.  Чтобы использовать в своей программе эти функции, достаточно подключить их к своему проекту и вперед. Замечу для тех, кто кодит на С/С++ &#8212; кроме winbase.h надо подключить еще windows.h.</p>
<p><strong>Описание</strong>:<br />
<strong>С/С++</strong></p>
<pre class=".brush: cpp">HANDLE CreateFile(
   LPCTSTR lpFileName,        // Указатель на имя файла (устройства)
   DWORD dwDesiredAccess,  //Параметры доступа
   DWORD dwShareMode,        //Разделяемый доступ
   LPSECURITY_ATTRIBUTES lpSecurityAttributes,    //безопасность
   DWORD dwCreationDistribution,// Описание
   DWORD dwFlagsAndAttributes,     // Атрибуты файла
   HANDLE hTemplateFile      // Файл шаблона
);</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
function CreateFile(
   lpFileName: PChar;   // Указатель на имя файла (устройства)
   dwDesiredAccess,     //Параметры доступа
   dwShareMode: DWORD;  //Разделяемый доступ
   lpSecurityAttributes: PSecurityAttributes; //безопасность
   dwCreationDisposition,       // Описание
   dwFlagsAndAttributes: DWORD; // Атрибуты файла
   hTemplateFile: THandle       // Файл шаблона
): THandle; stdcall;
</pre>
<p>Теперь к главному &#8212; как создать файл? Делается это так:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
   Handle FileHandle;
   FileHandle=CreateFile("file1.txt",GENERIC_READ |
      GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_NEW,
      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);
   CloseHandle(FileHandle);
}
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
var
  FileHandle:THandle;
begin
   FileHandle:=CreateFile(PChar('file1.txt'),GENERIC_READ or
      GENERIC_WRITE, FILE_SHARE_WRITE or FILE_SHARE_READ, nil, CREATE_NEW,
      FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0);
   CloseHandle(FileHandle);
end;
</pre>
<p>Теперь расмотрим используемые параметры:</p>
<ul>
<li>параметры <strong>GENERIC_READ</strong> и      <strong>GENERIC_WRITE</strong> определяют доступ на чтение и запись. Однако, можно указать что то одно в зависимости от ваших потребностей. Если в качестве этого параметра указать 0, то в этом случае функция отработает успешно, однако никакого доступа к файлу не получит. Этот вариант удобно использовать для теста существования файла.</li>
<li>параметры <strong>FILE_SHARE_WRITE</strong> or <strong>FILE_SHARE_READ</strong> &#8212; общий доступ на чтение и запись к данному файлу. То есть файл будет доступен при одновременном использовании несколькими процессами.</li>
<li>следующий параметр &#8212; атрибут безопасности неопределен. То есть все дескрипторы будут доступны дочерним процессам вашего приложения.</li>
<li>параметр <strong>CREATE_NEW</strong> указывает на создание нового файла. Если файл с заданным именем существует, то будет возвращен код ошибки. Если использовать параметр <strong>CREATE_ALWAYS</strong>, то в этом случае, если файл существует, то он будет перезаписан.</li>
<li>параметр <strong>FILE_ATTRIBUTE_NORMAL</strong> определяет файлу стандартные атрибуты. А если указывать флаг <strong>FILE_FLAG_OVERLAPPED</strong>, то файл будет доступен в асинхронном режиме.</li>
<li>так как мы не используем шаблоны, то в качестве этого параметра указываем ноль.</li>
</ul>
<p><strong>Функция OpenFile</strong></p>
<p>Данная функция, по сути своей, предназначена для открытия файлов или устройств. Функция OpenFile в случае успеха возвращает дескриптор (указатель) открываемого файла. В случае неудачи мы получим в качестве дескриптора значение <strong>INVALID_HANDLE_VALUE</strong>.<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
 HFILE WINAPI OpenFile(
  LPCSTR lpFileName,
  LPOFSTRUCT lpReOpenBuff,
  UINT uStyle
);
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
function OpenFile(
   lpFileName: LPCSTR,   //имя файла (устройства)
   lpReOpenBuff: TOFStruct,  //специальная структура открываемого файла
   uStyle: UINT //флаги доступа к файлу
): HFILE; stdcall;
</pre>
<p>Теперь рассмотрим используемые параметры:</p>
<ul>
<li>в качестве первого параметра указывается имя открываемого файла.</li>
<li>вторым параметром является специальная структура открываемого файла, в которую заносится полезная инфа о файле.</li>
<li>3 параметр представляет собой совокупность флагов для работы с файлом.</li>
</ul>
<p>Собственно, как открыть файл:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
   Handle FileHandle;
   FileHandle= OpenFile("Settings.ini", Buf, OF_Create |
                            OF_READWRITE | OF_SHARE_EXCLUSIVE);
   CloseHandle(FileHandle);
}
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
var
  FileHandle:THandle;
begin
   FileHandle:=OpenFile(PChar('Settings.ini'), Buf, OF_Create
                     Or OF_READWRITE Or OF_SHARE_EXCLUSIVE);
   CloseHandle(FileHandle);
end;
</pre>
<p>В данном примере стоит уделить внимание флагам. Первые 2 из которых определяют доступ к файлу, а флаг <strong>OF_SHARE_EXCLUSIVE</strong> сообщает системе, что доступ к этому файлу запрещен до тех пор, пока указатель на этот файл не освободится.</p>
<p><strong>Функция ReadFile</strong></p>
<p>Данная функция предназначена для чтения файлов или с устройств ввода/вывода. В случае успешного выполнения операции  чтения, возвращается логическое значение true, иначе false. А функция <strong>GetLastError</strong> вернет <strong>ERROR_HANDLE_EOF</strong>.<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
BOOL ReadFile(HANDLE hFile, //собственно указатель на файл
         LPVOID lpBuffer,  // указатель на буфер - куда записываем считанные данные
         DWORD nNumberOfBytesToRead, //объем считываемых данных, не может превышать размер буфера
         LPDWORD lpNumberOfBytesRead, //фактический размер считанных данных
         LPOVERLAPPED lpOverlapped   // флаг режима доступа к файлу: асинхронный(<strong>FILE_FLAG_OVERLAPPED</strong>)
                                    //или синхронный(<strong>NULL</strong>)
);
</pre>
<p><strong>Delphi</strong>
<pre class=".brush: pascal">
function ReadFile(
         hFile: THandle;   //собственно указатель на файл
         var Buffer;       // указатель на буфер - куда записываем считанные данные
         nNumberOfBytesToRead: DWORD;  //объем считываемых данных, не может превышать размер буфера
         var lpNumberOfBytesRead: DWORD; //фактический размер считанных данных
         lpOverlapped: POverlapped// флаг режима доступа к файлу: асинхронный(<strong>FILE_FLAG_OVERLAPPED</strong>)
                                    //или синхронный(<strong>nil</strong>)
): BOOL; stdcall;
</pre>
<p>Теперь поглядим рабочий пример:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
Handle FileHandle;
char Buf[1000];
...
     ReadFile(FileHandle, Buf, sizeof(buf),NULL);
...
}
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
var
  FileHandle:THandle;
  Buf:array[1..1000] of char;
begin
...
   ReadFile(FileHandle, Buf, sizeof(buf),NULL);
...
end;
</pre>
<p><strong>Функция WriteFile</strong></p>
<p>Данная функция предназначена для записи в файл или устройство ввода/вывода. С ней все аналогично что и с функцией ReadFile(). В случае успешного выполнения операции  чтения, возвращается логическое значение true, иначе false. А функция <strong>GetLastError</strong> вернет <strong>ERROR_HANDLE_EOF</strong>.<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
BOOL WriteFile(HANDLE hFile, //собственно указатель на файл
         LPVOID lpBuffer,  // указатель на буфер - откуда записываем данные в  файл
         DWORD nNumberOfBytesToWrite, //объем записываемых данных
         LPDWORD lpNumberOfBytesWrite, //фактический размер записанных данных
         LPOVERLAPPED lpOverlapped   // флаг режима доступа к файлу: асинхронный(<strong>FILE_FLAG_OVERLAPPED</strong>)
                                    //или синхронный(<strong>NULL</strong>)
);
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
function WriteFile(
         hFile: THandle;   //собственно указатель на файл
         var Buffer;       // указатель на буфер - откуда записываем данные в  файл
         nNumberOfBytesToWrite: DWORD;  //объем записываемых данных
         var lpNumberOfBytesWrite: DWORD; //фактический размер записанных данных
         lpOverlapped: POverlapped// флаг режима доступа к файлу: асинхронный(<strong>FILE_FLAG_OVERLAPPED</strong>)
                                    //или синхронный(<strong>nil</strong>)
): BOOL; stdcall;
</pre>
<p>Теперь поглядим рабочий пример:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
Handle FileHandle;
char Buf[1000];
...
     ReadFile(FileHandle, Buf, sizeof(buf),NULL);
...
}
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
var
  FileHandle:THandle;
  Buf:array[1..1000] of char;
begin
...
   ReadFile(FileHandle, Buf, sizeof(buf),NULL);
...
end;
</pre>
<p><strong>Функция CloseFile</strong></p>
<p>Эта функция достаточно проста. Выполняет действия по освобождению указателя на файл. Ее необходимость очевидна &#8212; чтобы не засорять память ненужными указателями и позволять работу с файлами другим процессам. В качестве ее единственного параметра передается указатель на ранее открытый файл.</p>
<p>Теперь поглядим рабочий пример:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
   Handle FileHandle;
   FileHandle= OpenFile("Settings.ini", Buf, OF_Create |
                            OF_READWRITE | OF_SHARE_EXCLUSIVE);
...
   CloseHandle(FileHandle);
}
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
var
  FileHandle:THandle;
begin
   FileHandle:=OpenFile(PChar('Settings.ini'), Buf, OF_Create
                     Or OF_READWRITE Or OF_SHARE_EXCLUSIVE);
...
   CloseHandle(FileHandle);
end;
</pre>
<p><strong>Функция DeleteFile</strong></p>
<p>Эта функция так же не отличается особой сложностью. Данная функция удаляет файл, который указан в параметре.  Функция возвращает значение true если выполняется успешно. Иначе возвращает false, а код ошибки можно получить с помощью <strong>GetLastError</strong>.<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
BOOL WINAPI DeleteFile(
      LPCTSTR lpFileName // имя файла, который надо удалить
);
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
function DeleteFile(
      lpFileName: PChar; // имя файла, который надо удалить
 ): BOOL; stdcall;
</pre>
<p>Теперь поглядим рабочий пример:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
...
     DeleteFile("C:\Temp\test.txt");// если указать только
// имя файла, то будет осуществлена попытка удалить файл из папки, откуда была запущена программа

...
}
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
begin
...
     DeleteFile('C:\Temp\test.txt');// если указать только
// имя файла, то будет осуществлена попытка удалить файл из папки, откуда была запущена программа
...
end;
</pre>
<p><strong>Функция CopyFile</strong></p>
<p>Основное назначение этой функции &#8212; копирование файла. В случае успеха возвращает true, иначе &#8212; false. Код ошибки можно получить с помощью <strong>GetLastError</strong>.<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
BOOL CopyFile(
     LPCTSTR lpExistingFileName,// Указатель на файл, который надо копировать
     LPCTSTR lpNewFileName, // Указатель на имя файла, куда надо копировать
     BOOL bFailIfExists //если указать true, то в случае существования такого файла,
      // произойдет ошибка, если false - то существующий файл будет перезаписан.
);
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
function CopyFile(
     lpExistingFileName, // Указатель на файл, который надо копировать
     lpNewFileName: PChar; // Указатель на имя файла, куда надо копировать
     bFailIfExists: BOOL //если указать true, то в случае существования такого файла,
      // он будет перезаписан, если false - то произойдет ошибка.
): BOOL; stdcall;
</pre>
<p>Теперь поглядим рабочий пример:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
...
     CopyFile("C:\Temp\test1.txt","C:\Temp\test2.txt", true); // если указать только
// имя файла, то все действия будут выполнены в папке из которой запущена прога
...
}
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
begin
...
     CopyFile('C:\Temp\test1.txt','C:\Temp\test2.txt', false);// если указать только
// имя файла, то все действия будут выполнены в папке из которой запущена прога...
end;
</pre>
<p><strong>Функция FindFirstFile</strong></p>
<p>Данная функция запускает поиск в указанной директории. Функция возвращает указатель на найденный файл, если нет, то возврат будет типа ERROR_NO_MORE_FILES.<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
HANDLE FindFirstFile(
    LPCTSTR lpFileName,	// Строка, содержащая путь для поиска файлов.
    LPWIN32_FIND_DATA lpFindFileData // Информация о найденном файле
);
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
function FindFirstFile(
   lpFileName: PChar; // Строка, содержащая путь для поиска файлов.
   var lpFindFileData: TWIN32FindData // Информация о найденном файле
): THandle; stdcall;
</pre>
<p>Теперь рассмотрим параметры подробней:</p>
<ul>
<li> lpFileName &#8212; строка, содержащая путь для поиска файла. Эта строка может указывать наконкретный файл типа &#8216;c:\filename.txt&#8217; или может хранить шаблон &#8216;c:\*.*&#8217;. Если указывать шаблон, то это даёт возможность перечислить все файлы удовлетворяющие шаблону.</li>
</ul>
<ul>
<li> lpFindFileData &#8212; структура WIN32_FIND_DATA, в которую будет записана инфа о найденом файле.</li>
</ul>
<p>Расмотрим структуру WIN32_FIND_DATA немного подробнее:</p>
<pre class=".brush: cpp">
typedef struct _WIN32_FIND_DATA {
          DWORD dwFileAttributes;  // Атрибуты файла
          FILETIME ftCreationTime; // Время создания
          FILETIME ftLastAccessTime;  //Время последнего доступа
          FILETIME ftLastWriteTime;   //Время последней записи в файл
          DWORD    nFileSizeHigh;     //Верхний байт размера файла
          DWORD    nFileSizeLow;      //Нижний байт размера файла
          DWORD    dwReserved0;       //Зарезервировано
          DWORD    dwReserved1;       //Зарезервировано
          TCHAR    cFileName[ MAX_PATH ];    //Имя файла
          TCHAR    cAlternateFileName[ 14 ]; //Имя файла для отображения в DOS (8:3)
} WIN32_FIND_DATA;
</pre>
<p>Атрибутами файла может быть комбинация из флагов:</p>
<ul>
<li>FILE_ATTRIBUTE_ARCHIVE &#8212; архивный</li>
</ul>
<ul>
<li> FILE_ATTRIBUTE_COMPRESSED &#8212; сжатый</li>
</ul>
<ul>
<li> FILE_ATTRIBUTE_HIDDEN &#8212; скрытый</li>
</ul>
<ul>
<li> FILE_ATTRIBUTE_NORMAL &#8212; нормальный</li>
</ul>
<ul>
<li> FILE_ATTRIBUTE_OFFLINE &#8212; данные файла недоступны</li>
</ul>
<ul>
<li> FILE_ATTRIBUTE_READONLY &#8212; только для чтения</li>
</ul>
<ul>
<li> FILE_ATTRIBUTE_SYSTEM &#8212; системный</li>
</ul>
<ul>
<li> FILE_ATTRIBUTE_TEMPORARY &#8212; временный</li>
</ul>
<p>Размер файла разложен на два байта. Чтоб получить полный размер файла нужно выполнить действие (FInfo.nFileSizeHigh * MAXDWORD) + FInfo.nFileSizeLow. Это не самый эффективный (эффективнее сдвигать), но самый понятный способ.</p>
<p>Теперь поглядим рабочий пример:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
   WIN32_FIND_DATA sss;
   HANDLE f;
   f = FindFirstFile("C:\*.*", &amp;sss);
...
   FindClose(f);
}
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
var
  sss: TWIN32FindData;
  f:THandle;
begin
...
  f:=FindFirstFile(PChar('C:\*.*'), sss);
...
  Windows.FindClose(f);
end;
</pre>
<p><strong>Функция FindNextFile</strong></p>
<p>Данная функция продолжает поиск начатый функцией FindFirstFile(). Если очередной файл найден, то функция возвращает значение true, иначе  возврат будет типа ERROR_NO_MORE_FILES.<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
BOOL FindNextFile(
    HANDLE hFindFile,	// Указатель на файл из предыдущего поиска
    LPWIN32_FIND_DATA lpFindFileData // Информация об очередном найденном файле
);
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
function FindNextFile(
    hFindFile: THandle; // Указатель на файл из предыдущего поиска
    var lpFindFileData: TWIN32FindData // Информация об очередном найденном файле
): BOOL; stdcall;
</pre>
<p>Со вторым параметром всё ясно, из описания функции FindFirstFile. А вот первый &#8212; это указатель на файл из предыдущего поиска. Он нужен, чтобы функция FindNextFile знала на каком файле был остановлен поиск и какой надо найти следующим.</p>
<p>Теперь поглядим рабочий пример:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
   WIN32_FIND_DATA sss;
   HANDLE f;
   f = FindFirstFile("C:\*.*", &amp;sss);
   if(f != INVALID_HANDLE_VALUE)
      do{
         ...
      }while(FindNextFile(f,&amp;sss));
   FindClose(f);
}
</pre>
<p>А теперь пример рекурсивного поиска файлов:<br />
<strong>Delphi</strong></p>
<pre class=".brush: pascal">
function find(put: string):integer;
var
  sss: TWIN32FindData;
  f:THandle;
  result:Boolean;
begin
...
  f:=FindFirstFile(PChar('C:\*.*'), sss);
  if f&lt;&gt;INVALID_HANDLE_VALUE then
  begin
    result:=true;
    while(result)do
    begin
      if not((sss.cFileName = '.')or(sss.cFileName = '..')) then
        if (sss.dwFileAttributes and faDirectory) &gt; 0  then
          find(put+'\'+sss.cFileName)
        else
          writeln(sss.cFileName);
       ...
      result:=FindNextFile(f,sss);
    end;
  end;
  Windows.FindClose(f);
end;
</pre>
<p><strong>Функция GetFileSize</strong></p>
<p>Данная функция определяет размер файла, на который ссылается переданный указатель. Если размер файла меньше 4 Гб, то функция возвращает размер файла. Если размер файла больше 4Гб, то размер файла записан во втором параметре. В случае возникновения исключения будет возвращено значение типа INVALID_FILE_SIZE.<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
DWORD GetFileSize(
   HANDLE hFile,	   // Указатель на файл
   LPDWORD lpFileSizeHigh // старший байт размера файла, в качестве
            // этого парамметра можно указать <strong>NULL</strong>
);
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
function GetFileSize(
    hFile: THandle;         // Указатель на файл
    lpFileSizeHigh: Pointer //старший байт размера файла, в качестве
             // этого парамметра можно указать <strong>nil</strong>
): DWORD; stdcall;
</pre>
<p>Теперь поглядим рабочий пример:<br />
<strong>C/C++</strong></p>
<pre class=".brush: cpp">
{
DWORD FileSize;
Handle f;
...
FileSize=GetFileSize(f,NULL);
...
}
</pre>
<p><strong>Delphi</strong></p>
<pre class=".brush: pascal">
var
  FileSize:DWORD;
  f:THandle;
begin
  ...
  FileSize:=GetFileSize(f,nil);
  ...
end
</pre>
<p>На этом пока все, если вдруг возникли какие нибуть вопросы или замечания, прошу их высказывать на <a href="/forum/">форуме</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200902/winapi-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0-%d1%81-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0%d0%bc%d0%b8-%d0%be%d1%81%d0%bd%d0%be%d0%b2%d0%bd%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Безопасность: Инспектор файлов.</title>
		<link>http://zetblog.ru/programming/200902/%d0%b1%d0%b5%d0%b7%d0%be%d0%bf%d0%b0%d1%81%d0%bd%d0%be%d1%81%d1%82%d1%8c-%d0%b8%d0%bd%d1%81%d0%bf%d0%b5%d0%ba%d1%82%d0%be%d1%80-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2/</link>
		<comments>http://zetblog.ru/programming/200902/%d0%b1%d0%b5%d0%b7%d0%be%d0%bf%d0%b0%d1%81%d0%bd%d0%be%d1%81%d1%82%d1%8c-%d0%b8%d0%bd%d1%81%d0%bf%d0%b5%d0%ba%d1%82%d0%be%d1%80-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 13:54:11 +0000</pubDate>
		<dc:creator>C0ffe1n</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[системное]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[файлы]]></category>

		<guid isPermaLink="false">http://zetblog.ru/?p=509</guid>
		<description><![CDATA[В этой статье мы немного углубимся в дебри компьютерной безопасности. И на повестке дня повис вопрос, как вы уже догадались &#8212; &#171;Инспектор файлов&#187;. Что это и для чего он нужен я расскажу по мере чтения вами этой статьи, но замечу сразу, что испокон веков компьютерной эры, с тех самых времен, когда операционная система содрогнулась от [...]]]></description>
			<content:encoded><![CDATA[<p>В этой статье мы немного углубимся в дебри компьютерной безопасности. И на повестке дня повис вопрос, как вы уже догадались &#8212; &#171;Инспектор файлов&#187;. Что это и для чего он нужен я расскажу по мере чтения вами этой статьи, но замечу сразу, что испокон веков компьютерной эры, с тех самых времен, когда операционная система содрогнулась от вирусной эпидемии, на стражу ваших и системных файлов встал гроза контроля и целостности &#8212; &#171;Инспектор&#187;. Прошу прощение за эпическое отступление ;).<br />
<span id="more-509"></span><br />
Так вот, помимо установленных антивирусов и прочих специальных программ, которые выполняют кучу всяких полезностей, порой даже абсолютно не нужных в данный момент и только лишь отнимают наше драгоценное время. А мы то знаем, что время &#8212; деньги!<br />
Что же меня побудило написать статью на эту тему? Во-первых, я считаю, и вам даю на заметку, что пользоваться готовым софтом &#8212; это утеха юзеров и прочих бездельников. Каждый уважающий себя программист должен иметь в своем арсенале собственноручно написанный инструментарий отвечающий его задачам и требованием, и не одной команды лишней. Да и кроме того вы сами знаете, что делает ваша программа, и в любой момент можете вспороть ее и что то подправить, добавить или удалить, в отличие от чужих программулек. Во-вторых, зная, а кто не знал запомните, что ни один антивирус не может вас защитить на 100% от свеженькой вредоносной информационной субстанции, то бишь вирус и прочая нечисть, так как антивирусная индустрия всегда позади на шаг впереди идущих создателей этой дряни. Поэтому вашу безопасность можете обеспечить только вы сами и одним из средств обеспечения в этом деле является &#171;Инспектор файлов&#187;, который непоколебимо несет свою службу на полях информационного пространства и &#171;своих&#187; знает в &#171;лицо&#187;.</p>
<p>После недолгих эпических отступлений, вы уж простите меня, без лишних слов приступаем к реализации нашего стражника &#171;Инспектора&#187;. В первую очередь нам необходимо поставить задачу. Ей будет:<br />
- реализовать поиск файлов<br />
- проверку файлов на наличие их в банке данных, по соответствующим признакам(путь к файлу, дата создания, изменения и контрольная сумма)<br />
- добавление в новых кандидатов на прописку в банк данных<br />
- реализация интерфейса, связывающего предыдущие описанные задачи и действия пользователя.</p>
<p>В целом, получается вот такое тех. задание. А теперь от слов к делу. Для начала определимся с дизайном формы. Здесь я полагаюсь на ваш вкус, но потребуется нам две кнопки и поле вывода информации(Memo или ListBox).<br />
Однуиз кнопок определим под выбор папки &#8212; &#171;Обзор&#187;, и для нее напишем следующий код</p>
<pre><strong>Delphi</strong>
<div class="codesnip-container" >
<div class="pascal codesnip" style="font-family:monospace;"><span class="kw1">procedure</span> TForm1.<span class="me1">Button1Click</span><span class="br0">&#40;</span>Sender<span class="sy0">:</span> TObject<span class="br0">&#41;</span>;
<span class="kw1">begin</span>
&nbsp; Path <span class="sy0">:=</span> GetPath<span class="br0">&#40;</span><span class="st_h">'Выберите папку'</span><span class="br0">&#41;</span>;
&nbsp; <span class="kw1">if</span> Path &amp;lt;&amp;gt; <span class="st_h">''</span>
&nbsp; &nbsp; &nbsp;<span class="kw1">then</span> Label4.<span class="me1">Caption</span> <span class="sy0">:=</span> Path;
<span class="kw1">end</span>;</div>
</div>
</pre>
<p>А теперь опишем используемую функцию GetPath():</p>
<pre><strong>Delphi</strong>
<div class="codesnip-container" >
<div class="pascal codesnip" style="font-family:monospace;"><span class="kw1">function</span> GetPath<span class="br0">&#40;</span>mes<span class="sy0">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy0">:</span><span class="kw4">string</span>;
<span class="kw1">var</span>
&nbsp; Root<span class="sy0">:</span> <span class="kw4">string</span>; &nbsp; &nbsp; &nbsp;<span class="co1">// корневой каталог</span>
&nbsp; pwRoot <span class="sy0">:</span> PWideChar;
&nbsp; Dir<span class="sy0">:</span> <span class="kw4">string</span>;
<span class="kw1">begin</span>
&nbsp; Root <span class="sy0">:=</span> <span class="st_h">''</span>; <span class="co1">// по умолчанию корневой каталог - рабочий стол</span>
&nbsp; GetMem<span class="br0">&#40;</span>pwRoot<span class="sy0">,</span> <span class="br0">&#40;</span>Length<span class="br0">&#40;</span>Root<span class="br0">&#41;</span><span class="sy0">+</span>1<span class="br0">&#41;</span> <span class="sy0">*</span> 2<span class="br0">&#41;</span>;
&nbsp; pwRoot <span class="sy0">:=</span> StringToWideChar<span class="br0">&#40;</span>Root<span class="sy0">,</span>pwRoot<span class="sy0">,</span>MAX_PATH<span class="sy0">*</span>2<span class="br0">&#41;</span>;
&nbsp; <span class="kw1">if</span> SelectDirectory<span class="br0">&#40;</span>mes<span class="sy0">,</span> pwRoot<span class="sy0">,</span> Dir<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp;<span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> length<span class="br0">&#40;</span>Dir<span class="br0">&#41;</span> <span class="sy0">=</span> <span class="nu0">2</span> &nbsp;<span class="co1">// пользователь выбрал корневой каталог</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">then</span> GetPath <span class="sy0">:=</span> Dir<span class="sy0">+</span><span class="st_h">'\'</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> GetPath <span class="sy0">:=</span> Dir
&nbsp; &nbsp; &nbsp;<span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GetPath <span class="sy0">:=</span> <span class="st_h">''</span>;
<span class="kw1">end</span>;</div>
</div>
</pre>
<p>Итак, процедура выбора каталога для проверки реализована. Теперь приступим к реализации проверки файлов. Но сначала для второй кнопки опишем следующий код:</p>
<pre><strong>Delphi</strong>
<div class="codesnip-container" >
<div class="pascal codesnip" style="font-family:monospace;"><span class="kw1">procedure</span> TForm1.<span class="me1">Button2Click</span><span class="br0">&#40;</span>Sender<span class="sy0">:</span> TObject<span class="br0">&#41;</span>;
<span class="kw1">begin</span>
&nbsp; Form1.<span class="me1">ListBox1</span>.<span class="me1">Items</span>.<span class="me1">Add</span><span class="br0">&#40;</span>TimeToStr<span class="br0">&#40;</span>Time<span class="br0">&#41;</span><span class="sy0">+</span><span class="st_h">' :&amp;gt; Сканирование началось.'</span><span class="br0">&#41;</span>;
&nbsp; ListFiles.<span class="me1">Clear</span>;
&nbsp; FindF<span class="br0">&#40;</span>Path<span class="br0">&#41;</span>;
&nbsp; Scan_File;
&nbsp; Form1.<span class="me1">ListBox1</span>.<span class="me1">Items</span>.<span class="me1">Add</span><span class="br0">&#40;</span><span class="st_h">'==================================================='</span><span class="br0">&#41;</span>;
&nbsp; Form1.<span class="me1">ListBox1</span>.<span class="me1">Items</span>.<span class="me1">Add</span><span class="br0">&#40;</span>TimeToStr<span class="br0">&#40;</span>Time<span class="br0">&#41;</span><span class="sy0">+</span><span class="st_h">' :&amp;gt; Сканирование завершено.'</span><span class="br0">&#41;</span>;
<span class="kw1">end</span>;</div>
</div>
</pre>
<p>А теперь последовательно опишем используемые функции и первой будет процедура FindF(). Эта процедура осуществляет рекурсивный поиск файлов относительно выбранного корневого каталога и добавляет их в список для проверки. Смотрим листинг:</p>
<pre><strong>Delphi</strong>
<div class="codesnip-container" >
<div class="pascal codesnip" style="font-family:monospace;"><span class="kw1">procedure</span> FindF<span class="br0">&#40;</span>path_f<span class="sy0">:</span><span class="kw4">string</span><span class="br0">&#41;</span>;
<span class="kw1">begin</span>
<span class="co1">//Инициируем поиск</span>
&nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>FindFirst<span class="br0">&#40;</span>path_f<span class="sy0">+</span><span class="st_h">'\*.*'</span><span class="sy0">,</span>faAnyFile<span class="sy0">,</span>SearchRec<span class="br0">&#41;</span> <span class="sy0">=</span> 0<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; <span class="kw1">repeat</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span><span class="br0">&#40;</span><span class="br0">&#40;</span>SearchRec.<span class="kw1">name</span> <span class="sy0">=</span> <span class="st_h">'.'</span><span class="br0">&#41;</span><span class="kw1">or</span><span class="br0">&#40;</span>SearchRec.<span class="kw1">name</span> <span class="sy0">=</span> <span class="st_h">'..'</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> SearchRec.<span class="me1">Attr</span> &amp;lt;&amp;gt; faDirectory <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ListFiles.<span class="me1">Add</span><span class="br0">&#40;</span>path_f<span class="sy0">+</span><span class="st_h">'\'</span><span class="sy0">+</span>SearchRec.<span class="kw1">Name</span><span class="br0">&#41;</span>; <span class="co1">//если файл, добавляем в список</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Inc<span class="br0">&#40;</span>Count_file<span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FindF<span class="br0">&#40;</span>path_f<span class="sy0">+</span><span class="st_h">'\'</span><span class="sy0">+</span>SearchRec.<span class="kw1">Name</span><span class="br0">&#41;</span>; <span class="co1">//если папка, запускаем рекурсию</span>

&nbsp; &nbsp; &nbsp; <span class="kw1">end</span>;
&nbsp; &nbsp; <span class="kw1">until</span> <span class="br0">&#40;</span>FindNext<span class="br0">&#40;</span>SearchRec<span class="br0">&#41;</span>&amp;lt;&amp;gt;0<span class="br0">&#41;</span>;
&nbsp; &nbsp; FindClose<span class="br0">&#40;</span>SearchRec<span class="br0">&#41;</span>;
&nbsp; <span class="kw1">end</span>;
<span class="kw1">end</span>;</div>
</div>
</pre>
<p>Далее рассмотрим процедуру Scan_File(). Ее задача проверить каждый найденный файл на наличие в своей базе данных, сверить контрольную сумму, дату создания и дату последнего изменения файла. В случае если будут обнаружены какие-либо несоответсвия, немедля бьет тревогу. Смотрим:</p>
<pre><strong>Delphi</strong>
<div class="codesnip-container" >
<div class="pascal codesnip" style="font-family:monospace;"><span class="kw1">procedure</span> Scan_File;
<span class="kw1">var</span>
&nbsp; crc32T<span class="sy0">,</span>dataCT<span class="sy0">,</span>dataMT<span class="sy0">:</span>Cardinal;
&nbsp; i<span class="sy0">:</span><span class="kw4">integer</span>;
&nbsp; f<span class="sy0">:</span> THandle;
&nbsp; SearchF<span class="sy0">:</span>TWIN32FindData;
&nbsp; temp<span class="sy0">:</span><span class="kw4">boolean</span>;
<span class="kw1">begin</span>
&nbsp; i<span class="sy0">:=</span><span class="nu0">0</span>;
<span class="co1">//проверка на первый запуск, а точнее была база только что создана или нет.</span>
&nbsp; <span class="kw1">if</span> newBase <span class="sy0">=</span> <span class="kw2">true</span> <span class="kw1">then</span>
&nbsp; <span class="co1">//если да, то заносим список найденых файлов с их</span>
&nbsp; <span class="co1">//параметрами(путь, контрольная сумма, дата создания, дата изменения) в базу</span>
&nbsp; &nbsp; <span class="kw1">while</span> i &amp;lt;<span class="sy0">=</span> Count_file<span class="sy0">-</span>1 <span class="kw1">do</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; WriteIB<span class="br0">&#40;</span>ListFiles.<span class="me1">Strings</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; Inc<span class="br0">&#40;</span>i<span class="br0">&#41;</span>;
&nbsp; &nbsp; <span class="kw1">end</span>;
<span class="co1">//далее производим проверку</span>
&nbsp; i<span class="sy0">:=</span><span class="nu0">0</span>;
&nbsp; <span class="kw1">while</span> i &amp;lt;<span class="sy0">=</span> Count_file<span class="sy0">-</span>1 <span class="kw1">do</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//проверяем наличие файла</span>
&nbsp; &nbsp; &nbsp; FS<span class="sy0">:=</span>TFileStream.<span class="me1">Create</span><span class="br0">&#40;</span>ListFiles.<span class="me1">Strings</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">,</span>fmOpenRead <span class="kw1">or</span> fmShareDenyNone<span class="br0">&#41;</span>;
&nbsp; &nbsp; <span class="kw1">except</span>
&nbsp; &nbsp; &nbsp; on Exception <span class="kw1">do</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; Form1.<span class="me1">ListBox1</span>.<span class="me1">Items</span>.<span class="me1">Add</span><span class="br0">&#40;</span><span class="st_h">'не открывается '</span><span class="sy0">+</span>ListFiles.<span class="me1">Strings</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span>;
&nbsp; &nbsp; <span class="kw1">end</span>;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//Вычисляем контрольную сумму</span>
&nbsp; &nbsp; crc32T<span class="sy0">:=</span>CRC32Stream<span class="br0">&#40;</span>FS<span class="sy0">,</span>0<span class="br0">&#41;</span>;
&nbsp; &nbsp; FS.<span class="me1">Free</span>;
&nbsp; &nbsp; f<span class="sy0">:=</span>FindFirstFile<span class="br0">&#40;</span>PChar<span class="br0">&#40;</span>ListFiles.<span class="me1">Strings</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">,</span>SearchF<span class="br0">&#41;</span>;
&nbsp; &nbsp; <span class="kw1">if</span> f &amp;lt;&amp;gt; INVALID_HANDLE_VALUE <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//определяем дату создания и дату изменения файла</span>
&nbsp; &nbsp; &nbsp; dataCT<span class="sy0">:=</span>SearchF.<span class="me1">ftCreationTime</span>.<span class="me1">dwLowDateTime</span>;
&nbsp; &nbsp; &nbsp; dataMT<span class="sy0">:=</span>SearchF.<span class="me1">ftLastWriteTime</span>.<span class="me1">dwLowDateTime</span>;
&nbsp; &nbsp; <span class="kw1">end</span>;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//запускаем процедуру поиска файла с найденными параметрами</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//по базе</span>
&nbsp; &nbsp; temp<span class="sy0">:=</span>FindIB<span class="br0">&#40;</span>ListFiles.<span class="me1">Strings</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">,</span>crc32T<span class="sy0">,</span>dataCT<span class="sy0">,</span>dataMT<span class="br0">&#41;</span>;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">Not</span> temp <span class="kw3">and</span> <span class="br0">&#40;</span>FindFlagB<span class="sy0">=</span>0<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//если файл отсутсвует то выводим тревожное сообщение</span>
&nbsp; &nbsp; &nbsp; Form1.<span class="me1">ListBox1</span>.<span class="me1">Items</span>.<span class="me1">Add</span><span class="br0">&#40;</span><span class="st_h">'ВНИМАНИЕ! Данный файл в базе отсутствует: '</span><span class="sy0">+</span>ListFiles.<span class="me1">Strings</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; <span class="kw1">end</span>;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//Если файл в наличии то выводим результат проверки</span>
&nbsp; &nbsp; <span class="kw1">if</span> temp <span class="kw3">and</span> <span class="br0">&#40;</span>FindFlagB<span class="sy0">=</span>1<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; Form1.<span class="me1">ListBox1</span>.<span class="me1">Items</span>.<span class="me1">Add</span><span class="br0">&#40;</span>ListFiles.<span class="me1">Strings</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">+</span><span class="st_h">' - файл проверен. ОК.'</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">not</span> temp<span class="br0">&#41;</span> <span class="kw3">and</span> <span class="br0">&#40;</span>FindFlagB<span class="sy0">=</span>1<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; Form1.<span class="me1">ListBox1</span>.<span class="me1">Items</span>.<span class="me1">Add</span><span class="br0">&#40;</span>ListFiles.<span class="me1">Strings</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">+</span><span class="st_h">' - файл был изменен.'</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; Inc<span class="br0">&#40;</span>i<span class="br0">&#41;</span>;
&nbsp; &nbsp; Form1.<span class="me1">Update</span>;
&nbsp; <span class="kw1">end</span>;
<span class="kw1">end</span>;</div>
</div>
</pre>
<p>Далее опишем функции для работы с базой. И первая функция FindIB(). Она осуществляет проверку наличия интересующего файла в базе и сверку переданных параметров искомого файла с теми, что соответствуют ему.</p>
<pre><strong>Delphi</strong>
<div class="codesnip-container" >
<div class="pascal codesnip" style="font-family:monospace;"><span class="kw1">function</span> FindIB<span class="br0">&#40;</span>strS<span class="sy0">:</span><span class="kw4">string</span>;crc32<span class="sy0">,</span>dataC<span class="sy0">,</span>dataM<span class="sy0">:</span>Cardinal<span class="br0">&#41;</span><span class="sy0">:</span><span class="kw4">Boolean</span>;
<span class="kw1">var</span>
&nbsp; fileS<span class="sy0">:</span>TextFile;
&nbsp; nameD<span class="sy0">,</span>fn<span class="sy0">:</span><span class="kw4">string</span>;
&nbsp; crc32D<span class="sy0">,</span>dataCD<span class="sy0">,</span>dataMD<span class="sy0">:</span>Cardinal;
&nbsp; i<span class="sy0">,</span>it<span class="sy0">:</span><span class="kw4">integer</span>;
<span class="kw1">begin</span>
&nbsp; FindFlagB<span class="sy0">:=</span><span class="nu0">0</span>;
&nbsp; AssignFile<span class="br0">&#40;</span>fileS<span class="sy0">,</span><span class="st_h">'IFdb.db'</span><span class="br0">&#41;</span>;
&nbsp; Reset<span class="br0">&#40;</span>fileS<span class="br0">&#41;</span>;
&nbsp; <span class="kw1">While</span> <span class="kw1">Not</span> <span class="kw3">EOF</span><span class="br0">&#40;</span>fileS<span class="br0">&#41;</span> <span class="kw1">do</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; <span class="co1">//считываем данные из базы</span>
&nbsp; &nbsp; <span class="kw3">ReadLn</span><span class="br0">&#40;</span>fileS<span class="sy0">,</span>nameD<span class="br0">&#41;</span>;
&nbsp; <span class="co1">// получаем имя файла</span>
&nbsp; &nbsp; it<span class="sy0">:=</span>Pos<span class="br0">&#40;</span><span class="st_h">'$'</span><span class="sy0">,</span>nameD<span class="br0">&#41;</span>;
&nbsp; &nbsp; fn<span class="sy0">:=</span>copy<span class="br0">&#40;</span>nameD<span class="sy0">,</span>1<span class="sy0">,</span>it<span class="sy0">-</span>1<span class="br0">&#41;</span>;
&nbsp; &nbsp; Delete<span class="br0">&#40;</span>nameD<span class="sy0">,</span>1<span class="sy0">,</span>it<span class="br0">&#41;</span>;
&nbsp; <span class="co1">//получаем контрольную сумму</span>
&nbsp; &nbsp; it<span class="sy0">:=</span>Pos<span class="br0">&#40;</span><span class="st_h">'$'</span><span class="sy0">,</span>nameD<span class="br0">&#41;</span>;
&nbsp; &nbsp; crc32D<span class="sy0">:=</span>StrToInt64<span class="br0">&#40;</span>copy<span class="br0">&#40;</span>nameD<span class="sy0">,</span>1<span class="sy0">,</span>it<span class="sy0">-</span>1<span class="br0">&#41;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; Delete<span class="br0">&#40;</span>nameD<span class="sy0">,</span>1<span class="sy0">,</span>it<span class="br0">&#41;</span>;
&nbsp; <span class="co1">//получаем дату создания файла</span>
&nbsp; &nbsp; it<span class="sy0">:=</span>Pos<span class="br0">&#40;</span><span class="st_h">'$'</span><span class="sy0">,</span>nameD<span class="br0">&#41;</span>;
&nbsp; &nbsp; dataCD<span class="sy0">:=</span>StrToInt64<span class="br0">&#40;</span>copy<span class="br0">&#40;</span>nameD<span class="sy0">,</span>1<span class="sy0">,</span>it<span class="sy0">-</span>1<span class="br0">&#41;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; Delete<span class="br0">&#40;</span>nameD<span class="sy0">,</span>1<span class="sy0">,</span>it<span class="br0">&#41;</span>;
&nbsp; <span class="co1">//получаем дату последнего изменения</span>
&nbsp; &nbsp; dataMD<span class="sy0">:=</span>StrToInt64<span class="br0">&#40;</span>copy<span class="br0">&#40;</span>nameD<span class="sy0">,</span>1<span class="sy0">,</span>length<span class="br0">&#40;</span>nameD<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; <span class="kw1">if</span> strS <span class="sy0">=</span> fn <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; FindFlagB<span class="sy0">:=</span><span class="nu0">1</span>;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> crc32 <span class="sy0">=</span> crc32D <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> dataC <span class="sy0">=</span> dataCD <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> dataM <span class="sy0">=</span> dataMD <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FindIB<span class="sy0">:=</span><span class="kw2">true</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CloseFile<span class="br0">&#40;</span>fileS<span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exit;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span>;
&nbsp; &nbsp; <span class="kw1">end</span>;
&nbsp; <span class="kw1">end</span>;
&nbsp; FindIB<span class="sy0">:=</span><span class="kw2">false</span>;
&nbsp; CloseFile<span class="br0">&#40;</span>fileS<span class="br0">&#41;</span>;
<span class="kw1">end</span>;</div>
</div>
</pre>
<p>Теперь рассмотрим функцию WriteIB(). Которая заносит в базу путь к файлу, его контрольную сумму, дату создания и дату последнего изменения.</p>
<pre><strong>Delphi</strong>
<div class="codesnip-container" >
<div class="pascal codesnip" style="font-family:monospace;"><span class="kw1">procedure</span> WriteIB<span class="br0">&#40;</span><span class="kw1">name</span><span class="sy0">:</span><span class="kw4">string</span><span class="br0">&#41;</span>;
<span class="kw1">var</span>
&nbsp; dbf<span class="sy0">:</span>TextFile;
&nbsp; i<span class="sy0">:</span>Cardinal;
&nbsp; s<span class="sy0">:</span><span class="kw4">string</span>;
&nbsp; f<span class="sy0">:</span> THandle;
&nbsp; SearchF<span class="sy0">:</span>TWIN32FindData;
<span class="kw1">begin</span>
<span class="co1">//открываем базу</span>
&nbsp; AssignFile<span class="br0">&#40;</span>dbf<span class="sy0">,</span><span class="st_h">'IFdb.db'</span><span class="br0">&#41;</span>;
&nbsp; Append<span class="br0">&#40;</span>dbf<span class="br0">&#41;</span>;
&nbsp; <span class="co1">//инициализируем переменные</span>
&nbsp; s<span class="sy0">:=</span><span class="kw1">name</span><span class="sy0">+</span><span class="st_h">'$'</span>;
&nbsp; <span class="kw1">try</span>
&nbsp; <span class="co1">//проверяем наличие добавляемого файла</span>
&nbsp; &nbsp; FS<span class="sy0">:=</span>TFileStream.<span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">name</span><span class="sy0">,</span>fmOpenRead <span class="kw1">or</span> fmShareDenyNone<span class="br0">&#41;</span>;
&nbsp; <span class="kw1">except</span>
&nbsp; &nbsp; on Exception <span class="kw1">do</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; Form1.<span class="me1">ListBox1</span>.<span class="me1">Items</span>.<span class="me1">Add</span><span class="br0">&#40;</span><span class="st_h">'не открывается '</span><span class="sy0">+</span><span class="kw1">name</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; exit;
&nbsp; &nbsp; <span class="kw1">end</span>;
&nbsp; <span class="kw1">end</span>;
&nbsp; <span class="co1">//вычисляем контрольную сумму</span>
&nbsp; i<span class="sy0">:=</span>CRC32Stream<span class="br0">&#40;</span>FS<span class="sy0">,</span>0<span class="br0">&#41;</span>;
&nbsp; s<span class="sy0">:=</span>s<span class="sy0">+</span>IntToStr<span class="br0">&#40;</span>i<span class="br0">&#41;</span>;
&nbsp; f<span class="sy0">:=</span>FindFirstFile<span class="br0">&#40;</span>PChar<span class="br0">&#40;</span><span class="kw1">name</span><span class="br0">&#41;</span><span class="sy0">,</span>SearchF<span class="br0">&#41;</span>;
&nbsp; <span class="kw1">if</span> f &amp;lt;&amp;gt; INVALID_HANDLE_VALUE <span class="kw1">then</span>
&nbsp; &nbsp;<span class="co1">//определяем дату создания и дату изменения файла s:=s+'$'+IntToStr(SearchF.ftCreationTime.dwLowDateTime)+'$'+IntToStr(SearchF.ftLastWriteTime.dwLowDateTime);</span>
&nbsp; <span class="kw3">writeln</span><span class="br0">&#40;</span>dbf<span class="sy0">,</span>s<span class="br0">&#41;</span>;
&nbsp; CloseFile<span class="br0">&#40;</span>dbf<span class="br0">&#41;</span>;
&nbsp; FS.<span class="me1">Free</span>;
<span class="kw1">end</span>;</div>
</div>
</pre>
<p>Далее надо объявить необходимые глобальные переменные:</p>
<pre><strong>Delphi</strong>
<div class="codesnip-container" >
<div class="pascal codesnip" style="font-family:monospace;"><span class="kw1">var</span>
&nbsp; SearchRec<span class="sy0">:</span> TSearchRec;
&nbsp; Count_file<span class="sy0">,</span>FindFlagB<span class="sy0">,</span>step<span class="sy0">:</span> <span class="kw4">integer</span>;
&nbsp; Path<span class="sy0">:</span> <span class="kw4">string</span>;
&nbsp; ListFiles<span class="sy0">:</span> TStrings;
&nbsp; FS<span class="sy0">:</span>TFileStream;
&nbsp; newBase<span class="sy0">:</span><span class="kw4">boolean</span>;</div>
</div>
</pre>
<p>Теперь необходимо для события onCreate написать следующее:</p>
<pre><strong>Delphi</strong>
<div class="codesnip-container" >
<div class="pascal codesnip" style="font-family:monospace;"><span class="kw1">procedure</span> TForm1.<span class="me1">FormCreate</span><span class="br0">&#40;</span>Sender<span class="sy0">:</span> TObject<span class="br0">&#41;</span>;
<span class="kw1">var</span>
&nbsp; f<span class="sy0">:</span> THandle;
&nbsp; SearchF<span class="sy0">:</span>TWIN32FindData;
<span class="kw1">begin</span>
&nbsp; SendMessage<span class="br0">&#40;</span>ListBox1.<span class="me1">Handle</span><span class="sy0">,</span>LB_SetHorizontalExtent<span class="sy0">,</span>1000<span class="sy0">,</span>0<span class="br0">&#41;</span>;
&nbsp; newBase<span class="sy0">:=</span> <span class="kw2">false</span>;
&nbsp; ListFiles<span class="sy0">:=</span>TStringList.<span class="me1">Create</span>;
&nbsp; Path<span class="sy0">:=</span><span class="st_h">'*.*'</span>;
&nbsp; f<span class="sy0">:=</span>FindFirstFile<span class="br0">&#40;</span><span class="st_h">'IFdb.db'</span><span class="sy0">,</span>SearchF<span class="br0">&#41;</span>;
&nbsp; <span class="kw1">if</span> f <span class="sy0">=</span> INVALID_HANDLE_VALUE <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; f<span class="sy0">:=</span>CreateFile<span class="br0">&#40;</span><span class="st_h">'IFdb.db'</span><span class="sy0">,</span> GENERIC_READ <span class="kw1">or</span> GENERIC_WRITE<span class="sy0">,</span> FILE_SHARE_WRITE <span class="kw1">or</span> FILE_SHARE_READ<span class="sy0">,</span> <span class="kw2">nil</span><span class="sy0">,</span> CREATE_NEW<span class="sy0">,</span> FILE_ATTRIBUTE_NORMAL <span class="kw1">or</span> FILE_FLAG_OVERLAPPED<span class="sy0">,</span> 0<span class="br0">&#41;</span>;
&nbsp; &nbsp; <span class="kw1">if</span> f &amp;lt;&amp;gt; INVALID_HANDLE_VALUE <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; CloseHandle<span class="br0">&#40;</span>f<span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; newBase<span class="sy0">:=</span> <span class="kw2">true</span>;
&nbsp; &nbsp; <span class="kw1">end</span>;
&nbsp; <span class="kw1">end</span>;
<span class="kw1">end</span>;</div>
</div>
</pre>
<p>На этом статью заканчиваю. Надеюсь статья и программный код описал максимально понятно. Но замечу, что код требует оптимизации, так как был написан таким образом, чтобы был понятен читателю. Пример может быть расширен, в него можно добавить кучу дополнительных возможностей. Все это зависит от вашей фантазии. Все вопросы и замечания высказываем на <a href="/forum/">форуме</a>.</p>
<p><strong>Необходимые файлы:</strong><br />
- модуль для вычисления CRC32. <a href="http://depositfiles.com/files/zy2y8ho7y">Скачать</a></p>
<p><strong>Рабочий пример</strong> скачать <a href="http://depositfiles.com/files/8kp2p3qbo">здесь</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://zetblog.ru/programming/200902/%d0%b1%d0%b5%d0%b7%d0%be%d0%bf%d0%b0%d1%81%d0%bd%d0%be%d1%81%d1%82%d1%8c-%d0%b8%d0%bd%d1%81%d0%bf%d0%b5%d0%ba%d1%82%d0%be%d1%80-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

