|
is it good practice, or even possible, to have one class factory produce instances of many different COM classes?
i'm trying to make a scripting engine using IActiveScript and such, but i have multiple COM classes implementing IActiveScript, IActiveScriptSite, etc... but I don't want to have a class factory for each one
any thoughts?
- Roman -
|
|
|
|
|
By definition, as the class factory the class object of some class must produce the many instances of that and only that class.
COM standard CoCreateInstance and CoGetClassObject fucntions realize this strategy with IClassFactory interface. But the class object can have another interface by which you can create any other objects as well.
With best wishes,
Vita
|
|
|
|
|
So I need many factories? i didn't understand the second part of your message, thanks anyway
- Roman -
|
|
|
|
|
A creation of a COM object begins from the creation of the its class object via CoGetClassObject(CLSID,context,NULL,IID_Ix,(void**)&pCoObj) where CocreateInstance uses IID_Ix is equal IID_IClassFactory. So created object is called a class factory object. Then CoCreateInstance uses pCoObj->IClassFactory::CreateInstance(pUnkOuter, IID_Iy, (void**)ppObj) to create a COM object with interface Iy.
Nobody prevents you to use other interface which let you create some COM objects, which may belong to different classes, by calling of some Ix function with some parameter - pCoObj->Ix::FuncCreate(BSTR type, IActiveScript* *ppScript).
Or create alone object M which will be a manager of your objects by previous scheme of a class object.
With best wishes,
Vita
|
|
|
|
|
Hi,
I am having some content in textfile.iam reading the content from file by using API called Read file.I convert this string to bstr using (_bstr_t)string and then i called the method LoadXML(string,bool).But when iam parsing this iam not getting output.
why it is so.
Thanks in advance.
|
|
|
|
|
Hi,
I'm a newbie here and I was hoping if anyone knew ANYTHING about the ICustomDownload interface. It's a COM interface for allowing control of downloads from Internet Explorer. I think it was introduced for IE v5.5 or something.
I read something about it in MSDN, but I can't seem to find it anymore - plus it didn't show enough info.
You've probably seen programs like GetRight, GoZilla and DAP which I think implement this interface.
Cheers
Dazza
|
|
|
|
|
I am currently working on a project to migrate some delphi based com objects to .NET, for reasons that are beyond the scope of this post I am going to be doing this method by method - so I am looking at using managed components from unmanaged code.
As a test project, I create a simple delphi based com object with two methods :
RandMethodA : Returns a random number from 0-100
RandMethodB : Returns a random number from 101-200
The idea is the redirect calls into RandMethodA to a piece of .NET managed code that does exactly the same thing.
Right thats the theory over with, this is the problem I am encountering :
I have created the .NET code and using the "tlbexp" & regasm" tools I have created a TLB file for it, I then added this TLB file to the delphi COM code - when I compile with the new TLB I get alot of compile errors in a file called mscorlib_TLB.pas which seems to be something that is autogenerated when I import the .NET TLB into the project.
eg: (some not all)
[Error] mscorlib_TLB.pas(4984): Illegal type in OLE automation section: 'Byte'
[Error] mscorlib_TLB.pas(4991): Illegal type in OLE automation section: 'Single'
[Error] mscorlib_TLB.pas(4992): Illegal type in OLE automation section: 'Double'
[Error] mscorlib_TLB.pas(10396): Illegal type in OLE automation section: 'Byte'
[Error] mscorlib_TLB.pas(10403): Illegal type in OLE automation section: 'Single'
[Error] mscorlib_TLB.pas(10404): Illegal type in OLE automation section: 'Double'
[Fatal Error] ManagedRandServer_TLB.pas(45): Could not compile used unit 'mscorlib_TLB.pas'
I sincerly hope this makes sense to somebody
Thanks in advance
RANT : Why does my boss give me these "projects" aaarrrggghhh
|
|
|
|
|
If I have call a COM object in an in-process server, which modifies a pointer, passed to it, in a worker thread as followers.
CoInitialize( NULL );
IProfile Profile;
Profile.CreateDispatch(_T("AutomationDispatch.Profile"));
int Size = Profile.GetDataSize();
double * pData = new double[ Size ];
Profile.GetData( pData );
Every works OK.
But if I call CoInitialize( NULL ) in the main thread before creating the worker thread. Then I get the following run-time error
Heap block at 00148698 modified at 001486A8 past requested size of 8.
When I debug the code, the pointer memory address passed to the COM object is changed in the COM object implementation.
If I pass the address of the pointer to COM object. Then there are no heap errors. I assume this because the address is passed by value.
|
|
|
|
|
Since you are planning to pass your COM object to different thread, call CoInitializeEx(NULL, COINIT_MULTITHREADED); . Your worker thread need to call CoInitialize(NULL) too.
|
|
|
|
|
:(I have one COM with function Connect(string,integer) which connects to a Socket Server,and property, Status which returns integer.The COM is working fine with VB.But not working with ASP.but it is returning status from the COM.I tried with one more property which returns string.That is also returning perfactly.
My Conclusion is there might be some type conversion problem.Can anyone suggest anything please.And one more problem is the dll remains in use ,if i close the page also.
Big D
|
|
|
|
|
Hi,
I am facing a problem.
Following is the description:
I have a COM server(EXE).
It has a method, "ServerMethodAAA". The "ServerMethodAAA" method, calls a Dll function, "DllFuncDlg()". "DllFuncDlg()" function invokes a dialog box.
I have a client app for my COM Server, which loads COM Server in hidden mode.
Problem:
When client calls method, "ServerMethodAAA", the dialog is displayed in hidden mode. That is, behind client application. I want that dialog should appear in fore ground window.
Please suggest me.
Regards.
|
|
|
|
|
Did you try SetForegroundWindow function?
|
|
|
|
|
Thanks for your reply.
I have tried doing following in Initdialog
this->EnableWindow(TRUE);
this->ShowWindow(SW_SHOW|SW_SHOWNORMAL);
SetForegroundWindow();
BringWindowToTop();
But, no use.
Regards.
|
|
|
|
|
i just asked this on the visual c++ forum, but i think this is probably a better place to ask....here goes nothing
i have 2 methods that are using IWebBrowser2 to execute a print method from a com object that is hosted on a webpage. here is the code for the methods:
---------------------------------
STDMETHODIMP CTemplatePrinter::IEPrintNoPrompt(VARIANT varTemplateURL)
{
CComPtr<iolecontainer> spContainer;
CComPtr<iserviceprovider> spSP;
CComPtr<iwebbrowser2> spWB;
CComPtr<idispatch> spDisp;
CComPtr<ihtmldocument2> spDoc;
CComPtr<iolecommandtarget> spCT;
CComVariant vPTPath = varTemplateURL;
m_spClientSite->GetContainer(&spContainer);
spContainer->QueryInterface(IID_IServiceProvider, (void**)&spSP);
spSP->QueryService(SID_SWebBrowserApp, IID_IWebBrowser, (void**)&spWB);
spWB->get_Document(&spDisp);
spDisp->QueryInterface(IID_IHTMLDocument2, (void**)&spDoc);
spDoc->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
// ******* THIS IS WHERE IT'S GOING CRAZY!!!! ******* //
spCT->Exec(&CGID_MSHTML, IDM_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, &vPTPath, NULL);
return S_OK;
}
---------------------------------------
STDMETHODIMP CTemplatePrinter::IEPrint(VARIANT varTemplateURL)
{
CComPtr<iolecontainer> spContainer;
CComPtr<iserviceprovider> spSP;
CComPtr<iwebbrowser2> spWB;
CComPtr<idispatch> spDisp;
CComPtr<ihtmldocument2> spDoc;
CComPtr<iolecommandtarget> spCT;
CComVariant vPTPath = varTemplateURL;
m_spClientSite->GetContainer(&spContainer);
spContainer->QueryInterface(IID_IServiceProvider, (void**)&spSP);
spSP->QueryService(SID_SWebBrowserApp, IID_IWebBrowser, (void**)&spWB);
spWB->get_Document(&spDisp);
spDisp->QueryInterface(IID_IHTMLDocument2, (void**)&spDoc);
spDoc->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
// ***** IT CALLS THIS 2 TIMES? ******** //
spCT->Exec(&CGID_MSHTML, IDM_PRINT, OLECMDEXECOPT_PROMPTUSER, &vPTPath, NULL);
return S_OK;
}
--------------------------
my question is: does anyone have any idea why the IOleCommandTarget::Exec method it going berzerk? when i call the method from a script, the first one keeps spooling pages into the printer, and the second one opens 2 print dialogs in a row...i also have another function for opening a print preview window that works fine....the only difference is my call to Exec is as follows:
spCT->Exec(&CGID_MSHTML, IDM_PRINTPREVIEW, OLECMDEXECOPT_PROMPTUSER, &vPTPath, NULL);
i've tried all that i can see...if i replace spCT->Exec(...) with
spWB->ExecWB(OLECMD_PRINT, OLECMDEXECOPY_PROMPTUSER, &vPTPath, NULL);
it still does the same thing...i've even tryied without passing in the &vPTPath (printing template path) argument
i also know that the method is only getting called once...i tested this by also using spDoc to write some stuff out to pop up a message box every time it got called, and the message box only came up once, but the printing kept going...
any suggestions?
michael griffith
--------------------
mgriffith@lauren.com
mdg12@po.cwru.edu
|
|
|
|
|
I want to pass byte data from VB into a VC++ COM.
In a setData(VARIANT msgdata), I write the code below, but it has error in pdata[i] = *padata[i]. What's wrong ?
<br />
if ((msgdata.vt & VT_ARRAY) == 0)<br />
return E_INVALIDARG;<br />
if ((msgdata.vt & VT_UI1) == 0)<br />
return E_INVALIDARG;<br />
<br />
SAFEARRAY *psa = msgdata.parray;<br />
PBYTE *padata;<br />
<br />
SafeArrayAccessData(psa, (void **) &padata);<br />
<br />
int nsize = psa->rgsabound->cElements;<br />
PBYTE pdata = new BYTE[nsize];<br />
for (int i=0; i< nsize; i++)<br />
{<br />
pdata[i] = *padata[i];<br />
}<br />
<br />
SafeArrayUnaccessData(psa);<br />
In VB, I'm doing some testing code like:
<br />
Dim ba(2) As Byte<br />
<br />
ba(0) = 5<br />
ba(1) = 7<br />
ba(2) = 19<br />
<br />
compSSM.setData(ba)<br />
|
|
|
|
|
I think that you do not need the dereference of pointer. In padata you will have a pointer to some BYTE values after SafeArrayAccessData().
BYTE *padata;
SafeArrayAccessData(psa, (void **) &padata);
//only one directly, no of element is the data length
int nsize = psa->rgsabound->cElements;
PBYTE pdata = new BYTE[nsize];
for (int i=0; i< nsize; i++)
{
pdata[i] = padata[i];
}
or yet
memcpy( pdata, padata, nsize*sizeof(BYTE) );
With best wishes,
Vita
|
|
|
|
|
Thanks, it's working now. Even I don't have the loop to copy the array. I can use it directly within the block SafeArrayAccessData() and SafeArrayUnaccessData().
|
|
|
|
|
I am back to C++ at least for one project and need a quick solution to this problem:
I have a MathLib component, written in ATL, with two COM classes: MathLib.Matrix and MathLib.Vector. For those of you who have no background in math, vector is an array and matrix is 2 dimensional array (i.e. int a[3][3] is a matrix whereas int b[3] is a vector). I only encapsulated functionality to objects because I am going to use these two classes from SQL server and it does not support COM & arrays very well.
Now I would like to perform some quantitative analysis (mathematical operations) on these two classes.
Suppose I have MathLib.Fn COM class. This COM class has function that adds the contents of two arrays and returns array of sums.
For example, I have
[1 2 3] + [4 5 6] = [5 7 9]
(because 1+4=5, 2+5=7, 3+6=9)
My function name is AddVectors, it takes two vector object as input parameters and return vector object as output. This function is in the same C++ dll as the two other ATL classes.
Now I need to know what is the easiest way to declare this function? Don't forget that the Vector and Matrix object will most likely be generated by SQL server transact SQL and only then passed, so I'll be dealing with late binding.
Basically, this is how they'll be used:
SQL SERVER
m=create object mathlib.matrix <--- will probably create IDispatch *
populate m with some values
fn=create object mathlib.fn
n=new matrix
n=fn.execute_some_function(m) <--- will pass object to my COM object
And the second question is how to use these pointers in the function, do I need any marshalling? Anyone has sample of such code?
Kind Regards,
Tomaz
|
|
|
|
|
You can provide the such COM class, named as MathLib.Fn, like the MathLib.Matrix and MathLib.Vector. This class must expose the own interface. Let it be a IFn interface with several functions. For example,
HRESULT AddVectors([in] IVector* v1, [in] IVector* v2, [out,retval] IVector* *vsum );
HRESULT AddMatrices([in] IMatrix* m1, [in] IMatrix* m2, [out,retval] IMatrix* *msum ); and so on, as you want.
You could use it on manner, something like
Set n = fn.AddVectors(v1,v2) ' for some Vectors
With best wishes,
Vita
|
|
|
|
|
Hello to everybody.
I'm making a COM object which receive a VARIANT type, I recover this value from database in an ASP page as a Byte Array (it's a bitmap), the COM object must draw something over this bitmap and send again to the ASP page. My problem comes because I need extract the data from the VARIANT in a CLongBinary* but I haven't idea how can I do it.
Can you help me?
Thanks.
|
|
|
|
|
Hi,
I've been reading the Inside COM / Microsoft Press book and got to page 20 or so. The whole book so far states, that COM is language-free, vendor-free (combinig vendors), etc etc, everything withh evrything, just keep the standard and then something like
"calling conventions: MS uses __stdcall (in C++) for their component's methods (interface methods, ok) and __cdecl for variable parametr count methods. You don't have to follow it (and as state, with some languages (aka compilators) you don't even have a chance to follow it) but you have been warned that your application will no longer be able to use MS COMPONENTS...
what's that????????
anybody knows how to use OLE without MFC? I'd love a snippet!
|
|
|
|
|
Hi,
I'm a beginner in Com and I need help.
I don't manage to get my specific C++ object in my COM client.
I have a C++ DLL that contains this object :
Class CDDSR_MON;
I have a COM server that contains this coclass:
class ATL_NO_VTABLE CoDDSR_CORE
public:
CDDSR_MON * m_pDDSRCORE;
BEGIN_COM_MAP(CoDDSR_Monitoring)
COM_INTERFACE_ENTRY(IDDSR_Monitoring)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
I'd like to pass this pointer m_pDDSRCORE to my COM Client so I do that :
In my COM server :
STDMETHODIMP CoDDSR_CORE::getMonitoringInfo(IDDSR_Monitoring **mon){
CDDSR_Mon * ddsrMon;
IDDSR_Monitoring * iddsrMon;
HRESULT hr = ::CoCreateInstance(CLSID_DDSR_Monitoring, NULL,CLSCTX_LOCAL_SERVER,IID_IDDSR_Monitoring, (void**)&iddsrMon);
CComObject<coddsr_monitoring> *pmon;
HRESULT hRes = CComObject<coddsr_monitoring>::CreateInstance(&pmon);
pmon->m_pDDSRMonitoring = ddsrMon;
pmon->QueryInterface(IID_IDDSR_Monitoring, (void**)iddsrMon);
mon = iddsrMon;
return S_OK;
}
In my COM client :
CDDSR_Monitoring* ddsrMonitoring = NULL;
// Now we will intilize COM
hr = CoInitialize(0);
// Use the SUCCEEDED macro and see if we can get a pointer
// to the interface
if(SUCCEEDED(hr))
{
IDDSR_CORE* pDDSR_CORE;
hr = CoCreateInstance( CLSID_DDSR_CORE, NULL, CLSCTX_LOCAL_SERVER,
IID_IDDSR_CORE, (void**) &pDDSR_CORE);
if(SUCCEEDED(hr))
{
IDDSR_Monitoring* iMon;
hr = ::CoCreateInstance(CLSID_DDSR_Monitoring, NULL, CLSCTX_LOCAL_SERVER,IID_IDDSR_Monitoring, (void**) &iMon);
if(FAILED(hr))
pDDSR_CORE->getMonitoringInfo(&iMon);
}
// Uninitialize COM
CoUninitialize();
|
|
|
|
|
Since Nobody can tell me how to use thumbctl. I have to find another way.
I dont want to popup new window or run any script in my Browser control.
how to do it?
thanks a lot.
<--MFC-->
|
|
|
|
|
This is the problem: I have a third party control. I'd like to add more functionalities to the control. So, I created a composite control and drop the third party control onto my newly created composite control. Then I tried to use :
LPUNKNWON pUnknown = GetDlgItem(IDC_THIRD_PARTY_CONTROL_ID);
pUnknown->QueryInterface();
The problem is that GetDlgItem() did not return a CWnd pointer. Therefore, I could call QueryInterface().
Would someone help me?
How do I instantiate the third party control?
|
|
|
|
|
I have two dialog based programs. one is Microsoft Automation. and the other one calls first dialog-based app.
To call first dialog-based app ( let me just say it app2) from first dialog-based app ( app1), I used ShellExecute();
anyway, It is working fine if you compile and execute app1.exe within VC++ 6.0.
if you go to mycomputer-> right click-> window explore->go to app1 folder->debug-> app1.exe, and it is not working anymore.
the error at, which is in app2
<br />
_Application application;<br />
if(!application.CreateDispatch("Word.Application)<br />
{<br />
AfxMessageBox("Couldn't create Word.Applicaiton");<br />
<br />
}<br />
if I go back to run and execute app1.exe it works again. but not from double clicking on app1.exe in window explore.
I know that's OLE initialization problem where i declare
<br />
if(!AfxOleInit())<br />
{<br />
AfxMessageBox("Couldn't create OLE COM");<br />
}<br />
<br /> it is in BOOL Capp2App::InitInstance(). From my knownladge, if OLE libs didn't get initialized, I couldn't createDispagech("Word.Application");
How can I initialize OLE Lib evertime i use so i don't have to execute app1.exe inorder to get Word.Application?
|
|
|
|
|