1

Firstly, I have to admit that I'm a C++ and Salesforce newbie (but not new to programming in general), so this question may appear totally stupid to a more experienced C++ programmer... Anyway, I just can't figure out how to solve it.

I try to create a new CTI connector for a Call Center that not yet has one. I followed the docs for Salesforce Spring '16 (v36.0) and installed Visual Studio 2008 Professional (tried with and without SP1).

I completed Building a CTI Connector Solution in Visual Studio, downloading the Demo Adapter Source Code, creating a new ATL project. When it came to configuring the Code Generation and Linker properties, I found that not all of the options to change were present in my Visual Studio. I currently can't remember exactly which ones, but I can reproduce it if this is a required information.

May main problem started afterwards: As described in Adding a COM Base Class to a CTI Adapter Project I used the ATL wizard to create a new class for my CTI system. It was step 6 that I wasn't able to follow entirely. The documentation says:

By default, the wizard automatically creates a new interface called ISalesforceCTIAdapter. You will need the version of ISalesforceCTIAdapter that has been defined by Salesforce for your new CTI connector. To use Salesforce’s version, open the .h file that the wizard generated (MyAdapterBase.h in the example above). In this file:

Delete the entry for __interface ISalesforceCTIAdapter : IDispatch and its corresponding attributes and comments.

Now I don't have that code in MyAdapterBase.h. Instead I have something that may or may not be a replacement:

BEGIN_COM_MAP(CMyAdapterBase)
    COM_INTERFACE_ENTRY(ISalesforceCTIAdapter)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

The same applies to __event __interface _IMyAdapterBaseEvents; which I'm supposed to delete, but which doesn't exist in my file. Instead I have

BEGIN_CONNECTION_POINT_MAP(CMyAdapterBase)
    CONNECTION_POINT_ENTRY(__uuidof(_ISalesforceCTIAdapterEvents))
END_CONNECTION_POINT_MAP()

So I tried to delete these, but to no avail. When I now attempt to build the project, I get a error C2011: 'ISalesforceCTIAdapter' : 'struct' type redefinition, because this is declared in another auto-generated file. Removing it there leads to the next error and so on and so on.

I suppose that this must have something to do with the way the ATL wizard generates the code. Obviously on my systems, something is different from the system that was used to create the docs.

If someone can point into the right direction, for example settings in Visual Studio that I may try or other versions of VS, then please let me know. I would already be happy to learn that I'm not the first one to hit that problem, though I'm probably the first one who's unable to solve it...

Thanks,

Patrick

  • 2
    I know this doesn't answer your question, but just a reminder that the desktop CTI Toolkit is no longer supported by Salesforce. Should you encounter problems that result in needing to open a support case you will be unable to get assistance. help.salesforce.com/apex/… – Paul H. Feb 26 '16 at 19:10
  • @Paul: Thanks very much for this info. I was totally unaware of this fact, and you saved me a lot of work :-) I'll concentrate on Open CTI now, which also releives me from having to write code in a foreign language. – Patrick Echterbruch Mar 17 '16 at 16:42
0

After doing some more research I found that (Microsoft? C++?) refers to the code mentioned by Salesforce as "attributed", and that Visual Studio 2008 doesn't support the generation of attributed ATL classes any more.

A new ATL project can be created as Attributed in VS 2005, and then there are the code lines referred to by the Salesforce docs, so I can follow the guidelines. But then again, Salesforce created the Demo Adapter Source in VS 2008, so VS 2005 refuses to open it.

I used the workaround found on Attribute option for ATL applications (2008):

After the initial Build of DemoAdapter in VS 2008 (to make sure the CTIAdapterLib.lib and CTIAdapterLibD.lib files are in place), create a new ATL project in VS 2005, make sure the Attributed checkbox is checked and then stupidly follow the Salesforce guide throughout Building a CTI Connector Solution in Visual Studio. After setting the project options, save all and close VS 2005.

In VS 2008 open the Solution DemoAdapter from the Demo Adapter Source. Instead of adding a new ATL project, right-click the solution in Solution Explorer, select Add -> Existing Project and choose the ATL project created in VS 2005. VS 2008 converts it to the new environment.

Right-click the now converted project and choose Add -> Class -> ATL Simple Object, just as the Salesforce doc says in Adding a COM Base Class to a CTI Adapter Project. Set the options as directed by the guide and voilà: The generated file looks exactly like the one referred by the documentation. Now there are the __interface ISalesforceCTIAdapter : IDispatch lines that are to be deleted.

Now there are a couple things more to do before a successful build

  • Also delete the __interface _ISalesforceCTIAdapterEvents declaration from the .h file because this interface is declared already.
  • When adding the method bodies to the .cpp file make sure to replace MyAdapterBase:: with the name chosen for your custom class (fairly obvious, but not obvious enough for me at the first build attempt...).
  • Add #include "CTILogger.h" to your .h file, because one of the methods uses the logger.
  • Modify the call to the logger so that it matches one of the 11 overloads... Problem is that the string literal "Sending XML..." is treated as char[25] where the logger only accepts wchar_t* - prefixing it with L does the trick: CCTILogger::Log(LOGLEVEL_HIGH,L"Sending XML (len %d): %s",xml.length(),(wchar_t*)xml);

And finally: Build succeeds, problem solved :-)

Update: More problems, more solutions...

When Creating the MyUserInterface (with inherits from CCTIUserInterface), building the Project generates a lot of linker errors like

comsuppwd.lib(comutil.obj) : error LNK2005: "class _variant_t vtMissing" (?vtMissing@@3V_variant_t@@A) already defined in comsupp.lib(comutil.obj)
msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::_Container_base_secure::~_Container_base_secure(void)" (??1_Container_base_secure@std@@QAE@XZ) already defined in CTIAdapterLibD.lib(CTILogger.obj)

The first one is caused by the Treat wchar_t as Built-in Type setting under C/C++ -> Language. For both Release and Debug, in CTIAdapterLib this is set to No (/Zc:wchar_t-) and in MyAdapterBase it is set to Yes. Modify your new Project to match the setting in CTIAdapterLib.

The others originate from the Runtime Library (C/C++ -> Code Generation) setting. According to the Salesforce docs, this should be set differently for Release and Debug with Release being Multi-threaded (/MT) and Debug being Multi-threaded Debug (/MTd). Again, in CTIAdapterLib, Runtime Library is set to Multi-threaded (/MT) and Multi-threaded Debug (/MTd) respectively, both without DLL. Modify the new project to match CTIAdapterLib.

At the next attempt to build the project, importing the CTIAdapterLib causes some linker errors because external symbols can't be resolved. Solution: In the Project Properties under Linker -> Input add to Additional Dependencies winmm.lib and winhttp.lib for both Debug and Release (leave the dependency to CTIAdapterLibD.lib resp. CTIAdapterLib.lib in place).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.