David's Blog

Subscribe to David's Blog feed
Updated: 1 day 16 hours ago

My Favorite New Delphi 10.3 Rio Features

Thu, 2019-09-05 00:18
Category: Programming

If you code a large share of your day, the IDE, or Integrated Development Environment, plays a key role in how productive you are. Getting around quickly and being very familiar with shortcut keys can save a lot of time. Several years ago, I bought Castalia, a popular Delphi IDE plugin that added several productivity enhancements. One of my favorite enhancements was stack-based bookmarks. You could hit F2, go navigate through your code or even bounce to a different file then by simply hitting Escape, you'd be right back where you left off and the temporary bookmark that had been left would be removed.

In 2014, Embarcadero purchased the product from TwoDesk, offered it for free to registered users of Delphi XE7 and then integrated parts of it into XE8. I was maintaining products in Delphi XE and XE2 and had let my Delphi subscription lapse so didn't pay much attention to it. Later, when I renewed, I found there were no more updates to Castalia and the stack-based feature I had loved didn't seem to exist. I was disheartened.

I forgot about it and started using manually created bookmarks more often when using Delphi 10 Seattle. The problem with them is they're only useful within the current source file and once you have several bookmarks in several different source files, it's easy to confuse yourself with which one goes where.

So when Delphi 10.3 came out and had a couple of new plugins available from it's GetIt Package Manager that provided this forgotten capability, I was elated. Reading about the Bookmarks and Navigator plugins, I found that stack-based bookmarks had been finally integrated into the Delphi IDE in 10.1 Berlin, but the hotkey, instead of being the simple function key used by Castalia was an obtuse, hard-to-remember combination of Ctrl+K & Ctrl+G. What? Why would they do that? Are they not creative enough to come up with something easier to remember than that?

Enter Parnassus. I had never heard of them before 10.3 Rio was released but evidently they had their "Bookmarks" plugin clear back in 2014.

But another, equally exciting plugin, also by Parnassus, is Navigator. This goes hand-in-hand with Bookmarks because it helps you jump quickly to places you might likely go temporarily, then quickly get back to work. For example, when I'm coding, I often realize I need to include a unit to support a method I need. So I have to go up to the implementation section, add a unit under the uses section, then go back to my code to continue. With the Navigator plugin, I can hit Ctrl+G (for Go), down-arrow two times to the Implementation-Uses section and hit Enter. That creates a stack-based bookmark where I am, jumps me up to the implementation section of my Delphi unit, I type in the name of the unit I need, possibly navigate inside and check the syntax, then simply hit Escape and I'm right back to where I can continue coding. Sweet!

Admittedly, this isn't really a built-in feature of Delphi, it's a third-party product they acquired (just like Castalia a few years prior) and are offering free. But at least now I know about it and once again have the convenience and productivity boost of fast navigation and stack-based bookmarks.

I just hope Embarcadero does not change the Navigator's hot key to some weird Ctrl+key combination that is hard to remember.

Categories: Developer Blogs

Delphi Locked-up with Git

Wed, 2018-10-31 07:28
Category: Programming

I needed to reinstall Delphi 10.2 recently and when I did, I finally decided to check the box that asks if you want to hook up a source code repository. I've always managed source in repositories outside of the IDE, but decided to see if and how much productivity improvement could be had it was built in with the project manager. I use Git so selected the installed git-cmd.exe file when prompted.

After installing Delphi, I loaded it up, set a few options, installed some templates and libraries and got to work--or tried to. I loaded a project and suddenly Delphi locked up (with an hourglass cursor forever and the title bar said "not responding" causing me to forcibly close the IDE). I thought that was strange and waited, checked a few things, finally restarted the computer and tried again. Creating a new standard application and running it seemed to work fine and then loading a project worked, but anytime I right-clicked on a project or tried any file activity, Delphi locked up again.

I've been using Delphi for many years (and almost every version ever produced) and had not seen anything quite like this. Large projects will take longer to load but even the smallest sample applications were locking it up. What's more is that I had been using Delphi on this same machine just fine a few weeks earlier and on a different machine it still worked. Not even uninstalling all IDE experts and libraries helped.

So I sent a tech support request to Embarcadero. After a couple of days of trying many things, I was asked to use Process Explorer to create a mini dump of activity when Delphi locked up. While I was loading that up, I saw that the moment Delphi locked up, a child process showed up: git-cmd!

After killing the IDE process and restarting, I went straight to the options and cleared out the git-cmd executable for the option I had setup when installing (and then forgotten about) and reran my "lockup" tests--everything worked beautifully!

So, why did it lock up? Maybe Delphi couldn't find git-cmd.exe or perhaps it was waiting for a response. Perhaps I chose the wrong executable. I'm not completely sure. It wasn't something I needed and had already spent many hours trying to figure out what was wrong and didn't want to take any more time on it.

My hope is that if anyone else runs into this (or my future self!), they'll find this blog and save some time trouble-shooting the issue. I also hope that Embarcadero improves the handling of source repositories--or at least gives some guidance when installing as to what executable you're supposed to use.

If anyone else successfully uses Git integrated with Delphi, I'd love to hear about it!

Categories: Developer Blogs

Mutliple InterBase Instances

Thu, 2018-10-25 16:24
Category: ProgrammingWindows

Way back in 2000, InterBase 6.0 was made open source. Soon a fork was made in the code and Firebird SQL was born. I started using this new powerful database engine and as InterBase went back to being a closed-source product, stuck with the free version or used other database engines. Many tools and Delphi component sets still support both IB and FB as they are still quite similar.

Recently, I was doing some research for a potential project dealing with InterBase and figured I should have IB installed for testing to make sure there were no surprises. I got the latest version installed and discovered the client had a previous version installed. Reading through the IB documentation, I discovered that IB allows for multiple versions to be installed simultaneously (this feature came out with version 7.5). The installer walks you through selecting a unique port and service name and sets it all up nicely.

The default service name and default port for IB are "gds_db" and 3050. Since I needed to install an earlier version (XE7), I now had two service names, one named "gds_db" and one named "XE7".

Since I like things named clearly and consistently, this just would not do. So, of course, I went looking through the documentation to figure out how to change it. I found an installer.log file and found it made several registry entries to start the Windows services. There are two services for each InterBase instance, a "guardian" service and the database service itself. (I believe the "guardian" service is there just to make sure the database service stays alive.) I figured I could just change a config file or a registry entry and clean up my naming and port assignments.

The registry entries to start the Windows services can be found in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services and they each start with IB so they weren't too difficult to find. And it looked like simply changing a couple of keys would do the trick: DisplayName and ImagePath. DisplayName is just the name that will be shown in the list of services and changing that is harmless. But the -p parameter in the ImagePath key defines the name of the service. It took me a while of trying to change that and finding InterBase would not start before I realized that the service name has to be uninstalled and reinstalled--I guess a copy of it (or a reference?) is buried somewhere deep in the Windows internals because I could never figure out how to change the service name from "gds_db" to anything more readable. (Looking back, I suppose I could've manually uninstalled the services and reinstalled using the sc command.)

If you want multiple instances of InterBase installed on the same machine simultaneously, you can do it, but use the installer--don't try to change the registry entries

One more thing, there's what looks like a config file in the installation folder for InterBase called, values.txt. That contains the port and service name setup during installation. I was hoping that changing the port number in that file (if assigned incorrectly during installation), would change what the IB engine runs. But even after shutting down the service, running Notepad as Administrator, changing the port and saving the file, then restarting the service, it was still trying to use the old port number.

So again, just use the InterBase installers if you need to change parameters!

Categories: Developer Blogs

Path Size with Multiple versions of Delphi

Sun, 2018-09-02 19:33
Category: ProgrammingWindows

I work on a variety of projects in several different versions of both Delphi and Visual Studio. A lot of these projects also include database access. To support all these different projects, a lot of different tools need to be installed and with each comes a set of paths that are setup for the applications to find libraries, support tools, and so forth. Since most software tools can also generate both 32-bit and 64-bit code these days, there are often two sets of paths for each type of compilation.

Recently, as I was installing my 6th version of Delphi on a new laptop, I encountered the warning that my PATH environment variable was reaching it's length limit. Sure enough, when I edited it from the System Control Panel, it also warned me that the PATH environment variable was too long--the dialog only allows values up to 2,047 characters long.

Since I had a few more versions to install, I had to make a work-around. I discovered this trick when I installed a Developer Express library a while back and saw how it shortened it's very long path to just another variable. First, it created the variable,
DXVCL=C:\Program Files (x86)\DevExpress.VCL

Then when it needed to add a PATH for it, it simply added this value: %DXVCL%\Library\Delphi15 instead of the full path.

A light-bulb came on in my head when I saw that and I thought, "if Dev Express can do it, why can't I?" I noticed Delphi was being installed in the base path, C:\Program Files (x86)\Embarcadero and that compiled packages were being added to paths under C:\Users\David\Documents\Embarcadero\Studio. So I created a couple of environment variables:

  • EMB=C:\Program Files (x86)\Embarcadero
  • EMB_USER=C:\Users\David\Documents\Embarcadero\Studio

Now, my path entries look like this:

When I finished, I had 3 versions of Visual Studio (2013, 2015, and 2017) and 10 different versions of Delphi installed (from Delphi 7 to Delphi 10.2 Tokyo), all one one Windows 10 machine!

Categories: Developer Blogs

Blog Conversion

Mon, 2018-08-27 07:05
Category: Cloud Computing

It's been a while since my last blog entry and so much has changed! I went from being fully employed to fully immersed in scaling up my business for the long term. I am strengthening connections and building upon experience gained in the technological landscape. That landscape continually evolves and it's a challenge to keep up!

As a business person, one has to decide which niche(s) to specialize in as being the jack-of-all-trades just isn't possible anymore. For programming languages, I had decided to broaden my skill set and have even considered moving away from Delphi at one point. But when clients ask if you've worked with a certain product or how you're going to accomplish a certain task, you suddenly realize how important the experience you already have is and you start thinking of ways to leverage that. Sure, you can teach yourself a new language--and you should constantly be doing that--but you also have to make sure the bills are paid!

So when I recently added SSL to my WordPress blog and saw images not showing up and subsequently spent hours hunting down solutions, adjusting links, trying plugins, and getting marginal success, I stopped and evaluated the situation from a business perspective and made a decision to scrap it. The reason? All of my other sites are in Drupal and trying to learn another technology well enough to fix anything just isn't in my best interest. There are a lot of highly skilled WordPress people around and working on content-rich web sites is not really the focus of my business. I know enough about WordPress to talk about it, I've tried it and like it, but my expertise with Drupal is much greater and I have a much deeper investment there.

From WordPress to Drupal

Now certainly, this has been done before, right? Yes, and there are Drupal modules to import content from a WordPress export. However, there are some gotchas (aren't there always?). Most of the Drupal world is encouraged to use Drupal 8, which has been out for quite awhile now. I'm still on Drupal 7 because the servers provided by the web hosting company where my sites reside have not yet been upgraded to the latest version of PHP or MySQL. Drupal 7 is still supported and very solid, but development has stopped on some of the modules. Of course, the WordPress import module is one of them that is getting left behind.

With nothing to lose, I installed it on my new blog site and ran the import. After a few tweaks to the XML file being imported and some adjustments in the module's PHP code, I was able to get all the blog entries and comments ported over. A few adjustments to the selected theme and you're now reading from the new and improved Technical Blog!

Categories: Developer Blogs

Programming Delphi for Various Platforms and Versions

Sat, 2017-04-22 12:55
Category: Programming

Delphi has come a long ways since it was first released in 1995. It now compiles 32-bit or 64-bit, still creates console or Windows applications but now also can create Android and iOS apps if you have the FireMonkey library and cross-platform tools, you can create Android and iOS apps.

There are a lot of compiler directives that can be used in your code to selectively compile different sections of code depending on the platform or options being used. There are also symbols defined for each version of Delphi.

Many years ago, to test some of these symbols before I found clear documentation like the links given above, I wrote a program to list out the symbols defined when compiled under different versions of Delphi, and later added other conditional symbols to list out other capabilities of the executing environment. I recently revisited this program, pulled all the compiler directives out of the main form into a generic unit, and added a couple new applications using this new unit to the project group. I have put this set of programs up on GitHub under the name DelphiVersions on the off-chance someone might find it useful.

As of the date of this writing, this compiles under Delphi 10 Seattle and includes each of the following:

  • Windows Console 32/64-bit
  • Windows VCL 32/64-bit
  • Windows FireMonkey 32/64-bit

Here are some screen shots:

Categories: Developer Blogs

Programming Delphi for Various Platforms and Versions

Sat, 2017-04-22 12:55

Delphi has come a long ways since it was first released in 1995. It now compiles 32-bit or 64-bit, still creates console or Windows applications but now also can create Android and iOS apps if you have the FireMonkey library and cross-platform tools, you can create Android and iOS apps.

There are a lot of compiler directives that can be used in your code to selectively compile different sections of code depending on the platform or options being used. There are also symbols defined for each version of Delphi.

To test some of these symbols before I found clear documentation like the links given above, I wrote a program to list out the symbols defined when compiled under different versions of Delphi, and later added other conditional symbols to list out other capabilities of the executing environment. I recently revisited this program, pulled all the compiler directives out of the main form into a generic unit, and added a couple new applications using this new unit to the project group. I have put this set of programs up on GitHub under the name DelphiVersions.

As of the date of the writing of this blog entry, this compiles under Delphi 10 Seattle and includes each of the following:

  • Windows VCL 32-bit
  • Windows VCL 64-bit
  • Windows Console 32-bit
  • Windows Console 64-bit
  • Windows FireMonkey 32-bit
  • Windows FireMonkey 64-bit

 

Here are some screen shots:

Categories: Developer Blogs

Broadening My Skill Set

Sun, 2016-01-31 11:06
Category: MiscellaneousProgramming

As an independent software developer, I make my living writing scripts and applications for others. In order to maximize my opportunities, I need to be a master of many environments. Since much of my career has involved Windows applications, I am spending quite a bit of effort in other areas.

Several months ago, I converted a Windows server application to a Linux module for a client. That was a lot of fun and a good departure from my usual coding. Another great experience was helping a client who is rewriting a retirement analysis package as a web-based application using an ASP.NET server and JavaScript on the front end. That work taught me a lot about the Bootstrap and Durandal frameworks. I have some possible C# work coming up in the future and a friend recently asked me to teach him Python. Finally, and on a very different platform, there's a possibility I'll get to work on some PLC components--that sounds intriguing!

Fortunately, I love learning new technologies. There are so many cool ways to do things, so many programming languages, so many frameworks and tools. It's impossible to know all of them, but in my position, I must be aware of the most popular ones--or at least the ones where I can find paying clients! More and more, those clients are expecting expertise in building web apps. That, of course, means JavaScript and several different frameworks. With Bootstrap under my belt, I'm now concentrating on AngularJS.

One problem with simply going through a tutorial book and learning the syntax of a language is that it doesn't give me real-world experience. One way to get experience is to work at a company that allows you to grow into new areas of expertise. Barring that, another way is to donate time to a local non-profit organization that you can later point to as an example of your work. It's time-consuming, but if you can swing it, opportunities like that can be a win-win for both sides.

Some people wonder why contractors charge so much, but when you think of the constant learning time that must be invested to stay relevant, not to mention a cushion for time off, it's actually quite a challenging endeavor. If one can manage it, the benefits of being your own boss and picking your own projects and tools are quite rewarding.

Categories: Developer Blogs

Broadening My Skill Set

Sun, 2016-01-31 11:06

As an independent software developer, I make my living writing scripts and applications for others. In order to maximize my opportunities, I need to be a master of many environments. Since much of my career has involved Windows applications, I am spending quite a bit of effort in other areas.

Several months ago, I converted a Windows server application to a Linux module for a client. That was a lot of fun and a good departure from my usual coding. Another great experience was helping a client who is rewriting a retirement analysis package as a web-based application using an ASP.NET server and JavaScript on the front end. That work taught me a lot about the Bootstrap and Durandal frameworks. I have some possible C# work coming up in the future and a friend recently asked me to teach him Python. Finally, and on a very different platform, there’s a possibility I’ll get to work on some PLC components–that sounds intriguing!

Fortunately, I love learning new technologies. There are so many cool ways to do things, so many programming languages, so many frameworks and tools. It’s impossible to know all of them, but in my position, I must be aware of the most popular ones–or at least the ones where I can find paying clients! More and more, those clients are expecting expertise in building web apps. That, of course, means JavaScript and several different frameworks. With Bootstrap under my belt, I’m now concentrating on AngularJS.

One problem with simply going through a tutorial book and learning the syntax of a language is that it doesn’t give me real-world experience. One way to get experience is to work at a company that allows you to grow into new areas of expertise. Barring that, another way is to donate time to a local non-profit organization that you can later point to as an example of your work. It’s time-consuming, but if you can swing it, opportunities like that can be a win-win for both sides.

Some people wonder why contractors charge so much, but when you think of the constant learning time that must be invested to stay relevant, not to mention a cushion for time off, it’s actually quite a challenging endeavor. If one can manage it, the benefits of being your own boss and picking your own projects and tools are quite rewarding.

Categories: Developer Blogs

Preventing Multiple Application Instances in Delphi with TMutex

Tue, 2015-10-20 11:27
Category: Programming

Having worked in Delphi for many years, I've seen the development tool and it's RTL evolve significantly, yet remain resilient in backwards compatibility. Early on, to prevent your application from running multiple times, there were generally two different approaches:

  1. Search for the name of your app's main form by name, or
  2. Search for a "mutex" created by your app.

There are other ways, but these two are the most popular I've seen. They both still work. The first one requires your application to actually show the main form--which obviously doesn't work for console applications. I'm writing an application that can be scheduled to run unattended and in that case will not be showing the main form, so I am using the second method. The last time I used this technique, I called CreateMutex which has a wrapper function in Delphi's RTL (see this forum for an example).

While reading about the threading and synchronizing topics in Delphi I found the TMutex class introduced way back in Delphi XE. I decided to put it to use, if for no other reason than for educational purposes. It turns out I like it better as it's more object-oriented.

I won't go into much detail as this is a fairly old topic with several examples and Windows API documentation that is still valid. So here's a code example:

program MutexExample;
uses
  Vcl.Forms, Vcl.Dialogs,
  System.SyncObjs, // defines TMutex
  Winapi.Windows,  // defines ERROR_SUCCESS
  Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
var
  AppMutex: TMutex = nil;
  MutexErr: Integer = 0;
procedure CheckSecondInstance;
const
  // any unique name will work--I chose to create a GUID
  UNIQUE_MUTEX_NAME = '{AD12094E-7308-4067-8CAC-565A1FF3ADDC}';
begin
  // try to create a mutex; don't need any security rights
  AppMutex := TMutex.Create(nil, True, UNIQUE_MUTEX_NAME);
  // check to see if it was successful
  MutexErr := GetLastError;
  // if not, previous instance of application already created the mutex
  if MutexErr <> ERROR_SUCCESS then
    ShowMessage(Application.Title + ' is already running.');
end;
begin
  // initialize app like normal, but don't start it yet
  Application.Initialize;
  Application.Title := 'Simple Mutex Example';

  // run our check here
  CheckSecondInstance;
  try
    // if the mutex was successfully created, this is the first instance of this app
    if MutexErr = ERROR_SUCCESS then begin
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end;
  finally
    // if a mutex was successfully created (and our app ran),
    // be sure to free it to release the mutex
    if Assigned(AppMutex) then
      AppMutex.Free;
  end;
end.
Categories: Developer Blogs

Preventing Multiple Application Instances in Delphi with TMutex

Tue, 2015-10-20 11:27

Having worked in Delphi for many years, I’ve seen the development tool and it’s RTL evolve significantly, yet remain resilient in backwards compatibility. Early on, to prevent your application from running multiple times, there were generally two different approaches:

  1. Search for the name of your app’s main form by name, or
  2. Search for a “mutex” created by your app.

There are other ways, but these two are the most popular I’ve seen. They both still work. The first one requires your application to actually show the main form–which obviously doesn’t work for console applications. I’m writing an application that can be scheduled to run unattended and in that case will not be showing the main form, so I am using the second method. The last time I used this technique, I called CreateMutex which has a wrapper function in Delphi’s RTL (see this forum for an example).

While reading about the threading and synchronizing topics in Delphi I found the TMutex class introduced way back in Delphi XE. I decided to put it to use, if for no other reason than for educational purposes. It turns out I like it better as it’s more object-oriented.

I won’t go into much detail as this is a fairly old topic with several examples and Windows API documentation that is still valid. So here’s a code example:

program MutexExample;

uses
  Vcl.Forms, Vcl.Dialogs,
  System.SyncObjs, // defines TMutex
  Winapi.Windows,  // defines ERROR_SUCCESS
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

var
  AppMutex: TMutex = nil;
  MutexErr: Integer = 0;

procedure CheckSecondInstance;
const
  // any unique name will work--I chose to create a GUID
  UNIQUE_MUTEX_NAME = '{AD12094E-7308-4067-8CAC-565A1FF3ADDC}';
begin
  // try to create a mutex; don't need any security rights
  AppMutex := TMutex.Create(nil, True, UNIQUE_MUTEX_NAME);

  // check to see if it was successful
  MutexErr := GetLastError;

  // if not, previous instance of application already created the mutex
  if MutexErr <> ERROR_SUCCESS then
    ShowMessage(Application.Title + ' is already running.');
end;

begin
  // initialize app like normal, but don't start it yet
  Application.Initialize;
  Application.Title := 'Simple Mutex Example';

  // run our check here
  CheckSecondInstance;
  try
    // if the mutex was successfully created, this is the first instance of this app
    if MutexErr = ERROR_SUCCESS then begin
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end;
  finally
    // if a mutex was successfully created (and our app ran),
    // be sure to free it to release the mutex
    if Assigned(AppMutex) then
      AppMutex.Free;
  end;
end.

Categories: Developer Blogs

Make the New Welcome Screen in Delphi Usable

Thu, 2015-10-08 01:14
Category: Programming

Why is it that when companies have a good thing, they have to go mess it up by changing its design? I've seen this in many different industries but since change happens so much more quickly in software, I seem to be annoyed much more often with changes in user interface. Of course, there are glaring examples like the ribbon in the Office products and the Windows 8 start screen (which I actually liked when using it on a tablet).

But today I'm talking about the Welcome screen in Delphi XE8 and newer. Way back in Delphi 2005 or 2007 (I forget when exactly), a new welcome screen was displayed when Delphi started and provided a nice collection of resources and helpful links to documentation. One of the features of this new interface was an editable list of favorite projects that could be put into "favorite groups" and made for a nice, quick link to lots of different projects. The font was small and it utilized the space pretty well. I used it a lot and since I work on lots of small projects, this was very useful.

I've recently upgraded to the latest version of Delphi and have found this useful interface has been completely revamped with a big banner ad and large-font shortcuts with big icons to things I can already get to with a few keyboard strokes. Yes, there's still a list of favorite projects, but you can't create groups any more and the scrollable region for them is so small that with the number of projects I work on, it's practically useless.

Why is this better???

Fortunately, the welcome screen is written in HTML and easily found in the Welcomepage folder of your Delphi installation. (Your Delphi is installed, by default, under C:\Program Files (x86)\Embarcadero\Studio\<BDS-Version>). As has been mentioned elsewhere, it's pretty easy to remove the banner (why we have to have advertisements inside our development tool is beyond me) so that was the obvious first step. But I wanted to go further. I have no need for the links to create a new project or the links to the tutorials. I can get to those easily enough. For my day-to-day work, I need quick access to the projects I'm working on.

So I cut it down to two lists: Favorite Projects and Recent Projects. I still like the old interface better--and I briefly tried copying the welcomepage from an older version, but it crashed violently, so didn't spend much time going down that path.

Here's a step-by-step list of how you can modify the Welcome Screen in your installation of Delphi, but first a disclaimer: Be sure and make a backup of your welcome page before you begin (I mention this in the steps below, but emphasize it here as well). Also, it really helps to understand HTML and CSS when editing these files in case things look a little different in your installation. These steps are mostly for Delphi 10 Seattle and the XE8 version is a little different. Also, you might be reading this using a newer version of Delphi and the file may have changed again (I would count on it). On the other hand, it's just the start screen and Delphi functions fine without it.

  1. First, locate the welcome page. As I mentioned above, the root folder for the welcome page files is simply Welcomepage under your Delphi installation. The "default.htm" file in this root folder is, to my knowledge not used. Instead, choose the 2-character abbreviation for your installed language and find the file there. For example, I use the English version of Delphi so found my copy of the welcome page for Delphi 10 Seattle in C:\Program Files (x86)\Embarcadero\Studio\17.0\Welcomepage\en.
  2. Make a backup of the file so if you mess anything up, you can always easily recover by going back to it.
  3. Now, pull up your favorite HTML editor, but there might be a catch. If you installed Delphi in the default folder, it's under Program Files (x86) and can only be edited by the administrator account. There's a trick used by Windows to prevent side-stepping this with some editors that even if you run as Administrator, it is only editing a "shadow copy" of the file. It's weird to me, but I just ended up using Notepad as it seems to save the right file. If you were smart and didn't install Delphi under Program Files, then you don't have to worry about this.
  4. Remove the banner ad. Find the <div> tag with id="topbanner" and delete everything until the matching <\div> tag. I removed 10 lines in mine. Now with the banner ad removed, there's no use keeping the Javascript around that spends time getting it online. So look for the function, tryShowOnlineBanners(). You should find the definition and the place where it is called in that same file--it's not defined or used externally. That function calls another function, showOnlineBanners() and you can remove that as well. I deleted 25 more lines.
  5. Now it's time to get rid of the new projects and tutorials short cuts. In XE8, the Favorites are across the bottom, in Delphi 10 Seattle, it's between the new projects (on top) and tutorials (on bottom). In Delphi 10 Seattle's Welcome page, look for <div class="section"> tags that contain "Projects" and "Tutorials" and remove those sections of the HTML (but not the one in the middle that contains "Favorite Projects"). In Delphi XE8's welcome page, do the same thing but realize the <div> tags may be in a different place. New projects call the Javascript function newProject() but it's in an external file, so it's best to leave it alone. The tutorials call the local Javascript function, doStartTotorial() so that can go (isn't it fun cutting out code?).
  6. With Delphi up, you can look at the welcome screen and even make changes on the fly, right-click, and Refresh to see your changes instantly. After the last edit, you'll notice the Favorite Projects is a small scrolling box in the top of left column of the page with nothing below it. So we need to adjust the height. Looking at the HTML, you'll see the Favorite Projects and Recent Projects sections with a few different CSS classes in use. You'd think this is where we need to modify things, but it turns out some Javascript further down the page overwrites the heights dynamically. In the resizePanels() function, the height property of the favorite-projects class is decreased by 388 whereas the recent-projects height is only decreased by 44. Let's use 44 in both cases so they're the same height.
  7. We're close but there's a bunch of space at the bottom. It turns out there's an extra box down there (with an id of "load_html") we aren't using the same way anymore. It's height is adjusted in the setFrameHeight() function. I found changing the reduction in the height property from 184 down to 70 filled the screen nicely.

Hopefully, nothing got messed up too badly and you have a nice clean list of projects that you can quickly get to rather than scrolling through a tiny box or hunting through folders if it scrolled off the recent projects list. Let me know in the comments if you found something different or if I skipped a step. Also, feel free to drop me a line of thanks either in the comments or on the contact page of my site, CorneliusConcepts.com if this helped you work more efficiently!

Categories: Developer Blogs

Make the New Welcome Screen in Delphi Usable

Thu, 2015-10-08 01:14

Why is it that when companies have a good thing, they have to go mess it up by changing its design? I’ve seen this in many different industries but since change happens so much more quickly in software, I seem to be annoyed much more often with changes in user interface. Of course, there are glaring examples like the ribbon in the Office products and the Windows 8 start screen (which I actually liked when using it on a tablet).

But today I’m talking about the Welcome screen in Delphi XE8 and newer. Way back in Delphi 2005 or 2007 (I forget when exactly), a new welcome screen was displayed when Delphi started and provided a nice collection of resources and helpful links to documentation. One of the features of this new interface was an editable list of favorite projects that could be put into “favorite groups” and made for a nice, quick link to lots of different projects. The font was small and it utilized the space pretty well. I used it a lot and since I work on lots of small projects, this was very useful.

I’ve recently upgraded to the latest version of Delphi and have found this useful interface has been completely revamped with a big banner ad and large-font shortcuts with big icons to things I can already get to with a few keyboard strokes. Yes, there’s still a list of favorite projects, but you can’t create groups any more and the scrollable region for them is so small that with the number of projects I work on, it’s practically useless.

Why is this better???

Fortunately, the welcome screen is written in HTML and easily found in the Welcomepage folder of your Delphi installation. (Your Delphi is installed, by default, under C:\Program Files (x86)\Embarcadero\Studio\<BDS-Version>). As has been mentioned elsewhere, it’s pretty easy to remove the banner (why we have to have advertisements inside our development tool is beyond me) so that was the obvious first step. But I wanted to go further. I have no need for the links to create a new project or the links to the tutorials. I can get to those easily enough. For my day-to-day work, I need quick access to the projects I’m working on.

So I cut it down to two lists: Favorite Projects and Recent Projects. I still like the old interface better–and I briefly tried copying the welcomepage from an older version, but it crashed violently, so didn’t spend much time going down that path.

Here’s a step-by-step list of how you can modify the Welcome Screen in your installation of Delphi, but first a disclaimer: Be sure and make a backup of your welcome page before you begin (I mention this in the steps below, but emphasize it here as well). Also, it really helps to understand HTML and CSS when editing these files in case things look a little different in your installation. These steps are mostly for Delphi 10 Seattle and the XE8 version is a little different. Also, you might be reading this using a newer version of Delphi and the file may have changed again (I would count on it). On the other hand, it’s just the start screen and Delphi functions fine without it.

  1. First, locate the welcome page. As I mentioned above, the root folder for the welcome page files is simply Welcomepage under your Delphi installation. The “default.htm” file in this root folder is, to my knowledge not used. Instead, choose the 2-character abbreviation for your installed language and find the file there. For example, I use the English version of Delphi so found my copy of the welcome page for Delphi 10 Seattle in C:\Program Files (x86)\Embarcadero\Studio\17.0\Welcomepage\en.
  2. Make a backup of the file so if you mess anything up, you can always easily recover by going back to it.
  3. Now, pull up your favorite HTML editor, but there might be a catch. If you installed Delphi in the default folder, it’s under Program Files (x86) and can only be edited by the administrator account. There’s a trick used by Windows to prevent side-stepping this with some editors that even if you run as Administrator, it is only editing a “shadow copy” of the file. It’s weird to me, but I just ended up using Notepad as it seems to save the right file. If you were smart and didn’t install Delphi under Program Files, then you don’t have to worry about this.
  4. Remove the banner ad. Find the <div> tag with id=”topbanner” and delete everything until the matching <\div> tag. I removed 10 lines in mine. Now with the banner ad removed, there’s no use keeping the Javascript around that spends time getting it online. So look for the function, tryShowOnlineBanners(). You should find the definition and the place where it is called in that same file–it’s not defined or used externally. That function calls another function, showOnlineBanners() and you can remove that as well. I deleted 25 more lines.
  5. Now it’s time to get rid of the new projects and tutorials short cuts. In XE8, the Favorites are across the bottom, in Delphi 10 Seattle, it’s between the new projects (on top) and tutorials (on bottom). In Delphi 10 Seattle’s Welcome page, look for <div class=”section”> tags that contain “Projects” and “Tutorials” and remove those sections of the HTML (but not the one in the middle that contains “Favorite Projects”). In Delphi XE8’s welcome page, do the same thing but realize the <div> tags may be in a different place. New projects call the Javascript function newProject() but it’s in an external file, so it’s best to leave it alone. The tutorials call the local Javascript function, doStartTotorial() so that can go (isn’t it fun cutting out code?).
  6. With Delphi up, you can look at the welcome screen and even make changes on the fly, right-click, and Refresh to see your changes instantly. After the last edit, you’ll notice the Favorite Projects is a small scrolling box in the top of left column of the page with nothing below it. So we need to adjust the height. Looking at the HTML, you’ll see the Favorite Projects and Recent Projects sections with a few different CSS classes in use. You’d think this is where we need to modify things, but it turns out some Javascript further down the page overwrites the heights dynamically. In the resizePanels() function, the height property of the favorite-projects class is decreased by 388 whereas the recent-projects height is only decreased by 44. Let’s use 44 in both cases so they’re the same height.
  7. We’re close but there’s a bunch of space at the bottom. It turns out there’s an extra box down there (with an id of “load_html”) we aren’t using the same way anymore. It’s height is adjusted in the setFrameHeight() function. I found changing the reduction in the height property from 184 down to 70 filled the screen nicely.

Hopefully, nothing got messed up too badly and you have a nice clean list of projects that you can quickly get to rather than scrolling through a tiny box or hunting through folders if it scrolled off the recent projects list. Let me know in the comments if you found something different or if I skipped a step. Also, feel free to drop me a line of thanks either in the comments or on the contact page of my site, CorneliusConcepts.com if this helped you work more efficiently!

Categories: Developer Blogs

dbForge Data Generator for SQL Server

Tue, 2015-08-18 14:28
Category: MiscellaneousDevArt Software has been busy at producing a great number of database tools and components for both Delphi and Visual Studio developers over the last few years. They're still coming out with new ones as well. One of the most recent additions is dbForge Data Generator for SQL Server. I purchased version 1.0 in April, 2015 and they've been hard at work improving and adding features--they're already at version 3.5! You can read about their features on their web site linked above, but I'd like to highlight a few I think are notable and have been very useful to me. As you would expect from a data generator, they support all the basic column types. But they don't stop there. Character strings, for example, could have several different purposes, from storing a person's name to an address or to a unique ID. All these choices of generators are available through a drop-down list. But wait--there's more! They even look at the field names and make good guesses about which type you want and pre-select them for you to make it easier. But wait--there's more! What if you want only names usually used by males? Or females? They have those separated out or combined as you wish. But wait--there's more! You can also choose from First Names, Middle Names (which include initials), just initials, Last Names, Nicknames, or even a Full Name. But wait--there's more! There are also Honorific Prefixes (Mr. Dr., etc.) and Honorific Suffixes (Ph.D, III, etc.). But wait--there's more! I also saw in the list DE First Names, DE Last Names, DE Honorific Prefixes. I believe these are Germanic versions of the samples you might use in the U.S. Examples of these are Wolfhard, Swena, and Christoph for First Names, Zurbriggen, Ittenbach, Schelling, and Günther for Last Names, and Herr, Frau, and Doktor for Titles. There are 10 different phone number generators (5 each for US and UK), social security numbers for both US and Canada, sample job titles, email addresses, courtesy titles, ethnic groups, and even sample twitter accounts! And that's just the list of generators in the Personal category! Let's say you wanted some random business names, or ISO codes, or stock ticker codes? They have those, too. Drug names, time zones, bank routing numbers, clothing sizes, colors, ISBNs and UPCs and VINs, shipping methods, product categories and names, and many more. For programmers, there are also random file paths, image names, document titles, IPv4 and IPv6 addresses. Maybe you don't need fake "real" data. Maybe all you need is some random text to fill the database. Of course there is Lorem Ipsum text, random strings of characters or numbers or both. One I used a lot was Weighted List. This allows you to enter list of allowed values and tell it to generate a certain percentage of each value in the generated rows. For example, one table I was working with held a list of "constituents" which could either be people or organizations. A field called KEY_INDICATOR of CHAR(1) could only be 'I' (for individual) or 'O' (for organization). My weighted list held these two values with it generating many more individuals than organizations. Finally, if all else fails, you can always resort to regular expressions. And if one of the built-in generators is close but not quite what you need, select it and see if it's one of the ones that are simply preset regular expressions. I needed to generate a random death date in a VARCHAR field but was unsure how to structure the regular expression to give a valid date. I first selected a date field (the generators are type-sensitive) and selected the Regular Expression generator. Then I copied that, switched back to my VARCHAR death field, and pasted it in--voila! This tool is also smart enough to deal with foreign keys. When selecting a random value for a field that is a foreign key to another table, you have the option of selecting one of those values instead of random data (which could break a table relationship). It also generates "child" tables before "parent" tables. For example, if you are generating data for an Address table and a People table where the People table links to records in the Address table, it will automatically generate Address records first so they'll be available to fill foreign key references in the People table. Another nice feature is forcing randomly generated data to be unique. This is especially nice considering foreign keys. In my People-Address example, you would might want all the AddressID references in the People table to be unique--unless the table includes spouses as separate records that share the same address. But this is where things can start to get a little muddy. I'm not sure any random database generator could cover every situation, and I found I had to write some SQL to do some additional processing after the bulk of the data was generated. For example, in the table I was working with that had a random death date, I wanted most of the people records to be alive, so I set the percentage of null values (another great feature for making the data seem real) rather high which would generate very few death dates. There's another field in that table called DECEASED. The generator doesn't (yet) have a way to set the value of a field based on another randomly generated value in the same record, so I defaulted the value for the DECEASED field to 0 (false) and wrote a short SQL statement to set DECEASED to -1 (true) where DEATH_DATE was not NULL. There were a few other instances that I had to do this. One parent-child table relationship had a two-way linking with both tables holding the ID of the other. There's no way that I could tell do that with this tool, especially since one of them was a VARCHAR holding an INT ID of the other and therefore needed to be CAST. When I had my data generators all setup and saved to a .DGEN file, I was ready to run it. In the first several runs, I was running it directly against the database so the data was there immediately--along with errors at first. But it can also generate all the INSERT statements to an editor window or to a saved .SQL file. This allows you to not only add your own custom SQL statements before running it, but also to send the whole script to someone who doesn't have dbForge Data Generator installed. I have been very happy with this purchase. I really appreciate DevArt's licensing structure (which is becoming quite common among software companies). The purchase price automatically gives you one year of updates after which you can renew that purchase subscription for a reduced rate. I am looking forward to even more enhancements in the months and years to come!
Categories: Developer Blogs

dbForge Data Generator for SQL Server

Tue, 2015-08-18 14:28

DevArt Software has been busy at producing a great number of database tools and components for both Delphi and Visual Studio developers over the last few years. They’re still coming out with new ones as well. One of the most recent additions is dbForge Data Generator for SQL Server. I purchased version 1.0 in April, 2015 and they’ve been hard at work improving and adding features–they’re already at version 3.5! You can read about their features on their web site linked above, but I’d like to highlight a few I think are notable and have been very useful to me.

As you would expect from a data generator, they support all the basic column types. But they don’t stop there. Character strings, for example, could have several different purposes, from storing a person’s name to an address or to a unique ID. All these choices of generators are available through a drop-down list. But wait–there’s more! They even look at the field names and make good guesses about which type you want and pre-select them for you to make it easier. But wait–there’s more! What if you want only names usually used by males? Or females? They have those separated out or combined as you wish. But wait–there’s more! You can also choose from First Names, Middle Names (which include initials), just initials, Last Names, Nicknames, or even a Full Name. But wait–there’s more! There are also Honorific Prefixes (Mr. Dr., etc.) and Honorific Suffixes (Ph.D, III, etc.). But wait–there’s more! I also saw in the list DE First Names, DE Last Names, DE Honorific Prefixes. I believe these are Germanic versions of the samples you might use in the U.S. Examples of these are Wolfhard, Swena, and Christoph for First Names, Zurbriggen, Ittenbach, Schelling, and Günther for Last Names, and Herr, Frau, and Doktor for Titles.

There are 10 different phone number generators (5 each for US and UK), social security numbers for both US and Canada, sample job titles, email addresses, courtesy titles, ethnic groups, and even sample twitter accounts! And that’s just the list of generators in the Personal category! Let’s say you wanted some random business names, or ISO codes, or stock ticker codes? They have those, too. Drug names, time zones, bank routing numbers, clothing sizes, colors, ISBNs and UPCs and VINs, shipping methods, product categories and names, and many more. For programmers, there are also random file paths, image names, document titles, IPv4 and IPv6 addresses.

Maybe you don’t need fake “real” data. Maybe all you need is some random text to fill the database. Of course there is Lorem Ipsum text, random strings of characters or numbers or both. One I used a lot was Weighted List. This allows you to enter list of allowed values and tell it to generate a certain percentage of each value in the generated rows. For example, one table I was working with held a list of “constituents” which could either be people or organizations. A field called KEY_INDICATOR of CHAR(1) could only be ‘I’ (for individual) or ‘O’ (for organization). My weighted list held these two values with it generating many more individuals than organizations.

Finally, if all else fails, you can always resort to regular expressions. And if one of the built-in generators is close but not quite what you need, select it and see if it’s one of the ones that are simply preset regular expressions. I needed to generate a random death date in a VARCHAR field but was unsure how to structure the regular expression to give a valid date. I first selected a date field (the generators are type-sensitive) and selected the Regular Expression generator. Then I copied that, switched back to my VARCHAR death field, and pasted it in–voila!

This tool is also smart enough to deal with foreign keys. When selecting a random value for a field that is a foreign key to another table, you have the option of selecting one of those values instead of random data (which could break a table relationship). It also generates “child” tables before “parent” tables. For example, if you are generating data for an Address table and a People table where the People table links to records in the Address table, it will automatically generate Address records first so they’ll be available to fill foreign key references in the People table.

Another nice feature is forcing randomly generated data to be unique. This is especially nice considering foreign keys. In my People-Address example, you would might want all the AddressID references in the People table to be unique–unless the table includes spouses as separate records that share the same address. But this is where things can start to get a little muddy. I’m not sure any random database generator could cover every situation, and I found I had to write some SQL to do some additional processing after the bulk of the data was generated.

For example, in the table I was working with that had a random death date, I wanted most of the people records to be alive, so I set the percentage of null values (another great feature for making the data seem real) rather high which would generate very few death dates. There’s another field in that table called DECEASED. The generator doesn’t (yet) have a way to set the value of a field based on another randomly generated value in the same record, so I defaulted the value for the DECEASED field to 0 (false) and wrote a short SQL statement to set DECEASED to -1 (true) where DEATH_DATE was not NULL.

There were a few other instances that I had to do this. One parent-child table relationship had a two-way linking with both tables holding the ID of the other. There’s no way that I could tell do that with this tool, especially since one of them was a VARCHAR holding an INT ID of the other and therefore needed to be CAST.

When I had my data generators all setup and saved to a .DGEN file, I was ready to run it. In the first several runs, I was running it directly against the database so the data was there immediately–along with errors at first. But it can also generate all the INSERT statements to an editor window or to a saved .SQL file. This allows you to not only add your own custom SQL statements before running it, but also to send the whole script to someone who doesn’t have dbForge Data Generator installed.

I have been very happy with this purchase. I really appreciate DevArt’s licensing structure (which is becoming quite common among software companies). The purchase price automatically gives you one year of updates after which you can renew that purchase subscription for a reduced rate. I am looking forward to even more enhancements in the months and years to come!

Categories: Developer Blogs

Career Developers and Passionate Technologists

Tue, 2015-08-11 13:57
Category: Miscellaneous

Programmers can be grouped into two broad categories: 1) Career Developers, and 2) Passionate Technologists. Career Developers will pick a language and a job and be very good at what they do, produce excellent work for their employer, and live happily ever after. Passionate Technologists will be constantly seeking different ways of doing things, learn a new language every year, keep old computer parts and reuse them in strange projects around the house, continually tinker with electronic gadgets of all sorts, and be considered the geekiest person around by all their friends and family. OK, perhaps that's a bit of an exaggeration and there can certainly be overlapping traits found in either group, but I'll bet most programmers can see themselves sliding over to one side or the other--or maybe they're a career developer at work but a passionate technologist at home.

Now before you fire up that email to me, let me be clear that I'm only contrasting two extremes. In no way do I want to insinuate that career developers cannot also be passionate about what they do. There are many great programmers that are very happy in their niche, are able to see the big picture, and yet stay focused on a product. This is a very good thing.

If you're running a business that needs some dedicated product development over a long period of time, you probably want a career developer on your team. If you have short-term needs that don't fit easily into a predefined job description, or need to integrate two systems that don't talk the same language, or just bought a computer but don't know what to do with it, call a technologist, someone who has breadth of experience, likes exploring new areas, thinks outside the box, and is always ready to learn something new.

I have found myself in both camps at different periods of my life but am leaning more and more toward the broad technologist side. Not that I'm losing focus on software development, but after being involved with so many different types of businesses and seeing such a wide variety of needs and solutions, I find myself naturally seeing the broader scope of things--no longer is my only tool a hammer and every problem a nail.

For a long time, I was all about Pascal. First Turbo Pascal, then Borland Pascal for DOS, then Delphi. These tools were ahead of their time being incredibly productive and leading innovation in software development. But other products have closed the gap by adding similar features and sometimes new angles to crafting software. And as the web has become ubiquitous and platforms have diversified, no longer is Windows on every desktop. In fact, no longer is the "desktop" to be assumed for any software platform.

Delphi has had a hard time adjusting to this and has adopted a technology to enable it to cross over into the iOS and Android platforms (it's had web support for a long time), but it's no longer the obvious advantage--unless all you know is Delphi. That's where being someone not encumbered by the history and culture of a business or a certain technology can be exactly what that business needs to innovate and stay relevant in a constantly changing technological world.

If you've been reading my blogs the last couple of years, it's obvious I've made an effort to move outside of the "Delphi box" by learning .NET, Android, and JavaScript. I've done quite a bit of HTML and PHP in the past, but have been updating those skills by adding CSS and HTML5 features. There are many other languages and technologies out there--and I hope to have time to tackle some of them. Alas, I'm not independently wealthy so must continue in some focused areas

Being a passionate technologist--whether focused or broad-minded--takes a lot of time and effort. But it's not possible to maintain the momentum without an underlying desire for learning and embracing new ideas. And being at least part geek!

Categories: Developer Blogs

Career Developers and Passionate Technologists

Tue, 2015-08-11 13:57

Programmers can be grouped into two broad categories: 1) Career Developers, and 2) Passionate Technologists. Career Developers will pick a language and a job and be very good at what they do, produce excellent work for their employer, and live happily ever after. Passionate Technologists will be constantly seeking different ways of doing things, learn a new language every year, keep old computer parts and reuse them in strange projects around the house, continually tinker with electronic gadgets of all sorts, and be considered the geekiest person around by all their friends and family. OK, perhaps that’s a bit of an exaggeration and there can certainly be overlapping traits found in either group, but I’ll bet most programmers can see themselves sliding over to one side or the other–or maybe they’re a career developer at work but a passionate technologist at home.

Now before you fire up that email to me, let me be clear that I’m only contrasting two extremes. In no way do I want to insinuate that career developers cannot also be passionate about what they do. There are many great programmers that are very happy in their niche, are able to see the big picture, and yet stay focused on a product. This is a very good thing.

If you’re running a business that needs some dedicated product development over a long period of time, you probably want a career developer on your team. If you have short-term needs that don’t fit easily into a predefined job description, or need to integrate two systems that don’t talk the same language, or just bought a computer but don’t know what to do with it, call a technologist, someone who has breadth of experience, likes exploring new areas, thinks outside the box, and is always ready to learn something new.

I have found myself in both camps at different periods of my life but am leaning more and more toward the broad technologist side. Not that I’m losing focus on software development, but after being involved with so many different types of businesses and seeing such a wide variety of needs and solutions, I find myself naturally seeing the broader scope of things–no longer is my only tool a hammer and every problem a nail.

For a long time, I was all about Pascal. First Turbo Pascal, then Borland Pascal for DOS, then Delphi. These tools were ahead of their time being incredibly productive and leading innovation in software development. But other products have closed the gap by adding similar features and sometimes new angles to crafting software. And as the web has become ubiquitous and platforms have diversified, no longer is Windows on every desktop. In fact, no longer is the “desktop” to be assumed for any software platform.

Delphi has had a hard time adjusting to this and has adopted a technology to enable it to cross over into the iOS and Android platforms (it’s had web support for a long time), but it’s no longer the obvious advantage–unless all you know is Delphi. That’s where being someone not encumbered by the history and culture of a business or a certain technology can be exactly what that business needs to innovate and stay relevant in a constantly changing technological world.

If you’ve been reading my blogs the last couple of years, it’s obvious I’ve made an effort to move outside of the “Delphi box” by learning .NET, Android, and JavaScript. I’ve done quite a bit of HTML and PHP in the past, but have been updating those skills by adding CSS and HTML5 features. There are many other languages and technologies out there–and I hope to have time to tackle some of them. Alas, I’m not independently wealthy so must continue in some focused areas

Being a passionate technologist–whether focused or broad-minded–takes a lot of time and effort. But it’s not possible to maintain the momentum without an underlying desire for learning and embracing new ideas. And being at least part geek!

Categories: Developer Blogs

Linux, Lazarus, and Lots of scripting

Tue, 2015-06-09 16:58
Category: ProgrammingCloud ComputingLinux

A friend of mine runs a business selling a Windows application for a niche market. Of course he has a web site with lots of information and a way to download a trial of his software and then pay and register it. Since he's a technical person, likes writing code, likes to keep overhead low, and his needs are fairly simple, he wrote the registration program himself. He's most fluent in Delphi so it was natural to write the registration program in Delphi&dash;&dash;an old, but very functional version of Delphi, Delphi 2007.

So naturally he needed a Windows server and after a little research, decided it wouldn't be that hard to host it himself out of his house. With a static IP address and stable power source, he's had this setup for quite some time with very little trouble.

Well, since he already has a static address and server running, why not host his own web site as well? That's running under Linux. No problem, just add a second server and redirect the ports. (I actually don't know which came first, the web server or the registration server.)

With the business running well and support calls low, he and his wife want to do some traveling. An extended weekend isn't any problem. A week away with someone looking after the place is doable. But what if a server goes down? Will anyone else be able to get it back up? What is the cost of potentially losing a customer because they can't find the web site or register the software?

These questions have been eating at him for a while and he finally decided to move them to a remotely hosted server. But since neither his web site nor his registration program are that heavily used, it would be a waste of resources and money to rent two servers&dash;&dash;he should combine them into one. The web site needs to stay on Linux. The registration program, even though it's in Delphi, could be re-written to work under Linux using Free Pascal. And using Lazarus as the IDE, the environment would be familiar. Finally, the Firebird database has no problem moving across platforms.

After looking at several options for remotely hosted virtual servers, it was clear the new Linux server would be running CentOS. Moving the web site over was not going to be difficult, but setting up the database and development environment would take some research. Not being very familiar with commands on Linux, he asked if I could help. Together, we got a virtual machine running CentOS and started the process of figuring out everything needed to get things going.

The first thing installed was the Firebird database engine and TurboBird, a Linux-based database tool that allows manipulation and querying of Firebird databases. We soon ran into problems and so downloaded Lazarus and the source for TurboBird to compile it thinking it may be something specific to our install. This is where the fun began!

I don't remember all the problems we had, but there were missing links to libraries, indications of insufficient permissions, and other error messages, leaving us scratching our heads and wondering if we had bitten off more than we could chew. I told him I'd go into hiding for a couple of days and figure out what was wrong.

What I found is that we were using a 64-bit version of Linux and trying to get a 32-bit version of Firebird and TurboBird working. I've should've known to check this near the beginning of the process as I've run into this type of problem in the past trying to get Windows applications to talk to Oracle databases using the wrong driver, but this is a different OS with different software producing different errors&dash;&dash;it totally escaped me.

There were other little odd things here and there that needed tidying up. For example, the version of Firebird he is using with his application is a couple of versions behind the current one and it requires an older version of a standard C++ library that is not included by default on the latest CentOS. The service manager, xinetd, needed to be installed and started. And a link to the specific Firebird library needed to be made. These would not be issues on Windows platforms, so it was easy to get tripped up multiple times.

But the thing I love about Linux is that you can run a command line to accomplish just about anything. When I emerged from hiding after a couple of days, I had a bash script that uninstalled the wrong versions of the software, downloaded and installed the right versions, installed git, and downloaded the project I had started. All he had to do was type in a couple of passwords, load the project into the Lazarus IDE, and compile it.

When it was all done, it was very satisfying to run the script and watch the magic happen!

Categories: Developer Blogs

Linux, Lazarus, and Lots of scripting

Tue, 2015-06-09 16:58

A friend of mine runs a business selling a Windows application for a niche market. Of course he has a web site with lots of information and a way to download a trial of his software and then pay and register it. Since he’s a technical person, likes writing code, likes to keep overhead low, and his needs are fairly simple, he wrote the registration program himself. He’s most fluent in Delphi so it was natural to write the registration program in Delphi‐‐an old, but very functional version of Delphi, Delphi 2007.

So naturally he needed a Windows server and after a little research, decided it wouldn’t be that hard to host it himself out of his house. With a static IP address and stable power source, he’s had this setup for quite some time with very little trouble.

Well, since he already has a static address and server running, why not host his own web site as well? That’s running under Linux. No problem, just add a second server and redirect the ports. (I actually don’t know which came first, the web server or the registration server.)

With the business running well and support calls low, he and his wife want to do some traveling. An extended weekend isn’t any problem. A week away with someone looking after the place is doable. But what if a server goes down? Will anyone else be able to get it back up? What is the cost of potentially losing a customer because they can’t find the web site or register the software?

These questions have been eating at him for a while and he finally decided to move them to a remotely hosted server. But since neither his web site nor his registration program are that heavily used, it would be a waste of resources and money to rent two servers‐‐he should combine them into one. The web site needs to stay on Linux. The registration program, even though it’s in Delphi, could be re-written to work under Linux using Free Pascal. And using Lazarus as the IDE, the environment would be familiar. Finally, the Firebird database has no problem moving across platforms.

After looking at several options for remotely hosted virtual servers, it was clear the new Linux server would be running CentOS. Moving the web site over was not going to be difficult, but setting up the database and development environment would take some research. Not being very familiar with commands on Linux, he asked if I could help. Together, we got a virtual machine running CentOS and started the process of figuring out everything needed to get things going.

The first thing installed was the Firebird database engine and TurboBird, a Linux-based database tool that allows manipulation and querying of Firebird databases. We soon ran into problems and so downloaded Lazarus and the source for TurboBird to compile it thinking it may be something specific to our install. This is where the fun began!

I don’t remember all the problems we had, but there were missing links to libraries, indications of insufficient permissions, and other error messages, leaving us scratching our heads and wondering if we had bitten off more than we could chew. I told him I’d go into hiding for a couple of days and figure out what was wrong.

What I found is that we were using a 64-bit version of Linux and trying to get a 32-bit version of Firebird and TurboBird working. I’ve should’ve known to check this near the beginning of the process as I’ve run into this type of problem in the past trying to get Windows applications to talk to Oracle databases using the wrong driver, but this is a different OS with different software producing different errors‐‐it totally escaped me.

There were other little odd things here and there that needed tidying up. For example, the version of Firebird he is using with his application is a couple of versions behind the current one and it requires an older version of a standard C++ library that is not included by default on the latest CentOS. The service manager, xinetd, needed to be installed and started. And a link to the specific Firebird library needed to be made. These would not be issues on Windows platforms, so it was easy to get tripped up multiple times.

But the thing I love about Linux is that you can run a command line to accomplish just about anything. When I emerged from hiding after a couple of days, I had a bash script that uninstalled the wrong versions of the software, downloaded and installed the right versions, installed git, and downloaded the project I had started. All he had to do was type in a couple of passwords, load the project into the Lazarus IDE, and compile it.

When it was all done, it was very satisfying to run the script and watch the magic happen!

Categories: Developer Blogs

Windows Services with Oxygene

Fri, 2015-06-05 17:11
Category: Programming

Some of my blog entries are just to remind myself how to do things later--and on several occasions they've been useful in that regard. I hope they are also useful to others that may encounter similar struggles. This is another one of those articles which I will likely refer back to at some point.

I've been doing more and more with .NET and using Oxygene makes the transition from Delphi a little more familiar. One of the things I've been working on lately is a set of plug-ins to a Delphi application that provide additional functionality. And with Hydra, I can write those plug-ins in either Delphi or Oxygene. Recently, I wanted one of my plug-ins to talk to a service on a remote server. The first step, of course, is to write the service for the remote server and learn how to get it installed.

Because Microsoft Visual Studio Community 2013 has such a large developer base, there are many resources to help you accomplish this (that's the beauty of working in .NET rather than Delphi). But just a few nuances here and there for someone that doesn't do this very often slowed me down a little. Finding just the right web reference or book chapter takes time, so once I find that, I tend to want to write it down.

New Project

First of all, Visual Studio makes it pretty simple to get started: just select the "Windows Service" new project template.

This gives you a project to start with that includes Main.pas, the main section of the code you'll be working with, Program.pas, which you can likely ignore but is necessary, and ProjectInstaller.pas.

Add Installer

The first thing to do is right-click on Main and View Designer. Look in the Properties window and click on Add Installer, a small link at the bottom. This adds a couple of components to the ProjectInstaller and allows you to easily name and describe your service.

Service Properties

Now in the ProjectInstaller designer view, click on the serviceInstaller component and set the DisplayName and Description properties. These will show up in the Services control panel after it's installed. Here's also where you can set the StartType (Manual, Automatic, or Disabled) and other properties affecting how the service behaves with Windows. If you then view the code for ProjectInstaller.Designer.pas, you'll see the properties you set listed in the InitializeComponent method.

Before you leave the ProjectInstaller, you need to check one more thing. Look at the properties for the other component in designer mode, serviceProcessInstaller. An important property is Account. By default, it's set to User, but in most cases it can be either LocalService or LocalSystem. I'll leave it to the reader to research the differences and choose what is most appropriate for your situation. For this simple test, setting it to LocalService is easiest.

Event Logging

Since a service does not typically interact with users but runs silently in the background, it's a good idea to provide some way to check to make sure it is running. There is an automatic way of doing this and all it takes is one line in the constructor of Main.pas: AutoLog := true;. This will add to the System Event Log when the service is started, stopped, paused, or resumed. You can add your own custom logging by using the EventLog component on by rolling your own.

Now even though this service doesn't do anything useful, it's got the basics to be compiled, run, installed, and started with logging to see it actually happen. So compile the project and move to the final step.

Install the Service

When a service is ready to install, use the command-line utility InstallUtil. This utility comes with the .NET framework. Normally, there is no path to the .NET framework tools, but both Visual Studio and Oxygene provide command shells you can launch that provide the path. However, you need to know which version of the .NET framework you used to build your project because the shells are specific to the version of the framework and if you run the wrong one, you'll get errors. Oxygene comes with one for .NET 2.0 but the default framework for new projects (as of this writing) is .NET 4.0. I have copied the batch file that is installed with Oxygene (C:\Program Files (x86)\RemObjects Software\Oxygene\bin\OxygenePrompt.bat) and separated them so I now have one for each of the two framework versions. (By the way, to tell which version your project is using, view the Application tab of the project's properties and you'll see it under Target Framework.) Once you have the correct command shell ready, be sure to Run as Administrator because standard users cannot install/uninstall Windows services.

With the command shell running as administrator, navigate to the bin\Release folder for your service and type InstallUtil MyServiceName.exe (where "MyServiceName" is the name of your project). Open the Services control panel (or refresh if it was already open) and you should see your new service. You can start or stop it just like other services (although if you've followed this example, it doesn't yet do anything once started).

Start/Stop, Check the Log

Now that the service is built and installed, start the service then go to the Windows Event Viewer. You should see events in both the Application and System sections of the Windows Logs.

Now, it's time to go back to Main.pas and add some useful code when it starts!

Categories: Developer Blogs

Pages