|
Well COM was originally intended to be a solution for DLL Hell[^]. In the old days... when CompanyX updated a Microsoft distributable DLL... it would often break the application written by CompanyY. "The procedure entry point.. blah blah could not be located..."
So naturally the user would phone CompanyY and complain about the crash. At this point CompanyY would send the user the original DLL to fix the issue. One problem... now the application written by CompanyX no longer works. COM was suppose to fix the problem by allowing multiple versions of the same component to be installed on the system and be located using a GUID in the registry.
Fast forward to the modern era... we still have the DLL Hell problem... and the new solution is called WinSxS[^].
History lesson over, lets have this conversation again in 10 years and see whats changed.
Best Wishes,
-David Delaune
|
|
|
|
|
Well it seems that the COM is like a patch of ActiveX and may be is more significant when we talk about Avtivex with Internet and browsers than Applications. Anyway Thanks for your reply even if the idea about COMs and The Hell of Dlls still fuzzy
Thank You
"The Ultimate Limit Is Only Your Imagination."
|
|
|
|
|
COM is the foundation ActiveX is build upon. DLL hell was just one of the problems COM was designed to solve, and it's not the major one. Essentially COM is a technology designed to provide language independent binary components.
Steve
|
|
|
|
|
I cam back just to say that your link for the WinSxS was very interesting and i knew many things that i ignored before. With the Dll Hell link i noticed that the interfaces are used to fix the uncompatibility of differents versions of Dlls and so when it says interaces that means the use of ATL / COM. That's the only fact that i had by reading that. SO am I right ??
"The Ultimate Limit Is Only Your Imagination."
|
|
|
|
|
Blood_HaZaRd wrote: so when it says interaces that means the use of ATL / COM. That's the only fact that i had by reading that. SO am I right ??
Not exactly. Win32, managed or COM components can be stored in an assembly (and much more). Side-by-side (SxS) simply keeps track of dependencies that your application needs. The contents of this collection is determined by your application manifest. For example... one of the most commonly used shared assemblies is Comctl32.DLL. You can tell the SxS manager which version of this DLL you require by adding a manifest file to your application.
Some additional documentation for you:
The End of DLL Hell[^] (Look at the date!)
Authoring DLLs for Side-by-side Assemblies[^]
Using Isolated Applications and Side-by-side Assemblies[^]
If you are wondering what the future holds for SxS then you should keep track of the recent Activation Contexts[^]. I was forced to learn everything I could about SxS Activation Contexts late last year when I began experiencing a strange bug in one of the products I maintain. You can read about it here:
http://www.codeproject.com/Messages/3282355/Re-0xC015000F-The-activation-context-being-deactiv.aspx[^]
Best Wishes,
-David Delaune
|
|
|
|
|
|
COM's got some advantages compared to calling functions in DLLs or rolling your own interprocess communication:
- Does all the marshalling for you
- Your components can be used relatively easily and transparently from non-C or C++ languages
- Location transparent (ish), your components can be in the same process, a different process or at the end of some convoluted communications network
Against that it's a bitch to use properly especially in languages that don't support it directly (e.g. C and C++). To be honest if you're writing code that doesn't need any of the things I've mentioned above stick to straight DLLs written in the same language as you main application.
Cheers,
Ash
|
|
|
|
|
Yeah Yeah, Indeed. Thank you
"The Ultimate Limit Is Only Your Imagination."
|
|
|
|
|
Hi ,
I have created one ATL COM add ons for IE which write file on C:\users\sample.txt path.
When i run application on my machine(Vista) then it writes files as correctly, but when I run application of another vista machine ,file is not written. Is there any setting in Vista which allow to write file on C:\users folders.
Thanks
ABM
|
|
|
|
|
It sounds to me as if the second machine has Internet Explorer running in protected mode. If this is the case then you will need to instead write your files into the FOLDERID_LocalAppDataLow special folder.
PWSTR pszPath[1];
HRESULT hr = SHGetKnownFolderPath(FOLDERID_LocalAppDataLow,KF_FLAG_NO_ALIAS | KF_FLAG_DONT_VERIFY,NULL,pszPath);
CoTaskMemFree(*pszPath);
Understanding and Working in Protected Mode Internet Explorer[^]
Best Wishes,
-David Delaune
|
|
|
|
|
Both machin have protected mode ON. But on other machin File is not written. Is there any other reason behind this?
abm
|
|
|
|
|
am 2009 wrote: Is there any other reason behind this?
If the GetLastError Function[^] is telling you Error 5 (Access Denied) then I would suggest redesigning your application so it can operate in a least-privilege environment.
Why do you need to write to the C:\Users folder? In my opinion applications should not be attempting to write into this folder.
Best Wishes,
-David Delaune
|
|
|
|
|
Thanks David,
Actually it is my project requirement that to write file in C:\Users folder. In my case file is created but, it application could not write any data into it. This is happend only on one testing machine of windows Vista.
Thanks
ABM
|
|
|
|
|
Problem with Activex control property pages. when any of the properties are changed and next property page is clicked using tabs and oncancel button is clicked of the property sheet the properties are saved.
When property page is changed "onapply" is getting called automatically and DoDataExchange function is gets called and properties gets updated even after oncancel button.
Inorder to avoid this wht needs to be done
sreenivas003@yahoo.co.in
|
|
|
|
|
class MyClass{
public:
MyClass(int key):fKey(key) {}
const int GetKey() const { return fKey; }
private:
int fKey;
};
bool operator==(const MyClass& lh, const MyClass& rh)
{
cout<<lh.GetKey()<<" "<<rh.GetKey()<<endl;
return (lh.GetKey() == rh.GetKey());
}
list<MyClass> myList;
MyClass val(3);
cout<<"Before remove"<<endl;
myList.remove(val);
cout<<"After remove"<<endl;
template<typename _Tp, typename _Alloc>
void
list<_Tp, _Alloc>::
remove(const value_type& __value)
{
iterator __first = begin();
iterator __last = end();
while (__first != __last)
{
iterator __next = __first;
++__next;
if (*__first == __value)
_M_erase(__first);
__first = __next;
}
}
void
_M_erase(iterator __position)
{
__position._M_node->unhook();
_Node* __n = static_cast<_Node*>(__position._M_node);
this->get_allocator().destroy(&__n->_M_data);
_M_put_node(__n);
}
My questing is whether it is possible that the value of "__value" might be changed in list::remove()?
I got a strange problem, it might remove 2 items from myList in only one statement "myList.remove(val);".
The log looks like:
Before remove
1 3
2 3
3 3
4 4
5 4
After remove
The issue is at the line "4 4", does anybody have any idea what happend?
My guess is the statement in list::remove() "_M_erase(__first);" might release or delete the object that __first is pointing to,
and which just is __value. I mean the object __value is not really existed any more after the statement. Is that possible?
Did i miss something? Or there is any rule i need to follow while using container list on MAC?
PS:
The code i posted is just a sample. In my real project, a customized type is used but not "int".
modified on Thursday, May 13, 2010 10:19 PM
|
|
|
|
|
I think i have got the reason, let's see the source code on Windows from MS vc++.
void remove(const _Ty& _Val_arg)
{ // erase each element matching _Val
/* Dinkumware makes a copy of _Val_arg in case it's removed along the way, i.e.
* when the user pass an element of the list as _Val_arg.
*
* We believe that the signature of std::list::remove should be changed
* from remove(const _Ty&) to remove(_Ty) to explicitly indicate that a copy is involved.
*/
const _Ty _Val = _Val_arg; // in case it's removed along the way
iterator _Last = end();
for (iterator _First = begin(); _First != _Last; )
if (*_First == _Val)
_First = erase(_First);
else
++_First;
}
Please pay attention to statement "const _Ty _Val = _Val_arg;" ant its comment.
The problem i faced is, the argument that passed into list::remove() is the object from list.
That means on MAC, the statement "_M_erase(__first);" would destroy the object __first pointing to, unfortunately, __first is pointing to __value.
Therefore, after "_M_erase(__first);", the __value is destroyed. Make a copy to be the argument to remove items from list is the solution.
|
|
|
|
|
Hey all,
I'm using the ATL on Windows Mobile 5/6. I have a non-modal dialog which derives from CStdDialogImpl and CMessageFilter (to call IsDialogMessage in PreTranslateMessage). In the OnFinalMessage handler i do a "delete this;" So far so good.
Once my dialog is up and the user decides to exit the application, my non-modal dialog eventually receives a WM_DESTROY, as expected. The child windows of that dialog are also supposed to get the WM_DESTROY msg. However, this fails since the OnFinalMessage handler has already been called (which in turn did a "delete this;") without the DialogProc in CDialogImplBase ever returning from WM_DESTROY (which would have triggered the WM_DESTROY msg being sent to my child windows?). So I end up with an assert saying that "Object deleted before window was destroyed". Which is true since "delete this;" has already been performed.
Am I overlooking something? It seems to me as there is no way to get this properly working on Windows CE, ever. (In the ATL sources a WM_NCDESTROY is simulated since Windows CE does not support that, but it's just a call to SendMessage, which results in a nested msg that won't trigger anything useful) A delete this; in OnFinalMessage just isn't going to work on Windows CE. Anybody else experiencing the same problem? Or perhaps a solution?
Edit:
I can see how this works on non-CE versions of Windows since on those versions the WM_NCDESTROY msg is not simulated by a call to SendMessage in ATL. So the child windows have time to process their WM_DESTROY msgs before the objects are being destructed by "delete this;" But not on CE, wM_NCDESTROY is just going to be a nested message that isn't going to be of any value to me.
|
|
|
|
|
Hi,
I would like to put a TrackBar in a menu (WTL), something like Vista Explorer does to change views.
I wonder if this is a new Vista menu property, or if there is a trick.
If a trick I suppose the control is created over the Popup menu, but how do I do this ?
Any idea ? Anybody knows ?
Thanks,
Yarp
http://www.senosoft.com/
|
|
|
|
|
I'm trying to create a borderless MDI child window. I've tried setting the initial window traits without sucess:
typedef CWinTraits <WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD> CFTraits;
class CChildFrame : public CMDIChildWindowImpl<CChildFrame, CMDIWindow, CFTraits>
I've also tried setting / removing various styles just after the create call:
int CChildFrame::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL);
DWORD dwStyle, dwExStyle;
dwStyle = ::GetWindowLong( m_hWndClient, GWL_STYLE);
dwExStyle = ::GetWindowLong( m_hWndClient, GWL_EXSTYLE);
::SetWindowLong( m_hWndClient, GWL_STYLE, dwStyle & ~WS_BORDER );
return 1;
}
I've not had any success - can anyone point me in the right direction?
thanks
|
|
|
|
|
Is the built-in ATL window traits class CMDIChildWinTraits
typedef'ed as:
CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD>
for MDI child windows the one you need? Or if not be using CWinTraitsOR to modify this?
|
|
|
|
|
I'm trying to add my header in all requests using next method.
And I have two problems:
When I call Refresh() method (by pressing F5, etc) there is no DISPID_BEFORENAVIGATE event, so Myheader is not added
Referer header is lost if Myheader was successfully added
HRESULT __stdcall DWebBrowserEventsImpl::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS
__RPC_FAR *pDispParams, VARIANT __RPC_FAR *pVarResult, EXCEPINFO __RPC_FAR *pExcepInfo, UINT __RPC_FAR *puArgErr)
{
.......
switch (dispIdMember)
{
case DISPID_BEFORENAVIGATE:
{
std::wstring strUrl( _bstr_t(pDispParams->rgvarg[5].bstrVal) );
if (_wcsicmp(&strUrl.at(strUrl.size() - 12), _T("navcancl.htm")) == 0)
{
m_cpParent->Stop();
*pDispParams->rgvarg[0].pboolVal = VARIANT_TRUE;
}
else
if (!m_cpParent->GetHeaderAdded())
{
m_cpParent->Stop();
*pDispParams->rgvarg[0].pboolVal = VARIANT_TRUE;
m_cpParent->NavigateWCustomHeader(_bstr_t(pDispParams->rgvarg[5].bstrVal),
L"Myheader: header\r\n", &pDispParams->rgvarg[4], &pDispParams->rgvarg[3],
pDispParams->rgvarg[2].pvarVal, pDispParams->rgvarg[1]);
}
else
{
m_cpParent->SetHeaderAdded(false);
VARIANT_BOOL bCancel = VARIANT_FALSE;
BeforeNavigate(_bstr_t(pDispParams->rgvarg[5].bstrVal),
0,
pDispParams->rgvarg[3].bstrVal,
pDispParams->rgvarg[2].pvarVal,
pDispParams->rgvarg[1].bstrVal,
pDispParams->rgvarg[0].pboolVal);
if (bCancel == VARIANT_TRUE)
res = E_INVALIDARG;
}
}
break;
}
......
}
modified on Wednesday, April 21, 2010 6:20 PM
|
|
|
|
|
Does your event handler ever get called? I assume you've hooked it up (using connection points)? Simply having the function isn't enough, you have to tell IE to call it.
Steve
|
|
|
|
|
Could you explain this more detail? I implemented DWebBrowserEvents class and as I thought DWebBrowserEventsImpl::Invoke is called on every user action (but when Refresh called, there is no DISPID_BEFORENAVIGATE dispIdMember)
class DWebBrowserEventsImpl : public DWebBrowserEvents
{
STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo);
STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo);
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId);
STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS __RPC_FAR *pDispParams,
VARIANT __RPC_FAR *pVarResult, EXCEPINFO __RPC_FAR *pExcepInfo, UINT __RPC_FAR *puArgErr);
HRESULT BeforeNavigate(_bstr_t URL, long Flags, _bstr_t TargetFrameName, VARIANT * PostData, _bstr_t Headers, VARIANT_BOOL * Cancel);
HRESULT DownloadBegin();
CWebBrowserView *m_cpParent;
public:
void SetParent(CWebBrowserView *pParent)
{
m_cpParent = pParent;
}
};
class CUIHandler:
public IOleCommandTarget,
public IDocHostUIHandler
{
public:
CUIHandler():
m_spDefaultOleCommandTarget(NULL),
m_pDefaultUIHandler(NULL)
{
}
void Clear()
{
if (m_spDefaultOleCommandTarget)
{
m_spDefaultOleCommandTarget->Release();
m_spDefaultOleCommandTarget = NULL;
}
if (m_pDefaultUIHandler)
{
m_pDefaultUIHandler->Release();
m_pDefaultUIHandler = NULL;
}
}
....................................................................
IOleCommandTarget *m_spDefaultOleCommandTarget;
IDocHostUIHandler *m_pDefaultUIHandler;
};
|
|
|
|
|
arbittorr wrote: Could you explain this more detail? [I assume you've hooked it up (using connection points)?]
I think Stephen is asking have you passed an interface pointer to your DWebBrowserEventsImpl object to IE? Usually done using an Advise method such as DispEventAdvise (...)
|
|
|
|
|
Yes I have passed an interface pointer. So, problem is still here. Maybe Refresh () method doesn't invoke DISPID_BEFORENAVIGATE at all?
class CWebBrowserView : public CAxDialogImpl<CWebBrowserView>
{
protected:
DWebBrowserEventsImpl m_events;
LPCONNECTIONPOINT m_pCP;
SHDocVw::IWebBrowser2 *m_pWebBrowser;
....
m_events.SetParent(this);
HRESULT hr = GetDlgControl(IDC_EXPLORER1, __uuidof(SHDocVw::IWebBrowser2), (void**) & m_pWebBrowser);
hr = m_pWebBrowser->QueryInterface(IID_IOleInPlaceActiveObject, (void**) & m_pIOIPAO);
if (m_pWebBrowser) {
LPCONNECTIONPOINTCONTAINER pCPC = NULL;
m_pWebBrowser->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pCPC);
pCPC->FindConnectionPoint(__uuidof(SHDocVw::DWebBrowserEventsPtr), &m_pCP);
pCPC->Release();
m_pCP->Advise((LPUNKNOWN)&m_events, &m_dwCPCookie);
}
.........
|
|
|
|
|