Search code examples
delphidelphi-7

Exception EOleSysError In Module


I'm getting error when i call AddExceptionToFirewall in my Console Application

Exception EOleSysError In Module at CoInitialize has not been called

how to fix it why I'm getting this error even using ComObj ,ActiveX in uses clause?

Procedure AddExceptionToFirewall(Const Caption, Executable: String);
      const
       NET_FW_PROFILE2_DOMAIN  = 1;
       NET_FW_PROFILE2_PRIVATE = 2;
       NET_FW_PROFILE2_PUBLIC  = 4;
       NET_FW_IP_PROTOCOL_TCP = 6;
       NET_FW_ACTION_ALLOW    = 1;
      var
      fwPolicy2      : OleVariant;
      RulesObject    : OleVariant;
      Profile        : Integer;
      NewRule        : OleVariant;
      begin
      Profile             := NET_FW_PROFILE2_PRIVATE OR NET_FW_PROFILE2_PUBLIC;
      fwPolicy2           := CreateOleObject('HNetCfg.FwPolicy2');
      RulesObject         := fwPolicy2.Rules;
      NewRule             := CreateOleObject('HNetCfg.FWRule');
      NewRule.Name        := Caption;
      NewRule.Description := Caption;
      NewRule.Applicationname := Executable;
      NewRule.Protocol := NET_FW_IP_PROTOCOL_TCP;
      NewRule.Enabled := TRUE;
      NewRule.Profiles := Profile;
      NewRule.Action := NET_FW_ACTION_ALLOW;
      RulesObject.Add(NewRule);
     end;

Solution

  • You need to call OleInitialize (or OleInitializeEx) in your application before you try and Create a COM object.

    MSDN: OleInitialize function Initializes the COM library on the current apartment, identifies the concurrency model as single-thread apartment (STA), and enables additional functionality described in the Remarks section below. Applications must initialize the COM library before they can call COM library functions other than CoGetMalloc and memory allocation functions.

    I do this in my main unit:

    initialization
      OleInitialize(nil);
    
    finalization
      OleUninitialize;
    

    This function is in the ActiveX unit (via an External) but is not automatically called by that unit. It could be that other units will call this. It depends on when your function runs.

    Here is a Stackoverflow question asking about calling OleInitialize twice.

    Also be aware that this is thread specific. If are starting a different thread where this function is running you need to call OleInitialize on that thread.

    Here is another good page that goes into a lot of detail: Inside the COM Client

    A relevant quote from that page:

    In a standard Delphi EXE COM application, CoInitialize/Ex and CoUninitialize is automatically called from within the ComObj module. The CoInitialize/Ex process is chained through the InitProc initialization sequence that gets called from TApplication.Initialize. Thus, it is important to call Application.Initialize (usually in the DPR file) as the first statement in an EXE application.

    The effect of forgetting to call Application.Initialize is usually the nasty "CoInitialize has not been called" error at the first statement that tries to make a COM call, or more specifically, the first statement that exports/imports a COM interface pointer. On a different note, ComObj calls CoInitialize/Ex only for EXEs, not for DLLs. A DLL's lifetime and threading requirements is a subset of its host application. Therefore, it is the responsibility of the host application to initialize the COM runtime before calling into a DLL application. Explicitly calling CoInitialize/Ex in a DLL can result in unpredictable behavior and nasty runtime failures.