Jump to content

Recommended Posts

Posted (edited)

If we use a known CLSID, such as {00024500-0000-0000-C000-000000000046} (Excel.Application), it works correctly. 
However, to test something I like to use custom clsid with ObjGet, I encounter the error 0x80040154: Class not registered.

Local $oClsid = custom clsid
Local $oTest = ObjGet("", $oClsid)
or
Local $oTest = ObjGet('clsid:' & $oClsid)


I attempted to resolve this using CoCreateInstance($oClsid, 0, 0x1, IDispatch, 0), but CoCreateInstance also failed.

I know I can make it work using GetActiveObject. 
However, my question is: Is there a way to make a custom CLSID work with ObjGet using a WinAPI call?

Edited by jugador
Posted

I use RegisterActiveObject to register custom clsid
RegisterActiveObject creates item moniker ==> !{12345678-1234-1234-1234-56789ABCDEF0}

So i tried

Local $oTest = ObjGet('clsid:' & $oClsid)
Local $oTest = ObjGet("moniker:!" & $oClsid)
Local $oTest = ObjGet("item:" & $oClsid)

but all this failed with custom clsid.

Does any one have GetObject monikers complete list.

Posted (edited)
On 5/15/2025 at 9:32 AM, jugador said:

If we use a known CLSID, such as {00024500-0000-0000-C000-000000000046} (Excel.Application), it works correctly. 
However, to test something I like to use custom clsid with ObjGet, I encounter the error 0x80040154: Class not registered.

Local $oClsid = custom clsid
Local $oTest = ObjGet("", $oClsid)
or
Local $oTest = ObjGet('clsid:' & $oClsid)


I attempted to resolve this using CoCreateInstance($oClsid, 0, 0x1, IDispatch, 0), but CoCreateInstance also failed.

I know I can make it work using GetActiveObject. 
However, my question is: Is there a way to make a custom CLSID work with ObjGet using a WinAPI call?

Instead of using ObjGet, which can be limited by registration requirements in the Windows registry or the Running Object Table (ROT) and may cause errors like 0x80040154, you can achieve a better result by using the AutoItObject.au3 UDF. This library allows you to create a custom COM object, register it with a specific CLSID using _AutoItObject_RegisterObject, and reliably retrieve it with _AutoItObject_ObjCreate in the same script. This approach uses internal WinAPI calls (such as CoRegisterClassObject) to register the object in the ROT, fulfilling your requirement for a WinAPI-based solution while being simpler and more robust than ObjGet. The following example, adapted from the provided code, demonstrates how to create a COM object, register it with a custom CLSID, and retrieve it with _AutoItObject_ObjCreate to call its methods.
 
 
#include "AutoItObject.au3"
#include <MsgBoxConstants.au3>
Opt("MustDeclareVars", 1)

; COM error handling
Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc()
    ConsoleWrite("COM Error, ScriptLine(" & $oError.scriptline & ") : 0x" & Hex($oError.number, 8) & " - " & $oError.windescription & @CRLF)
EndFunc

; Initialize AutoItObject
_AutoItObject_StartUp()

; Create the custom object
Global $oObject = _SomeObject()

; Register the object with a custom CLSID
Global Const $sMyCLSID = "{D07F2CEA-696F-47CD-99A9-D31E3641169A}" ; Custom CLSID
Global $hObj = _AutoItObject_RegisterObject($oObject, $sMyCLSID)

; Retrieve the object with _AutoItObject_ObjCreate
Global $oObjectNew = _AutoItObject_ObjCreate("cbi:" & $sMyCLSID)
If Not IsObj($oObjectNew) Then
    MsgBox($MB_ICONERROR, "Error", "Failed to retrieve the object")
Else
    $oObjectNew.MsgBox() ; Call the MsgBox method
EndIf

; Unregister the object
_AutoItObject_UnregisterObject($hObj)
$oObject = 0
$oObjectNew = 0

; Define the custom object
Func _SomeObject()
    Local $oClassObject = _AutoItObject_Class()
    $oClassObject.Create()
    $oClassObject.AddMethod("MsgBox", "_Obj_MsgBox")
    $oClassObject.AddProperty("Title", $ELSCOPE_PUBLIC, "My Object")
    $oClassObject.AddProperty("Text", $ELSCOPE_PUBLIC, "Custom Text")
    $oClassObject.AddProperty("Flag", $ELSCOPE_PUBLIC, 64 + 262144)
    Return $oClassObject.Object
EndFunc

; MsgBox method
Func _Obj_MsgBox($oSelf, $sTitle = "")
    If $sTitle Then Return MsgBox($oSelf.Flag, $sTitle, $oSelf.Text)
    MsgBox($oSelf.Flag, $oSelf.Title, $oSelf.Text)
EndFunc

 

  1. Initialization: _AutoItObject_StartUp() initializes the AutoItObject.au3 UDF.
  2. Object Creation: The _SomeObject function creates a COM object with a Title, Text, and Flag property, and a MsgBox method that displays a message.
  3. Registration: _AutoItObject_RegisterObject registers the object with the custom CLSID {D07F2CEA-696F-47CD-99A9-D31E3641169A} in the Running Object Table (ROT) using internal WinAPI calls (e.g., CoRegisterClassObject).
  4. Retrieval with _AutoItObject_ObjCreate: The object is retrieved in the same script using _AutoItObject_ObjCreate("cbi:" & $sMyCLSID), where the cbi: prefix indicates a local COM server. The MsgBox method is then called, displaying a dialog with the title "My Object" and text "Custom Text".
  5. Error Handling: A COM error handler (_ErrFunc) captures potential errors for debugging.
  6. Cleanup: The object is unregistered with _AutoItObject_UnregisterObject, and references are released.
Why This Is Better Than ObjGet
  • Reliability: _AutoItObject_ObjCreate is designed to work seamlessly with objects created and registered by AutoItObject.au3, avoiding errors like 0x80040154 ("Class not registered") that occur with ObjGet if the object is not properly registered.
  • Simplicity: The UDF handles the necessary WinAPI calls (e.g., CoRegisterClassObject) internally, meeting your requirement for a WinAPI-based solution without needing manual WinAPI coding.
  • Flexibility: You can define custom objects with specific methods and properties, as shown in the example, and manipulate them easily within the same script.
  • Avoids ObjGet Limitations: ObjGet requires the object to be registered in the Windows registry or active in the ROT, which can be problematic for custom CLSIDs. _AutoItObject_ObjCreate is optimized for objects created by the UDF, making access more straightforward and less error-prone.
Why This Addresses Your Question
  • Custom CLSID: The example uses a custom CLSID ({D07F2CEA-696F-47CD-99A9-D31E3641169A}) to register and retrieve the object, meeting your need to work with a specific CLSID.
  • WinAPI Call: _AutoItObject_RegisterObject uses internal WinAPI calls to register the object in the ROT, fulfilling your requirement for a WinAPI-based solution.
  • Avoiding 0x80040154: By using _AutoItObject_ObjCreate instead of ObjGet, you bypass registration issues that cause the "Class not registered" error, as the UDF handles temporary registration in the ROT.
Prerequisites
  • Download AutoItObject.au3 from the AutoIt forum or official site and place it in the same folder as your script or in AutoIt’s include directory.
  • Ensure your AutoIt version is up to date to guarantee compatibility with AutoItObject.au3.
Tips
  • Verify that the CLSID used in _AutoItObject_ObjCreate matches exactly the one defined in $sMyCLSID.
  • Use the COM error handler (as shown) to diagnose potential issues.
  • To add more methods or properties to the object, modify the _SomeObject function using _AutoItObject_Class().AddMethod or .AddProperty.
Limitations
  • Temporary Registration: Registration via _AutoItObject_RegisterObject is valid only during the script’s execution. For permanent registration in the Windows registry, you would need to create a COM DLL and register it with regsvr32, which is more complex.
  • UDF Dependency: This example relies on AutoItObject.au3. If you prefer to avoid the UDF, you would need to implement manual WinAPI calls (e.g., RegisterActiveObject via dllcall), which is more complex and requires a valid COM object.
Conclusion
The AutoItObject.au3 UDF provides a more robust and simpler solution than ObjGet for working with custom CLSIDs. By using _AutoItObject_RegisterObject to register a COM object and _AutoItObject_ObjCreate to retrieve it, as shown in the example, you can avoid errors like 0x80040154 and meet your need for a WinAPI-based solution. This simplified example demonstrates how to create, register, and retrieve a COM object in the same script. 
Edited by Numeric1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...