Discussion:
CoInitializeEx COINIT_MULTITHREADED and ShellExecute (and other shell commands) bug
(too old to reply)
AS
2004-01-28 01:31:14 UTC
Permalink
Im using a 3rd party DCOM library and must initialise DCOM using
CoInitializeEx with the COINIT_MULTITHREADED flag as much of the code using
this library is carried out in threads.

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.
Gary Chang
2004-01-28 03:26:37 UTC
Permalink
Hi AS,

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.
--------------------
AS
2004-01-28 12:10:27 UTC
Permalink
Hello Gary,

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


----- Original Message -----
From: "Gary Chang" <v-***@online.microsoft.com>
Newsgroups: microsoft.public.vc.mfc
Sent: Wednesday, January 28, 2004 3:26 AM
Subject: RE: CoInitializeEx COINIT_MULTITHREADED and ShellExecute (and other
shell commands) bug
Post by Gary Chang
Hi AS,
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.
--------------------
Gary Chang
2004-01-29 06:12:40 UTC
Permalink
Hi Andy,

Thanks for your quickly reply!
Post by AS
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!

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.
--------------------
AS
2004-01-30 00:13:07 UTC
Permalink
Isnt it annoying that everytime i (and anyone else) wish to write a
multithreaded application using DCOM i have to do all my Shell calls outside
the main thread !?

oh well ...
Post by Gary Chang
Hi Andy,
Thanks for your quickly reply!
Post by AS
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!
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.
--------------------
Yan-Hong Huang[MSFT]
2004-01-30 09:01:39 UTC
Permalink
Hello Andy,

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
This posting is provided "AS IS" with no warranties, and confers no rights.
Loading...