none
Deleted RRS feed

Answers

All replies

  • An in-process (Dll) COM Server created by the ATL wizard and derived from CAtlDllModuleT will contain an exported DllCanUnloadNow() function that calls ATL's implementation.

    	HRESULT DllCanUnloadNow() throw()
    	{
    		T* pT = static_cast<T*>(this);
    		return (pT->GetLockCount()==0) ? S_OK : S_FALSE;
    	}
    

    So in your DllCanUnloadNow() function could look like this -

    // Used to determine whether the DLL can be unloaded by OLE.
    STDAPI DllCanUnloadNow(void)
    {
    	HRESULT hr = _AtlModule.DllCanUnloadNow();
    	if (hr == S_OK)
    	{
    		//Uninitialize your library
    	}
    
    	return hr;
    }
    

    Monday, October 14, 2019 3:32 PM
  • Deleted
    Monday, October 14, 2019 4:46 PM
  • If COM does not immediately unload your library after DllCanUnloadNow() returns it is possible for another instance of your COM class to be created.  In that case, FinalConstruct will think that the library is initialized (even though it is not) because the local static variable was never reset.

    The Adobe documentation sounds to me like the initialization and termination functions must be called from the same thread.  That may not be happening.

    • Edited by RLWA32 Monday, October 14, 2019 5:03 PM
    Monday, October 14, 2019 4:58 PM
  • Deleted
    Monday, October 14, 2019 5:03 PM
  • First, I suggest you do a test to find out if the Adobe library's initialization and termination functions must run on the same thread.

    Monday, October 14, 2019 5:10 PM
  • You can hook into ATL module termination with CAtlModule::AddTermFunc . A singleton instance of CAtlModule is accessible via _pAtlModule global variable.

    Igor Tandetnik

    Monday, October 14, 2019 9:48 PM
  • Deleted
    Monday, October 14, 2019 11:12 PM
  • Are you using the Apartment threading model for your shell extension?

    Did you resolve the thread affinity question for the Adoble library's initialization and termination functions?

    Tuesday, October 15, 2019 11:34 AM
  • Deleted
    Tuesday, October 15, 2019 12:59 PM
  • Well, you could write a minimal program that initializes the library on its main thread, does some work, and then starts another thread that calls the library's termination function.  Observe the results.

    In FinalConstruct call GetCurrentThreadId to get the id of the thread on which the library's initialization function is running.

    Then, wherever you call the library's termination function in your shell extension call GetCurrentThreadId again. Does the id of the thread on which the termination function is called match the id of the initialization thread?

    Tuesday, October 15, 2019 1:10 PM
  • On a Windows 7 system I build the SDK RecipePropertyHandler sample.  It's not an ATL project, but I made sure the threading model was Apartment and inserted some debugging statements to display thread  ids in the COM object's constructor, destructor, and in COM server's DllCanUnloadNow function.  To avoid thread id reuse issues I used CoGetCurrentProcess function instead of GetCurrentThreadId.

    Then I opened explorer, navigated to a folder containing the .Recipe file and selected it.  Explorer loaded the extension.  Then I closed explorer and the extension was unloaded.

    This is what the debugging statements showed.

    [1512] In CRecipePropertyHandler::CRecipePropertyHandler thread id is 81
    [1512] In CRecipePropertyHandler::~CRecipePropertyHandler thread id is 81
    [1512] In DllCanUnloadNow thread id is 82
    [1512] In DllCanUnloadNow thread id is 81
    

    Note the multiple calls to DllCanUnloadNow and that they didn't always occur on the same thread used for the COM object.

    So I suggest you capture the thread id in FinalConstruct when you call the Adobe library's initialization function and make sure that you don't call the Adobe library's termination function unless your code is running on that same thread.

    Tuesday, October 15, 2019 3:04 PM
  • Deleted
    Tuesday, October 15, 2019 3:16 PM
  • In general, it would be impossible to guarantee that a) the library is initialized when the first COM object instance is constructed, b) the library is deinitialized when the last instance is destroyed, and c) these two happen on the same thread.

    It is possible for your COM client to produce this sequence of events:

    1. Thread A creates an instance X of your object
    2. Thread B creates an instance Y
    3. Thread A releases X
    4. Thread A terminates
    5. Thread B releases Y

    The library must be alive from 1 through 5, but at point 1 thread B doesn't exist yet, and at point 5 thread A doesn't exist already. There may not be a thread that exists for the whole lifetime of the library.


    Igor Tandetnik

    Tuesday, October 15, 2019 11:17 PM
  • Deleted
    Wednesday, October 16, 2019 1:31 PM
  • How about using your own thread to control the library initialization/termination functions?

    Wednesday, October 16, 2019 2:08 PM
  • Deleted
    Wednesday, October 16, 2019 5:25 PM
  • Hi,

    Thank you for posting here.

    According to your issue , I suggest you should ask it in Adobe Support Community Forum. And this thread will be moved to Off-Topic Posts.


    Best Regards,

    Suarez Zhou

           
    Thursday, October 17, 2019 2:55 AM
  • Deleted
    Monday, January 6, 2020 3:45 PM