|
-
Oct 7th, 2025, 06:05 PM
#1
COM dynamic proxy
I had a little fun with chatgpt this week. C dll is a dynamic proxy that wraps an arbitrary inner COM object. Lets you override methods or add new methods to an existing object. Wanted this for a looongg time and chatgpt pulled if off with some coercion.
we are basically creating our own IDispatchEx interface in about 600 lines of pure C++ for languages which don't support it. Final release dll with /MT is about 130kb
C Dll debug messages are output to Elroys: http://www.vbforums.com/showthread.p...g-Print-Window
You can find a compiled copy and maybe more up to date source here:
https://github.com/dzzie/js4vb/tree/master/dynproxy
Note: more stuff has been added to this as js4vb grew such as a custom CallByNameEx and event sink code.
Readme below.
-------------------
# dynproxy — Dynamic COM Proxy for VB6 (and beyond)
> *The missing dynamic layer VB6 never had.*
> A raw C++ COM proxy that turns VB6 into a dynamic runtime.
---
## What This Does
dynproxy.dll lets **VB6 (or any COM client)** create objects that respond to *any* property or method call dynamically — even ones that don’t exist.
It acts like a **programmable middle-man** between VB6 and COM:
- Intercepts every IDispatch::Invoke and GetIDsOfNames.
- Can forward to a real inner COM object or fake a response.
- Lets your **VB6 class** decide in real time what happens.
**No ATL. No MFC. Pure COM.**
---
## Why It Exists
No good reason..just a wish list
dynproxy fixes that: it lets you build **dynamic COM façades** that VB6 treats as real.
Now you can:
- Build **synthetic COM trees** (o.Kitty.Meow = 12).
- **Mock** sprawling APIs (Acrobat, Office, etc.).
- **Log or reroute** calls before they hit the real object.
- **Bridge** VB6 to scripting engines or remote APIs.
- Turn VB6 into something approaching Python or JavaScript’s Proxy.
---
## How It Works
### The Proxy Pipeline
text
VB6 Runtime
(calls o.SomeMethod)
IDispatch::Invoke("SomeMethod")
ProxyDispatch
(dynproxy.dll)
1 Inner object Forward call
2 Resolver class
• Call VB6: ResolveGetID / ResolveInvoke
• Pass name, args, and DISPATCH_ flags
3 Neither Invent a DISPID and let resolver fake it
### Call Flow Details
1. **VB6** late-bound calls always go through IDispatch::Invoke.
2. The proxy catches that and checks a cache (name DISPID).
3. If unknown, it calls:
* inner->GetIDsOfNames() first (default), or
* resolver->ResolveGetID() first if resolver-wins mode is active.
4. The final Invoke routes accordingly:
* Forward to the inner COM object, **or**
* Call your resolver’s ResolveInvoke(name, flags, args()).
---
## VB6 Resolver Interface
Your resolver implements two public methods:
Code:
Public Function ResolveGetID(ByVal name As String) As Long
' Return non-zero to claim this name
' Return 0 to let the inner object handle it
End Function
Public Function ResolveInvoke(ByVal name As String, _
ByVal flags As Long, _
args() As Variant) As Variant
' Handle the call
End Function
### flags meanings
| Flag | Hex | Meaning |
| ---- | --- | ------------------------------ |
| 1 | 0x1 | DISPATCH_METHOD (Sub/Function) |
| 2 | 0x2 | DISPATCH_PROPERTYGET |
| 4 | 0x4 | DISPATCH_PROPERTYPUT |
| 8 | 0x8 | DISPATCH_PROPERTYPUTREF |
---
## Example: Dynamic Tree
Code:
' --- CResolver.cls ---
Option Explicit
Private m_children As Object, m_props As Object
Private Sub Class_Initialize()
Set m_children = CreateObject("Scripting.Dictionary")
Set m_props = CreateObject("Scripting.Dictionary")
End Sub
Public Function ResolveGetID(ByVal name As String) As Long
Select Case LCase$(name)
Case "kitty", "meow": ResolveGetID = -30000
Case Else: ResolveGetID = 0
End Select
End Function
Public Function ResolveInvoke(ByVal name As String, ByVal flags As Long, args() As Variant) As Variant
Dim lname As String: lname = LCase$(name)
' Property GET
If (flags And 2) <> 0 Then
If lname = "kitty" Then
If Not m_children.Exists("kitty") Then
Dim child As CResolver: Set child = New CResolver
Dim p As Long: p = CreateProxyForObjectRaw(0&, ObjPtr(child))
Dim o As Object: Set o = ObjectFromPtr(p)
m_children.Add "kitty", o
End If
Set ResolveInvoke = m_children("kitty"): Exit Function
End If
If m_props.Exists(lname) Then ResolveInvoke = m_props(lname)
Exit Function
End If
' Property PUT
If (flags And 4) <> 0 Then
m_props(lname) = args(0): Exit Function
End If
End Function
Demo:
Code:
Dim root As New CResolver
Dim p As Long: p = CreateProxyForObjectRaw(0&, ObjPtr(root))
Dim o As Object: Set o = ObjectFromPtr(p)
o.kitty.meow = 12
Debug.Print o.kitty.meow ' 12
---
## Key Exports
Code:
| Function | Description |
| ---------------------------------------------------------- | ------------------------------------------------------ |
| CreateProxyForObjectRaw(inner, resolver) | Create proxy with an optional inner and resolver. |
| CreateProxyForObjectRawEx(inner, resolver, resolverWins) | Same, but choose resolver-first at creation. |
| SetProxyResolverWins(proxy, enable) | Toggle resolver-first mode at runtime. |
| ClearProxyNameCache(proxy) | Clear cached DISPIDs (call after toggling). |
| SetProxyOverride(proxy, name, dispid) | Force a name to route to resolver. |
| ReleaseDispatchRaw(ptr) | Manual release if you never wrapped the pointer in VB. |
All exports are stdcall, callable from VB6 directly.
---
## Build Notes
* **Language:** C++17
* **No** ATL or MFC
* **Link:** oleaut32.lib
* Build as **Win32 DLL**
cl /LD /std:c++17 dynproxy.cpp oleaut32.lib /EHsc /Fe:dynproxy.dll
## Why It’s Cool
* Intercepts and rewrites COM calls in real time.
* Lets VB6 behave like Python or JavaScript — dynamic and late-bound.
* Mocks any proprietary API instantly (no IDL hell).
* Enables powerful debugging, scripting, and adapter layers.
---
## Caveats
* Works only for **late-bound** (IDispatch) calls.
* STA threading only (standard VB6 COM).
* Don’t double-release VB6-wrapped objects.
* VB6 only runs 32-bit, so the DLL should be x86.
---
## * Credits & Origin
Implemented in pure C++ because ATL/MFC got in the way.
This project turns that pain into power — a *universal COM proxy* that lets old tech do new tricks.
---
**Platform:** Win32 COM
**Language:** C++ / VB6
**Keywords:** VB6, COM, IDispatch, dynamic proxy, API mocking, automation, Acrobat
---
Last edited by dz32; Jan 26th, 2026 at 09:46 AM.
-
Oct 8th, 2025, 11:05 AM
#2
Fanatic Member
Re: COM dynamic proxy
Very interesting.
This is the part that interests me most.
Code:
---
## ? Why It’s Cool
* Intercepts and rewrites COM calls in real time.
* Lets VB6 behave like Python or JavaScript — dynamic and late-bound.
* Mocks any proprietary API instantly (no IDL hell).
* Enables powerful debugging, scripting, and adapter layers.
---
I really like interoperability. If you make any more discoveries, I'd love to try them out.
Best regards
-
Oct 14th, 2025, 11:30 AM
#3
Re: COM dynamic proxy
Is it possible to support events?You develop a 64-bit, then what? Then develop a 32-bit proxy, 32-bit DLL, or control
This allows both 64-bit vbas to use 32-bit DLLs, OCX.
-
Oct 14th, 2025, 12:50 PM
#4
Re: COM dynamic proxy
I have no idea how late bound events are handled, feed that cpp file into chatgpt and ask if it can add events. it probably can?
It will compile as an x64 dll so my guess is it will work there.
This would not be the approach for a 64bit vba to use 32bit dlls, its not that type of proxy.
https://getyarn.io/yarn-clip/b6ba1c0...2-506130866f56
Last edited by dz32; Oct 14th, 2025 at 02:01 PM.
-
Oct 16th, 2025, 06:17 AM
#5
Re: COM dynamic proxy
Curious as to what parts necessitated writing in C++? Certainly one could write implementations of IDispatch/IDispatchEx in VB/tB.
64bit=twinBASIC
-
Oct 16th, 2025, 08:03 AM
#6
Re: COM dynamic proxy
I was wondering how many LOC a TB implementation would take for such a dynamic COM proxy. (This one is 600.)
cheers,
</wqw>
-
Oct 16th, 2025, 08:17 AM
#7
Re: COM dynamic proxy
You probably could pull it off in vb6 directly with lite weight objects and/or vtable patching.
In C/C++ this is just very standard COM plumbing though making it a natural choice.
Personally I rather stay within a languages strength zone. This is also step 1 of where I may take it.
I have some more ideas where a vb version would not work.
-
Oct 17th, 2025, 03:28 AM
#8
Re: COM dynamic proxy
 Originally Posted by wqweto
I was wondering how many LOC a TB implementation would take for such a dynamic COM proxy. (This one is 600.)
The functionality should be coverable completely, from what I've shown here, in plain, straight forward VB6-code:
https://www.vbforums.com/showthread....BaseInterfaces
(in less than 600 lines, I guess).
Olaf
-
Oct 21st, 2025, 02:47 PM
#9
Re: COM dynamic proxy
 Originally Posted by dz32
I have no idea how late bound events are handled, feed that cpp file into chatgpt and ask if it can add events. it probably can?
It will compile as an x64 dll so my guess is it will work there.
This would not be the approach for a 64bit vba to use 32bit dlls, its not that type of proxy.
https://getyarn.io/yarn-clip/b6ba1c0...2-506130866f56
Can you test how to call net DLL dynamically. And automatically late bind event
For example, epplus. DLL, nopi. DLL, dynamic call them to create tables, read and fill in the contents of cells.
Dynamically create. Net CEF. DLL, election. DLL, if it can also support cross-platform.
A Linux version of the com object wrapper that creates a virtual registry of its own.Or implement it without using the registry.
How to run com objects on Linux, com + + technology
Last edited by xiaoyao; Oct 21st, 2025 at 02:51 PM.
-
Oct 21st, 2025, 02:54 PM
#10
Re: COM dynamic proxy
??wine,I simulated a callback for a mouse event. It turned out that the mobile phone was very hot. I'm running an Android version of winE or something like that.
It runs very slowly on the computer. The same is true on Android phones, and it consumes a lot of power. But at least it can run, uh, windows programs.
It would be best if we could get rid of the wine system and directly use C + + to implement com objects on Linux.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|