-
November 21st, 2019, 04:54 PM
#1
Issue when run in release build
Hi,
I have a dll, with three functions which are now being run with the client. For the first function, which i have done with the help from here, it works fine in Debug mode with the tester. Now with the real client code, when run in release mode.
Code:
void GetAvailablePropagationModels(BSTR* modelList)
{
LPCTSTR pcszError = 0;
try
{
wstring in(*modelList);
if (in == L"")
return;
pathofXmls = in;
// Load the MODEL-LIST001.xml
std:wstring fullpath = pathofXmls + L"\\MODEL-LIST001.xml";
HRESULT hr = CoInitialize(NULL);
MSXML2::IXMLDOMDocumentPtr pXMLDom;
MSXML2::IXMLDOMDocumentPtr pXSLDoc;
MSXML2::IXMLDOMDocumentPtr pXMLOut;
// Load the XML file.
pXMLDom.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER);
pXMLDom->async = VARIANT_FALSE; // The default is true.
pXMLDom->validateOnParse = VARIANT_FALSE;
pXMLDom->resolveExternals = VARIANT_FALSE;
pXMLDom->load(fullpath.c_str());
_bstr_t Str = pXMLDom->Getxml();
// Load the XSLT style sheet.
FAILED(pXSLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));
pXSLDoc->async = VARIANT_FALSE; // The default is true.
pXSLDoc->validateOnParse = VARIANT_FALSE;
pXSLDoc->resolveExternals = VARIANT_FALSE;
pXSLDoc->load(L"XSLTFile1.xslt");
//Transform the XSLT to an XML string.
_bstr_t xmlStr = pXMLDom->transformNode(pXSLDoc);
// Parse the resulting xml String to the format of AssetDesign interface
const string mfirst = "MODEL ID=\"";
const string mlast = "\" TYPE=\"";
const string melem = "\" />";
const char* buf = xmlStr;
int bstrlen = xmlStr.length();
std::string inputstr(buf ? buf : "", bstrlen);
// Format the Models separated by newlines as per the AssetDesign Interface
stringstream check1(inputstr);
string output;
for (string token; getline(check1, token); ) {
const auto firstLim = token.find(mfirst);
const auto lastLim = token.find(mlast);
const auto mend = token.find(melem);
if ((firstLim != string::npos) && (lastLim != string::npos) && mend != string::npos) {
output += (output.empty() ? "" : "\n") + token.substr(firstLim + mfirst.size(), lastLim - firstLim - mfirst.size());
output += "-" + token.substr(lastLim + mlast.size(), mend - lastLim - mlast.size());
}
}
output += "\n";
// Free the XML path related info sent by the AssetDesign and replace with the Model list as in
// MODEL-LIST.xml
SysFreeString(*modelList);
CA2W ca2w(output.c_str());
wstring w = ca2w;
*modelList = SysAllocString(w.c_str());
CoUninitialize();
}
catch (bad_cast bc)
{
pcszError = _T("Bad cast");
}
catch (bad_typeid bt)
{
pcszError = _T("Bad typeid");
}
catch (...)
{
pcszError = _T("General cast");
}
}
I have tried to code this and my collegues (who are in the same company for 20 years) doesnot like me doing this work as a new comer. I feel really bad, that instead of helping me they are pulling my leg and the group makes fun of me saying that I wont complete this work. I landed up in my dream job. And i feel without kauds help in this project, i couldnot have delivered this much. Thanks a lot again for all the help
-
November 21st, 2019, 04:56 PM
#2
Re: Issue when run in release build
sorry forgot to mention that the client didnot have XSLTFile1.xslt. So they used the empty file with the same.
Could you kindly give me ,comments , inputs on the above function. FYI, i just added try catch block, just before sending to client, may need some more work on it.
-
November 21st, 2019, 10:14 PM
#3
Re: Issue when run in release build
One obvious issue is how you are handling file paths.
For example these:
Code:
std:wstring fullpath = pathofXmls + L"\\MODEL-LIST001.xml";
pXMLDom->load(fullpath.c_str());
pXSLDoc->load(L"XSLTFile1.xslt");
The problem is that each of these rely on these files being in the current directory of the calling program's exe. On program startup, the curry directory is typically the same folder as the program exe. However, this can change:
1) if the program is started by a shortcut and the startup folder is different than the location of the exe.
2) The program itself can change the current directory at any time by calling SetCurrentDirectory().
At any rate, it is best not to rely on current directory. In an ideal world, if these files are in the same folder as the exe, you would retrieve the current folder at program startup, and pass the path into GetAvailablePropagationModels. Inside the method you would use the path to derive the full paths to each of the files.
In addition, you would check if the files exist and return appropriate errors.
I see that the issue may be the empty xslt file. You should figure out a way to check for that. You can probably check for a parameter in pXSLDoc after you have loaded the template file. Then return a specific error to tell you an invalid template.
Btw, it's too bad about your old unhelpful blowhard coworkers. I too fall under at least part of that (i.e. old and blowhard). I wouldn't know but I guess coworkers that have been in the same company for 20 years may have settled on their level of expertise. Not surprising from the companies point of view. After all, why change something that works? But if the technology doesn't change, then the folks there are stuck in the same technology. Your coworkers' behavior may be because they're a bit worried about that.
Last edited by Arjay; November 21st, 2019 at 10:19 PM.
-
November 22nd, 2019, 05:42 AM
#4
Re: Issue when run in release build
You don't say what is the issue when run by the client in release mode?
Couple of questions. What version of C++/VS are you using? Have you tried release mode in your testing or just debug mode?
When using an API (or class method) that can return an error, then in every case you need to check (unless it raises an exception and you are using it within a try..catch block). You have for .CreateInstance() for XSLT but not for .XML. Also calling .load(), .transformNode() et al should also have return values checked (unless the documentation says they raise an exception).
The bottom line on this is that if the code works in testing, then in release it should either work or you should get an error message (or log entry etc) explaining where/what is the problem.
PS You really need to become experienced with debugging programs that should but don't work. This is an absolutely essential skill and you'll get nowhere in programming without it. With your code in post #1 you should be able to state 'the problem is on line xxx. I expected abc but got def which I don't understand'.
Last edited by 2kaud; November 22nd, 2019 at 05:52 AM.
Reason: PS
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
November 22nd, 2019, 08:32 AM
#5
Re: Issue when run in release build
A couple of comments re the code.
modelList is only used as a parameter to initialise in. Hence it should be const (and preferably const BSTR * const - const pointer to const data).
To determine if a string/wstring is empty, use .empty() and not comparing it to an empty string.
After in is initialised and tested, you then set pathofXmls. Why not set pathofXmls to *modelList and avoid multiple copies and the test pathofXmls?
You are setting pcszError in the catch() clauses - but are then doing nothing with it. How do you know that the catch() has been triggered?
fullpath should be const.
Where is Str used?
xmlStr should be const
you don't need bstrlen
inputstr should be const - and probably isn't needed
PS const variables that represent constants that are not at global scope or at main() function scope should be static so that they are only initialised once (global const can be static but it has a different meaning).
Last edited by 2kaud; November 23rd, 2019 at 08:34 AM.
Reason: PS
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|