Delphi: this version does not support command-line compiling (yes, it does)

There are a couple of rare cases where I do an automatic build of a Delphi application from a batch file. This uses the dcc32.exe command-line compiler. This worked great on one machine, but today it failed on another machine that had an identical setup. The error message was:

_PasCoreCompile: This version of the product does not support command line compiling.

2016-08-25_15-24-38

Lees meer over dit bericht

Work faster in Delphi XE8 by using Castalia’s keyboard shortcuts

keys

The new Delphi XE8 includes Castalia for easier code navigation and refactorings. The Castalia refactorings however are still separate from the ‘native Delphi’ refactorings and they partly overlap in functionality. They both have their pros and cons. A definite pro for Castalia is that most of the refactorings can be done ‘inline’, that is, there is no modal dialog involved and some way or another, most of your changes can be done directly in your code editor.

Well, no dialogs is nice, but that only improves your productivity if you do not still need your mouse to trigger the refactoring. That means I have a couple of new keyboard shortcuts to start memorizing! Lees meer over dit bericht

Delphi XE8 released, introduces Package Manager

xe8-embarcadero-header

Earlier I wrote about the new Delphi roadmap and mentioned some features I considered interesting for the upcoming XE8 version. Today, Delphi XE8 was released and in the New Features list, another one caught my eye that I think is potentionally even more promising: the GetIt Package Manager. Every time a new Delphi version is released, there are two main reasons that block me from updating immediately as soon as it comes out: Lees meer over dit bericht

New Delphi roadmap shows IDE and VCL enhancements (next to all the iOS, Android and IoT goodies…)

Brian Alexakis has recently published Delphi XE7 icosome slides outlining the Delphi (and RAD studio) roadmap. I consider it very good news that, next to all the iOS, Android, Internet-of-things and other hot technologies, there are also some important VCL enhancements on there. Next to IDE feature and stability improvements, which are always nice of course. Take a look at slides 7-9.

One in particular that caught my eye was 4K display / Large font support, which I interpret as improvements to scaling of Delphi applications on hi-res displays. Though I don’t have a 4K monitor yet, I am the proud owner of a Microsoft Surface Pro 3 that features a high resolution display so any improvements on that front are more than welcome. It can look awful when done wrong.

In general, I consider it good to know that all of us long time Delphi developers that have existing (VCL) codebases to maintain (and extend and improve) are not left in the dark by Embarcadero, just in order to put another buzzword on the box of the next Delphi release. Keep it up!

Bad Delphi upgrade experience (that was partly my own fault)

Latest update (11:45): I finally managed to install Update 1. Though I still think the update experience is not as smooth as it could be (most of the points I mention below are still valid), and the error message I was getting was in no way related to what was actually wrong, the original fault was probably my own. I already mentioned that I moved the installation folder over to another drive using a junction point to reference it from its original location. Well, the moved folder was missing one quite important file (setup.exe). I must have missed it when moving the folder, I cannot think of another explanation. After copying it from the original XE7 ISO, and a reboot after the (now successful) uninstallation, XE7 Update 1 is currently installing in the background. Lees meer over dit bericht

Check your compiler warnings and hints. They may still be errors.

I try to follow a zero hints and warnings policy for my code. (I admit I don’t always succeed though. 😉 ) But I was initially confused on how to solve this, and because of that learned something about not always following directions blindly…

See this example code.

function Test: boolean;
var Something: TSomething;
begin
  Result := false;
  Something := TSomething.Create;
  try
    // Perform something that may raise an exception
    Result := true;
  finally
    FreeAndNil (Something);
  end;
end;

This function should return true if everything went ok, without exceptions, and false otherwise. You’ve probably at some point written something like that too. However, I get a compiler hint pointing to the first line of the function:

[dcc32] H2077 Value assigned to 'Test' never used.

I can make the hint go away by removing the first Result := false assignment. However, is my Result then guaranteed to initialize to false, as I would like it to? Lees meer over dit bericht

Free up space on your OS disk by moving the Delphi XE6 installer files elsewhere

I noticed the free space on my SSD was getting smaller. Searching for ways to clean up a bit I discovered a ± 10 Gb hidden folder under c:\users\(account)\appdata\local\(guid). Inspecting its contents, it turned out to belong to the RAD Studio XE6 installer. No need to delete them, but I didn’t want them to take up precious space on my speedy SSD, the files are very infrequently (if ever) accessed and could easily rest on my slower but larger regular harddisk.

So I moved all files to a new folder on the HDD drive under D:\Installer files\Delphi XE6 using Windows Explorer.
When it was done, I opened a command prompt in c:\users\(account)\appdata\local. Then typed this:

mklink /j "{0DE47792-19BD-4AF4-B9CF-6378FBA44825}" "D:\Installer Files\Delphi XE6\{0DE47792-19BD-4AF4-B9CF-6378FBA44825}"

(The actual guid may or may not differ on your system.) This creates a so-called junction point on the original location. No need to go into the details, but think of it as a shortcut-link-on-steroids. Now, the RAD Studio installer won’t know any better than that the files are still where it expects them to be, should you ever need them. It’s just on another disk.

(Disclaimer: use this tip on your own risk.)

Ad. 02-06-2014: another great way to free up some space on your SSD is by moving the Windows Installer package cache to a secondary HDD. The article under the link takes it one step further by moving it into a VHD to make future moves easier. I had to modify it slightly, because the security descriptor that is mentioned was not valid on my system. Tip: you can get the descriptor by executing

cacls "%ProgramData%\Package Cache" /s

on the commandline.

All in all, it is not a straightforward operation but may be worth it, since it consumes 2 Gb on my system.

Solving I/O Error 103 in LoadXMLDocument

In a Delphi console application that reads its configuration from an XML file, I unexpectedly ran into “I/O error 103”. I/O error 103 will look familiar to most of you Delphi developers, it means “File not open”. I traced it to this source line:

xmlcfg := LoadXMLDocument(FConfigFilePath);

LoadXMLDocument comes from the Delphi unit XMLDoc.pas, so the problem was not in my code. Ouch, this could mean trouble. But, the exact same unit was used in another (Forms) application where it worked perfectly fine. What was going on here?

The solution was fortunately deceivingly simple: the XMLDoc unit uses interfaces, so you need a CoInitialize() call before doing anything. As it turned out, my CoInitialize() call was too late. It was further down, right before initializing some ADO components, but after the attempt to read the configuration file. So the solution was to put

CoInitialize(nil);

At the very top of my initialization code, before calling the configuration reader. Now it worked fine, no more “File not open” messages.

This proved once more that sometimes, the error message you get has little to do with the real issue at hand.

For reference: CoInitialize resides in the ActiveX unit.

Returning to previous editor tab in Delphi

Having done a lot of Visual Studio work lately, I’ve grown accustomed to the VS way of switching between open file tabs with the Ctrl+Tab keystroke: it switches between files in Most Recently Used order, the same way Alt+Tab does for open programs. This is extra easy when, while coding, you have to do a lot of switching back and forth between just two or three files. You can do so from your keyboard without reaching for your mouse.

I didn’t notice how much I’ve gotten used to it, until recently I had to do a lot of Delphi work again. Using Ctrl+Tab in Delphi also switches between tabs, but in the order the tabs are placed at the top of the editing window (mostly the order you loaded them in). While this is admittedly more predictable when you have lots of files open, in practice I find it much less useful. When I have lots of files (tabs) open, I rarely use the tabs at the tab to switch between files but instead use the Project Manager or hit Ctrl+F12 and start typing the unit name.

Looking for a Delphi equivalent of VS-like behavior for Ctrl+Tab (or a plugin that takes care of it), I stumbled upon this post by Joe White from a couple of years back. He mentions the use of Ctrl+B, which brings up a opened units list, but with the units sorted in MRU order, and with the focus already on the previously opened unit. Because of this, Ctrl+B followed by ENTER, immediately brings you to the window you previously were.

Ctrl+B brings up a unit list in Most Recently Used order, focusing the previously opened unit.

Ctrl+B brings up a unit list in Most Recently Used order, focusing the previously opened unit.

Summarized (Visual Studio -> Delphi)

  • Ctrl+TAB -> Ctrl+B, ENTER
  • Ctrl+TAB,TAB -> Ctrl+B, down arrow, ENTER
  • Ctrl+TAB,TAB,TAB -> Ctrl+B, down, down, ENTER
  • etc.

Still not exactly, but almost as good.

Keeping a modeless window accessible from a modal (dialog) window

In a C# WinForms application I was working on, users were effectively working with two more or less independent windows: one they worked in, and another that showed documents and other info they need to do that work. The problem was that when they were in a dialog, for example one to assist in creating a new object, the window holding the documents with info on the object was not accessible because the dialog is modal.

You can have the dialog take ownership of the document window, but that means also it will always be on top of it, which would be inconvenient.

So I borrowed a trick from my Delphi days that I found here. You only need to do a small Windows API call from your code. I added this code to utility class called FormsUtil, but you could of course put it anywhere that’s convenient to you.


[DllImport("user32.dll")]
private static extern bool EnableWindow(IntPtr hwnd, bool bEnable);

public static bool EnableWindow (Form form, bool enable) {
    return EnableWindow(form.Handle, enable);
}

This allows you to, in the dialog form, attach an event handler to the Shown event:

private void NewObjectForm_Shown(object sender, EventArgs e) {
    if (this.Modal) {
        var viewer = GetReferenceToDocumentViewerForm();
        FormsUtil.EnableWindow(viewer, true);
    }
}

Now the document viewer window is accessible from the “new object” dialog.

Tip: be careful if you ever choose to use EnableWindow(formX, false). It will disable that form completely, including not being able to close it.