CAPÍTULO IV: RESULTADOS Y DISCUSIÓN
4.2. RESULTADOS EXPLICATIVOS
The following issues can arise during the installation or use of AppConnectors:
Documentum menu does not appear in the authoring application — Check the following areas: • Find the install.log file that is created in the location from which the client installer is run. This
file will show whether the installation completed successfully.
• Check the Windows Task Manager to see whether at least two AppConnectors processes are running: Documentum Credentials Manager and Documentum Locale Manager.
• Verify that a menu configuration file has downloaded to the client, for example,
%ProgramFiles%\MyApp\Documentum\Webtop\appintgmenubar_menugroup.xml. If this file is not present, stop and start the Locale Manager Windows process. MyAppis the path that you have chosen for your application.
• Check the log4net log files for errors. If none are found, declare a more verbose logging level and restart the affected process.
User is asked to log in unexpectedly — Check the following causes for this problem:
• The client-side app.config file does not specify system scope. If this is the case, the user must log in for each authoring application instance.
• The Documentum Credential Manager is not running. Check this in the Windows Task Manager and restart the process if needed.
• Saved credentials are not supported by the configuration setting in the WDK application app.xml file (value of <save_credential>.<enabled> is true).
Unreliable content transfer (older Java applet basis) — Pre-WDK 5.3 content transfer applets and components, or custom components that extend them, are not supported with AppConnectors.
User credentials are not being saved as expected — You may be required to re-enter your login credentials. Check the processes running in Windows Task Manager to see if the Credential Manager process is running. To manually start the process, navigate to C:\Program Files\Documentum\AppConnector and double click
Troubleshooting
Localized UI not displayed — The Documentum Application Connector Locale Manager displays the localized menu. To start this program, double-click it in its default location: C:\Program Files\Documentum\AppConnector\Documentum.AppConnector.LocaleManager.exe.
Chapter 11
Creating Application Connectors That
Integrate with C++ or Visual Basic 6
Applications
This chapter includes these topics: • Introduction, page 83
• Overview, page 83
• Creating application connectors that integrate with C++ applications, page 84
Introduction
Documentum Application Connectors can work with .NET, C++, and Visual Basic 6 applications. If your application is written in C++ or Visual Basic 6, you can create a COM component that works as a bridge between your application connector and application. To create an application connector and COM object that work with a C++ application, follow the MDITextEditorSampleApp solution, which consists of a sample C++ application and C# application connector.
Overview
The MDITextEditorSampleAppConnector solution implements Microsoft ATL Connection Points. For more information about ATL Connection Points, see theMSDN ATL Connection Pointsweb page. For .NET-specific information, see theMSDN ComSourceInterfacesAttribute Classweb page (the Connect class in the MDITextEditorSampleApp solution uses the ComSourceInterfacesAttribute class). Figure 10, page 84shows that events in the Connect class of the MyCompany.AppConnector. MDITextEditorAppIntg sample application connector cause the AppConnectorEventClient class to call into the C++ application CMainFrame class. It also shows that calls from the CMainFrame class go through the _connect interface to the Connect class, which then calls either MDITextEditorAppIntegrationProvider or MenuProvider. In ATL connection points terms, the Connect class is the source that calls the IAppConnectorConnect outgoing interface.
Creating Application Connectors That Integrate with C++ or Visual Basic 6 Applications
Figure 10. MDITextEditorSampleAppConnector solution architecture
When the MDITextEditorApp application starts up, the Documentum menu is added to it in this sequence of execution:
1. The MDITextEditorApp Application class initializes the CMainFrame class, which instantiates the AppConnectorEventClient and Connect classes.
The AppConnectorEventClient class implements the IAppConnectorConnect interface. Through the IAppConnectorConnect interface, the Connect class’s outgoing events are fired.
2. When the CMainFrame class is initialized, it calls the Connect class’s InitAppIntegration method through the _connect interface.
3. The Connect class instantiates the MDITextEditorAppIntegrationProvider and MenuProvider classes.
4. Then, the MenuProvider’s menu info is sent via IAppConnectorConnect interface to the CMainFrame class, which builds the Documentum menu.
Creating application connectors that integrate
with C++ applications
This section describes how to create an application connector and modify your C++ application to work with that application connector. The sample code is drawn from the
MDITextEditorSampleAppConnector solution. See the MDITextEditorSampleAppConnector solution for the complete source code.
Creating Application Connectors That Integrate with C++ or Visual Basic 6 Applications
Creating your application connector
1. Follow the steps inCreating an application connector, page 19.
2. Immediately before the beginning of your MyAppIntegrationProvider class, add the ComVisible attribute and set it to false.
Because the default setting on the entire assembly level for the ComVisible attribute is true, each programming element that should not be visible to COM clients must be explicitly hidden by setting the ComVisible attribute to false.
For more information about the ComVisible attributes, see
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/ frlrfSystemRuntimeInteropServicesComVisibleAttributeClassTopic.asp.
3. In your MyAppIntegrationProvider class, add the CLSCompliant attribute immediately before the beginning of the InitializeAppIntegrationand set the attribute to false
Because the default setting on the entire assembly level for the CLSCompliant attribute is true, each programming element that uses elements that are not part of the Common Language Specification must be explicitly identified by setting the CLSCompliant attribute to false. For more information about the CLSCompliant attribute, seehttp://msdn.microsoft.com/library/ default.asp?url=/library/en-us/cpref/html/frlrfSystemCLSCompliantAttributeClassTopic.asp. 4. Instead of using MainForm as the parent class, use the Connect class.
a. Instead of declaring the parent as MainForm object in the Data members region of your MyAppIntegrationProvider class, add this code:
Connect parent;
Because your programming model does not have an application object as the methodology used inCreating an application connector, page 19assumes, your application connector uses the Connect class as the parent.
b. When you need to make sure that the parent object is a Connect object, use Connect. 5. To create event handlers and register for the specified events, in the InitializeAppIntegration
method right before the return(true) line, add this code:
Note: In order for VS.NET intellisense to recognize these events, you must first add the appropriate delegates in your Connect class.
this.parent.WindowActivate += new Connect.WindowActivateDelegate(WindowActivate); this.parent.DocumentOpen += new Connect.DocumentOpenDelegate(DocumentOpen); this.parent.NewDocument += new Connect.NewDocumentDelegate(NewDocument); this.parent.DocumentBeforeClose += new Connect.DocumentBeforeCloseDelegate(
DocumentBeforeClose); this.parent.DocumentBeforeSave += new Connect.DocumentBeforeSaveDelegate(
DocumentBeforeSave);
6. Create a C# file called Connect.cs and create an IAppConnectorConnect interface definition in a region similar to this one and generate your own GUID:
#region Source interface definition
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] [Guid("8A8FBEE2-70CA-41b8-8551-AF6411B61AF3")]
public interface IAppConnectorConnect {
[DispId(1)] void CreateMenuItem(int menuItemId, int parentId, bool isPopup, string caption);
Creating Application Connectors That Integrate with C++ or Visual Basic 6 Applications
[DispId(2)] long GetActiveWindowHandle();
[DispId(3)] void SetMenuItemState(int menuItemId, bool enabled); [DispId(4)] void DoOpenDocument(string filePath);
[DispId(5)] bool GetActiveDocumentModifiedSinceLastSave(); [DispId(6)] string SaveDocument(string targetFolder); [DispId(7)] void CloseActiveDocument();
}
#endregion
The IAppConnectorConnect event interface is implemented by the client-side sink. Functions of this interface are called by Connect class, which is the source. The AppConnectorEventClient class is the listener and is located in your main frame class file.
7. Create a Connect class declaration and corresponding COM interface definition similar to this one and generate your own GUID:
[ComSourceInterfaces(typeof(IAppConnectorConnect))] [ClassInterface(ClassInterfaceType.AutoDual)] [Guid("1B7D7AA4-216B-4ad0-B653-C499B7DC497A")] public class Connect
{ }
8. In the Connect class, implement these methods corresponding delegates and events that are fired by the IAppConnectorConnect implementation:
• FireCreateMenuItem • FireGetActiveWindowHandle • FireSetMenuItemState • FireDoOpenDocument • FireGetActiveDocumentModifiedSinceLastSave • FireSaveDocument • FireCloseActiveDocument
9. In the Connect class, implement these methods and corresponding delegates and events that are fired by your main frame class:
• FireWindowActivate • FireDocumentOpen • FireNewDocument • FireDocumentBeforeClose • FireDocumentBeforeSave
10. In the Connect class, implement these methods that are directly called by your main frame class: • InitAppIntegration
• CloseAppIntegration • HandleCustomMenuEvent
11. Create a C# file called MenuProvider.cs and immediately before the beginning of your MenuProvider class, add the ComVisible attribute and set it to false.
Creating Application Connectors That Integrate with C++ or Visual Basic 6 Applications
Because the default setting on the entire assembly level for the ComVisible attribute is true, each programming element that should not be visible to COM clients must be explicitly hidden by setting the ComVisible attribute to false.
For more information about the ComVisible attributes, see
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/ frlrfSystemRuntimeInteropServicesComVisibleAttributeClassTopic.asp.
12. In addition to the standard methods (as described inBuilding the Documentum menu, page 50) to implement in the MenuProvider class, also implement the HandleCustomMenuEvent method.
Creating your MyAppConnectorEventClient
1. In your application’s main frame class file, create a class, MyAppConnectorEventClient, that implements the connection point IAppConnectorConnect interface. For example:
class MyAppConnectorEventClient : public IDispEventSimpleImpl<1, AppConnectorEventClient, &DIID_IAppConnectorConnect> {
}
2. In MyAppConnectorEventClient, add this sink map: public: BEGIN_SINK_MAP(AppConnectorEventClient) SINK_ENTRY_INFO(1, DIID_IAppConnectorConnect, 1, OnCreateMenuItem, &OnCreateMenuItemInfo) SINK_ENTRY_INFO(1, DIID_IAppConnectorConnect, 2, OnGetActiveWindowHandle, &OnGetActiveWindowHandleInfo) SINK_ENTRY_INFO(1, DIID_IAppConnectorConnect, 3, OnSetMenuItemState, &OnSetMenuItemStateInfo) SINK_ENTRY_INFO(1, DIID_IAppConnectorConnect, 4, OnDoOpenDocument, &OnDoOpenDocumentInfo) SINK_ENTRY_INFO(1, DIID_IAppConnectorConnect, 5, OnGetActiveDocumentModifiedSinceLastSave, &OnGetActiveDocumentModifiedSinceLastSaveInfo) SINK_ENTRY_INFO(1, DIID_IAppConnectorConnect, 6, OnSaveDocument, &OnSaveDocumentInfo) SINK_ENTRY_INFO(1, DIID_IAppConnectorConnect, 7, OnCloseActiveDocument, &OnCloseActiveDocumentInfo) END_SINK_MAP()
3. In the constructor, add this code to create the connection:
AppConnectorEventClient(_Connect* pObj, CMainFrame* mainFrame) { pDotNetObject = pObj; this->mainFrame = mainFrame; pDotNetObject->AddRef(); DispEventAdvise((IUnknown*)pDotNetObject); }
In the private region of your class, declare this pointer: _Connect* pDotNetObject;
4. In the destructor, add this code to close the connection: ~AppConnectorEventClient()
{
Creating Application Connectors That Integrate with C++ or Visual Basic 6 Applications
DispEventUnadvise((IUnknown*)pDotNetObject); }
5. Implement these methods, which are basically pass-thru calls to the main frame class methods that actually implement the functionality:
• OnCreateMenuItem • OnGetActiveWindowHandle • OnSetMenuItemState • OnDoOpenDocument • OnGetActiveDocumentModifiedSinceLastSave • OnSaveDocument • OnCloseActiveDocument
Modifying your main frame class
1. In your main frame class file, create ATL code that creates function information for each event: _ATL_FUNC_INFO OnCreateMenuItemInfo = {CC_STDCALL, VT_EMPTY, 4, {VT_I4,
VT_I4, VT_BOOL, VT_BSTR}};
_ATL_FUNC_INFO OnGetActiveWindowHandleInfo = {CC_STDCALL, VT_I4, 0, {}}; _ATL_FUNC_INFO OnSetMenuItemStateInfo = {CC_STDCALL, VT_EMPTY, 2, {VT_I4,
VT_BOOL}};
_ATL_FUNC_INFO OnDoOpenDocumentInfo = {CC_STDCALL, VT_EMPTY, 1, {VT_BSTR}}; _ATL_FUNC_INFO OnGetActiveDocumentModifiedSinceLastSaveInfo = {CC_STDCALL,
VT_BOOL, 0, {}}; _ATL_FUNC_INFO OnSaveDocumentInfo = {CC_STDCALL, VT_BSTR, 1, {VT_BSTR}};
_ATL_FUNC_INFO OnCloseActiveDocumentInfo = {CC_STDCALL, VT_EMPTY, 0, {}};
2. In your main frame class constructor, declare these pointers: pAppConnectorEventClient = NULL;
pConnect = NULL;
3. In your main frame class onShowWindow event, initialize the MyCompany.AppConnector. MDITextEditorAppIntg Connect (through the _Connect class) and AppConnectorEventClient classes:
if (bShow) {
//Create instance of Connect class.
HRESULT hr = CoCreateInstance(CLSID_Connect, NULL, CLSCTX_SERVER, IID__Connect, (void**)&pConnect); if (SUCCEEDED(hr) && (pConnect != NULL))
{
//Create instance of AppConnectorEventClient class. pAppConnectorEventClient = new AppConnectorEventClient((_Connect*)pConnect, this); } pConnect->InitAppIntegration(); pConnect->FireWindowActivate(""); }
Creating Application Connectors That Integrate with C++ or Visual Basic 6 Applications
4. In your main frame class’s OnDestroy event, destroy and cleanup the MyCompany. AppConnector.MDITextEditorAppIntg Connect and AppConnectorEventClient classes:
if (pConnect != NULL) { pConnect->CloseAppIntegration(); pConnect->Release(); pConnect = NULL; } if (pAppConnectorEventClient != NULL) { delete pAppConnectorEventClient; }
5. Implement these events in your main frame class: • HandleCustomMenuEvent • OnDoOpenDocument • OnWindowActivate • OnDocumentOpen • OnNewDocument • OnClose • OnCloseDocument • OnSaveDocument • OnBeforeSaveDocument • OnCloseActiveDocument