I'm building my first MFC app. I'm successfully connecting to the database, but when I try to execute a query, hResult becomes DB_E_NOTABLE.
This is my code:
class CCitiesTable : public CTable<CAccessor<CCitiesTableAccessor> >
{
public:
bool SelectAll(CCitiesArray& oCitiesArray)
{
CDataSource oDataSource;
CSession oSession;
CCitiesTable oCitiesTable;
try
{
HRESULT hResult = CoInitialize(0);
if (FAILED(hResult))
{
//Message( _T("Unable to CoInitialize COM Interface.") );
return FALSE;
}
CDBPropSet oDBPropSet(DBPROPSET_DBINIT);
oDBPropSet.AddProperty(DBPROP_INIT_DATASOURCE, _T("LENOVO2\\SQL2008") ); // сървър
oDBPropSet.AddProperty(DBPROP_AUTH_USERID, _T("sa") );
oDBPropSet.AddProperty(DBPROP_AUTH_PASSWORD, _T("massive") );
oDBPropSet.AddProperty(DBPROP_INIT_CATALOG, _T("PhoneBookDB" ));
oDBPropSet.AddProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, false);
oDBPropSet.AddProperty(DBPROP_INIT_LCID, 1033L);
oDBPropSet.AddProperty(DBPROP_INIT_PROMPT, static_cast<short>(4));
// Свързваме се към базата данни
hResult = oDataSource.Open(_T("SQLOLEDB.1"), &oDBPropSet);
if (FAILED(hResult))
{
//Message(_T("Unable to connect to SQL Server database. Error: %d"), hResult);
return FALSE;
}
//Open session
hResult = oSession.Open(oDataSource);
if (FAILED(hResult))
{
//Message(_T("Unable to open session. Error: %d"), hResult);
oDataSource.Close();
return FALSE;
}
//Make query
CString strQuery;
strQuery = _T("SELECT * FROM dbo.CITIES");
// Execute query
hResult = oCitiesTable.Open(oSession, strQuery);
After executing the code above hResult is DB_E_NOTABLE. Except that the table is there. Database: PhoneBookDB Schema: dbo Table: CITIES. The query works just fine in SQL Server Management Studio.
According to the documentation for CTable::Open, CTable::Open expects a table name, not a select query. The error you are getting is saying that "SELECT * FROM dbo.CITIES" is not a table name (which it is not).
szTableName
[in] The name of the table to open, passed as an ANSI string.
You need to use:
CString strTable = _T("CITIES");
// Open Table
hResult = oCitiesTable.Open(oSession, strTable);
Related
How do I parse KLV data?
There is some codes below. I'd like to make a map using klv metadata. But how?
I know that the latitude and the longitude is in the 13th and 14th key in klv. But how could I use them and make a map.
ILMMpgDmx *CMainFrame::GetMPEG2DemuxInterface()
{
IUnknown *pSplitter;
HRESULT hr = m_player->GetSubObject(ltmmPlay_Object_Splitter, &pSplitter);
if (SUCCEEDED(hr))
{
ILMMpgDmx *pMpgDmx;
hr = pSplitter->QueryInterface(IID_ILMMpgDmx, (void **)&pMpgDmx);
if (SUCCEEDED(hr))
{
pSplitter->Release();
return pMpgDmx;
}
pSplitter->Release();
}
return NULL;
}
void CMainFrame::EnableMPEG2DemuxCallback()
{
HRESULT hr;
ILMMpgDmx *pMpgDmx = GetMPEG2DemuxInterface();
if (pMpgDmx)
{
// make sure the demux is not using the callback I am about to destroy
pMpgDmx->put_CallbackObj(NULL);
DeleteCallbackClass();
m_pCallback = new CMPEG2DemuxCallback(pMpgDmx);
// Force the callback to be called in the main thread. C++ applications in general can handle data in another thread, but our app is using MFC
// Our callback will display data in a window and MFC doesn't work well when you use windows from threads other than the main thread
// So, for simplicity, we will ask the demux to send the data to the main thread
hr = pMpgDmx->put_CallInSameThread(VARIANT_TRUE);
hr = pMpgDmx->put_CallbackObj(m_pCallback);
pMpgDmx->Release();
}
}
And the DataAvailable() function being called looks like this:
HRESULT STDMETHODCALLTYPE CMPEG2DemuxCallback::DataAvailable
(
/* [in] */ VARIANT *pData,
/* [in] */ long lDataSize,
/* [in] */ FileTypeConstants fileType,
/* [in] */ long streamPID,
/* [in] */ long streamType,
/* [in] */ PTSTypeConstants PTSType,
/* [in] */ double PTS,
/* [in] */ long flags
)
{
// skip small (most likely invalid) data chunks
if(lDataSize <= 1)
return S_OK;
//refresh control
{
static const DWORD MIN_REFRESH_TIME = 1000 ;//1 second
static DWORD dwLastTime = 0 ;//allow first data to be displayed
DWORD dwCurTime = GetTickCount ( ) ;
if ( dwCurTime - dwLastTime < MIN_REFRESH_TIME )
{
return S_OK ;
}
else
{
dwLastTime = dwCurTime ;
}
}
CPrivateDataView* pDataView = CPrivateDataViewManager::GetPrivateDataListView ( ) ;
if(!pDataView)
return S_OK;//skip
pDataView->SetRedraw ( FALSE ) ;
pDataView->GetListCtrl ( ).DeleteAllItems ( ) ;
{
HRESULT hr;
if(flags & DataFlag_IsKLV)
{
ILMKlvParser* pParser;
hr = m_pMpgDmx->GetKlvParser(streamPID, &pParser);
if(FAILED(hr))
return hr;
hr = EnumKlvKeys(pParser, pDataView, NULL, pData, lDataSize, flags);
if(FAILED(hr))
{
pParser->Release() ;
return hr;
}
pParser->Release();
}
else if(flags & DataFlag_IsAscii)
{
CString str;
hr = DumpVariantAsAscii(str, pData, lDataSize);
if(FAILED(hr))
return hr;
pDataView->AddValue (str) ;
}
else if(flags & DataFlag_IsBinary)
{
CString str;
hr = DumpVariantAsBinary(str, pData, lDataSize);
if(FAILED(hr))
return hr;
pDataView->AddValue (str) ;
}
else
{
ASSERT ( FALSE ) ;
return E_UNEXPECTED;
}
}
pDataView->SetRedraw ( TRUE ) ;
pDataView->RedrawWindow ( ) ;
return S_OK ;
}
These are all codes that I found. Also I found this klv library. I need a path for advicing.
https://github.com/Hunter522/libklv
I finally found how to parse KLV from MPEG2 TS.
i did the following
1. Use MPEg2- demux directshow filter that knows to parse the PID of metadata KLV.
2. i built my own directshow filter ( based on dump filter ) this filter accept in receive the entire PID of the KLV and than using the libklv from here
https://github.com/Hunter522/libklv
i added into the filter and this gave me the key , length and values.
But here is the trick:
KLV meta data can be part of protocol so in my case the protocol is MISB 601.8
here: https://upload.wikimedia.org/wikipedia/commons/1/19/MISB_Standard_0601.pdf
Every tag have its own formula, its units and name
there are 70 + tags.
thats mean that if a tag have 2 byte , go to its tag index in the MISB and the formula is there.
I am trying to connect my C++ project to SQL Server using ADO.it goes well when checking first "hr" but error encounter when opening database on the second "if" statement, it says 'Microsoft C++ exception: _com_error at memory location'.
i wonder what is the problem and how can i open database? or is there another way to open database?
i have already tried to change _ConnectionPtr pConnection = NULL; into this _ConnectionPtr pConnection("ADODB.Connection"). here is my code:
HRESULT hr = S_OK;
_ConnectionPtr pConnection = NULL;
_RecordsetPtr pRecordset = NULL;
_bstr_t strCon("Data Source=...\\SQLEXPRESS;Initial Catalog=TestDB;Integrated Security=True");
hr = pConnection.CreateInstance((__uuidof(Connection)));
if (FAILED(hr))
{
printf("Error instantiating Connection objectn");
}
//Open the SQL Server connection
hr = pConnection->Open(strCon, "", "", 0);
if (FAILED(hr))
{
printf("Error Opening Database object using ADO _ConnectionPtr n");
}
I'm validating XML files against XSD schemas as they do in the MSXML documentation example. I have the following code:
XMLSchemaValidation updateInfoSchema;
updateInfoSchema.DoInitialization(L"schema.xsd");
HRESULT hr = CoInitialize(NULL);
if(SUCCEEDED(hr))
{
try
{
_bstr_t bstrOutput = updateInfoSchema.validateFile(L"valid.xml");
}
catch(_com_error &e)
{
updateInfoSchema.dump_com_error(e);
}
CoUninitialize();
}
// Macro that calls a COM method returning HRESULT value.
#define CHK_HR(stmt) do { hr=(stmt); if (FAILED(hr)) goto CleanUp; } while(0)
_bstr_t XMLSchemaValidation::validateFile(_bstr_t bstrFile)
{
// Declare and initialize variables
MSXML2::IXMLDOMSchemaCollectionPtr pXS;
MSXML2::IXMLDOMDocument2Ptr pXD;
MSXML2::IXMLDOMParseErrorPtr pErr;
_bstr_t bstrResult = L"";
HRESULT hr = S_OK;
// Create a schema cache and add xsd schema to it.
CHK_HR(pXS.CreateInstance(__uuidof(MSXML2::XMLSchemaCache60), NULL, CLSCTX_INPROC_SERVER));
CHK_HR(pXS->add(L"", (LPCSTR)(SchemaFileName.GetString())));
// Create a DOMDocument and set its properties.
CHK_HR(pXD.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));
// Assign the schema cache to the DOMDocument's schemas collection.
pXD->schemas = pXS.GetInterfacePtr();
// Load bstrFile into the DOM document.
pXD->async = VARIANT_FALSE;
pXD->validateOnParse = VARIANT_TRUE;
pXD->resolveExternals = VARIANT_TRUE;
if(pXD->load(bstrFile) != VARIANT_TRUE)
{
pErr = pXD->parseError;
bstrResult = _bstr_t(L"Validation failed on ") + bstrFile +
_bstr_t(L"\n=====================") +
_bstr_t(L"\nReason: ") + _bstr_t(pErr->Getreason()) +
_bstr_t(L"\nSource: ") + _bstr_t(pErr->GetsrcText()) +
_bstr_t(L"\nLine: ") + _bstr_t(pErr->Getline()) +
_bstr_t(L"\n");
}
else
{
bstrResult = _bstr_t(L"Validation succeeded for ") + bstrFile +
_bstr_t(L"\n======================\n") +
_bstr_t(pXD->xml) + _bstr_t(L"\n");
}
CleanUp:
return bstrResult;
}
XMLSchemaValidation::DoInitialization(CString XSDFileName) gets the XSD schema file name into the CString XMLSchemaValidation::SchemaFileName.
The code then follows the one in the MSXML example, but I get
First-chance exception at 0x76f9c41f (KernelBase.dll) in CSW.exe: Microsoft C++ exception: _com_error at memory location 0x04a7f014..
when code reaches CHK_HR(pXS->add(L"", (LPCSTR)(SchemaFileName.GetString())));. hr has -2146697210.
Can anyone tell me why this happens?
MSXML is throwing the HRESULT OBJECT_NOT_FOUND (0x800C0006) because the xml you are using does not specify a character set, as detailed in this question. Or MSXML cannot find the file.
What I want to do is access a COM interface and then call the "Open" method of that interface.
I have a sample code in Visual Basic which works fine, but I need to write it in C++ and I can't seem to get it to work.
First of all, this is the working VB code:
Dim CANapeApplication As CANAPELib.Application
CANapeApplication = CreateObject("CANape.Application")
Call CANapeApplication.Open("C:\Users\Public\Documents\Vector\CANape\12\Project", 0)
CANape.Application is the ProgID which selects the interface I need.
After reading some docs at msdn.microsoft.com and this question, I wrote this code:
void ErrorDescription(HRESULT hr); //Function to output a readable hr error
int InitCOM();
int OpenCANape();
// Declarations of variables used.
HRESULT hresult;
void **canApeAppPtr;
IDispatch *pdisp;
CLSID ClassID;
DISPID FAR dispid;
UINT nArgErr;
OLECHAR FAR* canApeWorkingDirectory = L"C:\\Users\\Public\\Documents\\Vector\\CANape\\12\\Project";
int main(){
// Instantiate CANape COM interface
if (InitCOM() != 0) {
std::cout << "init error";
return 1;
}
// Open CANape
if (OpenCANape() != 0) {
std::cout << "Failed to open CANape Project" << std::endl;
return 1;
}
CoUninitialize();
return 0;
}
void ErrorDescription(HRESULT hr) {
if(FACILITY_WINDOWS == HRESULT_FACILITY(hr))
hr = HRESULT_CODE(hr);
TCHAR* szErrMsg;
if(FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&szErrMsg, 0, NULL) != 0)
{
_tprintf(TEXT("%s"), szErrMsg);
LocalFree(szErrMsg);
} else
_tprintf( TEXT("[Could not find a description for error # %#x.]\n"), hr);
}
int InitCOM() {
// Initialize OLE DLLs.
hresult = OleInitialize(NULL);
if (!SUCCEEDED(hresult)) {
ErrorDescription(hresult);
return 1;
}
// Get CLSID from ProgID
//hresult = CLSIDFromProgID(OLESTR("CANape.Application"), &ClassID);
hresult = CLSIDFromProgID(OLESTR("CanapeCom.CanapeCom"), &ClassID);
if (!SUCCEEDED(hresult)) {
ErrorDescription(hresult);
return 1;
}
// OLE function CoCreateInstance starts application using GUID/CLSID
hresult = CoCreateInstance(ClassID, NULL, CLSCTX_LOCAL_SERVER,
IID_IDispatch, (void **)&pdisp);
if (!SUCCEEDED(hresult)) {
ErrorDescription(hresult);
return 1;
}
// Call QueryInterface to see if object supports IDispatch
hresult = pdisp->QueryInterface(IID_IDispatch, (void **)&pdisp);
if (!SUCCEEDED(hresult)) {
ErrorDescription(hresult);
return 1;
}
std::cout << "success" << std::endl;
return 0;
}
int OpenCANape() {
//Method name
OLECHAR *szMember = L"Open";
// Retrieve the dispatch identifier for the Open method
// Use defaults where possible
DISPID idFileExists;
hresult = pdisp->GetIDsOfNames(
IID_NULL,
&szMember,
1,
LOCALE_SYSTEM_DEFAULT,
&idFileExists);
if (!SUCCEEDED(hresult)) {
std::cout << "GetIDsOfNames: ";
ErrorDescription(hresult);
return 1;
}
unsigned int puArgErr = 0;
VARIANT VarResult;
VariantInit(&VarResult);
DISPPARAMS pParams;
memset(&pParams, 0, sizeof(DISPPARAMS));
pParams.cArgs = 2;
VARIANT Arguments[2];
VariantInit(&Arguments[0]);
pParams.rgvarg = Arguments;
pParams.cNamedArgs = 0;
pParams.rgvarg[0].vt = VT_BSTR;
pParams.rgvarg[0].bstrVal = SysAllocString(canApeWorkingDirectory);
pParams.rgvarg[1].vt = VT_INT;
pParams.rgvarg[1].intVal = 0; // debug mode
// Invoke the method. Use defaults where possible.
hresult = pdisp->Invoke(
dispid,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&pParams,
&VarResult,
NULL,
&puArgErr
);
SysFreeString(pParams.rgvarg[0].bstrVal);
if (!SUCCEEDED(hresult)) {
ErrorDescription(hresult);
return 1;
}
return 0;
}
There are several problems with this.
Using the ClassID received from CLSIDFromProgID as the first parameter of CoCreateInstance does not work, it returns the error: class not registered
If i use the ProgID CanapeCom.CanapeCom (I found it by looking in the Registry), CoCreateInstance works. However, when I use pdisp->GetIDsOfNames I get the error message: Unkown name. Which I think means that the method was not found. That seems logical because I've used a different ProgID, but I just can't figure out how to get to the interface I'm looking for.
I have also tried to use the resulting CLSID from CLSIDFromProgID(OLESTR("CANape.Application"), &ClassID); as the 4th argument of CoCreateInstance but that resulted in a "No such interface supported" error.
Do I need the dll file of the software? In the VB example the dll file is used to get the interface and then create a new object using the ProgID. I'm not sure if I need to do the same in C++ or how this should work.
I'm really stuck here and hope that someone can help me.
Thanks for your comments.
I've fixed the problem, although the solution is kind of embarrassing...
In my defense, I'm still a student and new to this kind of stuff.
I've used the Process Monitor to check what happens when I execute the VB script.
I saw that the CLSID used there is the ID returned by CLSIDFromProgID(OLESTR("CANape.Application"), &ClassID);, which meant that this had to be the right one and the problem had to be somewhere else. I've looked again at the CoCreateInstance and then took a look at the other parameters. Turns out that the context CLSCTX_LOCAL_SERVER was wrong, it has to be CLSCTX_INPROC_SERVER. I don't know why I've set it to local_server in the first place or why I've never questioned it. I wrote that part of the code a few days ago and then focused too much on the CLSID and IID rather than on the other parameters.
I've also taken the first comment from Alex into account and created a tlb file.
This is a simplified version of the code that works:
#import "CANape.tlb"
int _tmain(int argc, _TCHAR* argv[])
{
_bstr_t path = "C:\\Users\\Public\\Documents\\Vector\\CANape\\12\\Project";
CLSID idbpnt;
CoInitialize(NULL);
HRESULT hr = CLSIDFromProgID (L"CANape.Application", &idbpnt);
CANAPELib::IApplication *app;
hr = CoCreateInstance(idbpnt,NULL,CLSCTX_INPROC_SERVER,__uuidof(CANAPELib::IApplication),(LPVOID*)&app );
app->Open(path,0);
CoUninitialize();
return 0;
}
I have to run a group query like this :
GROUP ON System.ItemName OVER ( SELECT TOP 20 System.ItemName FROM SystemIndex )
But when I run it using C++ ADO Recordset I get an exception at Open ( when I search the SELECT TOP 20 System.ItemName FROM SystemIndex query it ruturns just fine).
so... how to perform a group search like that ?
ADO Code:
_ConnectionPtr connection = NULL;
hr = connection.CreateInstance(__uuidof(Connection));
_RecordsetPtr recordset = NULL;
hr = recordset.CreateInstance(__uuidof(Recordset));
hr = recordset->Open("GROUP ON System.Kind AGGREGATE COUNT() as 'Total' OVER ( SELECT TOP 20 System.ItemName, System.ItemUrl FROM SystemIndex )",
connection.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly, adCmdText);
After trying for a long time I decide to run into OLE DB directly , but it seems dificult to retreive the search data
OLE DB code:
CDataSource cDataSource;
hr = cDataSource.OpenFromInitializationString(connectionstring);
if (SUCCEEDED(hr))
{
CSession cSession;
if (SUCCEEDED(hr))
{
CCommand<CDynamicAccessor, CRowset> cCommand;
hr = cCommand.Open(cSession, L"GROUP ON System.ItemName OVER ( SELECT TOP 20 System.ItemName, System.Itemurl FROM SystemIndex )");
if (SUCCEEDED(hr))
{
for (hr = cCommand.MoveFirst(); S_OK == hr; hr = cCommand.MoveNext())
{
DBORDINAL columns= cCommand.GetColumnCount();
for (DBORDINAL i = 1; i <= columns; i++)
{
PCWSTR pszName = cCommand.GetColumnName(i);
//HOW TO GET DATA TO A sdt::string ?
}
}
cCommand.Close();
}
}
}