Everything worked fine, until i started to use call shell functions. For
example, if i call ShellExecute I get the return value access denied - and
nothing happens. Also, if i create a CFileDialog window and navigate to My
Computer nothing is displayed! The reason for this is that i initialised COM
with the flag COINIT_MULTITHREADED.
To work around this problem i must call all shell related functions in
another thread! After searching unsuccessfully on google for a more
practical work around or even a fix - i was wondering if anyone from MS can
help me?!
Thanks
Andy S.
Thanks for posting in the community.
I am Gary and will assist you on this issue.
First I would like to confirm my understanding of your issue.
From your description, I understand that is there any ways to call Shell
API functions in the MTA thread.
Have I fully understood you? If there is anything I misunderstood, please
feel free to let me know.
Based on my experience, most shell API functions include UI components(and
for FileDialog) or OLE operation, and both of them should have to work in
the Apartment thread mode(STA), so we recommend you persist with your
original workaround(call the shell API function in another STA thread).
Thanks!
Best regards,
Gary Chang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
Thanks for the prompt reply.
Heres some code that shows the problem:
::CoInitializeEx(NULL, COINIT_MULTITHREADED);
{
ShellExecute (GetDesktopWindow(), _T("open"),
_T("http://www.microsoft.com"), NULL, NULL, SW_SHOWNORMAL); // fails
CFileDialog aDlg(TRUE); // Can NOT see contents of My Computer
aDlg.DoModal();
}
::CoUninitialize();
::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
{
ShellExecute (GetDesktopWindow(), _T("open"),
_T("http://www.microsoft.com"), NULL, NULL, SW_SHOWNORMAL); // OK!
CFileDialog aDlg(TRUE); // Can see contents of My Computer
aDlg.DoModal();
}
::CoUninitialize();
The workaround im using is ok for ShellExecute as I launch the thread which
in turn calls ShellExecute. However its a real pain when I have to call
CFileDialog in a separate thread.
Thanks for your help anyway,
Andy
Thanks for your quickly reply!
>The workaround im using is ok for ShellExecute as I launch the thread which
>in turn calls ShellExecute. However its a real pain when I have to call
>CFileDialog in a separate thread.
Since the ShellExecute and FileDialog's favorite residence is STA
apartment, your pain seems inevitable.
However, thanks for sharing your pain with us ;-)
Wish we can provide some useful advise next time!
oh well ...
"Gary Chang" <v-ga...@online.microsoft.com> wrote in message
news:BQbIq7i5...@cpmsftngxa07.phx.gbl...
I totally understand your concerns on it. Unfortunately, this is a known
issue in Shell programming. A call to CoInitializeEx(COINIT_MULTITHREADED)
allows calls to objects created on the calling thread to be run on any
thread. When accessing objects that use the apartment threading model from
a multithreaded apartment, COM will synchronize access to the object. In
order for this synchronization to occur, COM must marshal calls to the
object. Because the shell currently does not provide the necessary
information, either through a type library or proxy/stub code, for its
objects to be marshaled, attempts to access shell objects from a
multithreaded apartment fail.
For details on it, please refer to the KB article:
"INFO: Calling Shell Functions and Interfaces from a Multithreaded
Apartment"
http://support.microsoft.com/?id=287087
It explains exactly what you met.
Also, for some other Shell APIs, such as SHBrowseForFolder, we can see its
remark part form MSDN: You must initialize Component Object Model (COM)
using CoInitializeEx with the COINIT_APARTMENTTHREADED flag set in the
dwCoInit parameter prior to calling SHBrowseForFolder. You can also use
CoInitialize or OleInitialize, which always use apartment threading.
Note??If COM is initialized using CoInitializeEx with the
COINIT_MULTITHREADED flag, SHBrowseForFolder fails if the caller uses the
BIF_USENEWUI or BIF_NEWDIALOGSTYLE flag in the BROWSEINFO structure.
So for now, we have to create another thread to make it work. It gave rise
to another problem where is not behaving as modal dialog. As a workaround
we need to PeekMessage in while loop need to be called with PM_REMOVE flag.
DispatchMessage has to be called to dispatch the
messages to window procedures of the windows in the calling thread. When
other thread quits it will post a message which need to be checked here in
this loop to break from it.
Currently we are not sure of how that third party DCOM object works on your
side. If it is convenient, I suggest you create that DCOM object in another
thread so to workaround this issue.
If there is any more questions on it, please feel free to post here. Thanks
very much for your understanding.
Best regards,
Yanhong Huang
Microsoft Community Support
Get Secure! ¨C www.microsoft.com/security