Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to call Registeration-Free COM dll?
Forum Updated to NodeBB v4.3 + New Features

How to call Registeration-Free COM dll?

Scheduled Pinned Locked Moved Solved General and Desktop
36 Posts 4 Posters 6.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • hskoglundH Offline
    hskoglundH Offline
    hskoglund
    wrote on last edited by hskoglund
    #22

    0x8002801d (TYPE_E_LIBNOTREGISTERED) occurs I think because it's trying to read class information from the registry (which is a no-no since we're doing registration-free COM).

    It could be because the comObject you created is not the top object or that it is dependent on some other COM class to function (maybe test with some other coclass UUIDs listed in your .IDL file, i.e. look for this pattern [
    uuid(xxxx-xxxx-xx)
    ]
    coclass yyyy)

    It can also be a language/implementation reason, for example if your dll is written in C#, the same version of .NET 8 or .NET Framework needs to be installed on both the dev. PC and the target PC.

    To test your .dll from C#, try calling stuff in your COM .dll from a test program using the same type of calling that QAxObject does, in C# you do this via the InvokeMember method (example here )

    Finally, to debug this, download Process Monitor set a filter to exclude everything except the process name of your .exe test app. Look for registry read accesses to HKEY_CLASSES_ROOT :-)

    Edit: I looked if you could instead use the classes that dumpcpp gives you (from doing a "dumpcpp DataTypesLibrary.dll") but alas they are just inheriting from QAxObject so the same error 0x8002801d will probably occur with them as well.

    Bruce.ZhangB 1 Reply Last reply
    0
    • hskoglundH hskoglund

      0x8002801d (TYPE_E_LIBNOTREGISTERED) occurs I think because it's trying to read class information from the registry (which is a no-no since we're doing registration-free COM).

      It could be because the comObject you created is not the top object or that it is dependent on some other COM class to function (maybe test with some other coclass UUIDs listed in your .IDL file, i.e. look for this pattern [
      uuid(xxxx-xxxx-xx)
      ]
      coclass yyyy)

      It can also be a language/implementation reason, for example if your dll is written in C#, the same version of .NET 8 or .NET Framework needs to be installed on both the dev. PC and the target PC.

      To test your .dll from C#, try calling stuff in your COM .dll from a test program using the same type of calling that QAxObject does, in C# you do this via the InvokeMember method (example here )

      Finally, to debug this, download Process Monitor set a filter to exclude everything except the process name of your .exe test app. Look for registry read accesses to HKEY_CLASSES_ROOT :-)

      Edit: I looked if you could instead use the classes that dumpcpp gives you (from doing a "dumpcpp DataTypesLibrary.dll") but alas they are just inheriting from QAxObject so the same error 0x8002801d will probably occur with them as well.

      Bruce.ZhangB Offline
      Bruce.ZhangB Offline
      Bruce.Zhang
      wrote on last edited by Bruce.Zhang
      #23

      @hskoglund My COM dll was wrote in c++.
      I tried different UUID with no luck. And also the process monitor shows that the app was not access this registry.

      the idl file as follows:

      
      import "oaidl.idl";
      import "ocidl.idl";
      
       [
          object,
          uuid(d5c2a0e4-6b92-4278-ba56-479475ccfc42),
          dual,
          nonextensible,
          pointer_default(unique)
      ]
      interface IEventData : IDispatch
      {
          [propget, helpstring("property Key")] HRESULT Key([out, retval]long long *pVal);
          [propput, helpstring("property Key")] HRESULT Key([in] long long val);
          [propget, helpstring("property CD")] HRESULT CD([out, retval]double *pVal);
          [propput, helpstring("property CD")] HRESULT CD([in]double val);
          [propget, helpstring("property CameraCD")] HRESULT CameraCD([out, retval]double *pVal);
          [id(2)] HRESULT Clone([out] IDispatch **pVal);
      };
      
      [
          object,
          uuid(7e04492a-7143-4add-9ed3-a03bd023d63f),
          dual,
          nonextensible,
          pointer_default(unique)
      ]
      interface IFlawData : IDispatch
      {
          [propget, helpstring("property Key")] HRESULT Key([out, retval]long long *pVal);
          [propput, helpstring("property Key")] HRESULT Key([in] long long val);
          [propget, helpstring("property Deleted")] HRESULT Deleted([out, retval]VARIANT_BOOL *pVal);
          [propput, helpstring("property Deleted")] HRESULT Deleted([in]VARIANT_BOOL val);
          [id(1)] HRESULT Deserialize(unsigned char *pBytes);
      };
      
      [
          object,
          uuid(a4df6d7e-28e5-4e9f-8eab-10b2c38a636c),
          dual,
          nonextensible,
          pointer_default(unique)
      ]
      interface IImageData : IDispatch
      {
          [propget, helpstring("property Key")] HRESULT Key([out, retval]long long *pVal);
          [propput, helpstring("property Key")] HRESULT Key([in] long long val);
          [propget, helpstring("property JobKey")] HRESULT JobKey([out, retval]long *pVal);
          [propput, helpstring("property JobKey")] HRESULT JobKey([in] long val);
          [propget, helpstring("property ImageObject")] HRESULT ImageObject([out, retval] VARIANT* pVal);
          [propput, helpstring("property ImageObject")] HRESULT ImageObject([in] VARIANT val);
          [propget, helpstring("property Deleted")] HRESULT Deleted([out, retval]VARIANT_BOOL *pVal);
          [propput, helpstring("property Deleted")] HRESULT Deleted([in]VARIANT_BOOL val);
          [id(1)] HRESULT Deserialize(unsigned char *pBytes);
      };
      
      [
          object,
          uuid(631d7379-8a6c-4941-8ed1-8ad9b34bf558),
          dual,
          nonextensible,
          pointer_default(unique)
      ]
      interface ILineHardwareData : IDispatch
      {
          // LineHardware
          [propget, helpstring("property IP")] HRESULT IP([out, retval]BSTR *pVal);
          [propput, helpstring("property IP")] HRESULT IP([in]BSTR val);
          [propget, helpstring("property Port")] HRESULT Port([out, retval]long *pVal);
          [propput, helpstring("property Port")] HRESULT Port([in] long val);
          [propget, helpstring("property StopPixel")] HRESULT StopPixel([out, retval]long *pVal);
          [propput, helpstring("property StopPixel")] HRESULT StopPixel([in] long val);
      };
      
      [
          object,
          uuid(512F49E3-6FFE-49FF-9E84-1DAC0650428A),
          nonextensible,
          pointer_default(unique)
      ]
      interface IJobData : IDispatch
      {
          // TODO! these deserve known dispids
          [propget, helpstring("property Key")] HRESULT Key([out, retval] long* pVal);
          [propput, helpstring("property Key")] HRESULT Key([in] long val);
          [propget, helpstring("property OperatorName")] HRESULT OperatorName([out, retval] BSTR* pVal);
          [propput, helpstring("property OperatorName")] HRESULT OperatorName([in] BSTR val);
          [propget, helpstring("property CompanyName")] HRESULT CompanyName([out, retval] BSTR* pVal);
          [propput, helpstring("property CompanyName")] HRESULT CompanyName([in] BSTR val);
          [propget, helpstring("property InspectionType")] HRESULT InspectionType([out, retval] BSTR* pVal);
          [propput, helpstring("property InspectionType")] HRESULT InspectionType([in] BSTR val);
          [propget, helpstring("property MaterialType")] HRESULT MaterialType([out, retval] BSTR* pVal);
          [propput, helpstring("property MaterialType")] HRESULT MaterialType([in] BSTR val);
          [propget, helpstring("property OrderNumber")] HRESULT OrderNumber([out, retval] BSTR* pVal);
          [propput, helpstring("property OrderNumber")] HRESULT OrderNumber([in] BSTR val);
          [propget, helpstring("property JobID")] HRESULT JobID([out, retval] BSTR* pVal);
          [propput, helpstring("property JobID")] HRESULT JobID([in] BSTR val);
          [propget, helpstring("property StartDoffNumber")] HRESULT StartDoffNumber([out, retval] long* pVal);
          [propput, helpstring("property StartDoffNumber")] HRESULT StartDoffNumber([in] long val);
          [propget, helpstring("property StartDateTime")] HRESULT StartDateTime([out, retval]DATE *pVal);
          [propput, helpstring("property StartDateTime")] HRESULT StartDateTime([in]DATE val);
          [propget, helpstring("property EndDateTime")] HRESULT EndDateTime([out, retval]DATE* pVal);
          [propput, helpstring("property EndDateTime")] HRESULT EndDateTime([in]DATE val);
          [propget, helpstring("property LeftEdge")] HRESULT LeftEdge([out, retval]double* pVal);
          [propput, helpstring("property LeftEdge")] HRESULT LeftEdge([in]double val);
          [propget, helpstring("property RightEdge")] HRESULT RightEdge([out, retval]double* pVal);
          [propput, helpstring("property RightEdge")] HRESULT RightEdge([in]double val);
          [propget, helpstring("property JobLength")] HRESULT JobLength([out, retval]double* pVal);
          [propput, helpstring("property JobLength")] HRESULT JobLength([in]double val);
          [propget, helpstring("property Comment")] HRESULT Comment([out, retval] BSTR* pVal);
          [propput, helpstring("property Comment")] HRESULT Comment([in] BSTR val);
          [propget, helpstring("property Product")] HRESULT Product([out, retval] BSTR* pVal);
          [propput, helpstring("property Product")] HRESULT Product([in] BSTR val);
          [propget, helpstring("property Recipe")] HRESULT Recipe([out, retval] BSTR* pVal);
          [propput, helpstring("property Recipe")] HRESULT Recipe([in] BSTR val);
          [propget, helpstring("property LineHardware")] HRESULT LineHardware([out, retval] BSTR* pVal);
          [propput, helpstring("property LineHardware")] HRESULT LineHardware([in] BSTR val);
          [propget, helpstring("property Lanes")] HRESULT Lanes([out, retval] BSTR* pVal);
          [propput, helpstring("property Lanes")] HRESULT Lanes([in] BSTR val);
      };
      
      [
          object,
          uuid(8691d19e-004d-461e-9a15-a0b6c11e65b7),
          dual,
          nonextensible,
          pointer_default(unique)
      ]
      interface IJobQueueData : IDispatch
      {
          // TODO! these deserve known dispids
          [propget, helpstring("property Key")] HRESULT Key([out, retval] long* pVal);
          [propput, helpstring("property Key")] HRESULT Key([in] long val);
          [propget, helpstring("property OperatorName")] HRESULT OperatorName([out, retval] BSTR* pVal);
          [propput, helpstring("property OperatorName")] HRESULT OperatorName([in] BSTR val);
          [propget, helpstring("property CompanyName")] HRESULT CompanyName([out, retval] BSTR* pVal);
          [propput, helpstring("property CompanyName")] HRESULT CompanyName([in] BSTR val);
          [propget, helpstring("property InspectionType")] HRESULT InspectionType([out, retval] BSTR* pVal);
          [propput, helpstring("property InspectionType")] HRESULT InspectionType([in] BSTR val);
          [propget, helpstring("property MaterialType")] HRESULT MaterialType([out, retval] BSTR* pVal);
          [propput, helpstring("property MaterialType")] HRESULT MaterialType([in] BSTR val);
          [propget, helpstring("property OrderNumber")] HRESULT OrderNumber([out, retval] BSTR* pVal);
          [propput, helpstring("property OrderNumber")] HRESULT OrderNumber([in] BSTR val);
          [propget, helpstring("property JobID")] HRESULT JobID([out, retval] BSTR* pVal);
          [propput, helpstring("property JobID")] HRESULT JobID([in] BSTR val);
          [propget, helpstring("property StartDoffNumber")] HRESULT StartDoffNumber([out, retval] long* pVal);
          [propput, helpstring("property StartDoffNumber")] HRESULT StartDoffNumber([in] long val);
          [propget, helpstring("property Comment")] HRESULT Comment([out, retval] BSTR* pVal);
          [propput, helpstring("property Comment")] HRESULT Comment([in] BSTR val);
          [propget, helpstring("property Iterations")] HRESULT Iterations([out, retval] long* pVal);
          [propput, helpstring("property Iterations")] HRESULT Iterations([in] long val);
          [propget, helpstring("property JobOrderNumber")] HRESULT JobOrderNumber([out, retval] long* pVal);
          [propput, helpstring("property JobOrderNumber")] HRESULT JobOrderNumber([in] long val);
          [propget, helpstring("property AutoStartDoffNumber")] HRESULT AutoStartDoffNumber([out, retval] BOOL* pVal);
          [propput, helpstring("property AutoStartDoffNumber")] HRESULT AutoStartDoffNumber([in] BOOL val);
          [propget, helpstring("property ProductKey")] HRESULT ProductKey([out, retval] LONG* pVal);
          [propput, helpstring("property ProductKey")] HRESULT ProductKey([in] LONG val);
          [propget, helpstring("property LaneSetupKey")] HRESULT LaneSetupKey([out, retval] LONG* pVal);
          [propput, helpstring("property LaneSetupKey")] HRESULT LaneSetupKey([in] LONG val);
      };
      
      [
          object,
          uuid(EC7181F6-D03B-4DA5-802C-1B83D562DC3E),
          nonextensible,
          pointer_default(unique)
      ]
      interface IProductData : IDispatch
      {
          // TODO! these deserve known dispids
          [propget, helpstring("property Key")] HRESULT Key([out, retval] long* pVal);
          [propput, helpstring("property Key")] HRESULT Key([in] long val);
          [propget, helpstring("property Name")] HRESULT Name([out, retval] BSTR* pVal);
          [propput, helpstring("property Name")] HRESULT Name([in] BSTR val);
          [propget, helpstring("property RecipePath")] HRESULT RecipePath([out, retval] BSTR* pVal);
          [propput, helpstring("property RecipePath")] HRESULT RecipePath([in] BSTR val);
          [propget, helpstring("property PluginConfigs")] HRESULT PluginConfigs([out, retval] BSTR* pVal);
          [propput, helpstring("property PluginConfigs")] HRESULT PluginConfigs([in] BSTR val);
      };
      
      [
      	object,
      	uuid(88788dff-32ff-4c94-ac7c-3c0723444aeb),
      	dual,
      	nonextensible,
      	pointer_default(unique)
      ]
      interface ICommandData : IDispatch
      {
          [propput, helpstring("property Command")] HRESULT Command([in] long val);
          [propget, helpstring("property Value")] HRESULT Value([out, retval]VARIANT *pVal);
          [propput, helpstring("property Value")] HRESULT Value([in] VARIANT val);
          [propget, helpstring("property Value2")] HRESULT Value2([out, retval]VARIANT *pVal);
          [propput, helpstring("property Value2")] HRESULT Value2([in] VARIANT val);
          [propget, helpstring("property Value3")] HRESULT Value3([out, retval]VARIANT *pVal);
          [propput, helpstring("property Value3")] HRESULT Value3([in] VARIANT val);
          [propget, helpstring("property Value4")] HRESULT Value4([out, retval]VARIANT *pVal);
          [propput, helpstring("property Value4")] HRESULT Value4([in] VARIANT val);
          [propget, helpstring("property Value5")] HRESULT Value5([out, retval]VARIANT* pVal);
          [propput, helpstring("property Value5")] HRESULT Value5([in] VARIANT val);
          // Methods
          HRESULT SerializeClassToString([out]BSTR *pSerializedString);
      };
      [
          object,
          uuid(3909d320-59ef-4f64-a795-0188c06bf87e),
          dual,
          nonextensible,
          pointer_default(unique)
      ]
      interface ILaneData : IDispatch
      {
          [propget, helpstring("property Description")] HRESULT Description([out, retval] BSTR* pVal);
          [propput, helpstring("property Description")] HRESULT Description([in] BSTR val);
          [propget, helpstring("property Width")] HRESULT Width([out, retval]double *pVal);
          [propput, helpstring("property Width")] HRESULT Width([in]double val);
          [propget, helpstring("property Enabled")] HRESULT Enabled([out, retval] VARIANT_BOOL* pVal);
          [propput, helpstring("property Enabled")] HRESULT Enabled([in] VARIANT_BOOL val);
          [propget, helpstring("property LeftMargin")] HRESULT LeftMargin([out, retval]double *pVal);
          [propput, helpstring("property LeftMargin")] HRESULT LeftMargin([in]double val);
          [propget, helpstring("property RightMargin")] HRESULT RightMargin([out, retval]double *pVal);
          [propput, helpstring("property RightMargin")] HRESULT RightMargin([in]double val);
      };
      [
      	object,
      	uuid(1c64d549-f760-43ba-8ae1-dbddf1720a54),
      	dual,
      	nonextensible,
      	pointer_default(unique)
      ]
      interface ILaneSetupData : IDispatch
      {
          // NOTE: Don't move Lanes from the top spot unless you change const int "LANE_OBJECT_ARRAY_INDEX = 0;"
          // in c:\development\opsisnextgen\BuildCommonFiles\Wintriss\DatabaseLibrary\SQLEngine.cs
          [propget, helpstring("property Lanes")] HRESULT Lanes([out, retval] SAFEARRAY(VARIANT)* pVal);
          [propput, helpstring("property Lanes")] HRESULT Lanes([in] SAFEARRAY(VARIANT) val);
          [propget, helpstring("property Key")] HRESULT Key([out, retval]long *pVal);
          [propput, helpstring("property Key")] HRESULT Key([in] long val);
          [propget, helpstring("property Name")] HRESULT Name([out, retval] BSTR *pVal);
          [propput, helpstring("property Name")] HRESULT Name([in] BSTR val);
          [propget, helpstring("property EdgeDetectionType")] HRESULT EdgeDetectionType([out, retval]long *pVal);
          [propput, helpstring("property EdgeDetectionType")] HRESULT EdgeDetectionType([in] long val);
          [propget, helpstring("property UsePreSlit")] HRESULT UsePreSlit([out, retval] VARIANT_BOOL* pVal);
          [propput, helpstring("property UsePreSlit")] HRESULT UsePreSlit([in] VARIANT_BOOL val);
          [propget, helpstring("property CDReference")] HRESULT CDReference([out, retval]long *pVal);
          [propput, helpstring("property CDReference")] HRESULT CDReference([in] long val);
          [propget, helpstring("property NumberOfLanes")] HRESULT NumberOfLanes([out, retval]long *pVal);
          [propget, helpstring("property UseLeftOffset")] HRESULT UseLeftOffset([out, retval] VARIANT_BOOL* pVal);
          [propput, helpstring("property UseLeftOffset")] HRESULT UseLeftOffset([in] VARIANT_BOOL val);
          [propget, helpstring("property LeftWebMargin")] HRESULT LeftWebMargin([out, retval]double *pVal);
          [propput, helpstring("property LeftWebMargin")] HRESULT LeftWebMargin([in]double val);
          [propget, helpstring("property RightWebMargin")] HRESULT RightWebMargin([out, retval]double *pVal);
          [propput, helpstring("property RightWebMargin")] HRESULT RightWebMargin([in]double val);
          [propget, helpstring("property FirstKnifePosition")] HRESULT FirstKnifePosition([out, retval]double *pVal);
          [propput, helpstring("property FirstKnifePosition")] HRESULT FirstKnifePosition([in]double val);
      };
      [
          object,
          uuid(C29B84A8-422B-4460-A608-21B7EE023D0A),
          dual,
          nonextensible,
          pointer_default(unique)
      ]
      interface IJobLane : IDispatch
      {
          [propget, helpstring("property Key")] HRESULT Key([out, retval] long *pVal);
          [propput, helpstring("property Key")] HRESULT Key([in] long val);
          [propget, helpstring("property JobKey")] HRESULT JobKey([out, retval] long *pVal);
          [propput, helpstring("property JobKey")] HRESULT JobKey([in] long val);
          [propget, helpstring("property LaneNumber")] HRESULT LaneNumber([out, retval] long *pVal);
          [propput, helpstring("property LaneNumber")] HRESULT LaneNumber([in] long val);
          [propget, helpstring("property StartCD")] HRESULT StartCD([out, retval]double *pVal);
          [propput, helpstring("property StartCD")] HRESULT StartCD([in]double val);
          [propget, helpstring("property StopCD")] HRESULT StopCD([out, retval]double *pVal);
          [propput, helpstring("property StopCD")] HRESULT StopCD([in]double val);
          [propget, helpstring("property Enabled")] HRESULT Enabled([out, retval] VARIANT_BOOL *pVal);
          [propput, helpstring("property Enabled")] HRESULT Enabled([in] VARIANT_BOOL val);
      };
      
      [
      	object,
      	uuid(c50d4146-39e2-406f-81d8-f4961761b61f),
      	dual,
      	nonextensible,
      	pointer_default(unique)
      ]
      interface IErrorMessageData : IDispatch
      {
          [propget, helpstring("property Message")] HRESULT Message([out, retval]BSTR *pVal);
          [propput, helpstring("property Message")] HRESULT Message([in]BSTR val);
          [propget, helpstring("property IPAddress")] HRESULT IPAddress([out, retval]BSTR *pVal);
          [propput, helpstring("property IPAddress")] HRESULT IPAddress([in]BSTR val);
          [propget, helpstring("property OriginalData")] HRESULT OriginalData([out, retval]BSTR *pVal);
          [propput, helpstring("property OriginalData")] HRESULT OriginalData([in]BSTR val);
          [propget, helpstring("property Port")] HRESULT Port([out, retval]long *pVal);
          [propput, helpstring("property Port")] HRESULT Port([in] long val);
          [propget, helpstring("property DateTime")] HRESULT DateTime([out, retval]DATE *pVal);
          [propput, helpstring("property DateTime")] HRESULT DateTime([in]DATE val);
          [id(1)] HRESULT Deserialize(unsigned char *pBytes);
      };
      
      [
          uuid(A9D4AEA1-46D8-4E98-B9AA-BE93A21A58AD),
          version(1.0),
      ]
      library DataTypesLibraryLib
      {
          importlib("stdole2.tlb");
      
          typedef
          [
              uuid(C15BA150-A8BA-4A10-8C5C-0D65F97A9840),
              version(1.0)
          ]
      
          enum EventTypes
          {
              EVENT_UNKNOWN = 0,
              EVENT_FROM_RECIPE = 10000,
              EVENT_START_HISTORICAL_JOB = 10001,
              EVENT_WEB_POSITION_AND_SPEED = 10005,
              EVENT_BLOB_OVERRUN = 10009,
              EVENT_CUT_SIGNAL = 10019,
              EVENT_START_JOB = 10023,
              EVENT_STOP_JOB = 10024,
              EVENT_START_INSPECTION = 10025,
              EVENT_STOP_INSPECTION = 10026,
              EVENT_WEB_EDGE = 10036,
              EVENT_PAUSE_INSPECTION = 10045,
              EVENT_RESTART_INSPECTION = 10046,
              EVENT_JOB_PASSED = 10049,
              EVENT_JOB_FAILED = 10050,
              EVENT_DOFF_PASSED = 10051,
              EVENT_DOFF_FAILED = 10052,
              EVENT_ROLL_PASSED = 10053,
              EVENT_ROLL_FAILED = 10054,
              EVENT_EXTERNAL_RUNNEXTJOB = 10055,
              EVENT_DENSITY_EVENT = 10079,
              EVENT_WET_CAMERA_STATUS = 10180,
              EVENT_WET_START_CALIBRATION = 10181,
              EVENT_WET_STOP_CALIBRATION = 10182
          } EventTypes;
      
          enum CommandTypes
          {
              COMMAND_UNINITIALIZED = -1,
              COMMAND_START_JOB = 1,
              COMMAND_STOP_JOB,
              COMMAND_LINEPROFILE_START,
              COMMAND_LINEPROFILE_STOP,
              COMMAND_SNAPIMAGE
          };
      
          [
              uuid(0405e972-093d-4f16-9b4f-f9071cc8f9b2)
          ]
          coclass EventData
          {
              [default] interface IEventData;
          };
      
          [
              uuid(b5736d7e-0d93-4a0f-aa7d-33283e3c9a4e)
          ]
          coclass FlawData
          {
              [default] interface IFlawData;
          };
      
          [
              uuid(B6AFC998-139C-44CE-B431-9CD001774797)
          ]
          coclass ImageData
          {
              [default] interface IImageData;
              interface IStream;
          };
      
          [
              uuid(c6da7cb0-29e5-4df1-be12-ee863daf7797)
          ]
          coclass LineHardwareData
          {
              [default] interface ILineHardwareData;
          };
      
          [
              uuid(635a7140-dda9-4ccc-846a-03314e9ee5dd)
          ]
          coclass JobData
          {
              [default] interface IJobData;
          };
          [
              uuid(30cbf047-f7ac-43b6-9a7b-5b8edc4ccb45)
          ]
          coclass JobQueueData
          {
              [default] interface IJobQueueData;
          };
          [
              uuid(B1FB3525-376C-49BD-9F69-7C2E7DC26F2B)
          ]
          coclass ProductData
          {
              [default] interface IProductData;
          };
          [
      		uuid(976cf999-21ad-4302-8165-57ad5bccd3c1)
      	]
      	coclass CommandData
      	{
      		[default] interface ICommandData;
      	};
      	[
      		uuid(79cdf1bf-df4f-4720-9bef-b3ed0d3f95a2)
      	]
      	coclass LaneSetupData
      	{
      		[default] interface ILaneSetupData;
      	};
      	[
      		uuid(2455df8c-ff78-4434-8560-9df1e62bfaca)
      	]
      	coclass LaneData
      	{
      		[default] interface ILaneData;
      	};
          [
              uuid(f287dc18-74c9-446c-a753-e8e6b18e58f2)
          ]
          coclass JobLane
          {
              [default] interface IJobLane;
          };
      	[
      		uuid(0b4be3c3-f304-4f98-a870-e2933dee5b7e)
      	]
      	coclass ErrorMessageData
      	{
      		[default] interface IErrorMessageData;
      	};
      };
      
      import "shobjidl.idl";
      import "shobjidl.idl";
      
      1 Reply Last reply
      0
      • hskoglundH Offline
        hskoglundH Offline
        hskoglund
        wrote on last edited by
        #24

        Found another code snippet for COM debugging, insert this just before that failing call ..GetTypeInfo():

        // insert this code right after retrieving the ITypeInfo ptr
        
        // check that GetIDsOfNames works
        //    QString unicodeName = "Clone";        // use this one for IEventData
            QString unicodeName = "Deserialize";  // use this one for IErrorMessageData
            OLECHAR *name = reinterpret_cast<wchar_t *>(const_cast<ushort *>(unicodeName.utf16()));
            DISPID dispid = 0;
            hr = pDispatch->GetIDsOfNames(IID_NULL,&name,1,LOCALE_SYSTEM_DEFAULT,&dispid);
            if (FAILED(hr))
                qFatal() << "Error: GetIDsOfNames() failed" << QString::number((uint) hr,16);
            qDebug() << "ok, dispid =" << dispid;
          
        // old code     
            CComPtr<ITypeInfo> pTypeInfo;
        ...
        

        You could try this both for the coclass ErrorMessageData or if you flip the comments: for coclass EventData.

        Also: to make clear what's failing:

        1. On your development PC where the DataTypesLibrary.dll is visible in the registry everything works, both my old debugging code (i.e. GetTypeInfo()) and generateDocumentation(), right?

        2. On the target PC without any stuff in the registry GetTypeInfo() and generateDocumentation() both fails.

        P.S. Pls have another go at ProcessMonitor, a trick I use is to insert a call to QMessageBox just before the code to trace, like this:

            QMessageBox msgBox;
            msgBox.setText("Start Procmon now...");
            msgBox.exec();
        

        (don't forget to #include "QMessageBox" :-)

        Bruce.ZhangB 1 Reply Last reply
        0
        • hskoglundH hskoglund

          Found another code snippet for COM debugging, insert this just before that failing call ..GetTypeInfo():

          // insert this code right after retrieving the ITypeInfo ptr
          
          // check that GetIDsOfNames works
          //    QString unicodeName = "Clone";        // use this one for IEventData
              QString unicodeName = "Deserialize";  // use this one for IErrorMessageData
              OLECHAR *name = reinterpret_cast<wchar_t *>(const_cast<ushort *>(unicodeName.utf16()));
              DISPID dispid = 0;
              hr = pDispatch->GetIDsOfNames(IID_NULL,&name,1,LOCALE_SYSTEM_DEFAULT,&dispid);
              if (FAILED(hr))
                  qFatal() << "Error: GetIDsOfNames() failed" << QString::number((uint) hr,16);
              qDebug() << "ok, dispid =" << dispid;
            
          // old code     
              CComPtr<ITypeInfo> pTypeInfo;
          ...
          

          You could try this both for the coclass ErrorMessageData or if you flip the comments: for coclass EventData.

          Also: to make clear what's failing:

          1. On your development PC where the DataTypesLibrary.dll is visible in the registry everything works, both my old debugging code (i.e. GetTypeInfo()) and generateDocumentation(), right?

          2. On the target PC without any stuff in the registry GetTypeInfo() and generateDocumentation() both fails.

          P.S. Pls have another go at ProcessMonitor, a trick I use is to insert a call to QMessageBox just before the code to trace, like this:

              QMessageBox msgBox;
              msgBox.setText("Start Procmon now...");
              msgBox.exec();
          

          (don't forget to #include "QMessageBox" :-)

          Bruce.ZhangB Offline
          Bruce.ZhangB Offline
          Bruce.Zhang
          wrote on last edited by Bruce.Zhang
          #25

          @hskoglund I tried the below steps on my PC.

          First, I added the code and it still failed with 0x8002801D error.

          Below is the log from Process Monitor when exec this line of code:

              hr = pDispatch->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
          

          I add filter operation must starts with "Reg"

          5:29:48.3317575 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\Software\Microsoft\Rpc\Extensions	SUCCESS	Desired Access: Read
          5:29:48.3317744 PM	TestRegFreeCOM.exe	18844	RegQueryValue	HKLM\SOFTWARE\Microsoft\Rpc\Extensions\NdrOleExtDLL	SUCCESS	Type: REG_EXPAND_SZ, Length: 24, Data: combase.dll
          5:29:48.3317924 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKLM\SOFTWARE\Microsoft\Rpc\Extensions	SUCCESS	
          5:29:48.3318212 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKLM	SUCCESS	Query: HandleTags, HandleTags: 0x0
          5:29:48.3318302 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\Software\Microsoft\Rpc	SUCCESS	Desired Access: Read
          5:29:48.3318419 PM	TestRegFreeCOM.exe	18844	RegQueryValue	HKLM\SOFTWARE\Microsoft\Rpc\MaxRpcSize	NAME NOT FOUND	Length: 16
          5:29:48.3318539 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKLM\SOFTWARE\Microsoft\Rpc	SUCCESS	
          5:29:48.3318905 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\System\CurrentControlSet\Services\CCG	REPARSE	Desired Access: Read
          5:29:48.3319008 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\System\CurrentControlSet\Services\CCG	NAME NOT FOUND	Desired Access: Read
          5:29:48.3319106 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\System\CurrentControlSet\Services\CCG	REPARSE	Desired Access: Read
          5:29:48.3319179 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\System\CurrentControlSet\Services\CCG	NAME NOT FOUND	Desired Access: Read
          5:29:48.3319285 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName	REPARSE	Desired Access: Read
          5:29:48.3319360 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName	SUCCESS	Desired Access: Read
          5:29:48.3319458 PM	TestRegFreeCOM.exe	18844	RegQueryValue	HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName\ComputerName	SUCCESS	Type: REG_SZ, Length: 32, Data: DESKTOP-1AJB9L5
          5:29:48.3319577 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName	SUCCESS	
          5:29:48.3319648 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\System\Setup	SUCCESS	Desired Access: Read
          5:29:48.3319726 PM	TestRegFreeCOM.exe	18844	RegQueryValue	HKLM\SYSTEM\Setup\OOBEInProgress	SUCCESS	Type: REG_DWORD, Length: 4, Data: 0
          5:29:48.3319826 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKLM\SYSTEM\Setup	SUCCESS	
          5:29:48.3319892 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\System\Setup	SUCCESS	Desired Access: Read
          5:29:48.3319963 PM	TestRegFreeCOM.exe	18844	RegQueryValue	HKLM\SYSTEM\Setup\SystemSetupInProgress	SUCCESS	Type: REG_DWORD, Length: 4, Data: 0
          5:29:48.3320058 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKLM\SYSTEM\Setup	SUCCESS	
          5:29:48.3320151 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\TestRegFreeCOM.exe	NAME NOT FOUND	Desired Access: Query Value, Enumerate Sub Keys
          5:29:48.3320658 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKLM	SUCCESS	Query: HandleTags, HandleTags: 0x0
          5:29:48.3320726 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\Software\Policies\Microsoft\Windows NT\Rpc	NAME NOT FOUND	Desired Access: Read
          5:29:48.3320858 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKLM	BUFFER TOO SMALL	Query: Name, Length: 0
          5:29:48.3320930 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKLM	SUCCESS	Query: Name
          5:29:48.3321016 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\SOFTWARE\Microsoft\AppModel\Lookaside\machine\Software\Policies\Microsoft\Windows NT\Rpc	NAME NOT FOUND	Desired Access: Read
          5:29:48.3321373 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKLM	SUCCESS	Query: HandleTags, HandleTags: 0x0
          5:29:48.3321441 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\Software\Microsoft\Rpc	SUCCESS	Desired Access: Query Value
          5:29:48.3321531 PM	TestRegFreeCOM.exe	18844	RegQueryValue	HKLM\SOFTWARE\Microsoft\Rpc\IdleTimerWindow	NAME NOT FOUND	Length: 16
          5:29:48.3321639 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKLM\SOFTWARE\Microsoft\Rpc	SUCCESS	
          5:29:48.3322149 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKCU\Software\Classes	SUCCESS	Desired Access: Maximum Allowed, Granted Access: All Access
          5:29:48.3322969 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKLM	SUCCESS	Query: HandleTags, HandleTags: 0x0
          5:29:48.3323035 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\Software\Microsoft\COM3	SUCCESS	Desired Access: Read
          5:29:48.3323143 PM	TestRegFreeCOM.exe	18844	RegSetInfoKey	HKLM\SOFTWARE\Microsoft\COM3	SUCCESS	KeySetInformationClass: KeySetHandleTagsInformation, Length: 0
          5:29:48.3323280 PM	TestRegFreeCOM.exe	18844	RegQueryValue	HKLM\SOFTWARE\Microsoft\COM3\Com+Enabled	SUCCESS	Type: REG_DWORD, Length: 4, Data: 1
          5:29:48.3323389 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKLM\SOFTWARE\Microsoft\COM3	SUCCESS	
          5:29:48.3340202 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKCR\PackagedCom	SUCCESS	Desired Access: Read
          5:29:48.3340360 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKCR\PackagedCom\TypeLibIndex	NAME NOT FOUND	Desired Access: Read
          5:29:48.3340657 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKCU\Software\Classes	SUCCESS	Desired Access: Maximum Allowed, Granted Access: All Access
          5:29:48.3340779 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKCU\Software\Classes	SUCCESS	Query: Name
          5:29:48.3340872 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKCU\Software\Classes	SUCCESS	Query: HandleTags, HandleTags: 0x0
          5:29:48.3340935 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKCU\Software\Classes	SUCCESS	Query: HandleTags, HandleTags: 0x0
          5:29:48.3341005 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKCU\Software\Classes\TypeLib	SUCCESS	Desired Access: Maximum Allowed, Granted Access: All Access
          5:29:48.3341120 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKCU\Software\Classes	SUCCESS	
          5:29:48.3341200 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKCU\Software\Classes\TypeLib	SUCCESS	Query: Name
          5:29:48.3341280 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKCU\Software\Classes\TypeLib	SUCCESS	Query: HandleTags, HandleTags: 0x0
          5:29:48.3341335 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKCU\Software\Classes\TypeLib	SUCCESS	Query: HandleTags, HandleTags: 0x0
          5:29:48.3341406 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKCU\Software\Classes\TypeLib\{A9D4AEA1-46D8-4E98-B9AA-BE93A21A58AD}	NAME NOT FOUND	Desired Access: Maximum Allowed
          5:29:48.3341502 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKCR\TypeLib\{A9D4AEA1-46D8-4E98-B9AA-BE93A21A58AD}	NAME NOT FOUND	Desired Access: Maximum Allowed
          5:29:48.3341673 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKCU\Software\Classes\TypeLib	BUFFER TOO SMALL	Query: Name, Length: 0
          5:29:48.3341740 PM	TestRegFreeCOM.exe	18844	RegQueryKey	HKCU\Software\Classes\TypeLib	SUCCESS	Query: Name
          5:29:48.3341847 PM	TestRegFreeCOM.exe	18844	RegOpenKey	HKLM\SOFTWARE\Microsoft\AppModel\Lookaside\user\software\Classes\TypeLib\{A9D4AEA1-46D8-4E98-B9AA-BE93A21A58AD}	NAME NOT FOUND	Desired Access: Read
          5:29:48.3341984 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKCU\Software\Classes\TypeLib	SUCCESS	
          5:29:48.3345887 PM	TestRegFreeCOM.exe	18844	RegCloseKey	HKCU\Software\Classes	SUCCESS	
          
          

          Second, After I registered the DLL like this:

          regsvr32   xxx.dll
          

          Then everything goes fine.

          1 Reply Last reply
          0
          • hskoglundH Offline
            hskoglundH Offline
            hskoglund
            wrote on last edited by
            #26
            This post is deleted!
            1 Reply Last reply
            0
            • hskoglundH Offline
              hskoglundH Offline
              hskoglund
              wrote on last edited by
              #27

              Hi, I had written a post above where I more or less gave up, but I made another effort!

              It turns out that that ancient Qt enhancement suggestion speaking about manifest files wasn't completely science-fiction. I found this MSDN article and of course some StackOverflow posts helped a lot.

              Thanks to your ProcMon trace above we can see it haplessly looking for DataTypesLibrary.dll's type library in the registry. By adding manifest files we can provide a path to that type library.

              Actually we need two manifest files. The first you'll add to your TestRegFreeCOM.exe. I'm assuming you're using MSVC 64-bits compiler and ..pro file (not CMake).
              Qt already adds an .rc file to your .exe so we also need to remove that (there can only be one manifest). Add this to your TestRegFreeCOM.pro:

              CONFIG -= embed_manifest_exe
              QMAKE_MANIFEST = $$PWD/TestRegFreeCOM.exe.manifest
              

              then create a text file TestRegFreeCOM.exe.manifest in your project dir with this:

              <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
              <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
                <dependency>
                  <dependentAssembly>
                    <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" 
                     version="6.0.0.0" 
              	publicKeyToken="6595b64144ccf1df"
              	language="*"
              	processorArchitecture="*" />
                  </dependentAssembly>
                </dependency>
                <dependency>
                  <dependentAssembly>
                    <assemblyIdentity 
                      name="DataTypesLibrary.X" 
                      version="1.0.0.0" 
                      type="win32" 
              	language="*"
                     processorArchitecture="*" />
              </dependentAssembly>
                </dependency>
                <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
                  <security>
                    <requestedPrivileges>
                      <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
                    </requestedPrivileges>
                  </security>
                </trustInfo>
              </assembly>
              

              most of the contents is because we're replacing the Qt standard manifest with our own. The relevant part is where we add a dependentAssembly for the DataTypesLibrary. I think the old MSDN article I mentioned above started this trend of suffixing an .X, don't worry it works :-)

              The second manifest file is for the DataTypesLibrary.dll, create a text file called DataTypesLibrary.X.manifest with this:

              <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
              <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
               <assemblyIdentity 
                  name="DataTypesLibrary.X" 
                  version="1.0.0.0" 
                  type="win32"
                 processorArchitecture="AMD64" />
              
                <file name="DataTypesLibrary.dll">
                <comClass
                  progid="EventData"
                  clsid="{0405e972-093d-4f16-9b4f-f9071cc8f9b2}"
                  threadingModel = "Apartment" />
              
                 <typelib tlbid="{A9D4AEA1-46D8-4E98-B9AA-BE93A21A58AD}"
                  version="1.0" 
                  helpdir="" />
              
                </file>
              </assembly>
              

              then put the DataTypesLibrary.X.manifest and DataTypesLibrary.dll both in the same directory as TestRegFreeCOM.exe.

              To test, try something like:

              auto comObject = new QAxObject("EventData");
              qDebug() << comObject->generateDocumentation();
              

              If it fails, you can trace the manifest fiddling with the SXSTrace.exe tool, step 1, start the trace in a separate CMD window:
              sxstrace trace -logfile:sxstrace
              irun TestRegFreeCOM.exe and press Enter to stop the trace
              step 2: decode the trace
              sxxtrace parse -logfile:sxstrace -outfile:trace.txt
              then you can type trace.txt

              If this works for you, you owe me a beer :-))

              Bruce.ZhangB 2 Replies Last reply
              1
              • hskoglundH hskoglund

                Hi, I had written a post above where I more or less gave up, but I made another effort!

                It turns out that that ancient Qt enhancement suggestion speaking about manifest files wasn't completely science-fiction. I found this MSDN article and of course some StackOverflow posts helped a lot.

                Thanks to your ProcMon trace above we can see it haplessly looking for DataTypesLibrary.dll's type library in the registry. By adding manifest files we can provide a path to that type library.

                Actually we need two manifest files. The first you'll add to your TestRegFreeCOM.exe. I'm assuming you're using MSVC 64-bits compiler and ..pro file (not CMake).
                Qt already adds an .rc file to your .exe so we also need to remove that (there can only be one manifest). Add this to your TestRegFreeCOM.pro:

                CONFIG -= embed_manifest_exe
                QMAKE_MANIFEST = $$PWD/TestRegFreeCOM.exe.manifest
                

                then create a text file TestRegFreeCOM.exe.manifest in your project dir with this:

                <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
                  <dependency>
                    <dependentAssembly>
                      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" 
                       version="6.0.0.0" 
                	publicKeyToken="6595b64144ccf1df"
                	language="*"
                	processorArchitecture="*" />
                    </dependentAssembly>
                  </dependency>
                  <dependency>
                    <dependentAssembly>
                      <assemblyIdentity 
                        name="DataTypesLibrary.X" 
                        version="1.0.0.0" 
                        type="win32" 
                	language="*"
                       processorArchitecture="*" />
                </dependentAssembly>
                  </dependency>
                  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
                    <security>
                      <requestedPrivileges>
                        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
                      </requestedPrivileges>
                    </security>
                  </trustInfo>
                </assembly>
                

                most of the contents is because we're replacing the Qt standard manifest with our own. The relevant part is where we add a dependentAssembly for the DataTypesLibrary. I think the old MSDN article I mentioned above started this trend of suffixing an .X, don't worry it works :-)

                The second manifest file is for the DataTypesLibrary.dll, create a text file called DataTypesLibrary.X.manifest with this:

                <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
                 <assemblyIdentity 
                    name="DataTypesLibrary.X" 
                    version="1.0.0.0" 
                    type="win32"
                   processorArchitecture="AMD64" />
                
                  <file name="DataTypesLibrary.dll">
                  <comClass
                    progid="EventData"
                    clsid="{0405e972-093d-4f16-9b4f-f9071cc8f9b2}"
                    threadingModel = "Apartment" />
                
                   <typelib tlbid="{A9D4AEA1-46D8-4E98-B9AA-BE93A21A58AD}"
                    version="1.0" 
                    helpdir="" />
                
                  </file>
                </assembly>
                

                then put the DataTypesLibrary.X.manifest and DataTypesLibrary.dll both in the same directory as TestRegFreeCOM.exe.

                To test, try something like:

                auto comObject = new QAxObject("EventData");
                qDebug() << comObject->generateDocumentation();
                

                If it fails, you can trace the manifest fiddling with the SXSTrace.exe tool, step 1, start the trace in a separate CMD window:
                sxstrace trace -logfile:sxstrace
                irun TestRegFreeCOM.exe and press Enter to stop the trace
                step 2: decode the trace
                sxxtrace parse -logfile:sxstrace -outfile:trace.txt
                then you can type trace.txt

                If this works for you, you owe me a beer :-))

                Bruce.ZhangB Offline
                Bruce.ZhangB Offline
                Bruce.Zhang
                wrote on last edited by
                #28

                @hskoglund This really works now. That's very kind of you. Pretty much thanks. I owe you a beer^_^.

                1 Reply Last reply
                0
                • Bruce.ZhangB Bruce.Zhang has marked this topic as solved on
                • hskoglundH hskoglund

                  Hi, I had written a post above where I more or less gave up, but I made another effort!

                  It turns out that that ancient Qt enhancement suggestion speaking about manifest files wasn't completely science-fiction. I found this MSDN article and of course some StackOverflow posts helped a lot.

                  Thanks to your ProcMon trace above we can see it haplessly looking for DataTypesLibrary.dll's type library in the registry. By adding manifest files we can provide a path to that type library.

                  Actually we need two manifest files. The first you'll add to your TestRegFreeCOM.exe. I'm assuming you're using MSVC 64-bits compiler and ..pro file (not CMake).
                  Qt already adds an .rc file to your .exe so we also need to remove that (there can only be one manifest). Add this to your TestRegFreeCOM.pro:

                  CONFIG -= embed_manifest_exe
                  QMAKE_MANIFEST = $$PWD/TestRegFreeCOM.exe.manifest
                  

                  then create a text file TestRegFreeCOM.exe.manifest in your project dir with this:

                  <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
                    <dependency>
                      <dependentAssembly>
                        <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" 
                         version="6.0.0.0" 
                  	publicKeyToken="6595b64144ccf1df"
                  	language="*"
                  	processorArchitecture="*" />
                      </dependentAssembly>
                    </dependency>
                    <dependency>
                      <dependentAssembly>
                        <assemblyIdentity 
                          name="DataTypesLibrary.X" 
                          version="1.0.0.0" 
                          type="win32" 
                  	language="*"
                         processorArchitecture="*" />
                  </dependentAssembly>
                    </dependency>
                    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
                      <security>
                        <requestedPrivileges>
                          <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
                        </requestedPrivileges>
                      </security>
                    </trustInfo>
                  </assembly>
                  

                  most of the contents is because we're replacing the Qt standard manifest with our own. The relevant part is where we add a dependentAssembly for the DataTypesLibrary. I think the old MSDN article I mentioned above started this trend of suffixing an .X, don't worry it works :-)

                  The second manifest file is for the DataTypesLibrary.dll, create a text file called DataTypesLibrary.X.manifest with this:

                  <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
                   <assemblyIdentity 
                      name="DataTypesLibrary.X" 
                      version="1.0.0.0" 
                      type="win32"
                     processorArchitecture="AMD64" />
                  
                    <file name="DataTypesLibrary.dll">
                    <comClass
                      progid="EventData"
                      clsid="{0405e972-093d-4f16-9b4f-f9071cc8f9b2}"
                      threadingModel = "Apartment" />
                  
                     <typelib tlbid="{A9D4AEA1-46D8-4E98-B9AA-BE93A21A58AD}"
                      version="1.0" 
                      helpdir="" />
                  
                    </file>
                  </assembly>
                  

                  then put the DataTypesLibrary.X.manifest and DataTypesLibrary.dll both in the same directory as TestRegFreeCOM.exe.

                  To test, try something like:

                  auto comObject = new QAxObject("EventData");
                  qDebug() << comObject->generateDocumentation();
                  

                  If it fails, you can trace the manifest fiddling with the SXSTrace.exe tool, step 1, start the trace in a separate CMD window:
                  sxstrace trace -logfile:sxstrace
                  irun TestRegFreeCOM.exe and press Enter to stop the trace
                  step 2: decode the trace
                  sxxtrace parse -logfile:sxstrace -outfile:trace.txt
                  then you can type trace.txt

                  If this works for you, you owe me a beer :-))

                  Bruce.ZhangB Offline
                  Bruce.ZhangB Offline
                  Bruce.Zhang
                  wrote on last edited by Bruce.Zhang
                  #29

                  @hskoglund Sorry for bother you again. I had other COM dlls written in CSharp. I picked one to operate via dumpcpp, but if I generate .h only using " --nometaobject", then will have link errors. but will succeed when generating both .h and cpp.

                  The tlb and manifest files as follows:
                  https://drive.google.com/file/d/1-2240-43cqiw-rmdVIJvBKnMedPGCKau/view?usp=sharing

                  https://drive.google.com/file/d/1WoWapdes613jN86Eoy6EnrfXL-0fXWax/view?usp=sharing

                  https://drive.google.com/file/d/1p20BSfeuuFCaFUmhfRZi6lnurLlVBO3x/view?usp=sharing

                  1 Reply Last reply
                  0
                  • hskoglundH Offline
                    hskoglundH Offline
                    hskoglund
                    wrote on last edited by
                    #30

                    Do you need to use dumpcpp?
                    I think if you just write the manifest files using the .idl and try with the usual:

                    auto comObject = new QAxObject("RecipeManagement");
                    qDebug() << comObject->generateDocumentation();
                    

                    then you should be able to use QAxObject's dynamicall() and setProperty() etc. instead.

                    Bruce.ZhangB 1 Reply Last reply
                    0
                    • hskoglundH hskoglund

                      Do you need to use dumpcpp?
                      I think if you just write the manifest files using the .idl and try with the usual:

                      auto comObject = new QAxObject("RecipeManagement");
                      qDebug() << comObject->generateDocumentation();
                      

                      then you should be able to use QAxObject's dynamicall() and setProperty() etc. instead.

                      Bruce.ZhangB Offline
                      Bruce.ZhangB Offline
                      Bruce.Zhang
                      wrote on last edited by Bruce.Zhang
                      #31

                      @hskoglund said in How to call Registeration-Free COM dll?:

                      ");

                      I choose dumpcpp just because it seems very convenient to do this, I don't need to remember each property.

                      As C# COM dll doesn't has "DllGetClassObject", I could only call QLibrary("RecipeManagement.dll")->Load();

                      After that if I exec below code, then failed.

                       auto comObject = new QAxObject("RecipeManagement");
                                  qDebug() << comObject->generateDocumentation();
                      
                      The outputs:
                      
                      onecore\com\combase\catalog\catalog.cxx(2394)\combase.dll!00007FFD5C9EEFD0: (caller: 00007FFD5C934E30) ReturnHr(1) tid(518c) 800401F3 Invalid class string
                      onecore\com\combase\dcomrem\resolver.cxx(2299)\combase.dll!00007FFD5C8AE3BD: (caller: 00007FFD5C8AB2AE) ReturnHr(2) tid(518c) 80040154 Class not registered
                      onecore\com\combase\dcomrem\resolver.cxx(2507)\combase.dll!00007FFD5C8AB2D6: (caller: 00007FFD5C8ADC25) ReturnHr(3) tid(518c) 80040154 Class not registered
                      CoCreateInstance failure (Class not registered)
                      QAxBase::setControl: requested control RecipeManagement could not be instantiated
                      ""
                      
                      It was the same error if using 
                      "comObject = new QAxObject("RecipeManagement.SystemSettings");"
                      or other name declared in manifest.
                      

                      Although I can run using .h&.cpp generated by dumpcpp. but there will pop up error if I debug into it.

                      屏幕截图 2023-08-24 095914.png

                      If I just run the exe, will not popup any error dialog, and I can get correct output of
                      qDebug() << recipe.GetAsJSON();

                      1 Reply Last reply
                      0
                      • hskoglundH Offline
                        hskoglundH Offline
                        hskoglund
                        wrote on last edited by
                        #32

                        Hi, just to make sure, you're not still doing those calls? like

                        ...
                            HRESULT hr = regFreeGetDllClassObject(...
                        // and 
                            hr = pClassFactory->CreateInstance(..
                        etc.
                        

                        with manifest files you just need
                        auto comObject = new QAxObject("RecipeManagement");

                        which should be equivalent to using the .h & .cpp files generated by dumpcpp. I.e. if new QAxObject(..) fails then .h & .cpp files from dumpcpp should fail also (and the other way around).

                        Bruce.ZhangB 1 Reply Last reply
                        0
                        • hskoglundH hskoglund

                          Hi, just to make sure, you're not still doing those calls? like

                          ...
                              HRESULT hr = regFreeGetDllClassObject(...
                          // and 
                              hr = pClassFactory->CreateInstance(..
                          etc.
                          

                          with manifest files you just need
                          auto comObject = new QAxObject("RecipeManagement");

                          which should be equivalent to using the .h & .cpp files generated by dumpcpp. I.e. if new QAxObject(..) fails then .h & .cpp files from dumpcpp should fail also (and the other way around).

                          Bruce.ZhangB Offline
                          Bruce.ZhangB Offline
                          Bruce.Zhang
                          wrote on last edited by Bruce.Zhang
                          #33

                          @hskoglund said in How to call Registeration-Free COM dll?:

                          RecipeManagement
                          Hi, sorry for late reply,
                          I didn't use below code snipet, as DllClassObject didn't exists in C# dll.

                          HRESULT hr = regFreeGetDllClassObject(...
                          

                          After I exec

                          auto comObject = new QAxObject("RecipeManagement");
                              qDebug() << comObject->generateDocumentation();
                          

                          Error message as follows:

                          onecore\com\combase\catalog\catalog.cxx(2394)\combase.dll!00007FFF9549EFD0: (caller: 00007FFF953E4E30) ReturnHr(1) tid(1454) 800401F3 Invalid class string
                          onecore\com\combase\dcomrem\resolver.cxx(2299)\combase.dll!00007FFF9535E3BD: (caller: 00007FFF9535B2AE) ReturnHr(2) tid(1454) 80040154 Class not registered
                          onecore\com\combase\dcomrem\resolver.cxx(2507)\combase.dll!00007FFF9535B2D6: (caller: 00007FFF9535DC25) ReturnHr(3) tid(1454) 80040154 Class not registered
                          CoCreateInstance failure (Class not registered)
                          QAxBase::setControl: requested control RecipeManagement could not be instantiated
                          ""
                          
                          1 Reply Last reply
                          0
                          • hskoglundH Offline
                            hskoglundH Offline
                            hskoglund
                            wrote on last edited by
                            #34

                            Hi, I looked at your RecipeManagement.manifest file, at the top I think it lacks the processorArchitecture, i.e. try changing to this:

                            ...
                            <assemblyIdentity
                                        name="RecipeManagement"
                                        version="1.0.0.0"
                                        processorArchitecture="msil"
                                        />
                            ...
                            

                            and make sure the manifest file is linked/embedded into the RecipeManagement.dll (you can use mt.exe to check).

                            Also, you can always use sxstrace to trace, place a QMessageBox just before
                            auto comObject = new QAxObject("RecipeManagement");
                            (see my sxstrace instructions above)

                            Bruce.ZhangB 1 Reply Last reply
                            0
                            • hskoglundH hskoglund

                              Hi, I looked at your RecipeManagement.manifest file, at the top I think it lacks the processorArchitecture, i.e. try changing to this:

                              ...
                              <assemblyIdentity
                                          name="RecipeManagement"
                                          version="1.0.0.0"
                                          processorArchitecture="msil"
                                          />
                              ...
                              

                              and make sure the manifest file is linked/embedded into the RecipeManagement.dll (you can use mt.exe to check).

                              Also, you can always use sxstrace to trace, place a QMessageBox just before
                              auto comObject = new QAxObject("RecipeManagement");
                              (see my sxstrace instructions above)

                              Bruce.ZhangB Offline
                              Bruce.ZhangB Offline
                              Bruce.Zhang
                              wrote on last edited by
                              #35

                              @hskoglund The error code still the same.
                              The output file of sxstrace parse is empty.

                              and here is the XML of exe:

                              <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                              <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
                                  <dependency>
                                      <dependentAssembly>
                                          <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*"></assemblyIdentity>
                                      </dependentAssembly>
                                  </dependency>
                                  <dependency>
                                      <dependentAssembly>
                                          <assemblyIdentity name="DataTypesLibrary" version="1.0.0.0" type="win32" language="*"></assemblyIdentity>
                                      </dependentAssembly>
                                  </dependency>
                                  <dependency>
                                      <dependentAssembly>
                                          <assemblyIdentity name="RecipeManagement" version="1.0.0.0" type="win32" language="*"></assemblyIdentity>
                                      </dependentAssembly>
                                  </dependency>
                                  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
                                      <security>
                                          <requestedPrivileges>
                                              <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
                                          </requestedPrivileges>
                                      </security>
                                  </trustInfo>
                              </assembly>
                              
                              1 Reply Last reply
                              0
                              • hskoglundH Offline
                                hskoglundH Offline
                                hskoglund
                                wrote on last edited by
                                #36

                                Hi, the XML/manifest for the .exe, you forgot the "X" - suffix, it is necessary for reg-free COM to work, try change the XML to:

                                <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                                <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
                                    <dependency>
                                        <dependentAssembly>
                                            <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*"></assemblyIdentity>
                                        </dependentAssembly>
                                    </dependency>
                                    <dependency>
                                        <dependentAssembly>
                                            <assemblyIdentity name="DataTypesLibrary.X" version="1.0.0.0" type="win32" language="*" processorArchitecture="*"></assemblyIdentity>
                                        </dependentAssembly>
                                    </dependency>
                                    <dependency>
                                        <dependentAssembly>
                                            <assemblyIdentity name="RecipeManagement.X" version="1.0.0.0" type="win32" language="*" processorArchitecture="*"></assemblyIdentity>
                                        </dependentAssembly>
                                    </dependency>
                                    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
                                        <security>
                                            <requestedPrivileges>
                                                <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
                                            </requestedPrivileges>
                                        </security>
                                    </trustInfo>
                                </assembly>
                                

                                You already have a DataTypesLibrary.X.manifest file that works the DataTypesLibrary.dll written in C++
                                I think you should try the same with your C# RecipeManagement.dll, i.e. create a RecipeManagement.X.manifest file with something like this in it:

                                <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                                <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
                                 <assemblyIdentity 
                                    name="RecipeManagement.X" 
                                    version="1.0.0.0" 
                                    type="win32"
                                   processorArchitecture="msil" />
                                
                                <file name="RecipeManagement.dll">
                                
                                <clrClass
                                    clsid="{B0AFB6EB-67CB-457E-8709-B6384B02558B}"
                                    threadingModel="Both"
                                    name="RecipeManagement.SystemSettings"
                                    runtimeVersion="v4.0.30319" />
                                
                                <comClass
                                    progid="RecipeManagement.SystemSettings"
                                    clsid="{B0AFB6EB-67CB-457E-8709-B6384B02558B}"
                                    threadingModel = "Apartment" />
                                
                                  </file>
                                </assembly>
                                

                                I'm just guessing, but try first with a separate RecipeManagement.X.manifest file (not embedded in the .dll) with the above contents. Also I don't know if <clrClass> should be inside or outside the <filename XML line, you could try both.
                                Note that you also need the <typelib tlibid=xxx XML inside the <file.. (see my example above for the DataTypesLibrary.X.manifest) but that you can do a later step.

                                About the empty sxstrace trace.txt log file, yes sometimes it doesn't work and gives an empty log file, try logging in/out or rebooting your PC. When it works it will show traces for other ,exe files like edge,exe as well so you'll have to scroll/search for your file.
                                Note: there's a typing error above, here are the commands again:

                                sxstrace trace -logfile:sxstrace
                                sxstrace parse -logfile:sxstrace -outfile:trace.txt
                                
                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved