Настройка брандмауэра для консольной программы с использованием COM: решение проблемы с CoInitialize
В процессе разработки консольного приложения на языке Object Pascal, предназначенного для создания исключения в брандмауэре для основной программы, возникают различные технические трудности. Одной из таких проблем является ошибка CoInitialize has not been called, которая связана с использованием компонов COM (Component Object Model) в консольных приложениях. В данной статье мы рассмотрим, как правильно настроить взаимодействие с брандмауэром в консольных приложениях, используя пример создания исключения для программы, загружающей документы на сервер через FTP.
Проблема с CoInitialize
При работе с COM-объектами в консольных приложениях необходимо явно инициализировать COM-библиотеки, что не требуется в обычных оконных приложениях, где это делается автоматически. Ошибка CoInitialize has not been called возникает, когда попытка создать COM-объект происходит без предварительной инициализации. В контексте нашего приложения, это происходит при попытке создать объект HNetCfg.FwPolicy2, который используется для настройки правил брандмауэра Windows.
Пример кода
Ниже представлен пример кода консольного приложения, которое должно создавать исключение в брандмауэре для основной программы Client.exe. В коде используется функция AddExceptionToFirewall, которая создает новое правило для брандмауэра. Ошибка возникает в следующей части кода:
program ChangeFW;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
ComObj;
var
ExecName: string;
procedure AddExceptionToFirewall(Const Caption, Executable: String);
...
begin
Profile := NET_FW_PROFILE2_PRIVATE OR NET_FW_PROFILE2_PUBLIC;
fwPolicy2 := CreateOleObject('HNetCfg.FwPolicy2');
RulesObject := fwPolicy2.Rules;
...
end;
begin
try
ExecName := GetCurrentDir + '\' + 'Client.exe';
AddExceptionToFirewall('SIP Inventory',ExecName);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
При запуске приложения возникает сообщение об ошибке __EOIeSysError: Coinitialize has not been called, ProgID: “HNetCfg.FwPolicy2”.
Решение проблемы
Для решения проблемы с CoInitialize необходимо добавить вызов этой функции в начало основного блока программы, а также вызвать CoUninitialize в блоке finally, чтобы корректно завершить работу с COM-объектами. Пример исправленного кода:
program ChangeFW;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
ComObj;
var
ExecName: string;
...
begin
CoInitialize(nil);
try
try
ExecName := GetCurrentDir + '\' + 'Client.exe';
AddExceptionToFirewall('SIP Inventory',ExecName);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
CoUninitialize;
end;
end.
Таким образом, мы гарантируем корректную инициализацию COM-библиотек и их последующее освобождение.
Заключение
В данной статье мы рассмотрели, как важно правильно работать с COM-объектами в консольных приложениях, и как простое добавление вызовов CoInitialize и CoUninitialize может решить проблему с CoInitialize has not been called. Это знание позволит разработчикам избежать подобных ошибок в будущем и обеспечить корректную работу их консольных приложений, взаимодействующих с компонентами операционной системы.
Разработчики консольного приложения на Object Pascal столкнулись с проблемой, связанной с использованием COM для настройки брандмауэра Windows, и ошибкой `CoInitialize has not been called`, которую нужно решить путем правильной инициали
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.