Microtech büro+ und C++

Wie man mit VisualStudio und C++ über die COM-Aktiv Schnittstelle auf Daten in Microtech Büro Plus Next zugreift.

Mittlerweile sind unter Windows viele Programmieraufgaben über die komfortable API des .Net Frameworks und der verwalteten Programmiersprache C# zu erledigen. Aber gerade wenn es um tieferliegende oder historische APIs von Microsoft Produkten geht, führt kein Weg an MFC, ATL und deshalb C/C++ vorbei. Ein Beispiel ist das "Message Application Programming Interface" oder kurz MAPI. Wer also z.B. einen Adress Book Provider für Outlook oder Exchange schreiben will, kommt nicht umhin sich die Hände schmutzig zu machen.

Auf der anderen Seite unseres Problems steht Büro Plus Next der Firma Microtech aus Bad Kreuznach. Die Software bietet Handwerkern, Händlern und kleinen Unternehmen Module für Faktura, Warenwirtschaft, Einkauf und Finanzbuchhaltung. Die Software wird in Delphi entwickelt. Leider werden die Daten nicht in einer dezidierten, relationalen Datenbank abgelegt, die per SQL abgefragt werden kann. Der externe Zugriff auf Daten ist nur per COM Client/Server Schnittstelle möglich. Microtech nennt das "COM-Aktiv".

Wer nun den Komfort des automatisierten COM-Interop von C# gewohnt ist, steht bei C++ erst einmal auf dem Schlauch. Es gibt jedoch auch für C++ mächtige Tools, die den Zugriff ungemein erleichtern. Wir werden im folgenden sehen, wie man die Verbindung zu Büro Plus aufbaut und sich das BpNT::IAutoApplicationPtr-Interface besorgt.

Dreh- und Angelpunkt des Zugriffs auf COM-Server ist die #import-Directive. Dieser Präpozessor-Befehl extrahiert aus der im COM-Server eingebetteten Schnittstellenbeschreibung die Typen-Bibiliothek und generiert hieraus C++ Stubs.

#import "C:\WINDOWS\system32\RICHED20.dll" no_namespace rename("UINT_PTR", "TOMUINT_PTR")
#import "C:\Programme\microtech\Buero Plus NexT\BpNexT.exe" rename("LoadImage","BPNTLoadImage"),rename("GetVersionEx","BPNTGetVersionEx")

Der COM-Server im Fall von Büro Plus Next ist gleichzeitig das Executable des Anwendungs-Clients. Der obige Pfad muss also ggf angepasst werden. Die Möglichkeiten beim "Import" gehen sogar soweit, Konflikte im Namensraum auflösen, indem Typen in der Bibliothek per rename umbenannt werden.

Zunächst muss COM für den aktuellen Thread initialisiert werden:

CoInitialize(NULL);
Im nächsten Schritt muss eine Instanz des Methoden-Stubs erstellt und die Verbindung zum COM-Server aufgebaut werden. Hierzu sind zwei Indentifikationsschlüssel, CLSID und IID, nötig. Die CLSID oder Class-Id beschreibt den Server selbst. IID oder Interface-Id, identifiziert das jeweilige Interface innerhalb des COM-Servers. So lautet die IID des BpNT::IAutoApplicationPtr-Interface {C74FB8F1-A6EF-11D2-B95E-004005232B30} (einfach einmal nach der IID per regedit in der Registry suchen).

CLSID idbpnt;
HRESULT hr = ::CLSIDFromProgID (L"BpNT.Application", &idbpnt);
if(FAILED(hr))
{
    std::cerr << "CLSIDFromProgID failed" << std::endl;
    return NULL;
}

IID IID_IApplication;
hr = IIDFromString(L"{C74FB8F1-A6EF-11D2-B95E-004005232B30}", &IID_IApplication);
if(FAILED(hr))
{
    std::cerr << "IIDFromString failed" << std::endl;
    return NULL;
}

Nun kann die eigentliche Instanz angefordert werden.

BpNT::IAutoApplicationPtr app;
hr = CoCreateInstance(idbpnt, NULL, CLSCTX_LOCAL_SERVER, IID_IApplication, (LPVOID*)&app );
if(FAILED(hr))
{
    std::cerr << "CoCreateInstance failed" << std::endl;
    return NULL;
}

Nun liegt eine Instanz von BpNT::IAutoApplicationPtr vor, die mit dem BpNext.exe COM-Server verbunden ist. Anschließend folgt der Anmelde-Vorgang und die Selektion eines Mandanten. Dies geschieht analog zur Verwengung der COM-Aktiv-Schnittstelle aus VB oder C# und ist in den Mitgelieferten Beispielen von Microtech dokumentiert.

hr = app->Init(_bstr_t(FIRM), _bstr_t(""), _bstr_t(USER), _bstr_t(PASSWD));
if(FAILED(hr))
{
    std::cerr << "IAutoApplication::Init failed" << std::endl;
    return NULL;
}

hr = app->SelectMand(_bstr_t(MANDANT));
if(FAILED(hr))
{
    std::cerr << "IAutoApplication::SelectMand failed" << std::endl;        
    return NULL;
}

Nach der Verwendung der Anwendung muss COM für den aktuellen Thread beendet werden, so dass auch der BpNext.exe COM-Server beendet wird. Immerhin benötigt der eine Netzwerkbenutzerlizenz.

CoUninitialize();

Bei Anfragen zur Anbindung von Outlook, Exchange oder exotischerer Wünsche wie Waagen, Zähler oder sonstige BDE, kontaktieren Sie uns unverbindlich.