Archive for the ‘Delphi’ Category
Posted by jpluimers on 2014/08/27
Though I’ve done this automation in Delphi, this applies to automation from any development platform. In this particular project, the documents used Bookmarks. Those have changed over time, so has the Word support for it.
From Word 2000 until Word you could disable the showing of Bookmarks by setting the ShowBookmarks property to False like this:
<br />ActiveDocument.ActiveWindow.View.ShowBookmarks := False;<br />
Well, when doing this, Office 2013 can throw an error like this:
EOleException: The ShowBookmarks method or property is not available because this command is not available for reading
ErrorCode: 0x800A11FD
Source: Microsoft Word
HelpFile: wdmain11.chm
The full error message does not give any useful search results. But a partial search finds a Word 2013 issue towards the top of the results:
sometimes Words opens the document in Reading layout. Reading layout does not allow all operations in Word 2013.
If a document is protected, and you try to change something you should not, you get an error message like this:
This method or property is not available because the document is a protected document.
Usually, Cindy Meister is very accurate. However this time here code
...ActiveWindow.View = wdPrintView
should have been like
...ActiveWindow.View.Type = wdPrintView
Of course you also have to save/restore this property while you are enabling the ShowBookmarks property.
Read the rest of this entry »
Posted in Delphi, Delphi XE2, Delphi XE3, Delphi XE4, Development, Office, Office 2000, Office 2003, Office 2007, Office 2010, Office 2013, Office Automation, Power User, Software Development, Word | Leave a Comment »
Posted by jpluimers on 2014/08/26
Though I’ve done this automation in Delphi, this applies to automation from any development platform. In this particular project, I had to update Word documents. That is fine, unless your documents are protected. You can find out if a document is protected by probing the ProtectionType property of a Document object.
If a document is protected, and you try to change something you should not, you get an error message like this:
This method or property is not available because the document is a protected document.
If you have control of the documents or templates involved, then you can take the recommended steps from Document Handling with protected Microsoft Office Word Template:
Microsoft Office Word offers the possibility to enable document protection only to certain sections of a document. So you can place Bookmarks used by Dynamics AX in a section that is kept unprotected and the Form Controls in a section where Document Protection is enabled.
If you don’t, then you have to check for protection, unprotect, do the modifications, then re-protect the document. Read the rest of this entry »
Posted in Delphi, Delphi XE2, Delphi XE3, Delphi XE4, Development, Office, Office 2000, Office 2003, Office 2007, Office 2010, Office 2013, Office Automation, Power User, Software Development, Word | Leave a Comment »
Posted by jpluimers on 2014/08/22
While updating a project to a more recent version of Delphi, I also updated the JEDI.INC reference.
Note that since writing Delphi – finding the VERxxx define for a particular Delphi version: use JEDI.INC, the Delphi JEDI project moved from SoureForge to GitHub.
The fun thing: JEDI.INC got updated a few months ago to support Delphi XE7 provisionally.
Given the Delphi release cycle of twice a year, the Delphi Carpathia aka XE7 rumours this summer, I presume Delphi XE7 is near because of:
By then the list of Delphi Versionen | Delphi-Treff will likely also be updaed.
I’m anxious to see if the (Dutch + English) BIG Delphi Conference organized by Barnsten and Blaise from September 11-12 in the Netherlands will be part of the launch tour.
Anyway: here is the JEDI.INC portion with defines: Read the rest of this entry »
Posted in Delphi, Delphi 1, Delphi 2, Delphi 2005, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 3, Delphi 4, Delphi 5, Delphi 6, Delphi 7, Delphi 8, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Delphi XE7, Development, Software Development | 6 Comments »
Posted by jpluimers on 2014/08/20
Depending on how you organize locks (for instance via waiting on semaphores or mutexes or spinlocks), deadlocks can become livelocks:
Inability to make forward progress because of conflicting spinlocks is usually referred to as ‘livelock’.
Thanks to Martin James for reminding me of that and Danny Thorpe for describing different ways of locking.
Be sure to read on deadlock prevention as well.
–jeroen
via: c++ – Do deadlocks cause high CPU utilization? – Stack Overflow.
Posted in .NET, C++, Delphi, Development, Software Development | Leave a Comment »
Posted by jpluimers on 2014/08/19
Since this did not make it to DelphiFeeds yet: I’ve seen the function PaletteFromDIBColorTable in Graphics.pas go back as far at least until Delphi 2006, and references on the web as far back as Delphi 4.
So: this bug is old, but as it is a security one, make sure you patch soon.
For Delphi XE6, download 29913 BMP Buffer Overflow hotfix – Delphi, C++Builder, RAD Studio XE6.
For older Delphi versions, read this piece that was adapted from the EDN article Delphi and C++ Builder VCL Library Buffer Overflow:
For users of prior versions of Delphi and C++Builder: these steps should be followed to modify the VCL source code and add it to your application.
For each application:
- Add the modified Edit Vcl.Graphics.pas or Graphics.pas or Borland.Vcl.Graphics.pas to your project
- For C++Builder: Under Project | Options | Packages | Runtime Packages, set “Link with runtime packages” to false
- Rebuild your application
Once for the native VCL and .NET VCL:
- Note: Variable names and scoping might be slightly different depending on your product version.
- Edit Vcl.Graphics.pas or Graphics.pas or Borland.Vcl.Graphics.pas
- Locate the function PaletteFromDIBColorTable.
- Add the following code just before the line assigning a value to Pal.palNumEntries when the DIBHandle = 0
if ColorCount > 256 then
InvalidGraphic{$IFNDEF CLR}@{$ENDIF}SInvalidBitmap;;
–jeroen
via Delphi and C++ Builder VCL Library Buffer Overflow.
Posted in Delphi, Delphi 2005, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 4, Delphi 5, Delphi 6, Delphi 7, Delphi 8, Delphi x64, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Development, Software Development | Tagged: Buffer Overflow, Delphi, Delphi versions, vcl | 5 Comments »
Posted by jpluimers on 2014/08/19
I mentioned Delphi managed types is in Delphi “Variant Records”, a few notes indicating they are special.
Managed by the RTL, you can use them to your advantage when you have record types that – when on the stack – are only partially initialized by the RTL: only the managed types are initialized.
Given there is still no support to support “Initialize” and “Finalize” operators (vote for it on [WayBack] QualityCentral) the best you can do was mentioned by LU RD (an alias a very smart Swedish guy Leif Unéus):
Add a dummy string member into your record. Since a string is a managed type it will be initialized to an empty string when the record comes in scope.
So when calling your Clear method, test if the dummy string is empty first. Set the string to a value when appropriate to the use logic to mark the record as initialized.
It reminded me of a managed types idea that former Delphi compiler engineer Barry Kelly once posed to me when I was struggling with the initialization state of nullable records: I wanted the default to be NULL, so I added an extra field managed field “IsInitialized” and the “IsNull” property would negate that field.
Use the Delphi compiler to your advantage (:
–jeroen
via: delphi – Guarantee initialisation of stack record – Stack Overflow.
Posted in Delphi, Delphi XE2, Delphi XE3, Delphi XE4, Development, QC, Software Development | Leave a Comment »
Posted by jpluimers on 2014/08/12
In the With Statement series:
Lars Fosdal – Code Rants
The dreaded with…
Debugging today, I found another gotcha.
In this case, both Self and DisconnectedClient has a property named ClientIdentifier.
Note the difference for the mouse-over and the evaluation.
–jeroen
Read the rest of this entry »
Posted in Appmethod, Borland Pascal, Delphi, Delphi 1, Delphi 2, Delphi 2005, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 3, Delphi 4, Delphi 5, Delphi 6, Delphi 7, Delphi 8, Delphi x64, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Delphi XE7, Development, Pascal, Software Development, Turbo Pascal, With statement | Leave a Comment »
Posted by jpluimers on 2014/08/12
A long while ago, DelphiBasics.info (they are hosted on Google Sites) posted a very interesting via: uExecFromMem unit. It was only a code snippet, not much usage info.
One of the things you can do with this unit, is load the memory image of an executable from a database BLOB, then execute that.
bummi showed this as an uExecFromMemory example on StackOverflow including a small memory leak fix.
It opens way for some interesting deployment scenarios. Not for the everyday ones, but for the occassional situation where a regular deployment is impractical.
–jeroen
via: uExecFromMem by steve10120 – fixed for Win7x64 by testest – DelphiBasics.
Comment by Craig Peterson at G+: https://plus.google.com/109418621512564781181/posts/WZSa6Nt44rK
It’s a handy looking unit, but has a licensing bomb in it: The PerformBaseRelocation routine is lifted directly from BTMemoryModule.pas, which is only licensed LGPL without the binary linking exception. That means providing your DCUs so anyone can relink your app. It’s also a bit less maintainable than BTMemoryModule, since they replaced a bunch of declared constants with magic numbers.
Posted in Delphi, Delphi 2007, Delphi 2009, Delphi 2010, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Development, Software Development | 4 Comments »
Posted by jpluimers on 2014/08/07
Following up on yesterdays Delphi: using IInterface to restore cursor at end of mehod (prelude to a memento that executes any code at end of method) here is the memento I meant.
They are based on anonymous methods, which in Delphi are closures: they capture location.
The location is kept just as long as needed, based on a well known Delphi reference counting mechanism: interfaces. The same one I used for the TTemporaryCursor class (and one of the reasons the TTemporaryCursor will keep functioning).
My goal was to simplify code like this:
procedure TTemporaryCursorMainForm.TemporaryCursorClassicButtonClick(Sender: TObject);
var
Button: TButton;
SavedCursor: TCursor;
SavedEnabled: Boolean;
begin
Button := Sender as TButton;
SavedEnabled := Button.Enabled;
try
Button.Enabled := False;
SavedCursor := Screen.Cursor;
try
Screen.Cursor := crHourGlass;
Sleep(3000);
finally
Screen.Cursor := SavedCursor;
end;
finally
Button.Enabled := SavedEnabled;
end;
end;
Into this:
procedure TTemporaryCursorMainForm.TemporaryCursorMementoButtonClick(Sender: TObject);
var
Button: TButton;
SavedEnabled: Boolean;
begin
TTemporaryCursor.SetTemporaryCursor();
Button := Sender as TButton;
SavedEnabled := Button.Enabled;
TAnonymousMethodMemento.CreateMemento(procedure begin Button.Enabled := SavedEnabled; end);
Button.Enabled := False;
Sleep(3000); // sleep 3 seconds with the button disabled crHourGlass cursor
// Delphi will automatically restore the cursor
end;
We’ve already seen one of the try…finally…end blocks vanish by using TTemporaryCursor. Now lets look at TAnonymousMethodMemento:
unit AnonymousMethodMementoUnit;
interface
uses
System.SysUtils;
type
IAnonymousMethodMemento = interface(IInterface)
['{29690E1E-24C8-43A5-8FDF-5F21BB32CEC2}']
end;
TAnonymousMethodMemento = class(TInterfacedObject, IAnonymousMethodMemento)
strict private
FFinallyProc: TProc;
public
constructor Create(const AFinallyProc: TProc);
destructor Destroy; override;
procedure Restore(const AFinallyProc: TProc); virtual;
class function CreateMemento(const AFinallyProc: TProc): IAnonymousMethodMemento;
end;
implementation
{ TAnonymousMethodMemento }
constructor TAnonymousMethodMemento.Create(const AFinallyProc: TProc);
begin
inherited Create();
FFinallyProc := AFinallyProc;
end;
destructor TAnonymousMethodMemento.Destroy;
begin
Restore(FFinallyProc);
inherited Destroy();
end;
class function TAnonymousMethodMemento.CreateMemento(const AFinallyProc: TProc): IAnonymousMethodMemento;
begin
Result := TAnonymousMethodMemento.Create(AFinallyProc);
end;
procedure TAnonymousMethodMemento.Restore(const AFinallyProc: TProc);
begin
AFinallyProc();
end;
end.
Like TTemporaryCursor, I’ve kept it self-contained.
It uses a TProc parameter – a parameterless anonymous method – called AFinallyProc that needs to be executed right before the memento goes out of scope.
It can be called like any method, as to the compiler it is a method.
–jeroen
Posted in Delphi, Delphi 2009, Delphi 2010, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Development, Software Development | 11 Comments »