|
do u hav WTL installed and its path configured properly with VC++ IDE
-------------------------
Have a great day ahead!
Regards,
Sohail Kadiwala
(My COM Blog - http://lovecom.blogspot.com)
modified 21-Apr-21 21:01pm.
|
|
|
|
|
Figured it out. I had all proper paths specified under the Project Properties, but not in the Options sections (Tools -> Options). Seems like it shouldn't matter and VS should have been able to find the file, but obviously is couldn't.
Matt
|
|
|
|
|
Good
I was talking about the same "Options sections" settings for WTL.
-------------------------
Have a great day ahead!
Regards,
Sohail Kadiwala
(My COM Blog - http://lovecom.blogspot.com)
modified 21-Apr-21 21:01pm.
|
|
|
|
|
Is it possible to make a list view single selection at runtime or does LVS_SINGLESEL have to be set when you create the control?
|
|
|
|
|
Use CWindow::ModifyStyle() :
CWindow wndList = GetDlgItem ( IDC_YOUR_LIST );
wndList.ModifyStyle ( LVS_SINGLESEL, 0 );
--
I'm Michael Dunn and I approve this post.
Vote Trogdor in oh-four!
|
|
|
|
|
Hi,
I am writing a very simple ATL in-proc server to experience the STA mechanism.
My code is like that:
1) I defined an interface called IEcho, which has only one function called Echo(DWORD).
2) I implemeted this interface in coclass CoEcho,
which has a data member named "m_nNumber" with type "long" and which implements Echo(DWORD) as the following:
///------------------------------------------
ATLTRACE("%ld enter\n", GetCurrentThreadId());
this->m_nNumber = number;
Sleep(1000);
//!!!!! NOTICE THIS STAEMENT
//MessageBox(NULL, _T("WAIT"), _T("WAIT"), 0);
//!!!!!
ATLTRACE("the number passed in: %ld\n",
this->m_nNumber);
ATLTRACE("%ld leave\n", GetCurrentThreadId());
return S_OK;
///----------------------------------------------
3) Then, I create a STA Client, which creates a IEcho instance, marshals it and passes it to two threads sharing the same thread function.
the STA Client is like:
//------------------THREAD FUNCTION-----
//it is very simple
DWORD WINAPI ThreadFunc(LPVOID lpara){
CoInitialize(NULL);
IStream * pStream =(IStream*)lpara;
IEcho *pEcho;
CoGetInterfaceAndReleaseStream(pStream,
IID_IEcho,
(LPVOID*)&pEcho);
pEcho->Echo(GetCurrentThreadId());
pEcho->Release();
CoUninitialize();
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
IEcho * pEcho = NULL;
CoCreateInstance(CLSID_CoEcho, NULL,
CLSCTX_ALL, IID_IEcho,
(void **)&pEcho);
IStream * t1stream;
IStream * t2stream;
CoMarshalInterThreadInterfaceInStream(IID_IEcho,
pEcho, &t1stream);
HANDLE hThread1 = CreateThread(NULL, 0,
ThreadFunc, t1stream, 0, NULL);
CoMarshalInterThreadInterfaceInStream(IID_IEcho,
pEcho, &t2stream);
HANDLE hThread2 = CreateThread(NULL, 0,
ThreadFunc, t2stream, 0, NULL);
//message pump
MSG ms;
while(GetMessage(&ms, 0, 0, 0)){
TranslateMessage(&ms);
DispatchMessage(&ms);
}
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
CloseHandle(hThread1);
CloseHandle(hThread2);
pEcho->Release();
CoUninitialize();
return 0;
}
///
What I am expecting is that though two threads may call IEcho simultaneously with different thread ids, the data member "m_nNumber" of CoEcho should be well protected by COM STA since only one thread can enter IEcho::Echo function.
for examle, if main thread id is 3, the first thread's id is 1 and the second 2, the ECHO should output:
3 enter
the number passed in 1
3 leave
3 enter
the number passed in 2
3 leave
It works well
But if I have the statement
MessageBox(NULL, _T("WAIT"), _T("WAIT"), 0);
added, m_nNumber is damaged.
the output is something like:
//thread 1 in
3 enter
//thread 2 in?
3 enter <--- it should not be that, only one
thread can be here!!!
the number passed in 2 // thread 1's id is lost
....
I am very confused by that.
Any explaination?
Thanks a lot in advanced!
|
|
|
|
|
duckpond wrote:
Any explaination?
COM uses a hidden window's message queue to synchronize the calls towards the objects of an STA. It seems that when it hits MessageBox (NULL , ...), the hidden window's procedure must retreive and dispatch messages by itself; this makes it reentrant and thus the main apartment - which holds pEcho - unblocks, allowing the second call of Echo to execute.
It is, in essence, equivalent with a cross-apartment call.
"though nothing
will keep us together
we can beat them
for ever and ever"
rechi
|
|
|
|
|
Thanks Rechi I got it.
|
|
|
|
|
May I recommend the book Essential COM by Don Box? IIRC, this reentrancy behaviour is described in it. To summarize: objects living in an STA need not prepare itself for concurrency, but it should prepare itself for reentrancy, as your example shows.
Essential COM is a really good read, and a must for COM developers IMHO.
--
Weiter, weiter, ins verderben.
Wir müssen leben bis wir sterben.
|
|
|
|
|
Since we don't have OLE DB forum I think ATL is pretty close.
So!
I got a prob. I'm using a recordset with CDynamicAccessor.
when I close it it crashes in here:
in ATLDBCLI.H
<br />
class CAccessorBase<br />
.....<br />
HRESULT ReleaseAccessors(IUnknown* pUnk)<br />
{<br />
ATLASSERT(pUnk != NULL);<br />
HRESULT hr = S_OK;<br />
if (m_nAccessors > 0)<br />
{<br />
CComPtr<IAccessor> spAccessor;<br />
hr = pUnk->QueryInterface(IID_IAccessor, (void**)&spAccessor);<br />
if (SUCCEEDED(hr))<br />
{<br />
ATLASSERT(m_pAccessorInfo != NULL);<br />
for (ULONG i = 0; i < m_nAccessors; i++)<br />
spAccessor->ReleaseAccessor(m_pAccessorInfo[i].hAccessor, NULL);<br />
}<br />
m_nAccessors = 0;<br />
delete [] m_pAccessorInfo;
m_pAccessorInfo = NULL;<br />
}<br />
return hr;<br />
}<br />
Why that delete fails? I mean this code allocates it why can't it delete?
The only other note is that I put my code that uses this in a regular windows DLL. Could that be a prob?
|
|
|
|
|
inner wrote:
The only other note is that I put my code that uses this in a regular windows DLL. Could that be a prob?
Yes that could be the problem. Make sure your app and DLL links against the same C runtime library. If they don't, then they will get separate heaps. The heap is where memory is allocated from by using new, and returned to when deallocated using delete. If you allocate memory in the DLL, and delete it in the app, then errors will occur if they do not share the same heap.
--
Weiter, weiter, ins verderben.
Wir müssen leben bis wir sterben.
|
|
|
|
|
Need suggestions for the problem preferrably in VC6:
There are two machines A and B. A telnet(or SSH) to B.On logged in to B, B should give it's own window in Machine A. That is, B should be the owner of window in A.
If it is something to do with XWindows or Xterm, I am not clear how exactly to hit the problem.
I hate that lazy Java
|
|
|
|
|
i am working on a project which needs vc7 specific dlls ( atl71.dll msvcr71.dll etc) which i need to ship to the client thro the setup.
Since these dlls are not registered where should my setup register / copy these dlls so that my code uses them. if these are not COM dlls then how do they get referenced when any piece of code uses them?
|
|
|
|
|
Same directory as the binary or a directory which is in the PATH environment variable, C:\Windows[\system32]. I'd opt for same directory as binary, just to make sure no other app replaces your dll's.
--
Weiter, weiter, ins verderben.
Wir müssen leben bis wir sterben.
|
|
|
|
|
Installing anything into windows and/or system32 is discouraged these days, because it leads to DLL Hell™. Installing into the app dir, and creating a APPNAME.exe.local file is the way to go on Win2K+.
--
I'm Michael Dunn and I approve this post.
Vote Trogdor in oh-four!
|
|
|
|
|
What's the .local file for?
--
Weiter, weiter, ins verderben.
Wir müssen leben bis wir sterben.
|
|
|
|
|
In short, it tells the OS to load DLLs from the EXE's directory if they exist there, before searching the normal path for DLLs. More info here[^]
--
I'm Michael Dunn and I approve this post.
Vote Trogdor in oh-four!
|
|
|
|
|
Hmm.. wait. The beside-executable option may not work on Win9x. I'm not sure.
--
Weiter, weiter, ins verderben.
Wir müssen leben bis wir sterben.
|
|
|
|
|
Don't quote me on this but I recall that on NT4 (at least with SP3) and older OS such as Win9X the dll loading first looks in the system folders and then looks in the application folder ("beside-executable" option), resulting in windows loading what ever version is in the system and not the new version that is in your application folder.
As opposed to W2K and XP that first look in the application folder and then in the system folders.
|
|
|
|
|
This page implies that Windows looks in the application folder first for DLLs.
Stuart Dootson
'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'
|
|
|
|
|
Hi,
I'm using WTL7 (also tried WTL71) for a project that has to be kept small, so I'm using ATL_MIN_CRT when doing the release build, this works fine in VC6, no compile or link errors.
But, here's the problem, if I try to upgrade the project to VS.NET2003, the release build will not link properly, giving the following errors:
Linking...
LIBCMT.lib(crt0dat.obj) : error LNK2005: __osplatform already defined in atlmincrt.lib(atlinit.obj)
LIBCMT.lib(crt0.obj) : error LNK2019: unresolved external symbol _main referenced in function _mainCRTStartup
I know this is saying that something is causing the compiler/linker to use CRT, which fails due to ATL_MIN_CRT. Skipping ATL_MIN_CRT is not an option.
I have checked the project settings and everything seems to be correctly upgraded from VS6 to VS.NET2003 and the code haven't changed.
What could be the problem? Is it still a matter of trying to track down what function call is pulling in the CRT lib? This is anoying since, well, it worked before.
Any ideas or things to keep in mind when working with WTL and VS.NET2003?
Cheers!
|
|
|
|
|
OK, found it. I had an atoi() call somewhere, replacing that with StrToInt() did the trick. Strange that it worked in VS6 but not VS.NET2003.
Cheers
|
|
|
|
|
I believe you can find these dependencies quite easy. Link dynamically against the CRT without ATL_MIN_CRT. Launch the Dependency Walker (Depends.exe in your VS.NET tools directory), and open your binary with it. Locate the MSVCRT.DLL entry in the tree view and select it. On the right hand side you see two list views with function entry points. The top list view contains the functions which you import from the selected DLL. From there on, it's just a matter of Find in Files to rid yourself of the offending function call(s).
--
Weiter, weiter, ins verderben.
Wir müssen leben bis wir sterben.
|
|
|
|
|
Nice, I did not know this, that makes it a lot easier. Thanks!
|
|
|
|
|
thanks mr Jörgen for this great help
-----------------------------
"I Think It Will Help"
-----------------------------
Alok Gupta
visit me at http://www.thisisalok.tk
|
|
|
|
|