|
Can I write native C++ code which will run without the help of .NET Framework in VC++ 8.0?
I tried New Project -> VC++ -> Win32 -> Win32 Project. But it is not working without the help of Framework.
Regards,
Hogan
|
|
|
|
|
hogan.john wrote: But it is not working without the help of Framework.
How did you confirm that?
|
|
|
|
|
VC++ 8.0 and Framework 3.5 installed in my development machine. So I build it then copied the release folder into another machine that doesn’t have Framework. It showed the error message “The application is failed to start because the configuration is incorrect”. I assume this error because of the lack of framework.
Please let me know is it possible to write native code in VC++ 8.0 which will run without the help of Framework.
|
|
|
|
|
|
Thanks for your great help. So we need at least this service pack on the target machine. This is annoying me. Every one said that VC++ 8.0 is the best modern compiler. But the programs developed in this required a helper software. Ok once again thanks for your kind response
|
|
|
|
|
You can also link statically to the C-runtime library. I guess in that case you won't need to install the redist package. Not sure because I never worked with VC2008.
Of course in that case your exe will be larger.
|
|
|
|
|
I am sorry if my curiosity irate you. If there is no problem can tell me which tool you are using to develop C++ applications?
Regards,
Hogan
|
|
|
|
|
I'm using VC2005
|
|
|
|
|
No you don't necessarily have to install this, you can also copy DLL's along with the executable. The DLL's needed to be redistributed are in the folder "Microsoft Visual Studio 8.0\VC\redist\x86".
I think VC++ Express Edition do not come with "redist" folder, however, there is a solution discusses here[^].
There is an article here at codeproject discussing this same issuse (link[^]). Look at "Install a private assembly" section.
Lastly you can link with CRT DLL's statically so that there are no dependencies.
Also this is not specific to VC++, such dependencies will always be there no matter what compiler you will use. It might be easier to do this for other compilers but they will be there. There will always be libraries you link with and have to install them on user machine.
-Saurabh
|
|
|
|
|
Thanks for that link. It really help me
|
|
|
|
|
You are welcome.
-Saurabh
|
|
|
|
|
I had the saem problem as you. I could not get my programs tio run on a machine with just the OS. Now I
1) Change the Project defaults in the General Section to "Use MFC in a static library"
2) Uncheck "Inherit from Parent or project defaults" in the linker Additional Library Directories section (gets rid of a warning).
All my programs work on a machone with a "virgin" OS after these changes.
|
|
|
|
|
Statically linking is okay for projects which do not depend on other 3rd party components using MFC. If you link MFC statically in your project and use a component with dynamically linked MFC then there will be problems.
-Saurabh
|
|
|
|
|
Hello,
I have serialized objects which I write in dat/txt files. While writing it doesn't throw any errors but I feel it writes only 1 record instead of 2 & while reading after reading 2, it doesn't stop. I might be missing something in reading case, as I don't know how to know the number of records in the file or how to trap when it should stop.
The code for storing the objects in a Map & calling a function to write objects to/from map file.
void COperatorDlg::OnBnClickedWriteBtn()
{
CMap<int, int, OperatorDetails, OperatorDetails> newOperMap;
DbOperations db;
newOperMap.SetAt(1, OperatorDetails(1, _T("One")));
newOperMap.SetAt(2, OperatorDetails(2, _T("Two")));
db.WriteOperators(newOperMap);
}
void COperatorDlg::OnBnClickedReadBtn()
{
CMap<int, int, OperatorDetails, OperatorDetails>* existOperMap;
DbOperations db;
existOperMap = db.ReadOperators();
CString s = _T("Read Operators : ");
s.Format(_T("%s %d"), s, existOperMap->GetCount());
AfxMessageBox(s);
}
DbOperations::DbOperations()
{
operMap = new CMap<int, int, OperatorDetails, OperatorDetails>(10);
deptMap = new CMap<int, int, DeptDetails, DeptDetails>(10);
}
void DbOperations::WriteOperators(CMap<int, int, OperatorDetails, OperatorDetails> &opdtMap) {
HANDLE hFile = CreateFile(OPER_FILE,
GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
AfxMessageBox(_T("Error OPeniong File"));
else {
CFile myfile(hFile);
int key;
OperatorDetails od;
CArchive ar(&myfile, CArchive::store);
for (POSITION pos = opdtMap.GetStartPosition(); pos != NULL;) {
opdtMap.GetNextAssoc(pos, key, od );
ar.WriteObject(&od);
od.~OperatorDetails();
}
od.~OperatorDetails();
ar.Close();
myfile.Close();
}
return;
}
CMap<int, int, OperatorDetails, OperatorDetails>* DbOperations::ReadOperators()
{
int count =0;
if(operMap->IsEmpty() == false)
operMap->RemoveAll();
HANDLE hFile = CreateFile(OPER_FILE,
GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
AfxMessageBox(_T("Error OPening File"));
else {
CFile myfile(hFile);
OperatorDetails* od;
OperatorDetails odObj;
myfile.SeekToBegin();
CArchive ar(&myfile, CArchive::load);
while (true) {
od = (OperatorDetails*) ar.ReadObject( RUNTIME_CLASS(OperatorDetails) );
if (od == NULL)
break;
odObj.SetOperatorNo(od->GetOperatorNo());
odObj.SetOperName(od->GetOperName());
count++;
operMap->SetAt(odObj.GetOperatorNo(), odObj);
}
CString s;
s.Format(_T("%d %s %d"), operMap->GetCount(), _T(" Count = "), count);
AfxMessageBox(s);
odObj.~OperatorDetails();
od->~OperatorDetails();
delete od;
myfile.Close();
myfile.~CFile();
}
return operMap;
}
Initially I had tried with dat only, since it wan't working so looked for text. But both provides same results. The text & dat file written is :
ÿÿ
OperatorDetails Two
The Error basically says an attempt to read after the end of the file & then unhandled exception. Assert was throwing ASsertion Failure, so I replaced it with Set/Get methods.
I need help in solving the error. I believe in Read() my while loop is wrong. Can't figure out about Write(). The for loop runs for 2 times, takes both object details but the resulted output in file shows only first object that is the last one written in map & first read from map. Any help is highly appreciated. Would be great, if can provide help asap, as i am in a hurry now. Any improvement in the above code is also highly appreciated.
Thanks
Thanks
Terry
|
|
|
|
|
Trupti Mehta wrote: The Error basically says an attempt to read after the end of the file & then unhandled exception.
This isn't the correct way to loop through the archive:
while (true) {
od = (OperatorDetails*) ar.ReadObject( RUNTIME_CLASS(OperatorDetails) );
if (od == NULL)
break;
ReadObject() throws exceptions instead of returning a NULL pointer.
You can either write a count value to the archive and retrieve it
when deserializing, or catch exceptions to break the loop.
I personally prefer the first method FWIW.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: ReadObject() throws exceptions instead of returning a NULL pointer
In MSDN also I didn't found which exceptions ReadObject throws.
http://msdn.microsoft.com/en-us/library/bkcy8aad(VS.80).aspx[^]
Mark Salsbery wrote: either write a count value to the archive and retrieve it
when deserializing,
Can you guide me how to achieve the above, it would be really nice of you, Mark. Please. While writing to file, I should count the number of objects and store somewhere and before reading from file, first read that number & set the while loop accordingly. Or something else. Please guide me the best and appropriate way to achieve the goal.
Thanks
Terry
|
|
|
|
|
Trupti Mehta wrote: I didn't found which exceptions ReadObject throws.
Using the debug MFC library you may get an assertion.
Exceptions you may want to catch - CMemoryException, CArchiveException, CException.
Trupti Mehta wrote: Can you guide me how to achieve the above
CArchive ar(&myfile, CArchive::store);
ar << (int)opdtMap.GetCount();
for (POSITION pos = opdtMap.GetStartPosition(); pos != NULL; )
{
opdtMap.GetNextAssoc(pos, key, od );
ar << &od;
}
CArchive ar(&myfile, CArchive::load);
int count;
ar >> count;
for (int i = 0; i < count; i++)
{
ar >> od;
...
Or you can just serialize the CMap, since CMaps are serializable
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Oh Thaks Mark, this helped me get rid of the Assertion Errors/Exceptions. But still my condition hasn't improved, its in almost same place.
I store 2 objs in a map & send it to write.
newOperMap.SetAt(1, OperatorDetails(1, _T("One")));
newOperMap.SetAt(2, OperatorDetails(2, _T("Two")));
db.WriteOperators(newOperMap);
Write method
for (POSITION pos = opdtMap.GetStartPosition(); pos != NULL;) {
int key;
OperatorDetails od;
opdtMap.GetNextAssoc(pos, key, od );
ar << &od;
}
Executes for loop 2 times, od has respectives values i.e. "Two" followed by "One".
In my text file, I can see only "Two":
ÿÿ
OperatorDetails Two
While Reading:
OperatorDetails* od;
for (int i=0; i < count; i++) {
OperatorDetails odObj;
ar >> od;
if (od == NULL)
break;
odObj.SetOperatorNo(od->GetOperatorNo());
odObj.SetOperName(od->GetOperName());
operMap->SetAt(odObj.GetOperatorNo(), odObj);
}
delete od;
For loop executes twice as count is stored as 2 records while writing. Both the times it gets only "Two". So number of records actually retrieved are only 1 as the key is the same 2. While writing though &od has the proper object 2nd time i.e. 1 One, still it doesn't write only. ar << &od is also executing properly, still somehow something is acting weird.
Can you help me figure out that improper stuff. Would be glad enough & able to take a relaxed breath.
Thanks
Terry
|
|
|
|
|
First, I would change the CMap ARG_KEY and ARG_VALUE types to references:
CMap<int, int&, OperatorDetails, OperatorDetails&>
Second, can you post the OperatorDetails::Serialize() code?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
My Serialize code is :
void OperatorDetails::Serialize(CArchive &ar)
{
if (ar.IsStoring())
ar << operNo << operName;
else
ar >> operNo >> operName;
}
And the linker error says (the part that is cut for view.obj & Operator.obj) already defined in DbOperations.obj
Thanks
Terry
|
|
|
|
|
Trupti Mehta wrote: for (POSITION pos = opdtMap.GetStartPosition(); pos != NULL [Wink] {
int key;
OperatorDetails od;
opdtMap.GetNextAssoc(pos, key, od );
// ar.WriteObject(&od);
ar << &od;
}
I tested this and traced into the MFC code to see why only one
object was getting written to the archive.
There's an "optimization" in there - if the CObject* serialized with
WriteObject() (or ar << &od;, which calls WriteObject()) matches a
CObject* that's already been written to the archive, then just a reference to
the original serialized object is written to the archive.
Since the above code is passing the same pointer (a pointer to the same
object) each time, the first object found gets serialized, then only references
to that first object are written.
FWIW, here's an example of the correct way to serialize/unserialize a CMap:
typedef CMap<int, int, OperatorDetails, OperatorDetails&> OperatorDetailsMap;
template <> void AFXAPI SerializeElements <OperatorDetails> (CArchive &ar, OperatorDetails *pOperatorDetails, INT_PTR nCount)
{
for (int i = 0; i < nCount; i++, pOperatorDetails++)
{
pOperatorDetails->Serialize(ar);
}
}
void WriteArchive()
{
OperatorDetailsMap newOperMap;
newOperMap.SetAt(1, OperatorDetails(1, _T("One")));
newOperMap.SetAt(2, OperatorDetails(2, _T("Two")));
CFile myfile(_T("e:\\archive_test.txt"), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite);
CArchive ar(&myfile, CArchive::store);
newOperMap.Serialize(ar);
ar.Close();
myfile.Close();
}
void ReadArchive()
{
OperatorDetailsMap newOperMap;
CFile myfile(_T("e:\\archive_test.txt"), CFile::modeRead | CFile::shareDenyNone);
CArchive ar(&myfile, CArchive::load);
newOperMap.Serialize(ar);
ar.Close();
myfile.Close();
}
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
tHANKS mARK. I appreciate your efforts and help towards my problem.
The above code works perfectly with Visual Studio. But when I added in eVC++, I am getting Linker errors. Code is added & implemented in the same way in VS & eVC++.
I added the above code in my DbOperations class - SerializeElements is not a member of DbOperations, just added in the class cpp file. And from another dialog class Operator, I am calling db.WriteArchive() & ReadArchive(). From my view class, via a menu Operator.doModal is called, so view class is also in the picture. I get the following errors:
Linking...
MC_AppView.obj : error LNK2005: "void __cdecl SerializeElements(class CArchive &,class OperatorDetails *,int)" (?SerializeElements@@YAXAAVCArchive@@PAVOperatorDetails@@H@Z) already defined in DbOperations.obj
Operator.obj : error LNK2005: "void __cdecl SerializeElements(class CArchive &,class OperatorDetails *,int)" (?SerializeElements@@YAXAAVCArchive@@PAVOperatorDetails@@H@Z) already defined in DbOperations.obj
ARMV4IDbg/MC_App.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.
I tried making SerializeElemnets as a member of DbOperations, but that also gives lots of errors due to <>, etc. How do I avoid these errors?
Thanks
Terry
|
|
|
|
|
Mark,
I removed the template <> SerializeElements() from the code & ran the application. Its still running and giving the results as we expected, but after reading is completed, it throws Assertion Failure: on strcode.cpp Line 171 which falls under void CString::Release(), ASSERT(GetData()->nRefs != 0);
line.
If I do retry, it works properly. I need to get rid of this error. Do you know how to I catch exception in eVC++. If I write
try{
....
} catch(CException e) {
}
it shows warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX. The MSDN warning lists of 4530 mentions to specify /EHsc. How do I speicify any of this & where in the Project Settings. This will be a great help, as I like very much to catch exception and handle them. But in eVC I am not able to do it due to these errors/warnings.
Please would be nice if can help out in this.
Thanks
Terry
|
|
|
|
|
Trupti Mehta wrote: I removed the template <> SerializeElements() from the code & ran the application. Its still running and giving the results as we expected,
That won't work well with CStrings in the OperatorDetails class, since without a SerializeElements() override for the
CMap, the default serialization of the map's objects is binary bits - not good when pointers are involved
I'm not sure why the template function causes the link to fail.
You should be able to put the SerializeElements() template in ONE cpp file and it should work. I tested with it
in the same CPP file that does the serialization/unserialization of the CMap (just above my sample WriteArchive()
and ReadArchive functions).
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark, I also have added in the same file (DbOperations.cpp) just copied your code same way. All serialization.desera & template overrride are in the same file. I tried removing template<> & AFXAPI, but still no success.
You were very correct that with pointers of Map I will have a problem. To pass the DbOperations reference to other classes, I made a copy constructor & operator=, in this case I can't directly copy map tp map. So I made operatorMap as pointer & the other map deptMap is as a normal object only & not assigning in copy constru or =. deptMap additions & updations are possible (NOT a pointer), but operatorMap (a POINTER) operations are not allowed. It causes Assertion failure in afxtempl.h line 1368 which is Assert 1st line of CMap<> operator[].
I got to take out some solution of this. Can you tell how to assign a map to map in copy constructr & = operator. Basically copy a map to other. In DbOperations .h
typedef CMap<int, int, OperatorDetails, OperatorDetails&> OperatorDetailsMap;
typedef CMap<int, int, DeptDetails, DeptDetails&> DeptDetailsMap;
class ....{
OperatorDetailsMap* operMap;
DeptDetailsMap deptMap;
In .cpp
DbOperations::DbOperations(const DbOperations &d) {
this->operMap = d.operMap;
}
DbOperations& DbOperations::operator=(const DbOperations &d) {
this->operMap = d.operMap;
return *this;
}
My point is how do I copy this.deptMap with d.deptMap, where deptMap being normal objects & not a pointer. With this solution we wont have problem with serializeElements() & pointers. As SerializeElements() causes problems, so looking out for solution without serializeElements & pointers. SerializeElemtsis added only in DbOperations along with WriteArchive & ReadArchive. The same thing is working with Visual Studio, but not with eVC++4. Really it is difficult to code in eVC++ than VC++, many restrictions & uncompatibility.
Looking for solution as soon as possible. From days I have been looking for this solution & yet not solved. You have been extremely helpful throughout. I highly appreciate your help and look towards more help.
Thanks
Terry
|
|
|
|
|