IXMLDOM does not recognize XPath last() function? - delphi

Good day! I'm working with Delphi 2009 and MSXML2_TLB library (IXMLDOM). I need to select the last Meeting node:
Doc := CreateOleObject('Microsoft.XMLDOM') as IXMLDomDocument;
Doc.loadXML(XmlStr);
tmpNode:= Doc.selectSingleNode('//Meeting[last()]');
But on the last line of the code above I get exception:
Project test.exe raised exception class EOleException with message: 'Unknown method
//Meeting[-->last()<--]'
Is there a way how to select the last node using xpath or do I really have to write code to get node list and then select the last element?
Yet a version info:
Type Lib: C:\WINDOWS\system32\msxml6.dll (1)
LIBID: {F5078F18-C551-11D3-89B9-0000F81FE221}
HelpString: Microsoft XML, v6.0
Thank you in advance! Vojtech

This is because you are using a version of msxml where the last function is not defined, as far I know this function was introduced in the v 4.0 of MSXML
try
Doc := CreateOleObject('Msxml2.DOMDocument.6.0') as IXMLDomDocument;

Related

Delphi 2007 - Compile errors on updating Indy from 10.5.1.1 to 10.6.2.0

I recently updated the stock Indy that installs with Delphi 2007 (I think it is 10.5.1.1) with 10.6.2.0, which I downloaded from GitHub.
I'm now getting a compile error:
EAttachmentFileNotFound.IfFalse (FileExists (parActualAttachmentFileID), 'File ' + parActualAttachmentFileID + ' not found.') ;
Error: E2003 Undeclared identifier: 'IfFalse'
The fragment is from my own code but I'm pretty sure that bit came from something I found probably on S/Overflow.
I received a couple of other errors also:
SMTPClient.AuthType := atDefault ;
Error: E2003 Undeclared identifier: 'atDefault'
and
SMTPClient.OnWork := EmailThread.EmailOnWork ;
Error: E2010 Incompatible types: 'Int64' and 'Integer'
but the first is a member that was renamed, and the second a data type that was changed. While these were a simple enough workaround, I'm left wondering
whether there was ever a "breaking changes" document generated.
maybe I accidentally somehow got the wrong source set.
EAttachmentFileNotFound is not a standard Indy exception, so it must be coming from your own code, or another 3rd party library.
Delphi 2007 was released almost 16 years ago. A lot has changed in Indy during that time. In fact, I think the changes you mention were actually made prior to, or maybe around, the release of Delphi 2007 (as they already existed in Indy's code in early 2008).
For instance:
in EIdException, the If(True|False) methods were removed (I don't know when exactly that change happened). In which case, you will have to use your own if and raise expressions now, eg:
if not FileExists(parActualAttachmentFileID) then
raise EAttachmentFileNotFound.Create('File ' + parActualAttachmentFileID + ' not found.');
in TIdComponent, the AWorkCount/Max parameters of the OnWork... events were changed from Integer to Int64 in 2006 (see OnWork Events changed to 64 bit on Indy's blog).
in TIdSMTP, the atDefault value was renamed to satDefault (again, I don't know exactly when this change was made).
So, you need to update your code accordingly.
I'm left wondering whether there was ever a "breaking changes" document generated.
No such document was ever created, no. However, changes that affect user code are typically announced on Indy's blog, under the Changelog category.

Getting Delphi to read a database with a new version of Microsoft Access

We use a Delphi 10 programme that reads in an Access database. I do not deeply understand how it does it, except that I believe it uses units called DAO.pas and DAO_TLB.pas.
I recently upgraded from Office 2007 to Office 2016, and since then the Delphi programme is unable to read from the database; it gives the error:
Project MyProj.exe raised exception class EOleSysError with message 'Class not registered'.
I have tried to search to find how to fix this but am struggling because I don't really understand what's going on under the hood. I tried to install the Access 2016 type library, but that didn't seem to make any difference.
Extremely grateful for any help.
Thanks,
Tom
EDIT: DAO.pas is here. DAO_TLB.pas is where the error is triggered; the function which errors is:
class function CoDBEngine.Create: _DBEngine;
begin
Result := CreateComObject(CLASS_DBEngine) as _DBEngine;
end;
Where CLASS_DBEngine is a constant declared as:
CLASS_DBEngine: TGUID = '{CD7791B9-43FD-42C5-AE42-8DD2811F0419}';
I have also just noticed that, when the error occurs, if I click continue rather than break, a new error appears, saying:
Class not registered, ClassID: {CD7791B9-43FD-42C5-AE42-8DD2811F0419}
i.e. the ClassID is the CLASS_DBEngine constant.

how to html getsource in delphi cef3 component?

I want to load webpage html source into a Delphi (delphi 7) memo. It seems there are two methods for getting the source:
chromium1.Browser.MainFrame.GetSource(const visitor: icefstringvisitor);
chromium1.Browser.MainFrame.GetSourceproc(const proc: icefstringvisitorproc);
Can you please show how to use them. What is difference?
Thanks.
Update:
LD RD suggests in comments:
The GetSourceProc usage is exemplified in the examples following the source of TChromium, see GUIClient Main.pas
It works now, using GetSourceproc(const proc: icefstringvisitorproc);
Thank LD RD.
But i still do not know how to use MainFrame.GetSource(const visitor: icefstringvisitor);

Now that TEurekaExceptionRecord is deprecated in EurekaLog 7, what replaces LogText?

While migrating from EurekaLog 6 to 7, I came to notice a compiler warning that TEurekaExceptionRecord is deprecated and I should use TEurekaExceptionInfo.
In my Delphi 7 app with EurekaLog 6, there is a statement like:
exceptionRecord : TEurekaExceptionRecord;
myString := exceptionRecord.logText;
Now when I am using TEurekaExceptionInfo instead of TEurekaExceptionRecord in my Delphi XE4 with EurekaLog 7 like following:
exceptionInfo : TEurekaExceptionInfo;
myString := exceptionInfo.logText;
I am getting error on the second line because logText does not exist now. Which method has replaced it in EurekaLog 7?
I am the EurekaLog support person. There are large differences between v6 and v7. Your question is difficult to answer since while the globals you are used to in v6 remain in v7, you may not be able to modify or check them in the same way in v7. Success is dependent on when you read or modify the variables. There are several event handlers and each one reads/writes various fields in our EL classes. They are called sequentially, so this is where the timing issue I mentioned comes in. Log text is now created in our dialog box classes, but there are ways to extract raw log text from them.
I recommend that you open a trouble ticket on our web site and post some code that demonstrates what you are trying to do. You can also check our code snippets library for log management ideas.
If you are looking for getting general exception information (class, message, address, etc.) - see How to get exception information?
If you are looking for getting exception's call stack - see How to get exception's call stack?
If you are looking for saving report file into database or network share (with screenshots, attached files, web page, dumps, etc.) - see How to save report instead of sending?
If you want to operate on bug report file - see How to get file name for the bug report?
Normally you do not need to access bug report:
EurekaLog 7.7.8.2
Application:
-------------------------------------------------------
1.1 Start Date : Wed, 17 Oct 2018 16:23:33 +0300
1.2 Name/Description: Project1.exe
1.3 Version Number :
1.4 Parameters :
1.5 Compilation Date: Wed, 17 Oct 2018 16:23:15 +0300
1.6 Up Time : 6 second(s) Exception:
------------------------------------------------------------------------
2.1 Date : Wed, 17 Oct 2018 16:23:39 +0300
2.2 Address : 012A03F0
2.3 Module Name : Project1.exe
2.4 Module Version:
2.5 Type : ERangeError
2.6 Message : Range check error at Unit1.Button1Click (Line 261)
2.7 ID : ABBB0630
2.8 Count : 1
...
It is sufficient to use one of the mentioned above usage cases.
However, one particular example of when you want to access a simple bug report is when you are migrating old code from EurekaLog 6. Bug report was removed from OnExceptionNotify event because bug report does not exist outside of exception processing in EurekaLog 7 (unlike EurekaLog 6). For example, if you decide not to handle exception in OnExceptionNotify event handler - then there will be no bug report generated at all, thus saving processing time.
If you still want EurekaLog 6 style behavior - then bug report content can be retrieved from Dialog.BugReport property at any time (which is basically a cache of LogBuilder.Report property). For example:
uses
EException, // for TEurekaExceptionInfo
ELogBuilder; // for TBaseLogBuilder and RegisterEventEndReportGen
procedure UploadToDB(const ACustom: Pointer;
AExceptionInfo: TEurekaExceptionInfo;
ALogBuilder: TBaseLogBuilder;
var CallNextHandler: Boolean);
var
BugID: Cardinal;
Report: String;
begin
BugID := AExceptionInfo.BugID;
Report := ALogBuilder.Report;
// ... write bug report's content to your DB or
// do whatever you want with it
end;
initialization
RegisterEventEndReportGen(nil, UploadToDB, True);
end.
E.g. you should replace your OnExceptionNotify event handler with OnEndReportGen event handler. This event handler will be called like this:
UploadToDB
TBaseDialog.SaveBugReport
TBaseDialog.Execute
ShowException
ProcessException
ExceptionManager.Handle
Forms.TApplication.HandleException
Alternatively, bug report can be created at any time (on demand) - by using BuildBugReport function:
uses
EException, // for TEurekaExceptionInfo
ELogBuilder; // for BuildBugReport
var
EI: TEurekaExceptionInfo;
Report: String;
begin
try
// ...
except
on E: Exception do
begin
EI := ExceptionManager.Info(E);
// EI = nil for disabled EurekaLog
// or when exception is ignored
if Assigned(EI) then
begin
Report := BuildBugReport(EI);
// ... write bug report's content to your DB
// or do whatever you want with it
end;
end;
end;

Delphi and XPath functions

Can I use Xpath node set function position() in Delphi's function selectNodes() to select only a certain number of element from a node list? If I do like this:
selectNodes('Item[1]')
its all fine and I get the element with index 1, but when I try
selectNodes('Item[position()<10]')
I get exception 'unknown method', when I try
selectNodes('Item[<10]')
I get 'unexpected token <'.
Im using delphi7 and I also imported new type library into my project with newer versions of msxml.
This is not really a Delphi question I think, but an MSXML one. Check the MSXML docs or rather the MS XPath docs.
Hmm, according to the XPath examples posted on MSDN "Item[position() < 10]" should have worked, at least if "Item" is the name of the element you're after...
selectNodes requires a string, so you should try:
selectNodes('Item[position()<10]')
Or whatever xpath query.
Could it be a version-issue? I have imported typelibrary from MS XML 6, and gets no error.

Resources