I am trying to load PNGs for HBITMAP. I found this post from stackoverflow. When I run the code I get REGDB_E_CLASSNOTREG on CoCreateInstance(CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER, __uuidof(ipDecoder), reinterpret_cast<void**>(&ipDecoder). I am using Visual Studio 2012 RC, I've done CoInitlaize and I am still getting same error what could be possibly wrong?
WIC API suggest that you create decoder from factory, rather than directly using its CLSID. See IWICImagingFactory interface and sample code there.
You have options to create from file, stream or specifying container format GUID.
Related
I'm working on Visual Studio 2019 community, and I'm writing an MFC application in cpp. I want to add a functionality to the dialog box - such that when pressing a button it converts an existing xls file into pdf file. I've tried using the extension Aspose.Cells.Cpp and Aspose.PDF.Cpp with this code, but I get a lot of errors in the code of the DLL itself. I've also tried installing libHARU from here, but I didn't manage to make it work.
I've tried looking for another way to convert xls to pdf in MFC application in cpp, or another environment for creating desktop applications (which has some basic functionalities such as adding a pressing button in MFC, so I won't have to write everything from scratch with Win32 API), but I didn't find anything. Perhaps someone can explain to me how to perform this conversion in cpp so that I can use it when writing an MFC app, or could refer me to some useful information about another way of creating the application which supports this type of conversions?
You said in your comments to me that you can assume the user has Excel installed on his machine. If so, then you can use Excel's automation object model to manipulate Excel. You could do stuff like #import the type library and stuff...maybe that would make prettier C++. My experience, however, with driving Office apps is to stick more with just raw dispatch pointers. I've had less go wrong that way. This probably needs some more error checking and stuff, but that's up to you.
... and a big caveat. This is for an interactive app...which I halfway assume since you are using the MFC topic. With a service, Microsoft does not recommend you drive their Office applications in this manner. I tested this on one .xlsx file and it worked. Assume it will work for .xls as well. For other formats, you might need to use different import functions.
void ConvertFile(LPCWSTR lpszFileIn, LPCWSTR lpszFileOut)
{
CComDispatchDriver excel;
if (SUCCEEDED(excel.CoCreateInstance(_T("Excel.Application"), NULL, CLSCTX_LOCAL_SERVER)))
{
_variant_t vWorkbooks;
if (SUCCEEDED(excel.GetPropertyByName(L"Workbooks", &vWorkbooks)))
{
CComDispatchDriver workbooks(vWorkbooks.pdispVal);
_variant_t vWorksheet;
if (SUCCEEDED(workbooks.Invoke1(L"Open", &_variant_t(lpszFileIn), &vWorksheet)))
{
CComDispatchDriver worksheet(vWorksheet.pdispVal);
UINT xlTypePdf = 0;
HRESULT hr = worksheet.Invoke2(L"ExportAsFixedFOrmat", &_variant_t(xlTypePdf), &_variant_t(lpszFileOut), NULL);
if (FAILED(hr))
{
_com_error err(hr);
AfxMessageBox(err.ErrorMessage());
}
}
}
excel.Invoke0(L"Quit", NULL);
}
}
I'll give a solution, but this one doesn't use c++, just command line and LibreOffice app:
Use command line Libre Office tool: --convert-to
--convert-to output_file_extension[:output_filter_name] [--outdir output_dir] files
Batch convert files. If --outdir is not specified, then current working directory is used as output_dir.
Eg. --convert-to pdf *.doc
--convert-to pdf:writer_pdf_Export --outdir /home/user *.doc
More details about how to use this command you'll find here: https://help.libreoffice.org/Common/Starting_the_Software_With_Parameters
Later edit: Here is a sample of how to implement the above solution in a C++/MFC code:
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
PROCESS_INFORMATION pi = { 0 };
sCommand.Format(_T("C:\\WINDOWS\\System32\\cmd.exe /c
C:\\LibreOffice\\program\\swriter.exe --convert-to pdf -outdir
c:\\temp\\ c:\\temp\\MyFile.doc"));
::CreateProcess(0, sCommand, 0, 0, TRUE, CREATE_NO_WINDOW, 0, 0, &si, &pi);
I'm trying to use the SystemMediaTransportControls in Visual C++ using WRL (toolkit v140) but I'm having issues with the following:
Microsoft::WRL::ComPtr<ABI::Windows::Media::ISystemMediaTransportControls> controls;
HRESULT hResult = ABI::Windows::Foundation::GetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_Media_SystemMediaTransportControls).Get(), &controls);
The above code is returning E_NOINTERFACE but it's working if I follow the MSDN tutorial and activate a IUriRuntimeClassFactory.
Edit: I have initialized it prior to calling those functions.
ISystemMediaTransportControls is an interface implemented on SystemMediaTransportControls class, not its activation factory. Did you intend the controls variable to be Microsoft::WRL::ComPtr<ABI::Windows::Media:ISystemMediaTransportControlsStatics> instead?
I have an ATL DLL that I am trying to consume from an ATL Exe. When I try to create an instance of the object in the DLL it fails with an error REGDB_E_CLASSNOTREG. I have checked the registry and I can see the object is registered, both the ProgID as well as the CLSID.
CComPtr<IMyInterface> ptrMyInterface;
ptrMyInterface.CoCreateInstance(L"ProgID", nullptr, CLSCTX_ALL); // Fails
CLSID myClsid;
CLSIDFromString(L"{MyCLSID}"), &myClsid); // Correctly looks up the CLSID
ptrMyInterface.CoCreateInstance(myClsid, nullptr, CLSCTX_ALL); // Also fails
Any suggestions
Ok, I feel really kind of silly. The problem was the fact that CComPtr was trying to call QueryInterface on the object I was CoCreating. The Interface that I was using was not implemented by the class that I was creating. It seems that there would be a better error than REGDB_E_CLASSNOTREG. Something like E_NOINTERFACE would be a better return code IMHO.
CComPtr<IMyCorrectInterface> ptrMyInterface;
ptrMyInterface.CoCreateInstance(L"ProgID", nullptr, CLSCTX_ALL); // WORKS!!!
I am learning basics in COM, so I try to write simple COM component in VS2010 C++ Windows 7.
I created dll for component, registered it using following REG-file:
REGEDIT
HKEY_CLASSES_ROOT\Math.Component.1 = Chapter 6 Math Component
HKEY_CLASSES_ROOT\Math.Component.1\CurVer = Math.Component.1
HKEY_CLASSES_ROOT\Math.Component.1\CLSID = {A888F560-58E4-11d0-A68A-0000837E3100}
HKEY_CLASSES_ROOT\CLSID\{A888F560-58E4-11d0-A68A-0000837E3100} = Chapter 6 Math Component
HKEY_CLASSES_ROOT\CLSID\{A888F560-58E4-11d0-A68A-0000837E3100}\ProgID = Math.Component.1
HKEY_CLASSES_ROOT\CLSID\{A888F560-58E4-11d0-A68A-0000837E3100}\VersionIndependentProgID = Math.Component
HKEY_CLASSES_ROOT\CLSID\{A888F560-58E4-11d0-A68A-0000837E3100}\InprocServer32 = D:\Proga\COM\Debug\server.dll
HKEY_CLASSES_ROOT\CLSID\{A888F560-58E4-11d0-A68A-0000837E3100}\NotInsertable
In dll I exported (stubs for last two)
DllGetClassObject
DllCanUnloadNow
DllRegisterServer
DllUnregisterServer
In my COM client CLSIDFromProgID( szWideProgID, &clsid ); works as expected, returning {A888F560-58E4-11d0-A68A-0000837E3100}.
But when I try to get access to IClassFactory REGDB_E_CLASSNOTREG CoGetClassObject(clsid, CLSCTX_INPROC, NULL, IID_IClassFactory, (void **)&pCF) I get (0x80040154) error.
Both server and client compiled for Win32 target platform (although I tried x64 too). Source code I got from tutorial, so I don't understand what is wrong.
The tutorial you found no doubt is old, written long before 64-bit Windows came around. Registry keys need to be written to HKLM\Software\Wow6432Node\Classes for 32-bit COM servers, to HKLM\Software\Classes for 64-bit COM servers. Your .reg file isn't going to take care of that. You must avoid the HKEY_CLASSES_ROOT alias and replace it with the explicit HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes to avoid accidents.
Use the SysInternals' ProcMon utility if you still have problems, you'll see your test program searching for the registry keys and the DLL.
I have a C# dll that I properly have registered for COM Interop, and made COM visible. Using cppbuilder, I imported the type library, which generated the wrapper classes, and I am now attempting to use to create an instance of my C# class. However, I'm getting a REGDB_E_CLASSNOTREG error in my C++ code. I verified the dll is in the registry, and even re-registered it with regasm. No change. What could I be missing?
Here is my C++ code:
_MyClassPtr obj;
HRESULT hr = obj.CreateInstance(__uuidof(MyClass));
//now hr equals REGDB_E_CLASSNOTREG
I've also tried it as such:
IMyClass* obj;
HRESULT hr = CoCreateInstance(__uuidof(MyClass), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMyClass), (void**) &obj);
//same result, hr equals REGDB_E_CLASSNOTREG
I do have one additional dependency in the C# app. I registered it for COM as well with no difference, but did not import it's type library into the C++ project.
UPDATE: based on the comments below, I discovered that CreateInstance is looking up the class guid in the following places in the registry:
HKCU\Software\Classes\Wow6432Node\CLSID\{guid}
HKCR\Wow6432Node\CLSID\{guid}
HKCU\Software\Classes\CLSID\{guid}
HKCR\CLSID\{guid}
But, going through the registry, the only entry under any of the CLSID nodes that is related to my assembly is the guid for the assembly itself, which is, of course, different than the guid for the class, or the interface.
I've manually run regasm under both x86 and x64 mode to try to acheive different results. No differences.
Well, I found out what would work.
IMyClassPtr obj;
HRESULT hr = obj.CreateInstance(CLSID_MyClass);
CLSID_MyCLass was a guid constant in the generated MyClass_TLB.cpp file. Using it instead of __uuidof(...) for the class types enabled everything to start working correctly.