I have to read XML files in C++ and we are using XMLLite the problem I have is that the first line of my XML specifies the encoding
<?xml version="1.0" encoding="ISO-8859-15"?>
and when I try to parse the file with XMLLite, I'm getting the error MX_E_ENCODINGSIGNATURE. If I remove the encoding part, the XML parses fine.
<?xml version="1.0"?>
So is it possible to programmatically tell XMLLite to ignore the encoding resp. what other options do I have?
One solution would be to write my own input stream class and suppress this header, and inject the short version, but it would be nicer to have a clean solution.
Even though the documentation says that XMLLite can not handle different encodings it seems that you can go around this by using IMultiLanguage2, which is mentioned in the documentation but no example is given.
So here is how to enable it:
#include <mlang.h>
XMLLiteReader::XMLLiteReader(void)
{
mLanguage = NULL;
mXMLLiteReader = NULL;
mCOMInitialized = false;
HRESULT hr;
if(CoInitialize(NULL) != S_OK)
return;
mCOMInitialized = true;
if((hr = CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_ALL, IID_IMultiLanguage2, (void **)&mLanguage)) != S_OK)
return;
hr = CreateXmlReader(__uuidof(IXmlReader), (void**) &mXMLLiteReader, NULL);
if(hr != S_OK)
{
mXMLLiteReader = NULL;
return;
}
hr = mXMLLiteReader->SetProperty(XmlReaderProperty_MultiLanguage, (LONG_PTR)mLanguage);
}
Related
First time working with COM from C++, been using C# and Delphi before.
So here's the code
HRESULT Result;
Result = CoInitialize(nullptr);
if (!SUCCEEDED(Result))
return Result;
IShellDispatch* API;
Result = CoCreateInstance(CLSID_Shell, nullptr, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&API);
if ((!SUCCEEDED(Result)) || (nullptr == API))
goto Cleanup;
VARIANT Source1, Source2, Destination, Options;
VariantInit(&Destination);
Destination.vt = VT_BSTR;
Destination.bstrVal = SysAllocString(OutFile.c_str());
Folder* PDestination;
Result = API->NameSpace(Destination, &PDestination);
if (!SUCCEEDED(Result))
goto Cleanup;
VariantInit(&Source1);
VariantInit(&Source2);
Source1.vt = VT_BSTR;
Source2.vt = VT_BSTR;
Source1.bstrVal = SysAllocString(InFile1.c_str());
Source2.bstrVal = SysAllocString(InFile2.c_str());
VariantInit(&Options);
Options.vt = VT_I4;
Options.lVal = FOF_NO_UI;
PDestination->CopyHere(Source1, Options);
Sleep(1000);
PDestination->CopyHere(Source2, Options);
Sleep(1000);
PDestination->Release();
API->Release();
Cleanup:
CoUninitialize();
return Result;
OutFile, InFile1 and InFile2 are of type wstring as the program is (mostly) C++. I've managed to create an empty ZIP file, that's not the issue. The issue is that I get an exception claiming that PDestination is nullptr.
If it helps, the variants themselves seems to work. Inspecting them in the debugger yields the paths I provided. I've noticed though how the NameSpace-call returns an S_FALSE. Does anyone know what I can do about that?
Using a library doesn't exactly work, it's corporate code and there's some truly draconian rules when it comes to linking external code so using the Windows API is the easiest way.
I want to perform a specific action in my application based on whether outlook is opened or not.
I tried this piece of code, but it is always returning false.
CLSID clsid;
HRESULT hr = CLSIDFromProgID(_T("Outlook.Application"), &clsid);
if (hr != S_OK)
return false;
IUnknown *pUnknown = NULL;
hr = GetActiveObject(clsid, 0, &pUnknown);
return (hr == S_OK);
Could anyone please let me know how do we check whether "Outlook" is opened or not in c++.
As far as I know, C++ standard will not help in this case, as your question is operating system specific.
You can use "WinAPI" if you are on windows OS.
Below are some steps. The code for below steps is available in below MSDN link. You can modify the code as required for your usage.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682623(v=vs.85).aspx
Call "EnumProcesses". Will return the list of process IDs.
Iterate through each process using process ID return by "EnumProcesses".
Then find the name of process using "OpenProcess" and "GetModuleBaseName" as shown in above MSDN link.
Search for the string "Outlook" in the process name returned by above step (step 3).
This is a rough way I know.
Get the snapshot of all process running in the system, iterate to find
whether "outlook" is present in any of the exe name.
void isOutlookRunning()
{
bool retval = false;
PROCESSENTRY32 t_entry;
t_entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE t_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (Process32First(t_snapshot, &t_entry))
{
while (Process32Next(t_snapshot, &t_entry))
{
if(StrStrI(t_entry.szExeFile,"outlook")
retval = true;
}
}
CloseHandle(t_snapshot);
return retval;
}
I am using the XmlLite library to create an XML file. I want the resulting XML file's prolog to not include the encoding attribute (just the version):
<?xml version="1.0"?>
Here is my code:
HRESULT hr = S_OK;
IStream *pOutFileStream = NULL;
IXmlWriter *pWriter = NULL;
CComPtr<IXmlWriterOutput> pWriterOutput;
//Open writeable output stream
if (FAILED(hr = SHCreateStreamOnFile(output_file_name, STGM_CREATE | STGM_WRITE, &pOutFileStream)))
{
wprintf(L"Error creating file writer, error is %08.8lx", hr);
HR(hr);
}
if (FAILED(hr = CreateXmlWriter(__uuidof(IXmlWriter), (void**) &pWriter, NULL)))
{
wprintf(L"Error creating xml writer, error is %08.8lx", hr);
HR(hr);
}
if(FAILED(CreateXmlWriterOutputWithEncodingName(pOutFileStream, NULL, L"UTF-8", &pWriterOutput))){
wprintf(L"Error setting xml encoding, error is %08.8lx", hr);
HR(hr);
}
if (FAILED(hr = pWriter->SetOutput(pWriterOutput)))
{
wprintf(L"Error, Method: SetOutput, error is %08.8lx", hr);
HR(hr);
}
if (FAILED(hr = pWriter->SetProperty(XmlWriterProperty_Indent, 4)))
{
wprintf(L"Error, Method: SetProperty XmlWriterProperty_Indent, error is %08.8lx", hr);
HR(hr);
}
if (FAILED(hr = pWriter->WriteStartDocument(XmlStandalone_Omit)))
{
wprintf(L"Error, Method: WriteStartDocument, error is %08.8lx", hr);
HR(hr);
}
I have tried removing the call to CreateXmlWriterOutputWithEncodingName() but even then a default encoding attribute with UTF-8 is getting created.
I have also tried putting NULL as the third parameter to that function.
Assistance would be much appreciated!
The XML declaration is written by the WriteStartDocument method.
Instead of calling WriteStartDocument, you can call WriteProcessingInstruction with L"xml" as the name of the processing instruction to write the XML declaration the way you want, for example:
if (FAILED(hr = pWriter->WriteProcessingInstruction(L"xml", L"version=\"1.0\"")))
{
wprintf(L"Error, Method: WriteProcessingInstruction, error is %08.8lx", hr);
HR(hr);
}
This will write the XML declaration as <?xml version="1.0"?>.
I'm trying to open an exclusive stream with an output device using WASAPI. I'm having trouble choosing an acceptable format, since there appear to be no hints as to what formats are accepted by a given device.
In my case, IAudioClient::GetMixFormat(), which would otherwise return a sort of default format for the device, returns a format that can't be used in exclusive mode (IAudioClient::IsFormatSupported() returns AUDCLNT_E_UNSUPPORTED_FORMAT). I don't know where to go from there. There's a ridiculous number of combinations of wave format parameters - do I literally have to iterate through every one of them until something works?
Well, I asked the MSDN forums and they came up with a good answer.
You need to check the device's default device format via IMMDevice::OpenPropertyStore(), and subsequently IPropertyStore::GetValue(), not IAudioClient::GetMixFormat(). Here is the code that retrieved an acceptable WAVEFORMATEX structure:
//CoInitialize/Enumerate devices
IPropertyStore* store = nullptr;
hr = device->OpenPropertyStore(STGM_READ, &store);
if (FAILED(hr)) {
ExitProcess(1);
}
PROPVARIANT prop;
hr = store->GetValue(PKEY_AudioEngine_DeviceFormat, &prop);
if (FAILED(hr)) {
ExitProcess(2);
}
hr = device->Activate (
__uuidof(IAudioClient),
CLSCTX_ALL,
NULL,
(void**)&audioClient
);
device->Release();
device = nullptr;
if (FAILED(hr)) {
ExitProcess(3);
}
hr = audioClient->IsFormatSupported (
AUDCLNT_SHAREMODE_EXCLUSIVE,
(PWAVEFORMATEX)prop.blob.pBlobData,
NULL
);
if (FAILED(hr)) {
ExitProcess(4);
}
The final value of hr is S_OK.
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;
}