|
scottdj wrote: The C++ Unmanaged DLL has been around for quite a while, it has been register via Component Services many times without problems.
Ok...so you can safely rule out a problem with the registration.
scottdj wrote: After removing the global, I can now register A.dll via RegSvr32, but when I attempt to register via Component Services, it just hangs.
Try using the Assembly binding log viewer tool I mentioned previously. This will allow you to see what assemblies the loader is trying to read in and where it is trying to read them from.
scottdj wrote: If indeed you have .NET 1.1 & .NET 2.0 code in a Dll it will use .NET 2.0 for everything then I think we have a problem with this in itself. Not necessarily the cause of Component Services hanging trying to Register A.dll. If indeed the code is running the .NET 2.0 Framework, there must be some mechanism to allow running of older components, at least I hope this is the case.
There is a way to target different runtime versions, see this
MSDN article[^] for more information. That being said, this probably isn't the problem.
Scott.
—In just two days, tomorrow will be yesterday.
—Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai
[ Forum Guidelines] [ Articles] [ Blog]
|
|
|
|
|
Could you expound on this statement:
>>I think part of the problem you are running in to is the fact that this >>is running under Component Services, so you don't really have any >>control over which version of the runtime will be loaded (it will >>always load the latest version of the runtime, regardless of what >>version the assembly was compiled against). Also, you can't have one >>process running different versions of the .NET runtime.
I have a C++ Unmanaged Console app, that does the COM Interop with the C# .NET 2.0 Class Lib, which in turn calls the C# .NET 1.1 Class Lib. This seems to work fine. So, in this case, nothing is registered via Component Services. I thought that the C# .NET 1.1 Class Lib would use .NET 1.1, and the C# .NET 2.0 Class Lib would use .NET 2.0. Are you saying that this is not the case?
THX
Scott
|
|
|
|
|
I can try...
When you start a .NET application, it must be run inside a specific sandbox (technically an AppDomain). Each process gets one AppDomain that is responsible for running (hosting) that process. Due to the way the runtime actually works, you can't have different versions of the runtime loaded in to the same process.
Normally, when you run an application it uses the version of the runtime that it was compiled against. However, a "third-party" application (such as Component Services) that is unmanaged must load (host) managed code it does so by loading the .NET runtime into it's memory space. The default behavior here is that the unmanaged process will always load the latest version of the runtime available on that machine. This means that if you have .NET 1.1 code it will be loaded and run under a .NET 2.0 environment.
scottdj wrote: I have a C++ Unmanaged Console app, that does the COM Interop with the C# .NET 2.0 Class Lib, which in turn calls the C# .NET 1.1 Class Lib. This seems to work fine. So, in this case, nothing is registered via Component Services. I thought that the C# .NET 1.1 Class Lib would use .NET 1.1, and the C# .NET 2.0 Class Lib would use .NET 2.0. Are you saying that this is not the case?
In this situation, the C++ console app would host the 2.0 runtime in order to call the C# 2.0 library. In turn, the 1.1 library would also be running under the 2.0 runtime since it is all in the same process space. Normally this isn't an issue. There are ways to target specific runtime versions, see this MSDN article[^] for more information.
Scott.
—In just two days, tomorrow will be yesterday.
—Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai
[ Forum Guidelines] [ Articles] [ Blog]
|
|
|
|
|
On another note, once I added Guid's to the Interface & Class in the C#.NET 2.0 Class Lib, I was able to add the componet to a COM+ application.
Two questions:
1) I run gacutil & RegAsm as part of the Post Build steps for the C# .NET 2.0 Class Lib. Do I need to run RegAsm, if I am going to add the component to a COM+ application?
2) Do I need to derive my class from System.EnterpriseServices.ServicedComponent to get the COM+ functionality? Remember that what I am adding is an C++ Unmanaged COM DLL, that just happens to link in a static lib that includes code to call the C# .NET 2.0 Class Lib via COM Interop.
THX
|
|
|
|
|
Both excellent questions, unfortunately I'm not sure of the answers.
1. My guess is that you probably do need to run RegAsm since the component is running under a COM application.
2. I think you would only need to derive from ServicedComponent if you were hosting the C# 2.0 library in COM+ directly.
Scott.
—In just two days, tomorrow will be yesterday.
—Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai
[ Forum Guidelines] [ Articles] [ Blog]
|
|
|
|
|
hi,
i tried to write a programm that gives me the "titel" information from files in a folder (if exists)
if my file is a word or excel file it works fine, but if i try to read the titel of an mp3 file (for example) i get the error-reply
STG_E_FILENOTFOUND
A property set of the indicated name does not exist.
http://msdn2.microsoft.com/en-us/library/aa379965(VS.85).aspx[^]
i found this tutorial: http://www.codeproject.com/KB/files/SummInfoPropSetFile.aspx[^]
but i could not figure out me mistake.
here my code that reads the titel information
<br />
const FMTID PropSetfmtid ={<br />
0xf29f85e0,<br />
0x4ff9,<br />
0x1068,<br />
{0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 }<br />
};<br />
-------------------------<br />
std::wstring get_titel(std::wstring path)<br />
{<br />
HRESULT hr = S_OK;<br />
IPropertyStorage *pPropStg = NULL;<br />
IPropertySetStorage *pPropSetStg = NULL;<br />
PROPSPEC propspec; <br />
PROPVARIANT propRead;<br />
<br />
hr = StgOpenStorageEx( path.c_str(),<br />
STGM_READ | STGM_SHARE_EXCLUSIVE, STGFMT_ANY, 0, NULL, NULL, IID_IPropertySetStorage,<br />
reinterpret_cast<void**>(&pPropSetStg) );<br />
<br />
if (hr != S_OK)<br />
return std::wstring(L"StgOpenStorageEx - ERROR");<br />
<br />
<br />
hr = pPropSetStg->Open(PropSetfmtid, STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READ, &pPropStg );<br />
<br />
if (hr != S_OK)<br />
return std::wstring(L"Open - ERROR");<br />
<br />
<br />
propspec.ulKind = PRSPEC_PROPID;<br />
propspec.propid = 0x00000002;
<br />
<br />
hr = pPropStg->ReadMultiple(1, &propspec, &propRead);<br />
<br />
if (hr != S_OK)<br />
return std::wstring(L"Read - ERROR");<br />
<br />
std::string temp = propRead.pszVal;<br />
TCHAR rtTC[1024]={0};<br />
MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, temp.c_str(), static_cast<int>(temp.length()), rtTC, static_cast<int>(temp.length()));<br />
<br />
std::wstring rtn = rtTC;<br />
<br />
pPropSetStg->Release();<br />
pPropStg->Release(); <br />
return rtn;<br />
}<br />
</int></int></void**>
the error usually occurs at this point : "pPropSetStg->Open(...)
does anyone has an idea what i'm doing wrong?
|
|
|
|
|
I have written a small C++ program, what can download a HTML page from a specified URL, and writes its body to a specified file (this is a simple command line utility). It is almost fine, but in few cases the Internet Explorer causes application error (instruction at address xxxx memory address xxxx can not be read, where to xxxx-s are same usually), immediately before my program finishes (or after, I don't know). I suspect, that this is a synchronization problem, may be I destroy some object (IWebBrowser2 or IConnectionPoint) too early, but I am unable to find this bug. I append my source code, please help me to find the bug. The code is commented in english, and in hungarian. Sorry for my english. Thanx in advance.
#include <windows.h><br />
#include <exdisp.h><br />
#include <mshtml.h><br />
#include <stdio.h><br />
#include <winnls.h><br />
#include <comdef.h><br />
#include <conio.h><br />
#include <exdispid.h><br />
#include <oleauto.h><br />
<br />
#define WM_CONNECTRELEASE WM_USER+100<br />
#define TIMEOUT 30000 //30 seconds<br />
<br />
#define PUT(x) x<br />
<br />
int DocumentDownloaded=0;<br />
<br />
class Sink : public IDispatch
{<br />
public:<br />
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void __RPC_FAR *__RPC_FAR *ppvObject)<br />
{<br />
PUT(printf("QueryInterface\r\n");)<br />
if(riid==IID_IUnknown || riid==IID_IDispatch || riid==DIID_DWebBrowserEvents2 || riid==DIID_DWebBrowserEvents){<br />
*ppvObject=(void*)this;<br />
AddRef();<br />
return S_OK;<br />
}<br />
else{<br />
*ppvObject=NULL;<br />
return E_NOINTERFACE;<br />
}<br />
} <br />
<br />
virtual ULONG STDMETHODCALLTYPE AddRef() <br />
{<br />
PUT(printf("AddRef\r\n");) <br />
InterlockedIncrement(&m_cRef);<br />
return m_cRef;<br />
} <br />
<br />
virtual ULONG STDMETHODCALLTYPE Release()<br />
{<br />
if(m_cRef>0)InterlockedDecrement(&m_cRef);<br />
if(m_cRef==1){<br />
PostMessage(0,WM_CONNECTRELEASE,0,0);
}<br />
PUT(printf("Release %d\r\n",m_cRef);)<br />
return m_cRef;<br />
}<br />
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT __RPC_FAR *pctinfo)<br />
{<br />
PUT(printf("GetTypeInfoCount\r\n");)<br />
return E_NOTIMPL;<br />
}<br />
<br />
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)<br />
{<br />
PUT(printf("GetTypeInfo\r\n");) <br />
return E_NOTIMPL;<br />
}<br />
<br />
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(<br />
REFIID riid,<br />
LPOLESTR __RPC_FAR *rgszNames,<br />
UINT cNames,<br />
LCID lcid,<br />
DISPID __RPC_FAR *rgDispId)<br />
{<br />
PUT(printf("GetIDsOfNames\r\n");)<br />
return E_NOTIMPL;<br />
}<br />
<br />
virtual HRESULT STDMETHODCALLTYPE Invoke(<br />
DISPID dispIdMember,<br />
REFIID riid,<br />
LCID lcid,<br />
WORD wFlags,<br />
DISPPARAMS __RPC_FAR *pDispParams,<br />
VARIANT __RPC_FAR *pVarResult,<br />
EXCEPINFO __RPC_FAR *pExcepInfo,<br />
UINT __RPC_FAR *puArgErr);<br />
Sink(IWebBrowser2 *pWebBrowser,HANDLE fo):m_pWebBrowser(pWebBrowser),m_cRef(1),m_pIConnectionPoint(0),m_dwEventCookie(0),m_hOutputFile(fo)<br />
{<br />
<br />
}<br />
<br />
~Sink()<br />
{<br />
<br />
}<br />
<br />
bool SetupConnectionPoint();<br />
<br />
void UnadviseConnectionPoint()<br />
{<br />
if(m_pIConnectionPoint){<br />
PUT(printf("Before Connectionpoint Unadvise\r\n");)<br />
m_pIConnectionPoint->Unadvise(m_dwEventCookie);<br />
m_dwEventCookie=0;<br />
<br />
PUT(printf("Before Connectionpoint Release\r\n");)<br />
}<br />
}<br />
<br />
ULONG ReleaseConnectionPoint()<br />
{<br />
ULONG ret=0;<br />
if(m_pIConnectionPoint!=NULL){<br />
ret=m_pIConnectionPoint->Release();<br />
m_pIConnectionPoint=NULL;<br />
}<br />
PUT(printf("After Connectionpoint Release\r\n");)<br />
return ret;<br />
}<br />
<br />
protected:<br />
<br />
IWebBrowser2 *m_pWebBrowser;<br />
IConnectionPoint *m_pIConnectionPoint;<br />
DWORD m_dwEventCookie;<br />
LONG m_cRef;<br />
HANDLE m_hOutputFile;<br />
};<br />
<br />
int DownloadDocument(IWebBrowser2 *pBrowser2,HANDLE fo)<br />
{<br />
IDispatch *pDoc=NULL;<br />
IHTMLDocument2 *pHtmlDoc=NULL;<br />
IHTMLElement *body=NULL;<br />
HGLOBAL hg=NULL;<br />
BSTR bstr=NULL;<br />
HRESULT hr;<br />
int ret=0;<br />
<br />
if(!SUCCEEDED(pBrowser2->get_Document(&pDoc))){<br />
goto vege;<br />
}<br />
if(!SUCCEEDED(pDoc->QueryInterface(IID_IHTMLDocument2,(void **)&pHtmlDoc))){<br />
pHtmlDoc=NULL;<br />
goto vege;<br />
}<br />
if(!SUCCEEDED(pHtmlDoc->get_body(&body))){<br />
goto vege;<br />
}<br />
if(!SUCCEEDED(body->get_innerText(&bstr))){<br />
goto vege;<br />
}<br />
hr=SysStringByteLen(bstr)/2;<br />
<br />
unsigned long m;<br />
char c;<br />
int i;<br />
for(i=0;i<hr;++i){><br />
c=bstr[i];<br />
WriteFile(fo,&c,1,&m,NULL);<br />
}<br />
ret=1;<br />
<br />
vege:<br />
if(pHtmlDoc!=NULL)pHtmlDoc->Release();<br />
return ret;<br />
}<br />
<br />
bool Sink::SetupConnectionPoint()<br />
{<br />
<br />
IConnectionPointContainer* pIConnectionPointContainerTemp=NULL;<br />
IUnknown *pIUnknown=NULL;<br />
bool ret=true;<br />
<br />
<br />
if(!SUCCEEDED(QueryInterface(IID_IUnknown,(void**)&pIUnknown))){<br />
ret=false;<br />
pIUnknown=NULL;<br />
goto vege;<br />
}<br />
<br />
if(!SUCCEEDED(m_pWebBrowser->QueryInterface(IID_IConnectionPointContainer,(void**)&pIConnectionPointContainerTemp))){<br />
ret=false;<br />
pIConnectionPointContainerTemp=NULL;<br />
goto vege;<br />
}<br />
if(!SUCCEEDED(pIConnectionPointContainerTemp->FindConnectionPoint(DIID_DWebBrowserEvents2,&m_pIConnectionPoint))){<br />
ret=false;<br />
m_pIConnectionPoint=NULL;<br />
goto vege;<br />
}<br />
if(!SUCCEEDED(m_pIConnectionPoint->Advise(pIUnknown,&m_dwEventCookie))){<br />
ret=false;<br />
m_dwEventCookie=0;<br />
m_pIConnectionPoint->Release();<br />
m_pIConnectionPoint=NULL;<br />
goto vege;<br />
}<br />
vege:<br />
if(pIUnknown!=NULL)pIUnknown->Release();<br />
if(pIConnectionPointContainerTemp!=NULL)pIConnectionPointContainerTemp->Release();<br />
return ret;<br />
}<br />
<br />
HRESULT STDMETHODCALLTYPE Sink::Invoke(<br />
DISPID dispIdMember,<br />
REFIID riid,<br />
LCID lcid,<br />
WORD wFlags,<br />
DISPPARAMS __RPC_FAR *pDispParams,<br />
VARIANT __RPC_FAR *pVarResult,<br />
EXCEPINFO __RPC_FAR *pExcepInfo,<br />
UINT __RPC_FAR *puArgErr)<br />
{<br />
PUT(printf("Invoke %d\r\n",dispIdMember);) <br />
if(dispIdMember==DISPID_DOCUMENTCOMPLETE){<br />
PUT(printf("Document complete\r\n");)<br />
IUnknown* pUnk;<br />
LPDISPATCH lpWBDisp,lpDisp;<br />
HRESULT hr;<br />
<br />
lpDisp=pDispParams->rgvarg[1].pdispVal;<br />
hr=m_pWebBrowser->QueryInterface(IID_IUnknown,(void **)&pUnk);<br />
hr=pUnk->QueryInterface(IID_IDispatch, (void**)&lpWBDisp);<br />
<br />
if(lpDisp==lpWBDisp){<br />
PUT(printf("Page complete\r\n");)<br />
DocumentDownloaded=DownloadDocument(m_pWebBrowser,m_hOutputFile);<br />
HRESULT hr;<br />
hr=m_pWebBrowser->Quit();<br />
PUT(printf("Quit %d\r\n",hr);)<br />
}<br />
<br />
lpWBDisp->Release();<br />
pUnk->Release();<br />
return S_OK;<br />
}<br />
else if(dispIdMember==DISPID_ONQUIT){<br />
UnadviseConnectionPoint();<br />
return S_OK;<br />
}<br />
else{<br />
return E_NOTIMPL;<br />
}<br />
}<br />
<br />
int main(int argc,char *argv[])<br />
{<br />
HANDLE fo=INVALID_HANDLE_VALUE;<br />
int ret=0;<br />
Sink *psink=NULL;<br />
IWebBrowser2 *pBrowser2=NULL;<br />
VARIANT vEmpty;<br />
WCHAR wurl[MAX_PATH];<br />
VariantInit(&vEmpty);<br />
BSTR bstrURL=NULL;<br />
<br />
DocumentDownloaded=0;<br />
<br />
if(argc<3){<br />
printf("\r\Usage: iecom <url> <output file="">");<br />
return 1;<br />
}<br />
<br />
if((fo=CreateFile(argv[2],GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))==INVALID_HANDLE_VALUE){<br />
return 1;<br />
}<br />
<br />
if(MultiByteToWideChar(CP_ACP,0,argv[1],-1,wurl,MAX_PATH)==0 || (bstrURL=SysAllocString(wurl))==NULL){<br />
CloseHandle(fo);<br />
return 1;<br />
}<br />
<br />
if(!SUCCEEDED(OleInitialize(NULL))){<br />
ret=1;<br />
goto vege;<br />
}<br />
<br />
if(!SUCCEEDED(CoCreateInstance(CLSID_InternetExplorer,NULL,CLSCTX_LOCAL_SERVER,IID_IWebBrowser2,(void**)&pBrowser2)) || pBrowser2==NULL){<br />
ret=1;<br />
goto vege;<br />
}<br />
<br />
psink=new Sink(pBrowser2,fo);<br />
if(psink==NULL || !psink->SetupConnectionPoint()){<br />
ret=1;<br />
HRESULT hr;<br />
hr=pBrowser2->Quit();<br />
PUT(printf("Quit %d\r\n",hr);)<br />
hr=pBrowser2->Release();<br />
PUT(printf("Webbrowser Release %d\r\n",hr);)<br />
goto vege;<br />
}<br />
<br />
if(!SUCCEEDED(pBrowser2->put_Visible(VARIANT_FALSE)) || !SUCCEEDED(pBrowser2->Navigate(bstrURL,&vEmpty,&vEmpty,&vEmpty,&vEmpty))){<br />
ret=1;<br />
HRESULT hr;<br />
hr=pBrowser2->Quit();<br />
PUT(printf("Quit %d\r\n",hr);)<br />
}<br />
<br />
<br />
UINT timer;<br />
timer=0;<br />
timer=SetTimer(NULL,0,TIMEOUT,NULL);
MSG msg;<br />
while(1){<br />
GetMessage(&msg,0,0,0);<br />
PUT(printf("WinMessage %d\r\n",msg.message);)<br />
if(msg.message==WM_TIMER){<br />
if(DocumentDownloaded==0){<br />
DownloadDocument(pBrowser2,fo);<br />
}<br />
HRESULT hr;<br />
hr=pBrowser2->Quit();<br />
PUT(printf("Quit %d\r\n");)<br />
}<br />
else if(msg.message==WM_CONNECTRELEASE){<br />
<br />
PUT(printf("ReleaseConnectionPoint\r\n");)<br />
ULONG rel;<br />
rel=psink->ReleaseConnectionPoint();<br />
PUT(printf("Connection point Release %d\r\n",rel);)<br />
rel=pBrowser2->Release();<br />
PUT(printf("Webbrowser Release %d\r\n",rel);)<br />
psink->Release();<br />
break;<br />
}<br />
DispatchMessage(&msg);<br />
}<br />
if(timer!=0)KillTimer(NULL,timer);<br />
vege:<br />
if(psink!=NULL)delete psink;<br />
SysFreeString(bstrURL);<br />
OleUninitialize();<br />
PUT(printf("After OleUninitialize\r\n");)<br />
CloseHandle(fo);<br />
return ret;<br />
}</output></url></hr;++i){></oleauto.h></dispatch.h></exdispid.h></conio.h></comdef.h></winnls.h></stdio.h></mshtml.h></exdisp.h></windows.h>
|
|
|
|
|
Inadvertently the vEmpty variable was not initialized before pBrowser2->Navigate(...). I did it, but this didn't solve the problem.
|
|
|
|
|
Hi Experts,
I am so curious to get the link file path but I could not. I am creating a shell context menu. As I click on link file(shortcut) Program resolve the name before the InvokeCommand() function. But in QueryContextMenu() I can detect the link file type through flag CMF_VERBSONLY but I could not get the link file path.
How can I do this?
|
|
|
|
|
I have the following:
- A C# Class Libary written in .NET 1.1, lets call this Component A.
- A C# Class Library written .NET 2.0 that servers as a wrapper for A, called B. B is set up for COM Inetop, Strong Name, installed in GAC, REGASM run. BTW it works fine from an unmanaged C++ Console app.
- I added a class to an existing static library to call methods in B, which in turn calls corresponding methods in A.
The static lib, where the C++ class resides in linked into a C++ unmanaged DLL.
- CoInitializeEx(NULL, COINIT_MULTITHREADED); has already been called in another part of the app, a MFC C++ app that servers as a test client.
- When I try and do a
pIPTConfigManagerCOM_InteropPtr.CreateInstance(PTConfigManagerCOM_Interop::CLSID_CFPTConfigManagerCOM_Interop);
I get the following in the output window:
<mda:msg xmlns:mda="http://schemas.microsoft.com/CLR/2004/10/mda">
<!--
Attempting managed execution inside OS Loader lock. Do not attempt to run
managed code inside a DllMain or image initialization function since doing so
can cause the application to hang.
-->
<mda:loaderLockMsg break="true"/>
</mda:msg>
ProductPayTestClient.exe has triggered a breakpoint
The breakpoint is it in vswprint.c
- I have turned off LoadLock exception being thrown in Debug->Exceptions->Managed Debuggin Assistants.
- I have declared a pointer to the Interface. Sometimes when I am stepping through, the pointer has an address of 0x00000000, but the m_pInterface seems to have a valid value. Sometimes when running MY test client, I see the Interface pointer is 0x00000000 and other times is seems to have a valid value. But in all cases my C++ unmanged test harness works, it, like the class I wrote in the static lib, imports the typelib, intellisense sees the members of the class.
Any ideas will be appreicated.
THX
Scott
|
|
|
|
|
More Info
The .NET 1.1 Class Library was written whith VS .NET 2003.
All other components were written with VS 2005.
|
|
|
|
|
This looks very much like this question[^]. Please don't re-post questions. Everyone here answers on a volunteer basis and may not respond in a timeframe you feel is appropriate. Posting multiple times generally doesn't help you get a response.
Scott.
—In just two days, tomorrow will be yesterday.
—Hey, hey, hey. Don't be mean. We don't have to be mean because, remember, no matter where you go, there you are. - Buckaroo Banzai
[ Forum Guidelines] [ Articles] [ Blog]
|
|
|
|
|
Dear All,
I have a com with source code compiled as dll now is there any way that i can use the class in dll without registering the com. I am new to com so dont have any idea about it
i read some where that with loadlibray we can use dll as late binding and get procaddres to access class or methods in .def file but is it possible to use class not in .def file
|
|
|
|
|
justintimberlake wrote: I have a com with source code compiled as dll now is there any way that i can use the class in dll without registering the com. I am new to com so dont have any idea about it
Check these two URLs. Let me know if this is what you are looking for.
Registration-Free Activation of .NET-Based Components: A Walkthrough[^]
Registration-Free Activation of COM Components: A Walkthrough[^]
Registering COM Applications[^] will help you understand COM application registration basics.
justintimberlake wrote: i read some where that with loadlibray we can use dll as late binding and get procaddres to access class or methods in .def file but is it possible to use class not in .def file
Yes, with LoadLibrary and GetProcAddress you can access functions in DLLs. But a COM Inprocess server is a special kind of DLL (that is designed with COM specification rules and with intention of it being used by COM aware clients). In general, as far as I know, to use a function using LoadLibrary and GetProcAddress, a function should be exported by that DLL. There are various ways to export a function, one of which is .DEF file you mentioned (see Exporting from a DLL [^] )
Let me know if this helps.
Sohail
modified 21-Apr-21 21:01pm.
|
|
|
|
|
Thanx Sohail for your i really appricite that. Can i ask you few question if i have any problem in near future because i was given only one day for the project and i couldn't do it so will have to see some other day only for my satisfaction. Once again thanx a lot
|
|
|
|
|
Sure. No problem.
Cheers,
Sohail
modified 21-Apr-21 21:01pm.
|
|
|
|
|
I am reading a book and it says the following:
"AddRef() and Release() calls by the client do not result in an ORPC call until the final release has been detected"
I can understand the benefit (of not having a round trip from client to remote server) but can anyone please enlighten me step by step me on this one? The illustration is a big box for the Client's Process Space which has 3 main entities inside: the Client, Proxy Manager, and the Channel Objects. The Proxy Manager aggregates all the Proxy Objects that make use of IRPCProxyBuffer (1 for each Proxy Object). The diagram also implies 1 Channel Object for each remote interface.
TIA.
I am a SysAdmin, I battle my own daemons.
|
|
|
|
|
Hi All,
I have an ActiveX control. And the event map is defined in the control's implementation (.CPP) file.
Say the event map has a function
EVENT_CUSTOM("SomeEvent", FireSomeEvent, VTS_BOOL)
defined in it...
Now I can very easily call the function 'FireSomeEvent' from the control's implementation cpp file.
Can I call 'FireSomeEvent' from some other cpp file....means some other's class's code ??
If yes then how??
Urgent help needed...
Thanks and Regards,
AbbyIndian
...A Programmer may or may not be the master of the programming language grammar...
|
|
|
|
|
Hi,
I tried the (provided) code as part of an AddIn for Excel. I am able to call the function and also pass data to it. However, midway through the processing Excel crashes. I use the default way to debug the application i.e. when it crashes I click on Debug and use the Visual Studio IDE to debug the application.
NOTE: Please bear in mind that I have almost no experience with Visual C++ and very little experience with C++. I have tried to build upon some code that was handed over to me and have succeeded in passing non-array variables from Excel to COM and performing operations and successfully returning values. I have started facing problems while passing and returning arrays.
I get the error: Unhandled exception at 0x77c47fd4 in EXCEL.EXE: 0xC00000005: Access violation reading location 0x00000008.
CODE:
<br />
STDMETHODIMP CAddin::TEST(VARIANT input, VARIANT* output)<br />
{<br />
LONG lstart, lend;<br />
LONG idx = -1;<br />
LONG nPOS;<br />
HRESULT hr;<br />
BSTR HUGEP* pbstr;<br />
pbstr[input.parray->rgsabound->cElements];<br />
std::list holder;<br />
SAFEARRAY *sa = V_ARRAY(&input);<br />
hr=SafeArrayGetLBound(sa,1,&lstart);<br />
if (FAILED(hr)) return hr;<br />
hr=SafeArrayGetUBound(sa,1,&lend);<br />
if (FAILED(hr)) return hr;<br />
LOG_DEBUG(lstart<<" "<<lend<<std::endl);<br />
USES_CONVERSION;<br />
hr=SafeArrayAccessData(sa,(void HUGEP* FAR*)&pbstr);<br />
LOG_DEBUG("PBSTR "<<pbstr<<" "<<*pbstr<<std::endl);<br />
if (SUCCEEDED(hr)){<br />
for (idx=lstart;idx<=lend;idx++){<br />
CComBSTR s;<br />
LOG_DEBUG(idx<<" "<<pbstr[idx]<<std::endl);<br />
holder.push_back(W2A(s.m_str));<br />
}<br />
hr=SafeArrayUnaccessData(sa);<br />
if (FAILED(hr)) return hr;<br />
for (int i=0;i<holder.size();i++){><br />
LOG_DEBUG("Vals "<<holder.front()<<std::endl);<br />
holder.pop_front();<br />
}<br />
}<br />
else<br />
return hr;<br />
}<br />
</holder.size();i++){>
The LOG_DEBUG (...) function simply prints stuff into a log file.
From the debug session, it looks like the value for pbstr is ok, it is 06BAE7E8 but the value stored at that location is not good, it is 0x00000008 which is an inaccessible location address. Does this mean that the SafeArrayAccessData is not providing me with the correct memory addresses? BTW, the bounds of the passed array are good and so is the data in the safearray as I have found out from the debug session.
When I debug the crash, I get to see the following code:
<br />
CComBSTR& operator=(__in_opt LPOLESTR pSrc)<br />
{<br />
if (pSrc != m_str){<br />
::SysFreeString(m_str);<br />
if (pSrc != NULL){<br />
m_str = ::SysAllocString(pSrc);<br />
if (!*this)<br />
{<br />
AtlThrow(E_OUTOFMEMORY);<br />
}<br />
}else{<br />
m_str = NULL;<br />
}<br />
return *this;<br />
}<br />
The value for pSrc us 0x00000008<bad_ptr> and the value for m_str is 0x00000000<bad_ptr>.
Some questions:
1. Why am I getting an inaccessible location address?
2. Why do we use HUGEP* and FAR* instead of a simple **? I was using ** earlier but in my efforts to make this work, picked these up from some googled doc/articles online.
3. HOW can I paste stuff into this textbox? I had to rewrite all the code and it has also lost its indentation?
Thanks for any help in this matter. I assure you all, that once I get this working I'd get over this mental block about Visual C++. I want to know what is it that I am doing wrong here...
Cheers
Sukant
P.S. Again, please note that I have just begun my journey of COM/VisualC++/C++, so I would really appreciate any pointers (or FAR* for that matter) on this issue. Any criticism and feedback is more than welcome.
|
|
|
|
|
ssaddi wrote: 1. Why am I getting an inaccessible location address?
My guess is that input does not contain an array of BSTR. I'd suggest adding a check that input.vt is the correct value, which would be something like (VT_ARRAY | VT_BSTR) .
ssaddi wrote: 2. Why do we use HUGEP* and FAR* instead of a simple **? I was using ** earlier but in my efforts to make this work, picked these up from some googled doc/articles online.
You can probably leave out the HUGEP and FAR. They come from the Windows 3.1 days or earlier.
ssaddi wrote: 3. HOW can I paste stuff into this textbox? I had to rewrite all the code and it has also lost its indentation?
You can paste into almost any text box using Ctrl-v. To keep the indentation, you need to put your sections into a <pre></pre> block.
Nathan
|
|
|
|
|
Thanks for your response Nathan.
From the debug session, input looks like this
<br />
input | safearray of VARIANT=[84](BSTR=0x001a5a74"129521",BSTR=0x001a5b54"142732".....)<br />
input | vt = 8204<br />
| safearray | <br />
| [0] | BSTR=0x001a5a74"129521" | vt = 8<br />
I have tried to put in textual representation of the tree kind of view of the variable I get to see while debugging. It looks like it is an array of BSTRs. Does this provide any insight on what I am doing wrong here?
Thanks for the point about HUGEP* and FAR*, hated those in my code anyway...so from now onward won't be using them at all.
BTW, I tried CTRL-V last time and this time as well. All I get when I try to paste something is . Is anyone else getting annoyed because of this?
Again, any help will be appreciated people. Looking forward to some replies.
Cheers
Sukant
|
|
|
|
|
ssaddi wrote: I have tried to put in textual representation of the tree kind of view of the variable I get to see while debugging. It looks like it is an array of BSTRs. Does this provide any insight on what I am doing wrong here?
To me, it looks like an array of variants, each of which contains a BSTR.
ssaddi wrote: BTW, I tried CTRL-V last time and this time as well. All I get when I try to paste something is . Is anyone else getting annoyed because of this?
It sounds like something is very wrong on your computer. It may be your web browser. I suppose that it could ba a bug in Code Project, but if it is, it's one that doesn't affect most people.
Nathan
|
|
|
|
|
I didn't receive a response to my last post. Was it useful?
Nathan
|
|
|
|
|
Hi Nathan,
Sorry I was a little busy with implementing stuff because of that response. It was very useful. Turns out that it was a variant of variants with each containing a BSTR within it.
Actually, that variant of variants is also returned by another call to one of the other functions in my dll which uses one of the produc's available functions. Their function converts std::list<std::string> to Variant[Variant[BSTR]]. It's all good as long as I know what is coming out as resultant from the product's library functions. I think I'll try and make my own function to create variant of BSTRs instead of Variant of Variants.
Anyway, Thanks for all your help. You have been very helpful.
Cheers
Sukant
|
|
|
|
|
ssaddi wrote: Sorry I was a little busy with implementing stuff because of that response. It was very useful. Turns out that it was a variant of variants with each containing a BSTR within it.
Thanks! I'm glad I helped.
I'm not sure what you mean by what is wrong with the code. It looks like the createStringArray function is intended to create a variant array of variants, each of which is a BSTR. What is the problem you want to fix?
Nathan
|
|
|
|
|