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.