I'm not that sharp on ODL language so I wonder what I do wrong?
I get this error when I try to pass a GUID struct.
Here is the VB code:
Code:
Private Sub Command6_Click()
Dim pINWLM As INetworkListManager
Dim pICP As IConnectionPoint
Dim pICPC As IConnectionPointContainer
Dim hr As Long
Dim dwCookie As Long
Dim iid As GUID
hr = GetINetWorkListManager(pINWLM)
If hr = S_OK Then
Set pICPC = pINWLM
CLSIDFromString StrPtr("{B196B286-BAB4-101A-B69C-00AA00341D07}"), iid
pICPC.FindConnectionPoint iid, pICP '<--- The red colored struct raise error
End If
End Sub
And here is the ODL code:
Code:
typedef struct GUID {
LONG Data1;
SHORT Data2;
SHORT Data3;
BYTE Data4[8];
} GUID;
interface IConnectionPointContainer : IUnknown
{
HRESULT EnumConnectionPoints(
[out] IEnumConnectionPoints** ppEnum);
HRESULT FindConnectionPoint(
[in] GUID riid, <--- The red colored struct raise error
[out] IUnknown** ppConnectionPoint
);
And if I try to comment out the VB GUID struct and use the GUID struct from the TLB file I get an error that says I use an Automation type that is not allowed in VB.
I tried to rework it with this code:
The first vierd error seems to disapered but another strange error appeared.
IID_IConnectionPoint is a DefineUUID function.
Code:
Private Sub Command6_Click()
Dim pINWLM As INetworkListManager
Dim pICP As IConnectionPoint
Dim pICPC As IConnectionPointContainer
Dim hr As Long
Dim dwCookie As Long
hr = GetINetWorkListManager(pINWLM)
If hr = S_OK Then
Set pICPC = pINWLM
pICPC.FindConnectionPoint IID_IConnectionPoint, pICP
End If
End Sub
In addition stdole2 is usually ahead of other references in the priority list, and contains a GUID definition with unsigned types that are not supported in vb6. That's why oleexp uses UUID for that kind of data (GUID, UUID, CLSID, and a few others are all the same).
In addition stdole2 is usually ahead of other references in the priority list, and contains a GUID definition with unsigned types that are not supported in vb6. That's why oleexp uses UUID for that kind of data (GUID, UUID, CLSID, and a few others are all the same).
But as I wrote in answer to wqweto I have tried UUID as well with same error. I'm stuck.
But I commented out my own VB GUID struct and insted using the one declared in my TLB file works.
However this error playing my mind instead.
That Event is not even in that Interface. The raising this error belongs to IDispatch which is in the stdole2.tlb file.
You can't call stdole.IDispatch methods from VB. You'd need to substitute a VB-compatible implementation or perhaps use DispCallFunc to get around errors from unsigned types. You might be able to cast to oleexp.IDispatch which is VB compatible but I'm not sure.
You can't call stdole.IDispatch methods from VB. You'd need to substitute a VB-compatible implementation or perhaps use DispCallFunc to get around errors from unsigned types. You might be able to cast to oleexp.IDispatch which is VB compatible but I'm not sure.
Aha okey, I did put in IDispatch into the typelib and used the inheritance IUknown : IDispatch
And also own IUnknown. But the problem still remains. But I shall post the src later today.
I bet all the GUID unsignedness, IUnknown/IDispatch interface VB-izing and most other issues are already solved in some popular TLBs available here on VBForums but OP has history of refusing to peek their sources to learn how it's done and prefers to discover the hot water in lengthy discussions here.
I bet all the GUID unsignedness, IUnknown/IDispatch interface VB-izing and most other issues are already solved in some popular TLBs available here on VBForums but OP has history of refusing to peek their sources to learn how it's done and prefers to discover the hot water in lengthy discussions here.
cheers,
</wqw>
Actually I tried to find redy TLB-file with the these network interfaces but did only find
Delphi coded so I went on and copied the code from MSDN.
Slightly difference in syntax from MSDN to ODL.
Fafalone’s nice typelib doesn’t include these interfaces.
Try this TLB it works without problem, each GUID parameter is transformed into 2 Currency parameters and the binding to NetworkListManager is done by ConnectToConnectionPoint, there is no need to import INetworkListManage.
Code:
Private Declare Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As Long, riidEvent As Any, _
ByVal fConnect As Long, ByVal punkTarget As Long, ByRef pdwCookie As Long, Optional ByVal ppcpOut As Long) As Long
Private Declare Function IIDFromString Lib "ole32.dll" (ByVal lpsz As Long, lpiid As Any) As Long
Private Declare Function CoInitialize Lib "ole32" (ByVal pvReserved As Long) As Long
Private Declare Sub CoUninitialize Lib "ole32" ()
Private Declare Function CoCreateInstance Lib "ole32" (clsid As Any, ByVal unkOuter As Long, _
ByVal dwClsContext As Long, IID As Any, pv As Any) As Long
Private Declare Function CLSIDFromString Lib "ole32" (ByVal str As Long, id As Any) As Long
Implements VbNetwork.INetworkConnectionEvents
Public NewObj As IUnknown
Private Sub Command1_Click()
Dim hr As Long
Dim dwCookie As Long
Dim CLASS_NetworkListManager(0 To 15) As Byte, IID_IUnknown(0 To 15) As Byte
Dim IID(0 To 15) As Byte
CLSIDFromString StrPtr("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"), CLASS_NetworkListManager(0)
IIDFromString StrPtr("{00000000-0000-0000-C000-000000000046}"), IID_IUnknown(0)
IIDFromString StrPtr("{DCB00004-570F-4A9B-8D69-199FDBA5723B}"), IID(0)
CoCreateInstance CLASS_NetworkListManager(0), 0, 5, IID_IUnknown(0), NewObj
hr = ConnectToConnectionPoint(ObjPtr(Me), IID(0), 1, ObjPtr(NewObj), dwCookie)
MsgBox Hex(hr)
End Sub
Private Sub Form_Load()
CoInitialize 0
End Sub
Private Sub Form_Unload(Cancel As Integer)
CoUninitialize
End Sub
Private Sub INetworkConnectionEvents_NetworkAdded(ByVal G1 As Currency, ByVal G2 As Currency)
Debug.Print "NetworkAdded"
End Sub
Private Sub INetworkConnectionEvents_NetworkConnectivityChanged(ByVal G1 As Currency, ByVal G2 As Currency, ByVal newConnectivity As Long)
Debug.Print "NetworkConnectivityChanged"
End Sub
Private Sub INetworkConnectionEvents_NetworkDeleted(ByVal G1 As Currency, ByVal G2 As Currency)
Debug.Print "NetworkDeleted"
End Sub
Private Sub INetworkConnectionEvents_NetworkPropertyChanged(ByVal G1 As Currency, ByVal G2 As Currency, ByVal newConnectivity As Long)
Debug.Print "NetworkPropertyChanged"
End Sub
Delphi ridl, try to translate it Note: The correct name of the interface should be INetworkEvents, not INetworkConnectionEvents, that was a mistake on my part
Actually I was mistaken, sorry. INetworkListManager does have compatibility issues. But, a VB compatible version *is* included in oleexp; source is in exp_netcon.odl.
Note that an interface isn't shown in Object Browser if it's the default interface for a coclass.
And the ByVal GUID needs special handling... declare Dim g(3) As Long, then copy the regular GUID type with CopyMemory into g(0), then pass g(0), g(1), g(2), g(3) to the 4 parts of the GUID argument. You'll need even more special handling in x64; the method described must continue to be used for x86 while for x64 you pass a GUID ByRef, as the x64 calling convention overrides ByVal UDTs over 8 bytes and converts to ByRef.
Last edited by fafalone; Feb 10th, 2025 at 05:47 PM.
Try this TLB it works without problem, each GUID parameter is transformed into 2 Currency parameters and the binding to NetworkListManager is done by ConnectToConnectionPoint, there is no need to import INetworkListManage.
Code:
Implements VbNetwork.INetworkConnectionEvents
Public NewObj As IUnknown
Private Sub Command1_Click()
Dim hr As Long
Dim dwCookie As Long
Dim CLASS_NetworkListManager(0 To 15) As Byte, IID_IUnknown(0 To 15) As Byte
Dim IID(0 To 15) As Byte
CLSIDFromString StrPtr("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"), CLASS_NetworkListManager(0)
IIDFromString StrPtr("{00000000-0000-0000-C000-000000000046}"), IID_IUnknown(0)
IIDFromString StrPtr("{DCB00004-570F-4A9B-8D69-199FDBA5723B}"), IID(0)
CoCreateInstance CLASS_NetworkListManager(0), 0, 5, IID_IUnknown(0), NewObj
hr = ConnectToConnectionPoint(ObjPtr(Me), IID(0), 1, ObjPtr(NewObj), dwCookie)
MsgBox Hex(hr)
End Sub
But where is IConnectionPoint interface? Here you just refer to stdole.IUnknown.
And need to QueryInterface with IUknown to get IConnectionPointContainer.
The Set statement is equivalent to QueryInterface.
You could access IUnknown through an unrestricted, compatible version like oleexp has, but
Code:
Dim pUnk As oleexp.IUnknown
Set pUnk = Interface1
pUnk.QueryInterface IID_IInterface2, Interface2
and
Set Interface2 = Interface1
are equivalent; the first is what the second does under the hood.
Yes, I know these to ways to go. The latter one I suspect is for stdole.IUnknown since its not possible to QueryInterface with that one.
However I tried my example again and then @anycoder's example and both return Com Error 80040202 which is "An event was delivered but there were no subscriber", So the interfaces is VB compatible I belive. So what exactly does that COM Error mean?
Code:
Private Sub Command6_Click()
Dim pINWLM As INetworkListManager
Dim pICP As IConnectionPoint
Dim ppICP As Long
Dim pICPC As IConnectionPointContainer
Dim lpIID_INetworkListManagerEvents As GUID
Dim hr As Long
Dim dwCookie As Long
Dim pIUNK As network.IUnknown
Dim pIRC As IRemoteComputer
' Dim NewObj As IUnknown
'
' Dim CLASS_NetworkListManager(0 To 15) As Byte, IID_Unknown(0 To 15) As Byte
' Dim IID(0 To 15) As Byte
'
' CLSIDFromString StrPtr("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"), CLASS_NetworkListManager(0)
' CLSIDFromString StrPtr("{00000000-0000-0000-C000-000000000046}"), IID_Unknown(0)
' CLSIDFromString StrPtr("{DCB00004-570F-4A9B-8D69-199FDBA5723B}"), IID(0)
'
' CoCreateInstance CLASS_NetworkListManager(0), 0, 5, IID_Unknown(0), NewObj
'
' hr = ConnectToConnectionPoint(ObjPtr(Me), IID(0), 1, ObjPtr(NewObj), dwCookie)
'
' MsgBox Hex(hr)
hr = GetINetWorkListManager(pINWLM)
If hr = S_OK Then
Set pIUNK = Me
hr = pIUNK.QueryInterface(IID_IConnectionPointContainer, pICPC)
CLSIDFromString StrPtr("{DCB00001-570F-4A9B-8D69-199FDBA5723B}"), lpIID_INetworkListManagerEvents
hr = ConnectToConnectionPoint(ObjPtr(pIUNK), ByVal VarPtr(lpIID_INetworkListManagerEvents), 1, ObjPtr(pINWLM), dwCookie, ppICP)
MsgBox Hex(hr)
End If
End Sub
I’ve updated my previous post and added the complete code.
So when I disconnect and then reconnect to my wifi router I get this list of notifications:
NetworkAdded
NetworkConnectivityChanged
NetworkConnectivityChanged
NetworkConnectivityChanged
NetworkDeleted
NetworkConnectivityChanged
I’ve updated my previous post and added the complete code.
So when I disconnect and then reconnect to my wifi router I get this list of notifications:
NetworkAdded
NetworkConnectivityChanged
NetworkConnectivityChanged
NetworkConnectivityChanged
NetworkDeleted
NetworkConnectivityChanged
Nice!
Where do you put your event code? The implementation you do.
Last edited by nebeln; Feb 11th, 2025 at 08:54 AM.
Try this TLB it works without problem, each GUID parameter is transformed into 2 Currency parameters and the binding to NetworkListManager is done by ConnectToConnectionPoint, there is no need to import INetworkListManage.
Code:
Private Declare Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As Long, riidEvent As Any, _
ByVal fConnect As Long, ByVal punkTarget As Long, ByRef pdwCookie As Long, Optional ByVal ppcpOut As Long) As Long
Private Declare Function IIDFromString Lib "ole32.dll" (ByVal lpsz As Long, lpiid As Any) As Long
Private Declare Function CoInitialize Lib "ole32" (ByVal pvReserved As Long) As Long
Private Declare Sub CoUninitialize Lib "ole32" ()
Private Declare Function CoCreateInstance Lib "ole32" (clsid As Any, ByVal unkOuter As Long, _
ByVal dwClsContext As Long, IID As Any, pv As Any) As Long
Private Declare Function CLSIDFromString Lib "ole32" (ByVal str As Long, id As Any) As Long
Implements VbNetwork.INetworkConnectionEvents
Public NewObj As IUnknown
Private Sub Command1_Click()
Dim hr As Long
Dim dwCookie As Long
Dim CLASS_NetworkListManager(0 To 15) As Byte, IID_IUnknown(0 To 15) As Byte
Dim IID(0 To 15) As Byte
CLSIDFromString StrPtr("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"), CLASS_NetworkListManager(0)
IIDFromString StrPtr("{00000000-0000-0000-C000-000000000046}"), IID_IUnknown(0)
IIDFromString StrPtr("{DCB00004-570F-4A9B-8D69-199FDBA5723B}"), IID(0)
CoCreateInstance CLASS_NetworkListManager(0), 0, 5, IID_IUnknown(0), NewObj
hr = ConnectToConnectionPoint(ObjPtr(Me), IID(0), 1, ObjPtr(NewObj), dwCookie)
MsgBox Hex(hr)
End Sub
Private Sub Form_Load()
CoInitialize 0
End Sub
Private Sub Form_Unload(Cancel As Integer)
CoUninitialize
End Sub
Private Sub INetworkConnectionEvents_NetworkAdded(ByVal G1 As Currency, ByVal G2 As Currency)
Debug.Print "NetworkAdded"
End Sub
Private Sub INetworkConnectionEvents_NetworkConnectivityChanged(ByVal G1 As Currency, ByVal G2 As Currency, ByVal newConnectivity As Long)
Debug.Print "NetworkConnectivityChanged"
End Sub
Private Sub INetworkConnectionEvents_NetworkDeleted(ByVal G1 As Currency, ByVal G2 As Currency)
Debug.Print "NetworkDeleted"
End Sub
Private Sub INetworkConnectionEvents_NetworkPropertyChanged(ByVal G1 As Currency, ByVal G2 As Currency, ByVal newConnectivity As Long)
Debug.Print "NetworkPropertyChanged"
End Sub
Delphi ridl, try to translate it Note: The correct name of the interface should be INetworkEvents, not INetworkConnectionEvents, that was a mistake on my part
Oh now I see you have added the module class implementation but where do you activate/trigger the events implementation?
I can’t find where you use that.
Btw, what's up with explicit CoInitialize/CoUninitialize? Are these needed?
Actually there is no need to use them same remarque for CoCreateInstance, the coclass of NetworkListManager can be included in the new TLB ,this will make the creation of the object easier via the New constructor.
but where do you activate/trigger the events implementation?
You need to implement in your class the interface to which you want to connect ..
like this way
Code:
Implements VbNetwork.INetworkConnectionEvents
Private Sub INetworkConnectionEvents_NetworkAdded(ByVal G1 As Currency, ByVal G2 As Currency)
Debug.Print "NetworkAdded"
End Sub
Private Sub INetworkConnectionEvents_NetworkConnectivityChanged(ByVal G1 As Currency, ByVal G2 As Currency, ByVal newConnectivity As Long)
Debug.Print "NetworkConnectivityChanged"
End Sub
Private Sub INetworkConnectionEvents_NetworkDeleted(ByVal G1 As Currency, ByVal G2 As Currency)
Debug.Print "NetworkDeleted"
End Sub
Private Sub INetworkConnectionEvents_NetworkPropertyChanged(ByVal G1 As Currency, ByVal G2 As Currency, ByVal newConnectivity As Long)
Debug.Print "NetworkPropertyChanged"
End Sub
But classes derived from IDispatch are less complicated, it's possible to select the events to intercept only by specifying the dispid of method in your class.
Actually there is no need to use them same remarque for CoCreateInstance, the coclass of NetworkListManager can be included in the new TLB ,this will make the creation of the object easier via the New constructor.
You need to implement in your class the interface to which you want to connect ..
like this way
Code:
Implements VbNetwork.INetworkConnectionEvents
Private Sub INetworkConnectionEvents_NetworkAdded(ByVal G1 As Currency, ByVal G2 As Currency)
Debug.Print "NetworkAdded"
End Sub
Private Sub INetworkConnectionEvents_NetworkConnectivityChanged(ByVal G1 As Currency, ByVal G2 As Currency, ByVal newConnectivity As Long)
Debug.Print "NetworkConnectivityChanged"
End Sub
Private Sub INetworkConnectionEvents_NetworkDeleted(ByVal G1 As Currency, ByVal G2 As Currency)
Debug.Print "NetworkDeleted"
End Sub
Private Sub INetworkConnectionEvents_NetworkPropertyChanged(ByVal G1 As Currency, ByVal G2 As Currency, ByVal newConnectivity As Long)
Debug.Print "NetworkPropertyChanged"
End Sub
But classes derived from IDispatch are less complicated, it's possible to select the events to intercept only by specifying the dispid of method in your class.
YES!! IT WORKS FOR ME AS WELL!!
Actually first time ever I do an implementation that just need to be included in the (form1) module to become triggered.
I use my own TLB file I started this thread with.
My example looks like this...
Code:
Private Sub Command6_Click()
Dim pINWLM As INetworkListManager
Dim pICP As IConnectionPoint
Dim ppICP As Long
Dim pICPC As IConnectionPointContainer
Dim lpIID_INetworkEvents As GUID
Dim hr As Long
Dim dwCookie As Long
Dim pIUNK As network.IUnknown
hr = GetINetWorkListManager(pINWLM)
If hr = S_OK Then
Set pIUNK = Me
hr = pIUNK.QueryInterface(IID_IConnectionPointContainer, pICPC)
CLSIDFromString StrPtr("{DCB00004-570F-4A9B-8D69-199FDBA5723B}"), lpIID_INetworkEvents
hr = ConnectToConnectionPoint(ObjPtr(Me), lpIID_INetworkEvents, 1, ObjPtr(pINWLM), dwCookie, ppICP)
'Take the optional returning pointer and copy the pointer to the interface itself
'Then you need to change the parameter from ByVal to ByRef for outgoing pointer.
If (hr = S_OK) And (ppICP <> 0) Then
MoveMemory pICP, ppICP, 4
'Do someting with IConnectionPoint Interface...
End If
End If
End Sub
Private Sub INetworkEvents_NetworkAdded(networkID As UUID)
MsgBox "Network Added!", vbInformation
End Sub
Private Sub INetworkEvents_NetworkConnectivityChanged(networkID As UUID, ByVal newConnectivity As NLM_CONNECTIVITY)
End Sub
Private Sub INetworkEvents_NetworkDeleted(networkID As UUID)
MsgBox "Network Deleted!", vbInformation
End Sub
Private Sub INetworkEvents_NetworkPropertyChanged(networkID As UUID, ByVal flags As NLM_NETWORK_PROPERTY_CHANGE)
End Sub
3 times become INetworkEvents_NetworkAdded fired then I start network connection.
And 3 times for disconnecting.
However you DONT need to use CoInitialize and CoUninitialize cus VB do that for you.
I just realised that if you use the pointer to the IConnectionPoint the events will not fire for any reason
I have included my TLB file.
Last edited by nebeln; Feb 11th, 2025 at 04:42 PM.
You both do realise how ridiculously complicated this thread is? Here is your code using one particular typelib that OP does not want to use:
Code:
Option Explicit
Private WithEvents m_oList As NetworkListManager
Private Sub Form_Load()
Set m_oList = New NetworkListManager
End Sub
Private Sub m_oList_NetworkAdded(ByVal networkId1 As Long, ByVal networkId2 As Long, ByVal networkId3 As Long, ByVal networkId4 As Long)
MsgBox "Network Added!", vbInformation
End Sub
Private Sub m_oList_NetworkConnectivityChanged(ByVal networkId1 As Long, ByVal networkId2 As Long, ByVal networkId3 As Long, ByVal networkId4 As Long, ByVal newConnectivity As oleexp.NLM_CONNECTIVITY)
'
End Sub
Private Sub m_oList_NetworkDeleted(ByVal networkId1 As Long, ByVal networkId2 As Long, ByVal networkId3 As Long, ByVal networkId4 As Long)
'
End Sub
Private Sub m_oList_NetworkPropertyChanged(ByVal networkId1 As Long, ByVal networkId2 As Long, ByVal networkId3 As Long, ByVal networkId4 As Long, ByVal flags As oleexp.NLM_NETWORK_PROPERTY_CHANGE)
'
End Sub
Think about it: If you are already using a typelib of your own there is no reason *not* to declare interfaces/coclasses decent enough so that you will be able to do what is possible with the one particular typelib too, is there?
Do you see API declares in code above? CoInitialize or CoCreateInstance is just New operator. ConnectToConnectionPoint is just WithEvents. All gory details hiden behind standard language constructs.
VB6 is the ultimate COM consumer -- just provide decent typelib and it will do the heavy lifting.
cheers,
</wqw>
Last edited by wqweto; Feb 12th, 2025 at 06:39 AM.