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.
Related
How can I get the simple application name from following code of IAudioSessionControl2 ? Should I substring or use other method such as using GUID, although I dont know how to get app name from GUID. My target is to know the app name that is using a audio session.
Code:
LPWSTR instId = NULL;
hr = pSessionControl2->GetSessionInstanceIdentifier(&instId);
if (S_OK == hr)
{
wprintf_s(L"SessionInstanceIdentifier: %s\n", instId);
}
GUID guid;
HRESULT hr1 = CLSIDFromString(instId, (LPCLSID)&guid);
if (hr1 != S_OK) {
// bad GUID string...
//std::cout << "\nHi___\n" << guid.Data1 << "\n";
}
// out:
// SessionInstanceIdentifier: {0.0.0.00000000}.{db6e6565-391a-45a1-970d-41d8389b71ae}|\Device\HarddiskVolume4\Program Files\WindowsApps\App_15.83.3408.0_x86__kzf8qxf38zg5a\App\App.exe%b{00000000-...}|1%b9532
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);
I'm using IApplicationActivationManager::ActivateApplication() from MSDN ActivateApplication API
to write a console app EXE (VC++) which launches a "Photos metro app & displays a PNG image". Here is teh code snippet. It's activating the "Photos metro application" but not able to display the image using the "Photos app".
CoInitializeEx(NULL, COINIT_MULTITHREADED);
LPCWSTR appId = L"Microsoft.Windows.Photos_8wekyb3d8bbwe!App";
LPCWSTR imageArg = L" C:\\data\\Users\\Public\\Pictures\\image123.png";
IApplicationActivationManager* paam = NULL;
HRESULT hr = E_FAIL;
__try
{
hr = CoCreateInstance(CLSID_ApplicationActivationManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&paam));
if (FAILED(hr))
{
cout << "Error creating CoCreateINstance & HR is" <<hr<< endl;
return 0;
}
DWORD pid = 0;
hr = paam->ActivateApplication(appId, imageArg, AO_NONE, &pid);
if (FAILED(hr))
{
cout << "Error in ActivateApplication call & HR is " <<hr<< endl;
return 0;
}
cout << hex << hr;
if (hr == 0)
wprintf(L"Activated %s with pid %d\r\n", appId, pid);
}
__finally
{
if (paam) paam->Release();
}
CoUninitialize();
I'm sure the error is in the 2nd argument of the "ActivateApplication()" function, where I'm giving the argument. I tried different ways of giving arguments like :
LPCWSTR imageArg = L"
C:\data\Users\Public\Pictures\image123.png"; OR
LPCWSTR imageArg = L"-
C:\data\Users\Public\Pictures\image123.png";
LPCWSTR
imageArg = L"C:\data\Users\Public\Pictures\image123.png";
To perform a file activation use the IApplicationActivationManager::ActivateForFile method.
You can create a ShellItem from a file path with SHCreateItemFromParsingName (the path is a parsing name) and can create a ShellItemArray from that with
SHCreateShellItemArrayFromShellItem
The Photos app won't listen for a file name on ActivateApplication's activation argument, and it wouldn't have access to the file by path if it did. The ActivateForFile method will convert the passed in ShellItems to StorageFiles which carry permissions to allow the app to open them.
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;
}
Im working on an application that uses a CHtmlView. New requirements mean I would like to be able to get the HTML source from the class to parse for a specific tag (or if possible just get the information in the tag). This would be fine if we were using a newer system and I could use CHtmlView::GetSource but it doesn't exist.
I've had a pretty extensive search online but am pretty new to most of Windows programming and haven't been able to achieve anything useful yet.
So if anyone has an example of how to extract the HTML from a CHtmlView without using GetSource I would appreciate seeing it. I've tried
BSTR bstr;
_bstr_t * bstrContainer;
HRESULT hr;
IHTMLDocument2 * pDoc;
IDispatch * pDocDisp = NULL;
pDocDisp = this->GetHtmlDocument();
if (pDocDisp != NULL) {
hr = pDocDisp->QueryInterface (IID_IHTMLDocument2, (void**)&pDoc);
if (SUCCEEDED(hr)) {
if (pDoc->toString(&bstr) != S_OK) {
//error...
} else {
bstrContainer = new _bstr_t(bstr);
size = (bstrContainer->length()+1)*2;
realString = new char[size];
strncpy(realString, (char*)(*bstrContainer), size);
}
} else {
//error
}
pDocDisp->Release();
}
but it mostly just gives me "[object]" in realString. Like I said, new to Windows.
Any help appreciated.
Add this helper function into your CHtmlView-derived class to retrieve the html source. Remember to check the returned boolean state from this function as com-interface can be quite unreliable when system resources are low.
/* ============================================== */
BOOL CTest1View::GetHtmlText(CString &strHtmlText)
{
BOOL bState = FALSE;
// get IDispatch interface of the active document object
IDispatch *pDisp = this->GetHtmlDocument();
if (pDisp != NULL)
{ // get the IHTMLDocument3 interface
IHTMLDocument3 *pDoc = NULL;
HRESULT hr = pDisp->QueryInterface(IID_IHTMLDocument3, (void**) &pDoc);
if (SUCCEEDED(hr))
{ // get root element
IHTMLElement *pRootElement = NULL;
hr = pDoc->get_documentElement(&pRootElement);
if (SUCCEEDED(hr))
{ // get html text into bstr
BSTR bstrHtmlText;
hr = pRootElement->get_outerHTML(&bstrHtmlText);
if (SUCCEEDED(hr))
{ // convert bstr to CString
strHtmlText = bstrHtmlText;
bState = TRUE;
SysFreeString(bstrHtmlText);
}
pRootElement->Release();
}
pDoc->Release();
}
pDisp->Release();
}
return bState;
}