how to use C++ load a COM server written in C#? - c++

I am trying to use a COM server generated by Visual Studio 2010 .
When I run CreateInstance(..) , I get error code 0x80040154 .
I enabled fusion log and ran fuslogvw . Fuslogvw reported that loading of assembly (by unknown caller assembly)
mscorlib.resources, Version=4.0.0.0, Culture=zh-HK, PublicKeyToken=b77a5c561934e089
I have already installed .net framework 4 language pack for traditional chinese and also simplified chinese .
Please help . Thanks in advance.
My c++ code is as follow:
#include "stdafx.h"
#import "/Project/TestCOM/MyProject.tlb"
#include <comutil.h>
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
MyProject::_PHPStarterPtr pCalc;
HRESULT hRes = pCalc.CreateInstance(__uuidof(MyProject::PHPStarter));
if(FAILED(hRes))
{
printf("MyProject::_PHPStarterPtr failed w/err 0x%08lx\n", hRes); // it printed MyProject::_PHPStarterPtr failed w/err 0x80040154
}
else
{
pCalc->AddRef();
bstr_t s("hello");
bstr_t outStr = pCalc->Echo(s);
printf("outStr = %s\n", (const char *)outStr);
pCalc->Release();
printf("Dispose() done\n");
}
CoUninitialize();
return 0;
}

0x80040154 means "class not registered". To register COM components inside .NET assemblies, you use regasm.exe tool from the .NET framework directory. It can be done manually, or as a custom post-build step.

Related

VS 2019 C++ console app gets parameters in UTF-8 instead of expected UTF-16LE

I'm building a new project in Visual Studio 2019. It's a console app that includes MFC headers. Here's the relevant code:
int main(int argc, TCHAR* argv[]) // VS wrote "int main()", I added parameters myself.
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(nullptr);
if (hModule != nullptr)
{
// initialize MFC and print and error on failure
if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
{
// TODO: code your application's behavior here.
wprintf(L"Fatal Error: MFC initialization failed\n");
nRetCode = 1;
}
else
{
nRetCode = MyFunction(argc, argv);
}
}
else
{
// TODO: change error code to suit your needs
wprintf(L"Fatal Error: GetModuleHandle failed\n");
nRetCode = 1;
}
return nRetCode;
}
Most of this is boilerplate code generates by VS. I added parameters to the main function and the call to my own code, namely MyFunction(). It built just fine; didn't issue so much as a warning. On the very first test run I found that the text in argv[1] and argv[2] are in plain 8-bit ASCII or UTF-8. I was expecting UNICODE as UTF-16LE.I do have the project properties set to use UNICODE. What have I done wrong to get command line parameters in UTF-8? Here's my setup in VS 2019:
My OS is Windows 10.
main() only works with char in the argv[] array. If you want to use wchar_t instead, you need to rename main() to wmain() instead.
Or, since you are using TCHAR, you can rename main() to _tmain(), so that it will automatically map to main() in a MBCS build, and to wmain() in a Unicode build. See What is difference between main and _tmain in Visual studio

Sqlite: Execute Spatialite Functions in Qt5.4.2 or vs2010 along with Qt-addin

Does anyone know whether it is possible to execute spatialite functions on sqlite-databases in Qt5 or visual studio 2010 along with Qt-addin?
In particular, I would be interested in using functions on type Point.
Thanks!
PS: Functions do work within the official spatialite-gui, however I don't think there is a way to use the spatialite-gui programmatically, is there?
Here is what I tried so far: In Qt5.4.2 I connected SQLITE spatialite database and tried using function ST_X(point), ST_Y(point), ST_PointN and ST_NumPoints with no success:
SELECT ST_X(ST_PointN(Geometry, 1)) AS StartX, ST_Y(ST_PointN(Geometry, 1)) AS StartY, ST_X(ST_PointN(Geometry, ST_NumPoints(Geometry))) AS EndX, ST_Y(ST_PointN(Geometry, ST_NumPoints(Geometry))) AS EndY FROM "国道"
Then this always cannot be excuted successfully. And I also find some relate solution about java in Sqlite: Execute Spatialite Functions in Intellij but these yet cannot solve my problem:
step 1: download mod_spatialite-4.3.0a-win-x86.7z file from spatialite website and uncompress it into c:\sqlite3
PS: In Window 10, I open sqlite3 by cmd, SQL sentence that SELECT load_extension('mod_spatialite') could be excuted successfully.
step 2: In my Qt's code, add SELECT load_extension('mod_spatialite') before SQL statement contained spatialite function. Unfortunately, return value by excute QSqlQuery.exec("SELECT load_extension('mod_spatialite')") is false. Oh no, this is a depressing message.
What's more, I also find some relate solution about Qt in https://forum.qt.io/topic/69835/why-can-t-qt-be-installed-with-sqlite-that-has-load_extension-enabled. However, This need recompile Qt from source and it beyond my skill. Finally, How do I in Qt5.4.2 or visual studio 2010 along with Qt-addin? Has anybody done this before?
The load_extension() documentation says:
For security reasons, extension loaded is turned off by default.
You have to enable it with the C function sqlite3_enable_load_extension() or sqlite3_db_config(…SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION…).
And when you're calling C functions anyway, you can also use sqlite3_load_extension().
If you are not able to call the SQLite library functions directly from your Qt application, then your only choice is to recompile Qt (or the Qt plugin).
Thanks for your help very much, particularly, #Marco and #CL..
Below is my two solution:
PS:
First of all, download mod_spatialite-4.3.0a-win-x86.7z from http://www.gaia-gis.it/gaia-sins/windows-bin-x86/. Then, copy file named mod_spatialite.dll to your project's execute content(equal to your .exe program files). Next, write your Qt project and run this Qt project to test it.
My machine runtime: Window 10 + Qt5.4.2 + Sqlite3
First Solution:
As #CL. says,
If you are not able to call the SQLite library functions directly from your Qt application, then your only choice is to recompile Qt (or the Qt plugin).
So I recompile sqlite Qt plugin (file path is C:\Qt\Qt5.4.2\5.4\Src\qtbase\src\plugins\sqldrivers). Then modify two position:
add DEFINES -= SQLITE_OMIT_LOAD_EXTENSION in sqlite.pro;
add below code block in function named open of qsql_sqlite.cpp:
if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, NULL) == SQLITE_OK) {
...
char* zErrMsg = 0;
char* spatialiteDll = "mod_spatialite";
sqlite3_enable_load_extension(d->access, 1);
sqlite3_load_extension(d->access, spatialiteDll, 0, &zErrMsg);
...
}
Second Solution: Reference links: https://www.sqlite.org/quickstart.html
As #Marco says,
QSqlQuery is a c++/Qt class that you are using to get data from the sqlite database, but Qt is also c++ so you are free to use any c++ sqlite library to open you sqlite database. sqlite.org/quickstart.html
So, I get below code to execute SQL sentence along with spatialite function in Qt5.
Example Code:
#include <QCoreApplication>
#include <stdio.h>
#include <sqlite3.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char **argv){
QCoreApplication a(argc, argv);
sqlite3 *db;
char *zErrMsg = 0;
int rc;
if( argc!=3 ){
fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
return(1);
}
rc = sqlite3_open(argv[1], &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
char* spatialiteDll = "mod_spatialite";
sqlite3_enable_load_extension(db, 1);
sqlite3_load_extension(db, spatialiteDll, 0, &zErrMsg);
fprintf(stderr, "sqlite3 error: %s\n", zErrMsg);
rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return a.exec();
}

windows C++ Ldap build error _imp__ldap_init()

I am building a C++ program that queries against Active Directory using (Apache Directory studio) LDAP . Iam doing it with codeblocks IDE and windows 10. I have the following code sample from the program:
#include<iostream>
#include<windows.h>
#include<winldap.h>
using namespace std;
int main() {
LDAP* testLdapConnection = NULL;
ULONG version = LDAP_VERSION1;
ULONG connectionSuccess = 0;
testLdapConnection = ldap_initA("localhost",389);
if(testLdapConnection==NULL){
cout<<"connection Failed";
}
else{
cout<<"Success";
}
}
When I try to build this sample in codeblocks, the build fails and the line with ldap_init() is underlined in red. When I hover the mouse over the error, it says "Undefined reference to _imp__ldap_initA()."
You have to add Wldap32.lib to list of linked libraries in your project.

C++ Application That Uses MSI Automation API 32 and 64bit

I am trying to create simple c++ win32 console app(in vs2010) that calls windows installer automation api. But I am failing so far. This approach causes the "Microsoft C++ exception: _com_error at memory location" error.
How to correctly use this api? How to make it work correctly on 32 and 64 bit system with only one .exe file?
Many thanks,
Marek
#include "stdafx.h"
#include <windows.h>
#include <atlstr.h>
#import "msi.dll"
using namespace WindowsInstaller;
_bstr_t GetInstalledProduct(InstallerPtr pInstaller,_bstr_t upgradeCode){
StringListPtr installedProducts = pInstaller->GetRelatedProducts(upgradeCode);
return installedProducts->Count > 0 ? installedProducts->GetItem(0) : "";
}
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
InstallerPtr pInstaller("WindowsInstaller.Installer");
_bstr_t upgradeCode("4C34BD16-CAD4-4059-B074-777793406C5F");
_bstr_t installedProduct = GetInstalledProduct(pInstaller, upgradeCode);
StringListPtr features = pInstaller->GetFeatures(installedProduct);
::CoUninitialize();
return 0;
}
I finally found the solution. The correct way is include msi.lib in linker includes and use Msi.h from windows sdk.
#include "stdafx.h"
#include <windows.h>
#include <Msi.h>
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t productCode[255];
int result = MsiEnumRelatedProducts(L"{4C34BD16-CAD4-4059-A074-777493406C5F}", 0, 0, productCode);
wchar_t featureName[255];
wchar_t featureParent[255];
MsiEnumFeatures(productCode, 0, featureName, featureParent);
INSTALLSTATE featureState = MsiQueryFeatureState(productCode, L"FeatureName");
return 0;
}

Using COM dll in a Qt project

In vs c++ I used the following code to use some functions in a dll file that I don't have its header
#import "dll path"
HRESULT hr = CoInitialize(NULL);
if (hr==S_OK)
{cout<<"INITIALIZED\n";}
Trans_ATLLib::ITransCriptPtr Trans;
hr = Trans.CreateInstance(__uuidof(Trans_ATLLib::TransCript));
if (hr==S_OK)
{cout<<"INSTANCE CREATED\n";}
hr =Trans->EnableLastCharTashkeel(true);
if (hr==S_OK)
{cout<<"EnableLastCharTashkeel DONE\n";}
hr =Trans->EnableEmphaticLAM_RAA(true);
if (hr==S_OK)
{cout<<"EnableEmphaticLAM_RAA DONE\n";}
VARIANT_BOOL test;
test = Trans->SetText(arabic_string);
if (test==0)
{cout<<"error in setting the arabic sting\n";}
string result;
result = Trans->GetResult();
istringstream iss(result);
vector<string> phonemes;
copy(istream_iterator<string>(iss),istream_iterator<string>(),back_inserter<vector<string> >(phonemes));
return phonemes;
}
But I found that Qt doesn't use the same method.
Can any one help me in calling these functions in Qt?
Thanks in advance.
If you use c++ - do the same! Qt is a set of libraries, not a different programming language - call to winApi everywhere you need, but don't forget that it is not portable.