We have some old C++ code which is being called from Classic ASP. It runs on Windows 2000 and is invoked using CreateObject via COM from the ASP. The code uses an ADO recordset (server side) which is passed to it from ASP and loops through the records, producing an XML file.
We have moved the C++ DLL onto a Windows 2008 server and it is a lot slower. Using Wireshark we can see this is because every time it moves to a a new record it restablishes the connection.
The old server used ADO 2.7 the new server uses ADO 6, but these are functionally equivalent and its just a new label for the version as I understand it.
Here is the main body of the code. It doesn't compile because I have removed bits to try and simplify the structure.
{
STDMETHODIMP Crender::generatexmldoc(LPDISPATCH adorecordset)
_Recordset rs;
rs.AttachDispatch(adorecordset);
CStringArray* fieldnames = new CStringArray();
int recno = 0;
LPDISPATCH fs = rs.GetFields();
while ( rs.GetState() == 1 && ! rs.GetEof() && recno++ != maxrecords) {
_generatexmlelement(fs , arecordname, TRUE, fieldnames);
rs.MoveNext();
}
fs->Release();
rs.DetachDispatch();
fieldnames->RemoveAll();
delete fieldnames;
}
void Crender::_generatexmlelement(LPDISPATCH adofields, LPCSTR elementname, BOOL closeelement, CStringArray* fieldnames)
{
USES_CONVERSION;
if (fieldnames->GetSize() == 0) {
for (index.uiVal = 0; index.uiVal < total; index.uiVal++) {
LPDISPATCH dItem = fs.GetItem(index);
fd.AttachDispatch(dItem);
CString name = fd.GetName();
fieldnames->Add(name);
fd.DetachDispatch();
dItem->Release();
}
}
writeoutfile(CString("<") + elementname);
for (index.uiVal = 0; index.uiVal < total; index.uiVal++) {
LPDISPATCH dItem = fs.GetItem(index);
fd.AttachDispatch(dItem);
value.Attach(fd.GetValue());
// code removed - data comes from value
writeoutfile(data, data.GetLength());
}
value.Clear();
value.Detach();
fd.DetachDispatch();
dItem->Release();
}
}
What in here could be causing the round trips to re-establish the connection?
Related
This is not C++/CLI. This is UWP C++/CX
I am trying to send an HttpRequestMessage outside of a managed class in C++. I looked at the UWP samples, but their requests occur inside of a managed class.
All I want to do is send the request, and then have a callback function. I don't need fancy async/await patterns. This is looking to be a lot more difficult than it should be.
EDIT: I have gotten it to work, but the error handling is atrocious. The extra error handling code from the UWP HttpClient example was not compiling.
client = ref new Windows::Web::Http::HttpClient();
client->DefaultRequestHeaders->UserAgent->Append(ref new Windows::Web::Http::Headers::HttpProductInfoHeaderValue("Windows", "10"));
cancellation_token_source cancellationTokenSource = cancellation_token_source();
create_task(client->SendRequestAsync(message)).then([=](Windows::Web::Http::HttpResponseMessage^ response)
{
auto operation = response->Content->ReadAsBufferAsync();
auto task = create_task(operation);
if (task.wait() == task_status::completed)
{
webResponse->statusCode = (int)response->StatusCode;
auto buffer = task.get();
size_t length = buffer->Length;
if (length > 0)
{
Array<byte>^ array = nullptr;
CryptographicBuffer::CopyToByteArray(buffer, &array);
webResponse->contentLength = array->Length;
webResponse->data = (byte*)malloc(webResponse->contentLength);
memcpy(webResponse->data, array->Data, webResponse->contentLength);
delete array;
}
for each(IKeyValuePair<String^, String^>^ pair in response->Headers)
{
std::string key = PlatformStringToString(pair->Key);
std::string value = PlatformStringToString(pair->Value);
if (key == "Content-Type" && false)
{
// Should have this for completeness, but do we really care?
}
else
{
Web::WebHeader *header = new Web::WebHeader(key.c_str(), value.c_str());
webResponse->AddHeader(header);
}
}
if (request->receiveDoneCallback)
request->receiveDoneCallback(webResponse, request->userPtr);
}
else
abort();
delete request;
delete response;
});
I've a big plain c++ project where I implemented a webbrowser control (the idea come from https://github.com/Tobbe).
Well I inject some external method with the AddCustomObject. The problem is when I need to dispose a big page (1.9KB) with many object (tinymce, jquery ecc) for local editing ... the memory increasing every time I open the page.
I've searched, googled, readed, contacted the original developer... nope.
In the close method the code is this:
if (ibrowser != 0) {
IConnectionPointContainer *cpc = 0;
ibrowser->QueryInterface(IID_IConnectionPointContainer, (void**)&cpc);
if (cpc != 0) {
IConnectionPoint *cp = 0;
cpc->FindConnectionPoint(DIID_DWebBrowserEvents2, &cp);
if (cp != 0) {
cp->Unadvise(cookie);
cp->Release();
}
cpc->Release();
}
IOleObject *iole = 0;
ibrowser->QueryInterface(IID_IOleObject, (void**)&iole);
/*ibrowser->Stop();
ibrowser->ExecWB(OLECMDID_CLOSE, OLECMDEXECOPT_DONTPROMPTUSER, 0, 0);
ibrowser->put_Visible(VARIANT_FALSE);*/
UINT refCount = ibrowser->Release();
ibrowser = 0;
if (iole != 0) {
iole->Close(OLECLOSE_NOSAVE);
iole->Release();
}
}
Debugging in Vs2008 I've saw many CustomObject::AddRef and Release maybe due to setTimeout
I've no idea how to resolve this... need help!
Thank's!
Andrea
I need to register a .NET COM dll from a C++ program that is using it. For .NET versions older then .NET 4 this is explained in How to run regasm.exe from a C++ program?. Following is the minimal code (no checks) that provides the path to an older version of the CLR.
CComBSTR mscoreeName("mscoree.dll");
HINSTANCE hMscoree = CoLoadLibrary(mscoreeName, FALSE);
typedef HRESULT (WINAPI *LPFNGETCORSYSDIR)(LPWSTR, DWORD, DWORD*);
LPFNGETCORSYSDIR lpfunc = (LPFNGETCORSYSDIR)GetProcAddress(hMscoree,_T("GetCORSystemDirectory"));
DWORD bufferSize = 256;
DWORD bufferUsed;
LPWSTR pwzBuffer = new WCHAR[bufferSize];
(*lpfunc)(pwzBuffer, bufferSize, &bufferUsed);
However since I use .NET 4 the method GetCORSystemDirectory is superseded by the ICLRRuntimeInfo::GetRuntimeDirectory which is not an entry point in mscoree.dll (checked with depends). According the documentation on MSDN the method is included as a resource in MSCorEE.dll.
Question is how to get access to this method from C++?
Besides that I'm wondering if there is no easier way...
The problem with the way of working in the question is in finding the correct location of RegAsm. Thanks to the comment of Hans Passant to use RegistrationService.RegisterAssembly I changed the ClassLibrary into a self-registering executable.
static void Main(string[] args)
{
if (args.Length != 1)
{
ShowHelpMessage();
return;
}
if (args[0].CompareTo("/register") == 0)
{
Assembly currAssembly = Assembly.GetExecutingAssembly();
var rs = new RegistrationServices();
if (rs.RegisterAssembly(currAssembly, AssemblyRegistrationFlags.SetCodeBase))
{
Console.WriteLine("Succesfully registered " + currAssembly.GetName());
} else
{
Console.WriteLine("Failed to register " + currAssembly.GetName());
}
return;
}
if (args[0].CompareTo("/remove") == 0)
{
Assembly currAssembly = Assembly.GetExecutingAssembly();
var rs = new RegistrationServices();
if (rs.UnregisterAssembly(currAssembly))
{
Console.WriteLine("Succesfully removed " + currAssembly.GetName());
}
else
{
Console.WriteLine("Failed to remove " + currAssembly.GetName());
}
return;
}
ShowHelpMessage();
}
in my MFC SDI application, i'm trying to override CDocument::DoSave to save my document. I'm using a third part component (TxTextControl) to build a text control. When i save the document, the file is created, but after about one minute my app crashes rising read access error 0xFEEEFEEE, in ole32.dll.
This is my code, txtCtrl is my component:
BOOL CEditorTxDoc::DoSave(LPCTSTR lpszPathName, BOOL bReplace)
{
CString path, nome;
VARIANT vt1, vt2, vt3;
POSITION pos = GetFirstViewPosition();
CEditorTxView *pView = (CEditorTxView*)this->GetNextView(pos);
VariantInit(&vt1);
vt1.vt = VT_INT;
vt1.intVal = -1;
VariantInit(&vt2);
vt2.vt = VT_INT;
vt2.intVal = 3;
VariantInit(&vt3);
vt3.vt = VT_BOOL;
vt3.boolVal = FALSE;
if (lpszPathName == NULL) {
CFileDialog fSaveDlg(FALSE);
fSaveDlg.m_pOFN->lpstrFilter = _T("File Tx (*.tx)");
fSaveDlg.m_pOFN->lpstrDefExt = _T("tx");
fSaveDlg.m_pOFN->lpstrTitle = _T("Salva documento");
fSaveDlg.m_pOFN->lpstrInitialDir = _T("c:");
if(fSaveDlg.DoModal()==IDOK)
{
path = fSaveDlg.GetPathName();
nome = fSaveDlg.GetFileName();
pView->txtCtrl.Save(path, vt1, vt2, vt3);
SetTitle(nome);
SetModifiedFlag(FALSE);
SetPathName(path);
}
} else {
pView->txtCtrl.Save(GetPathName(), vt1, vt2, vt3);
SetModifiedFlag(FALSE);
}
return TRUE;
}
Magic debug values:
FEEEFEEE Used by Microsoft's HeapFree() to mark freed heap memory
That is, the problem comes up from the fact that the code deals with released memory as if it is still alive. To isolate the issue to specific code fragment, debug and use call stack information at the time of exception.
I'm developing Qt/C++ application and I need simple function that retrive me User idle time in seconds on Mac OS X.
I found this code for detection User idle time.
#include <IOKit/IOKitLib.h>
/**
Returns the number of seconds the machine has been idle or -1 if an error occurs.
The code is compatible with Tiger/10.4 and later (but not iOS).
*/
int64_t SystemIdleTime(void) {
int64_t idlesecs = -1;
io_iterator_t iter = 0;
if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOHIDSystem"), &iter) == KERN_SUCCESS) {
io_registry_entry_t entry = IOIteratorNext(iter);
if (entry) {
CFMutableDictionaryRef dict = NULL;
if (IORegistryEntryCreateCFProperties(entry, &dict, kCFAllocatorDefault, 0) == KERN_SUCCESS) {
CFNumberRef obj = CFDictionaryGetValue(dict, CFSTR("HIDIdleTime"));
if (obj) {
int64_t nanoseconds = 0;
if (CFNumberGetValue(obj, kCFNumberSInt64Type, &nanoseconds)) {
idlesecs = (nanoseconds >> 30); // Divide by 10^9 to convert from nanoseconds to seconds.
}
}
CFRelease(dict);
}
IOObjectRelease(entry);
}
IOObjectRelease(iter);
}
return idlesecs;
}
How to convert this code to C++, to be used with my Qt/C++ project?
You just need to add IOKit.framework in the list of linked frameworks. Think of a framework as a bundle of shared libraries and associated resources. IOKit.framework is at
/System/Library/Frameworks/IOKit.framework
I don't know how to do that in a Qt project; the project should have a list of extra frameworks which you want to link against.
If it's a standard XCode project, there's a menu entry called add a framework to the project or something like that.