|
I have built a COM DLL with a number of functions in version 1:
- OnlineAvailCheck_V2 --> first public function
- DownloadProductInfo_V2 --> second public function
- DownloadPriceInfo_V2 --> third public function
The COM DLL is called from an external application; the functions appear in the same order as shown above.
In version 2, the DownloadProductInfo function has become obsolete, and needs to be replaced by V31
- OnlineAvailCheck_V2 --> first public function
- DownloadProductInfo_V2 --> becomes private
- DownloadPriceInfo_V2 --> second public function
- DownloadProductInfo_V31 --> third public function
If I make the V2 function private (because it must no longer be used), the external application makes a shift in the code: all references to DownloadProductInfo_V2 are now replaced by references to the third public function, i.e. DownloadPriceInfo_V2 function.
Is there any way I can give a fixed sequence number to the functions, so that I can avoid the shift? Or is there any other way to deal with this? Thank you.
Dox Girl, where are you?
|
|
|
|
|
Use the DispIdAttribute attribute[^] to specify the COM dispatch identifier for your methods and properties. That way, the order doesn't matter.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
As a side note, once interfaces are defined they should be fixed unless you are willing to re-compile all clients also. So if you want to alter the interface you should re-compile your client too. If you don't want to re-compile the client, then implement a new interface and have calls to your old interface redirect or forward to the method on the new interface. The redundant methods will just remain there, you can have them return errors if you want to indicate they shouldn't be called. Any new client, or client you don't mind re-compiling, will reference your new interface. This way all old and new clients still see the interfaces they were compiled against.
You might be able to configure the interface forwarding for you automatically using the registry, it's been a while and back in the day interface forwarding was handled by the compiled and COM registration tools.
|
|
|
|
|
Hi all,
I am trying to control the Undo/Redo Stack in excel but I can't seem to get a pointer to the UndoManager Interface in the ppv out argument when calling the QueryService Method .. it always returns Nothing ..
I hope someone can tell me what I am doing wrong .. I think the "SID_SApplicationObject" is not the right SID
Note : I am using the olelib.tlb
Code :
Sub Test()
Dim pUnk As olelib.IUnknown
Dim IServiceProvider As olelib.IServiceProvider
Dim IID_IServiceProvider As olelib.UUID
Dim IID_IOleUndoManager As olelib.UUID
Dim SID_SApplicationObject As olelib.UUID
Dim ppv As IUnknown
CLSIDFromString IIDSTR_IServiceProvider, IID_IServiceProvider
CLSIDFromString "{0C539790-12E4-11CF-B661-00AA004CD6D8}", SID_SApplicationObject
Set pUnk = Excel.Application
pUnk.QueryInterface IID_IServiceProvider, IServiceProvider
IServiceProvider.QueryService SID_SApplicationObject, IID_IOleUndoManager, ppv
End Sub
Any help will be much appreciated
Regards.
|
|
|
|
|
The following code is supposed to redirect the call to the Excel Calculate Method to my own function (MeMsg)
After running the HookCOMFunction routine , the Test Macro successfully executes the MeMsg replacement function as expected .. So far so good
However, when executing an excel calculation via the User Interface (not via code) such as by pressing the F9 key , the MeMsg replacement function doesn't get called ... I thought that replacing the 'Calculate' VTable offset address with the address of my replacement function would also work everytime excel is calculated via the User Interface
Any thoughts anyone ? My goal is to hook the excel Calculate Method via code as well as via the UI
Regards.
Code :
Option Explicit
Private Declare Sub CopyMemory Lib "Kernel32" Alias "RtlMoveMemory" ( _
Destination As Any, _
Source As Any, _
ByVal Length As Long _
)
Private Declare Function VirtualProtect Lib "kernel32.dll" ( _
ByVal lpAddress As Long, _
ByVal dwSize As Long, _
ByVal flNewProtect As Long, _
lpflOldProtect As Long _
) As Long
Private Const PAGE_EXECUTE_READWRITE As Long = &H40&
Sub HookCOMFunction()
Dim pVTable As Long
Const lFuncOffset As Long = 84
CopyMemory pVTable, ByVal ObjPtr(Application), 4
VirtualProtect pVTable + lFuncOffset, 4&, PAGE_EXECUTE_READWRITE, 0&
CopyMemory ByVal pVTable + lFuncOffset, AddressOf MeMsg, 4
End Sub
Private Function MeMsg(ByVal voObjPtr As Long, ByVal Param As Long) As Long
MsgBox "Excel 'Calculate Method Hooked !!"
End Function
Sub Test()
Application.Calculate
End Sub
|
|
|
|
|
Bump ..
Any thoughts on this anyone ?
|
|
|
|
|
I have created a COM object in VS2013. I can call it from VBA late-bound. I want to be able to call it early-bound. However, the COM object name shows twice in the reference list. Likt this:
[books icon] COMName
[object icon] COMName
If I try to early bind I get a compile error:
Expected user-defined type, not project
How can I get around this?
Thanks,
Crew
|
|
|
|
|
Sorry friends. This's a guide.
The Windows Scripting Host (WSH) enables a number of file system and network operations to be performed from a script file. Fortunately, it is very simple to directlyprogram the WSH in a .NET program by including a reference to the WSH runtime library (IWshRuntimeLibrary). To do this within the Visual Studio .NET IDE, do the following:
After creating a new project
- right-click on the project name within the Solution Explorer
- select "Add Reference"
- select the "COM" tab, find and select the "Windows Script Host Object Model" in the listbox
- click "Select", and then click "OK". Next, include a reference to the library
|
|
|
|
|
|
I have a very simple dot net library that uses COM Interop and a simple test program in VB that uses CreateObject to instantiate the COM component.
This works fine if I register the dot net library using REGASM but I cannot get it to work with a side by side manifest. I tried creating the manifest manually as well as using a number of different tools. The manifests look fine but it is unable to create the COM object.
Is there anything special I am missing? any ideas what to look for?
thanks
Mike
|
|
|
|
|
You have to register your component using regasm and you can't do things like side-by-side. Although your component is written in .net, it is exposing itself via COM and COM is registry based and you can't leverage .net features like just loading assemblies from a directory. When you use REGASM it creates the required registry entries that give the exact location of your assembly to load when a COM client asks for your component.
|
|
|
|
|
Not true. COM works with side x side. I've done it myself but have to confess it is a while since I have done it. (Only visiting the COM forum for nostalgia)
|
|
|
|
|
I meant COM doesn't work easily side-by-side in the .net sense, but yes you can use the sxs framework to make side by side com assemblies. However re-reading the original question I think he was talking about registration free COM manifest files over standard registry-based registration.
https://msdn.microsoft.com/en-us/library/fh1h056h(v=vs.110).aspx[^]
But I think that only applies to .net clients, not the likes of VB.
|
|
|
|
|
Hi,
Please if some help me to find the solution or some inputs
i am interested to subclass Content Control or rather i will
say i am in need to create my custom control which will have same behavior as Content Control ,
how can i go for it i need in C++ /ATL/Com dont like to use clr c++ or any other .
if some one can help me .
|
|
|
|
|
COSERVERINFO si;
si.dwReserved1=0;
si.pwszName=szIP;
si.pAuthInfo=NULL;
si.dwReserved2=0;
IID iid=__uuidof(ITCSUser);
MULTI_QI qi={&iid,0,0};
HRESULT hRes=CoCreateInstanceEx(__uuidof(TCSUser),NULL,CLSCTX_REMOTE_SERVER,&si,1,&qi);
if (FAILED(hRes))
{
Log(_T("Can't create user object, error 0x%.8X"),hRes);
return false;
}
I am developing a third party app by using this so-called TCS Api, the GUID of both class and interface(ITCSUser,CTCSUser) can be found in registry. while the CLASSNOTREG error will be generated after executing CoCreateInstanceEx. I have been stuck here so long and not yet figure it out. I am a beginner of COM/DCOM, could anyone help or give a little hint. By the way, this app is run on Windows server 2008 r2, someone told me the OS is not supported DCOM. Is this really mattered?
|
|
|
|
|
Billy Bang wrote: this so-called TCS Api, If this is a third-party product you might want to talk to the people who create it.
Also check in your code that all parameters are correct, particularly the value returned by __uuidof(TCSUser) .
|
|
|
|
|
Thanks for your reply, maybe there is something I did not express very clear. Here is the thing, I was asked to develop a third-party app by using the API of "TCS" which is a app developed by Nokia, it is short for Tetra Connectivity Server and basically a programm used in telecommunication. By adopting this "#import XXX/tcsapi.dll" in my code, I can freely used the api of it(e.g getVoiceCall()). The __uuidof(TCSUser) has value and can be checked in the registry, but the error still be there.
|
|
|
|
|
It's impossible to guess why that may be happening; maybe you should try re-installing the library. Alternatively, ask Nokia for assistance.
|
|
|
|
|
I was developing a context menu handle on windows OS. I followed the website guide "The Complete Idiot's Guide to Writing Shell Extensions - Part I[^]", and can show my own submenu item when right-click a shorcut. But I want remove the other submenu items, such as "copy", "open", "zip" and so on. May any body tell me how to do it? thx a lot.
|
|
|
|
|
Hi all,
I'm absolutely no expert with COM but I have a (maybe very easy) question to you.
I have a .dll file and would like to call some functions out of that. So I've created now a .tlb file out of the .dll with the command:
regasm XYZ.dll /tlb
This worked great and now I could also create the .tlh file out of this .tlb If I add this line in my C++ code:
#import "XYZ.tlb" named_guids raw_interfaces_only
and recompile the project.
That all worked great right now. But now I have the problem how I must call this part in my code to use the functions out of this .dll file?
I know that it should work with the CoCreateInstance(...) function but I don't know what parameters I must set there exactly?
Maybe I could send to someone my little example and he could help me? I thinks this should be no problem for an expert?
In this forum it's not possible to add a little attachment .
Thanks for any help!!!
Regards,
Jürgen
|
|
|
|
|
|
Yes, I've read this page and it works also for another project. But this time I have another one and I don't know exactly how I can go on with this one . Could you take a look at the project I have? Just a few minutes. That would be really great!!!
|
|
|
|
|
I'm having trouble getting an Access plugin working for all users. The setup application installs/registers the dll and associated tlb file absolutely fine (installed for all users) and my VBA code (below) also works successfully when logged in as an administrator, but attempting to use it under a non-privileged user account fails here:
Private Sub Form_Load()
With COMAddIns("MyPlugIn.Connect")
.Connect = True
.Object.HookupControls cmdUploadImage
End With
End Sub
The returned error is: This add-in is installed for all users on this computer and can only be connected or disconnected by an administrator.
Is there any way to prevent this?
Some additional information:
- The dll/tbl and setup application are all created in C# (.net 3.5)
- The target machine is virtualised, so any user could potentially log into it (thus installing the plugin for the active user isn't an option... though if there's a way to silently install the file in a user login script that might work?)
Thanks in advance... though I'm more hopeful than expectant! 
|
|
|
|
|
I'm testing Viscomsoft powerpoint viewer ActiveX in demo version.
Using example code I loaded a ptt, but when press next slide in the last slide, powerpoint show a save dialog.
What could i do to remove that dialog?
Im trying to make a "safe" viewer for Powerpoint/Excel files, in which the final users can see the files but they cannot save its.
I made an encryption software for mask the ptt and excel files and the other issue its, If the ptt has a link to an excel file, the activeX open Excel and I want to catch the press link to open the excel file inside my program.
Is there any way to catch the link click event?
|
|
|
|
|
In the "Dynamic Selection of a Component" section of the book <com+ programming="" -="" a="" practical="" guide="" using="" visual="" c++="" and="" atl="">, there is an example teach me to load dll dynamically. Here is my code:
It couldn't run. I guess error in the file "tv.cpp". This code couldn't return a function pointer(I print the value of proc, and computer shows that proc = 0): "CREATEVCRPROC proc = reinterpret_cast<createvcrproc>(GetProcAddress(h, "CreateVcr"));"
PS: I use Microsoft C++ Compiler to compile this files
> cl -c tv.cpp
> cl -c vcr.cpp
> link -dll vcr.obj
> link tv.obj
Could anyone help me? Thank you very much!!
#include "video.h"
class CVcr : public IVideo{
public:
CVcr(void);
long _stdcall GetSignalValue();
void _stdcall Delete();
private:
long m_lCurValue;
int m_nCurCount;
};
#include "vcr.h"
CVcr::CVcr(){
m_lCurValue = 5;
m_nCurCount = 0;
}
long CVcr::GetSignalValue(){
m_nCurCount++;
if(5 == m_nCurCount){
m_lCurValue = 5;
m_nCurCount = 1;
}
long lReturnValue = m_lCurValue;
m_lCurValue += 10;
return lReturnValue;
}
IVideo * _stdcall CreateVcr(void){
return new CVcr;
}
void CVcr::Delete(){
delete this;
}
class IVideo{
public:
virtual long _stdcall GetSignalValue() = 0;
virtual void _stdcall Delete() = 0;
};
extern "C" IVideo * _stdcall CreateVcr();
#include "video.h"
#include <iostream>
#include <windows.h>
using namespace std;
IVideo * CreateInstance(char * pszDll){
typedef IVideo * (_stdcall * CREATEVCRPROC)(void);
HINSTANCE h = LoadLibrary(pszDll);
CREATEVCRPROC proc = reinterpret_cast<CREATEVCRPROC>(GetProcAddress(h, "CreateVcr"));
printf("proc = %d", proc);
return (*proc)();
}
int main(int argc, char* argv[])
{
int i;
IVideo * pVideo = CreateInstance("vcr.dll");
for(i=0; i<10; i++) {
long val = pVideo->GetSignalValue();
cout << "Round: " << i << " - Value: " << val << endl;
}
pVideo->Delete();
return 0;
}
|
|
|
|