|
Advantages:
Any idiot can code VB COM components.
Disadvantages:
Only idiots code VB COM components.
Furor fit laesa saepius patientia
|
|
|
|
|
nice one, daniel.
Sorry ganesh I do not have any links to pass on. As it must be obvious to you, in VB you don't really get a taste of what is COM. In VC++/ATL you get to meddle around with the inner working's of COM and get a real feel of how complicated COM actually is.
I'm an alien, I'm an alien
it's a beautiful life....
Bush
|
|
|
|
|
Ease of development v's tighter (better;) ) code.
|
|
|
|
|
Hi All,
I am developing an application which uses SQL Server CE as the database, from which I need to synchronize the data to the SQL Server on the server machine. When I tried to synchronize the data using the emulator, it worked perfectly. But, when I tried the same application on my iPAQ pocket PC, I got an error, "DLL for the class not found". When I debugged, the CoCreateInstance() method fails and returns the HRESULT with the error code corresponding to this error message. When I checked the CLSID on the registry, an entry was there in the registry and the corresponding DLL was there in the /Windows directory . Could any one help me to come out of this problem. Any help on this highly appreciated.
This is the line of code I wrote:
hr = CoCreateInstance(CLSID_RemoteDataAccess, NULL, CLSCTX_INPROC_SERVER, IID_ISSCERDA, (LPVOID *)&m_pRda);
Jabir
|
|
|
|
|
hello
i have this com function (using ATL):
STDMETHODIMP Cmanager::iniGetString(BSTR sSectionName, BSTR sKeyName, BSTR sFileName, BSTR *sRetVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
char sTemp[MAX_PATH];
memset(sTemp, '\0', MAX_PATH);
GetPrivateProfileString (_bstr_t(sSectionName), _bstr_t(sKeyName), "none", sTemp, MAX_PATH, _bstr_t(sFileName));
sRetVal = SysAllocString ((OLECHAR *)sTemp);
return S_OK;
}
the sRetVal return nothing.
how can i return sTemp?
|
|
|
|
|
Hi,
Try using the .copy member of the _bstr_t class. Something like this has worked well for me:
STDMETHODIMP XXX::get_String(/*[out, retval]*/ BSTR* pVal)
{
HRESULT hr;
_bstr_t aBstr = "Hello!!";
*pVal = aBstr.copy();
return S_OK;
}
|
|
|
|
|
There are two problems with the code. First, sRetVal is a pointer to a BSTR, so assigning to sRetVal won't do anything. Second, sTemp isn't a Unicode string, so casting it to (OLECHAR*) will give you unpredictable results. You can use CComBSTR to handle the memory allocation and character set conversion:
CComBSTR bstr ( sTemp );
*sRetVal = bstr.Detach();
--Mike--
http://home.inreach.com/mdunn/
Trillian: What are you supposed to do with a manically depressed robot?
Marvin: You think you've got problems. What are you supposed to do if you are a manically depressed robot?
|
|
|
|
|
Hello everyone!I am Sree Ram working on COMAddins for Word2000 and Excel2000.I have programmatically added a Command Bar and Menu Bar (and menu items) for both Word2000 and Excel2000.The button Handlers for these r working properly according to the code.My problem is both the Word and Excel are giving a macro security warning.The Word2000 is saying "the macro cannot be found or has been disabled because of your Macro Security settings" and the Excel2000 is saying "The macro cannot be found".I added the command bar and menu bar programmatically using ATLCom.I changed the security level by using tools/macros and templates and security.But this didnot solve my problem.Can anyone who has previously solved this problem or is able to solve this problem kindly help me to solve this problem.Please reply back to me.
Bye
Thanking You,
Sincerely,
Sree Ram
|
|
|
|
|
Does the MFC classes CFtpFileFind and CFtpConnection support timeouts?
I'm an alien, I'm an alien
it's a beautiful life....
Bush
|
|
|
|
|
CFtpFileFind don't need Timeout because is a boolean, the file is there or not...
CFtpConnection, have a own timeout, You can't set the timeout time. I think that the timeout can be seted in the registry.
Cheers!!!
Carlos Antollini.
Happy Friday
|
|
|
|
|
I am trying to instantiate a COM Server on a remote machine without
configuring either the client or the server machine via DCOMDNCFG.EXE.
Basically, the COM Server will NOT be registered on the client machine, but
only registered on the server machine. The calling client is a VB COM
object trying to remote another COM object. I have it working with some
objects that I wrote... but I cannot get it to work with the SQLDMO objects
(Server/Restore).
I found some information on the web for doing something similar, but it only
worked if you had a dummy COM server with the same interface registered on
the client machine so that when calling CLSIDFromProgID(), the call would
succeed in retrieving the CLSID for the later call to CoCreateInstanceEx().
I changed it to pass in the CLSID so I didn't need the call to
CLSIDFromProgID(), and I convert it to a UUID structure for passing to
CoCreateInstanceEx(). It works with some other VB objects I wrote... and
at first, I thought it was because they are registered on the client
machine. However, so are the SQLDMO objects, and they fail to work using
this method.
See the code below. Anyone have any ideas for me?
Thanks,
Rob
--
Public Function CreateObjectRemoteByCLSID(ByVal strCLSID As String, ByVal
strServerName As String) As Object
' NOTE: Can be used even if the CLSID specified is NOT installed on
client machine.
Const PROC_NAME = MODULE_NAME & ".CreateObjectRemoteByCLSID"
Const RPC_S_OK As Long = 0
Dim server() As Byte
Dim QI As MULTI_QI
Dim SS As SERVER_STRUCTURE
Dim refiid(16) As Byte
Dim lngReturn As Long
Dim CLSID As UUID
' ensure that leading and trailing {} are dropped
If Right$(strCLSID, 1) = "}" Then strCLSID = Left$(strCLSID,
Len(strCLSID) - 1)
If Left$(strCLSID, 1) = "{" Then strCLSID = Mid$(strCLSID, 2)
' build UUID structure from CLSID
lngReturn = UuidFromString(strCLSID, CLSID)
If lngReturn <> RPC_S_OK Then
Err.Raise -1, PROC_NAME, "Invalid CLSID: " & strCLSID
End If
' setup variables for CoCreateInstanceEx; initialize OLE
GetIIDforIDispatch refiid() 'set an IID for IDispatch
QI.pIID = VarPtr(refiid(0)) 'point to the IID
server = strServerName & Chr$(0) 'specify the server
OleInitialize 0 'initialise OLE
' point to server name and
' invoke a remote instance of the desired object
SS.pServer = VarPtr(server(0))
lngReturn = CoCreateInstanceEx(CLSID, 0, 16, SS, 1, QI)
If lngReturn <> 0 Then
Err.Raise lngReturn, PROC_NAME, "CoCreateInstanceEx returned error
code " & Hex$(lngReturn)
End If
' pass back object reference
Set CreateObjectRemoteByCLSID = QI.pInterface
End Function
|
|
|
|
|
I am developing an application which confirms to COM specifications in VC++ 6.0 using ATL COM. Some times I need to pass nearly more than 100 variable values across components, for which I need to provide Set / Get functions to set the get the same, which is tedious.
In order to avoid writing 200 functions, I have a thought of creating a structure or class with those variable and sending the object of this structure/class across components.
Could you please help me to accomplish the same?
(with some sample code )
Thanking you ...
Shesh
|
|
|
|
|
Are these variables are of the same type? You could send an array (look up size_is() and length_is() in IDL). You may want to consider using an enumerator.
|
|
|
|
|
Hi Shesh,
If the variables fits logically into a structure, you can create a COM object/interface to encapsulate the contents of this structure. Then just pass the disp interface of the structure across. This is the most generic way to do this, and will allow all types of clients (including scripting cilents) access to the contents of the struct. When you get the disp interface on the other side, just QI for the specific interface. Add the fields in the struct as read/write properties on the COM object representing the structure. This will still conform to the oleautomation attribute if you are using dual interfaces.
The interface for the object that contains the struct could look something like:
[
object,
uuid(D867979C-B209-41CD-9EA9-2455B98C64F1),
dual,
helpstring("IMyObject Interface"),
pointer_default(unique)
]
interface IMyObject : IDispatch
{
[id(1), helpstring("method GetData")] HRESULT GetData([out, retval] LPDISPATCH* pVal);
};
While the interface for the struct might look like:
[
object,
uuid(979D94E5-A586-452D-855D-0CE997BCC0AC),
dual,
helpstring("IDataStruct Interface"),
pointer_default(unique)
]
interface IDataStruct : IDispatch
{
[propget, id(1), helpstring("property Field1")] HRESULT Field1([out, retval] double *pVal);
[propput, id(1), helpstring("property Field1")] HRESULT Field1([in] double newVal);
[propget, id(2), helpstring("property Field2")] HRESULT Field2([out, retval] double *pVal);
[propput, id(2), helpstring("property Field2")] HRESULT Field2([in] double newVal);
};
In general, you can pass "objects" around in a dispatch friendly way by passing their dispatch interfaces, then dispatch clients will be able to use them. C++ clients can QI for the most specific interface (in this case, IDataStruct).
If you are not exposing dual interfaces on your COM object, you may want to have a look at the MIDL struct declaration. This would only be useful if you are using custom interfaces and did not have to worry about satisfying the oleautomation attribute.
I think there are a lot of other approaches to this as well, but I've had success with this one.
|
|
|
|
|
Hi,
I might look a bit selfish here, but,
have you tried this ?
www.codeproject.com\atl\udtdemo.asp
Hope this helps
|
|
|
|
|
I have had problem with registering COM components on clean winNT (sp 6) systems. Now it seems that the c++ runtime libraries on a clean system are older than on a system with WinNT & visual studio 6 (sp 4). Is there any way (application/source) that can check for MISSING dependencies of a COM component (exe & dll)?
regards,
Brian.
|
|
|
|
|
Hi,
Would you tell me How to send variant data type to Invoke method of a IDispatch interface through "named argument"?
I am doing Excel automation in C++. I got the pointer to Worksheet IDispatch interface. From this interface I want to get the pointer to Range IDispatch interface. The Range method in Worksheet IDispatch interface with take the cell position (eg. A1, A2) as in parameter of type VARIANT.
I need the information of how to send this argument to Invoke method of Range IDispatch interface.
regards,
Shiva
|
|
|
|
|
HRESULT hr=ADsGetObject(L"WinNT://chenway",
IID_IADsContainer,
(void**)&pSchema);
LPOLESTR szBuffer = new OLECHAR[MAX_PATH*2];
wcscpy(szBuffer,L"cn=");
wcscat(szBuffer,L"TestAttrName");
if (!pSchema)
return E_POINTER;
hr = pSchema->Create(L"attributeSchema",szBuffer,&pDisp);
the pDisp pointer is returned NULL?why?
I want to add the user class a new attribute.
Sandos
|
|
|
|
|
I have little experience with COM and am trying to build my knowledge in this department
The plan :
Create a COM object which will handle writing records and deleting records from a file.
What I've done so far:
(I didn't get very far) I created a new ATL COM AppWizzard project. Then I inserted a new simple Simple ATL Object. This created my interface. I then tried to add the following function to the interface:
HRESULT writeRecord (char * record, int recordLength)
The Problem:
After doing this I compiled the project and got the following error:
template <class t1="">
class CComCreator
{
public:
static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
{
ATLASSERT(*ppv == NULL);
HRESULT hRes = E_OUTOFMEMORY;
T1* p = NULL;
ATLTRY(p = new T1(pv))//--------------> Error occurs here!!
if (p != NULL)
{
p->SetVoid(pv);
p->InternalFinalConstructAddRef();
hRes = p->FinalConstruct();
p->InternalFinalConstructRelease();
if (hRes == S_OK)
hRes = p->QueryInterface(riid, ppv);
if (hRes != S_OK)
delete p;
}
return hRes;
}
};
"c:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1827) : error C2259: 'CComObject<class cfileeditor="">' : cannot instantiate abstract class due to following members:
c:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1823) : while compiling class-template member function 'long __stdcall ATL::CComCreator<class atl::ccomobject<class="" cfileeditor=""> >::CreateInstance(void *,const struct _GUID &
,void ** )'"
My Guess:
The compiler doesn't like the char* parameter in the function. I added some functions successfully, however none of them received a char* as an argument
Could someone explain this to me?
Thank you
|
|
|
|
|
not sure about the compiler error, but you're right that COM doesn't like "char *". COM likes "BSTR"s for strings. this is a length-prefixed string with two bytes per character. it's not a C=style string by any means.
you should take a look at classes like _bstr_t or CComBSTR.
actually, that compiler error probably says that the IDL file or your ATL object's .h file is declaring something that you haven't implemented.
-c
------------------------------
Smaller Animals Software, Inc.
http://www.smalleranimals.com
|
|
|
|
|
Alright I've changed things around so that my function looks as follows:
HRESULT writeRecord(BSTR record, int recordLength, BSTR fileName)
Function definition is:
// FileEditor.cpp : Implementation of CFileEditor
#include stdio.h
#include comdef.h
#include "stdafx.h"
#include "FileEdit.h"
#include "FileEditor.h"
/////////////////////////////////////////////////////////////////////////////
// CFileEditor
STDMETHODIMP CFileEditor::writeRecord(BSTR record, int recordLength, BSTR fileName)
{
FILE * file = NULL;
_bstr_t fName = fileName;
char * pFName = fName.operator char *fName;
file = fopen(fileName, "r+");
return S_OK;
}
Now for some reason the compiler doesn't recognize the _bstr_t data type (even though I have included the comdef.h file).
|
|
|
|
|
try swapping the stdafx.h and comdef.h includes.
-c
------------------------------
Smaller Animals Software, Inc.
http://www.smalleranimals.com
|
|
|
|
|
What is the exact error message?
Does the following code make any difference
_bstr_t fName(fileName);
char* pFName = (char*) fName;
|
|
|
|
|
EUREKA!!!
THANKS GUYS!
The cause of the problem was that stdafx.h wasn't the first file include.
the result:
// FileEditor.cpp : Implementation of CFileEditor
#include "stdafx.h"
#include stdio.h
#include comdef.h
#include "FileEdit.h"
#include "FileEditor.h"
/////////////////////////////////////////////////////////////////////////////
// CFileEditor
STDMETHODIMP CFileEditor::writeRecord(BSTR record, int recordLength, BSTR fileName)
{
FILE * file = NULL;
_bstr_t fName = fileName;
char * pFName = fName.operator char *();
file = fopen(pFName, "r+");
return S_OK;
}
|
|
|
|
|
Hi!
We have :
typedef struct Str_ {
int array[100];
int n;
//...
} Str;
and a member variable Str x;
I want x to be exported into
an ActiveX control, using Visual C++6, and I don't know what
is the appropriate last parameter in the DISP_PROPERTY macro.
Wish for help!
Thanks!
|
|
|
|
|