I was given the project to add information to the summary property page of non-office files. I have almost no experience with C++, but I managed to find a program that does add information to the summary page. I need to read in the information from a text file, which contain four lines of information which are assigned to the following 'variables' Filename, RevLevel,CadStatus and RevReason.
I am not sure if the code is correct to read in the data and then assign the data.
The second part of the problem I am having is I get an error when I compile the project.
SummaryPropPage.cpp
H:\SummaryPropPage\SummaryPropPage.cpp(70) : error C2440: '=' : cannot convert from 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *' to 'char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
H:\SummaryPropPage\SummaryPropPage.cpp(96) : error C2664: 'StgOpenStorageEx' : cannot convert parameter 1 from 'char' to 'const unsigned short *'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
Error executing cl.exe.
SummaryPropPage.obj - 2 error(s), 0 warning(s)
It seems to me that the value I am trying to use (*ptrFileName) is not the same type as required by the function.
Any help is greatly appreciated.
Thanks,
Craig
// SummaryPropPage.cpp : Defines the entry point
// for the application.
//
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// ifstream is used for reading files
// We'll read from a file
ifstream infile ("H:\\summary_info.txt");
// If we couldn't open the input file stream for reading
if (!infile)
{
// Print an error and exit
cerr << "File could not be opened for reading!" << endl;
exit(1);
}
// While there's still stuff left to read
while (!infile.eof())
{
// read stuff from the file into a string. Not sure if this is working correctly. The summary_info.txt file has 4 lines of data
//std::string strInput;
getline(infile, FileName);
getline(infile, RevLevel);
getline(infile, CadStatus);
getline(infile, RevReason);
}
infile.close();
//set_property ()
char *ptrFileName; // this is a guess in an attempt to correct the error
ptrFileName = &FileName; // Ditto
// Open a file and a property set within it.
hr = StgOpenStorageEx( *ptrFileName, // When this is hard coded it works fine, but the filename changes so I need a way to open a different file each time the program is run.
STGM_DIRECT|STGM_SHARE_EXCLUSIVE| // hard coded means "H:\\summary_info.txt"
STGM_READWRITE,
STGFMT_ANY,
// STGFMT_STORAGE //Structured
//Storage property sets
// STGFMT_FILE //NTFS file system
//property sets
0,
NULL,
NULL,
IID_IPropertySetStorage,
reinterpret_cast<void**>(&pPropSetStg) );
//we can identify any property through its Name or its ID
// propspec.ulKind = PRSPEC_LPWSTR;
// propspec.lpwstr = L"Title"; // this is also going to need to be changed to a variable/pointer as well
StgOpenStorageEx() takes a pointer to a wide string as the first parameter.
The compiler error is cause because you're trying to implicitly convert a pointer to an std::string to a pointer to a C string (don't even dare do the explicit conversion).
This does not work: ptrFileName = &FileName;
There's a method for returning the internal C string: std::string::c_str().
But there's more. Since StgOpenStorageEx() takes a pointer to a wide string, you need to use a string that uses wide characters, instead. There's a typedef for that: std::wstring. I'm not sure if getline() will work with it, though.
In summary, this is what you need to do:
1. Make FileName an std::wstring.
2. Pass FileName.c_str() as the first parameter of StgOpenStorageEx().
Here is my next attempt at getting this to work, though I am still not sure what is a proper way to read in a wstring, but when I use the cstring I can watch the values and see that I am reading the text file correctly. I can not do this with the wstring. This compiles and builds with no errors, but when I run it it terminates with a Debug error. I have marked the line where the error occurs.
Any ideas or suggestions?
Thank you,
Craig
// SummaryPropPage.cpp : Defines the entry point
// for the application.
//
//#include <stdlib.h> // these four line were added for wstring conversion
//#include "atlbase.h"
//#include "atlstr.h"
//#include "comutil.h"
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// ifstream is used for reading files
// We'll read from a file
ifstream infile ("H:\\summary_info.txt");
// If we couldn't open the input file stream for reading
if (!infile)
{
// Print an error and exit
cerr << "File could not be opened for reading!" << endl;
exit(1);
}
// While there's still stuff left to read
while (!infile.eof())
{
// read stuff from the file into a string and print it
//std::string FileName;
getline(infile, FileName);
getline(infile, RevLevel);
getline(infile, CadStatus);
getline(infile, RevReason);
}
infile.close();
// added to convert string to wstring
// Convert to a wchar_t*
size_t origsize = strlen(FileName.c_str()) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs(wcstring, FileName.c_str(),newsize);
wcscat(wcstring, L" (wchar_t *)");
wFileName = wcstring;
// Open a file and a property set within it.
hr = StgOpenStorageEx(wFileName.c_str(),
STGM_DIRECT|STGM_SHARE_EXCLUSIVE|
STGM_READWRITE,
STGFMT_ANY,
// STGFMT_STORAGE //Structured
//Storage property sets
// STGFMT_FILE //NTFS file system
//property sets
0,
NULL,
NULL,
IID_IPropertySetStorage,
reinterpret_cast<void**>(&pPropSetStg) );
if( FAILED(hr) )
throw L"Failed StgOpenStorageEx"; // this is where the Debug error occurs when I step through the program
Don't use strlen() on the pointer returned by std::string::c_str(). There already is std::string::size().
DEFINITELY don't use mbstowcs() to convert between strings of different size. I'm pretty sure if you just do wFileName = FileName the conversion will be done automatically.
Did you try passing different flags to StgOpenStorageEx()? It may be that it's not giving you the access rights you ask for.
Next time you post code, put code tags around it. Like this:
[code] int main(){
std::cout <<"Hello, World!"<<std::endl;
return 0;
}
[/code]
Helios,
I tried to use wFileName= FileName and got the following error.
H:\SummaryPropPage\SummaryPropPage.cpp(74) : error C2679: binary '=' : no operator defined which takes a right-hand operand of type 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' (or there is no acceptable
conversion).
Also, can you be more specific (show an example) as to the best way to read in std::wstrings from a text file. I have not found anything that I can use and that really makes sense to me on my many searches on the internet.
Getfile does not work with wstrings as you suggested, but I did get it to work with std::string.
And yeah, doing input and output for wide strings is not easy. You might want to consider doing the IO to a narrow string and then copying the data to the wide string.