Fix for endless registration loop with Delphi 2006

With the acquisition, our login accounts are being migrated to a new domain.  We are doing this in multiple parts, with the first part changing our existing domain logins from using our last name plus first initial (millerc) to what is referred as the User Principal Name (basically our email addresses).  Of course, when I say “we”, I refer to our IT manager.  I’m just along for the ride and to make witty comments when it breaks.  That part went smoothly, the second step occurred last Sunday night when said IT Manager changed our logins (pre Windows 2000 format) from last name plus first initial to last name “.” first name (chris.miller).

When we logged in this morning and started up Borland Developer Studio 2006 (aka Delphi 2006), something broke.  We would get errors like

The license manager reported the following error:

License storage c:\documents and settings\millerc\.borland\borlands.lic does not apply to current user or host machine.

Please register your Borland products(s).(7006).

Do you want to run the registration wizard?


Fatal error validating license for Borland Developer Studio 2006

The license manager reported the following error:

Missing activation file.  Please register again. (7029).

Do you want to run the registration wizard?

Just what I wanted to see first thing on a Monday morning.  Thank you, sir. May I have another?

Each time we would run the registration wizard, we would go through all of the steps to register Delphi and it would report that it was successfully registered.  After closing the wizard, we would get the same error message again.  Not a good sign.

I ran the registration wizard one more time and selected register by phone and called the number for US support.  The support representative was friendly but had no clue for what was happening.  The only thing she could was to open a support case.  I tried a few more times after completing the call and found out that you could only register 10 times, after that your registration code has been used up.  I was somewhat less than thrilled when I found that little gem.

After four hours had passed, I decided to call that support number again.  The support representative that answered this time was much more helpful.  He immediately contacted a support engineer, who knew what the problem was and referred to it as “an endless registration loop”.  They emailed me a list of instructions and I was able to get Delphi 2006 up and running again.  He also updated my account to accept two more registrations.

The funny part for me was that I had migrated all of my projects to Delphi 2007, which was not affected by the change in user id’s.  I jumped in to help out the other developement team, who were still on Delphi 2006. 

The following is a slightly edited version of the steps that CodeGear support had sent to me.

Sometimes the registration information on a machine can become corrupted and cause an endless registration loop. This also happens when the user login name is changed or if a machine is changed to log in to a Domain. The following steps should help to resolve the problem.

WARNING: These step will remove registration information for other Borland IDE products as well.

  1. Close down Delphi and the Registration Wizard if they are running
  2. Browse to the .borland directory in your user home directory. For Windows 2000 and XP this will be located at c:\documents and Settings\\.borland
  3. Open the file registry.dat and copy the SerialNumber and AuthorizationKey values stored under “[Delphi 2006]”, this save you the step of trying to remember where you had stored that information. Also make a note of either the UserName or EmailAddress values stored under “user”. You will need these values when you register Delphi.
  4. Delete the borland.lic and registry.dat files in the .borland directory. You may also want to move those files to another location that is not on the path
  5. Remove the . directories from your User Home (directory name will start with a . and contain 6 or 7 random numbers and letters)
  6. Remove the ..slip files from your User Home file name will start with a . and contain 6 or 7 random numbers followed by .slip)
  7. Remove any activation files that you saved in your User Home. These will by default be in the format of reg*.txt
  8. Launch BDS 2006 which will activate the Registration Wizard.
  9. Cancel completely out of the Registration Wizard (This is an important step and will write new correct default information to your User Home).
  10. Launch BDS 2006 a second time and this time register the product when the Registration Wizard comes up.
  11. If you ran the registration wizard too many times, your serial number will get locked out. You are limited to 10 installations. If you exceed this count, you will need to call CodeGear (800-523-7070 for the US) and asked for that count to be raised. They can raise the count limit by two each time that you request it.

This worked for me, but the usual YMMV caveats apply.  I added steps 3 and 11.  Once you delete the registry.dat file, you will have deleted the cached copy of your serial number and authorization key.  By making a copy of them, it becomes one less this to have to lookup.  If you already have Delphi 2007 or RAD Studio 2007 installed, these steps will not affect them.

Resizing the “Bookmark this page” dialog in Firefox 3

I like using the new Firefox 3, but there is a little thing that annoys me.   When you go to bookmark a page, you get the “Bookmark this page” dialog.  Inside that dialog, there is a folder tree that will display your bookmark folders.  Out of the box, you can only see a little more than handful of folders at time, you have to scroll around to find the folder to use.  If you are as hierarchal-retentive as I am, you can have lots of folders, some nested pretty deep.  I know about the new tags functionality, but I still like to file my bookmarks like a squirrel with his acorns.

The “Bookmark this page” (and the “Page Bookmarked”) dialog isn’t doesn’t have the resize widgets.  You can’t just drag an edge or a corner and resize it with a mouse.  For some reason, it’s size is fixed.  Unless you want to go under the hood and tweak the UI a bit.

There is a file named userChrome.css in the chrome sub folder of the profile folder.  This file lets you override various GUI settings in the Mozilla product line.  It’s doesn’t exists by default, you have to put one in the chrome folder.  A file named userChrome-example.css should exist already in that folder.  All you need to do is to  copy that file to userChrome.css and you are ready to start.

I added the following CSS code to increase the size of the folder tree control that is located in the middle of the dialog.

min-width:400px !important;
min-height:600px !important;

After adding that definition and saving the file, you will need to restart FireFox.  This should work for Firefox 2, but I haven’t tested it there.  I found that little gem right here on the mozillaZine forum.  That will give you a much longer list when you open the folder tree.

A new user to Delphi reports on his annoyances

Branden Tanga posted a list of annoyances with Delphi on his blog.  While there are some legitimate complaints you can make about Delphi (the borked help system), his complaints largely stem from being unfamiliar with the IDE. I’m going to paraphrase his complaints to just list the gist of complaint and my responses.  Other people have commented on his complaints, but I did want to note that his first one has some value.

  • “Can’t indent a block of text”  You can indent by pressing Shift+CTRL+i and unindent with Shift+Ctrl+u.  You would never know by looking the IDE.  Those actions could have been listed on the “Edit” menu.  I searched the help and could not find it.  If you are new to Delphi, there is no way you would have know how to do this with asking someone.  I had to go back the Delphi 7 help system and search on “Block commands”.  I hope that Nick Hodges is following this.  And there is a free plugin named DDevExtensions that (among other things) will give you the ability to use the Tab/Shift+Tab for indent/unindent.
  • “Weird bug where RAD will crash”  Hmm, can’t say much without knowing what he was trying to do at the time.  The obvious question is did he have all of the updates and hotfixes installed?
  • “If you launch your application from within RAD, it must be managed within RAD”  That’s because you are running it from within the debugger.  And you can stop it from the debugger.
  • “You have to pay 3rd parties for extra widgets. That makes absolutely no sense to me. Visual Studio and the Windows API provide me all the widgets I could want….Delphi developers like to make their own widgets and sell them to each other.”  That one made me stop and say “Huh?”  Out of the box, you get more components with Delphi than with VS.  Delphi has Project JEDI and their huge library of controls and other functionality.  There is nothing quite like that in the Microsoft ecosystem.   Is Branden aware of the huge market of 3rd party components for Visual Studio Telerik, DevExpress, Infragistics, etc)?  I just don’t see how he came up this complaint.
  • “There is no free version of CodeGear RAD”  Actually there is a version, it’s called Turbo Delphi.  It’s not the current version of Delphi (Delphi 2006 based), but it’s current enough to introduce you to the product.  I hope that the new owner of Delphi, Embarcadero, will release new versions of the Turbo line.  it’s fine line that they will need to walk.  Having the Turbo Editions allow people to get a taste for Delphi without having a large expense, but they don’t want to take away from sales of the full product.  it is a commercial product, sales revenues pay for the continued development of the tool.
  • “You can only write Delphi code using RAD, which costs money to own.”  That’s negated my previous comment about Turbo Delphi.  The whole idea of doing application development with Delphi is that it’s a RAD tool.  Why would you want to do app development with notepad anyway?
  • ”There are properties and objects that are COMPLETELY HIDDEN from the developer, and the only way to access them is through RAD’s wysiwyg editor.”  The visual properties and objects are stored in the .dfm files, which are text based.  If you embed graphics into a component, the image will be streamed as series of hex values, but you would get the same type of stream with images embedded in .NET components.

Out of all of those complaints, only the one with any value is the blocking indenting issue.  And that’s a help/documentation issue as Delphi has a full set of block commands, they just are not documented anymore.  I work in both VS 2008 and Delphi 2007, they both have their strengths and they both have their weaknesses.  I am curious about how much time Branden spent with Delphi before composing his list.

Understanding locking issues with multithreaded code

From Joe White’s blog, I came across a link to an interesting article about working with various locking models when writing multithreaded code.  It was written by Vance Morrison, the compiler architect for the .NET Runtime and it’s required reading for anyone doing multithreaded coding.  It was written a few years back, but is still relevant.  I’ve read it a couple of times and I still have not grokked all of it.

The article is written for the .NET Framework 2.0, but the concepts are applicable to anyone doing multithreaded code.  I agree with Joe’s assessment, if you don’t understand what Vince is talking about for any of the techniques described in the article, then don’t use that that technique.  Debugging thread interactions is not easy and using a debugger will change your program flow enough to make it difficult to catch thread conflicts.

What’s good with this article is that Vince goes down to the metal and explains how the multiprocessor machines changed the game with how threads access memory.  Memory access is no long serially consistent, each processor has multiple levels of cache memory and the processor will attempt to retrieve cached memory before checking system memory.  Know how that works and when cache memory is synchronized back to system memory is important and can be a factor in determining what type of locking mechanism to build into your threads.  This article describes situations where you can eliminate locks for locks for some types of threaded memory access.  Vince refers to these techniques as “Low-Lock”.

It is important to note that using Low-Lock will make your code fragile as you are much more dependant on on how the hardware will behave in terms of memory access.  They should only be used when the performance increase is absolutely required.   Vince has a related article called “Concurrency: What Every Dev Must Know About Multithreaded Apps” does a very good job of explaining how to use locks properly with multithreaded code.  He linked to that article in the lock lock article, but that link is broken.  Use this one instead.

Evans Data’s 2008 IDE User Satisfaction Survey

Evans Data has released their 2008 edition of their Integrated Development Environments User Satisfaction Survey.  They surveyed actual IDE users and asked them to rate the various features and capabilities.

The IDE’s that were ranked by the survey:

  • Adobe Macromedia Studio/ Creative Suite 3
  • CodeGear Delphi
  • IBM Rational Application Developer
  • Microsoft Visual Studio
  • MyEclipse
  • NetBeans
  • Oracle JDeveloper
  • Sun Studio

They were ranked based on the ratings for the following features:

  • Debugger
  • Editor
  • Make/Build Functions
  • Documentation
  • Application Modeling Tools
  • Web Design Tools
  • Sample Applications
  • Profiler
  • Compiler Performance
  • Performance of Resulting Applications
  • Ease of Use
  • Ability to Integrate 3rd Party Tools
  • Availability of 3rd Party Tools
  • Quality of Technical Support Options
  • Size and Quality of Developer Community

Delphi was rated 6th and Visual Studio was 3rd.  The survey is worth reading because despite Delphi’s mid-pack rating, it scored at the top or near the top for the following features:

  • Debugger
  • Editor
  • Compiler Performance
  • Performance of Resulting Applications
  • Ease of Use
  • Ability to Integrate 3rd Party Tools
  • Availability of 3rd Party Tools

It’s kind of an eclectic mix of IDE’s.  Half of the IDE’s are Java development, Adobe is all about the graphics and Flash development, Sun is C and C++ for their OS.  That leaves Visual Studio and Delphi for the Windows camp.  It does identify what we already know abut the weaknesses of Delphi.  Namely the documentation is still pretty bad.  Documentation has been a moving target for Delphi since Delphi 2006 has been released.  It’s been getting better, but still has a way to go.  I hope the new owner is willing to put in the resources to get it the documentation back up to the level it was at with Delphi 7.  As I noted earlier, the Delphi talent pool is shrinking and Embarcadero needs to decide soon where they want to take Delphi.

Thanks to Roland Beenhakker for posting about this survey on his blog.

Good help (Delphi programmers) is hard to find

I was just reading a post on Bart Roozendaal’s Sevensteps blog titled “Are Delphi programmersa dying breed?”.  The title pretty much sums up Bart’s point, it’s getting harder and harder hire programmers with Delphi experience.  It took a long time for us to find our last two Delphi hires.  Here in Albany, we never had a huge talent pool to pick from, and these days you just can’t find the Delphi talent.

Whenever I posted for open positions on the Borland jobs newsgroup, the only responses were from outsourcing companies.  That was something we just didn’t want to pursue.  The domain knowledge in getting up to speed with our products can be a little steep, we prefer to keep that knowledge in house and make a long term investment in our development staff.

So where did they all go?  At my last place of employment (nearly 9 years ago), I was on a team of 7 programmers, all using Delphi.  Right after I was hired, we bought by a company that had no use for Delphi and decided that we would be the Java team (minus the tools and the training).  To make a short story long, within 6 months the team all departed to other local companies.  Of that group, I’m the only one still using Delphi.  And I’m not even full time Delphi, it’s 50% Delphi and 50% C# (and the Delphi percentage is trending down).

For the other 6, two of them went the Java route, just not at that company.  Another went back to his AS/400 and DB2 roots, the rest bounced around with VB and ASP and eventually ended up in .NET.  I’m betting that’s happening to a lot of the Delphi programmers.  A lot of the work out there is for web based applications.  For that market, the Microsoft stack is much stronger than the web based development tools that Delphi provides.

This has to be hitting the companies that still do desktop applications with Delphi pretty hard.  I still think that Delphi is a better choice for desktop applications and services than .NET.  The problem is finding people that still want to work with Delphi.  We are fully staffed now, but it too a long time to get the last two.

Is anyone taking up Delphi anymore?  if you are a fresh new programmer, Delphi probably isn’t going to be something you will take up on your own.  I don’t know how Embarcadero is going to deal with this.  They just bought a powerful development tool in Delphi, but will they get people to take it up?  Without fresh blood coming in, the Delphi talent pool is going to continue to shrink.

Is there ever a good reason to “Google Bomb”?

I was just reading this article in Computer world about a political blogger, Chris Bowers, using a tactic called “Google Bombing” to raise the profile of some negative articles about Senator John McCain.  While I’m not likely to be considered a McCain supporter, I’m not a big fan of Google Bombing.

If you are not familiar with the term, “Google Bombing” is the practice of getting as many sites as you can to link to the same page or pages, using the same format for the links.  The intent is to raise the page rank of the links, so that they show up earlier in the Google search results.  For a more in-depth explanation and some historical context, please visit your local Wikipedia.

Basically this blogger is trying to game the system to promote his viewpoint.  if you have to stoop to tricks like that, that tells me that what you have to say is not strong enough to stand on it’s own.  Bowers isn’t the only one doing this, he’s just being the most vocal about doing it.  It wouldn’t surprise me to hear that both the Obama and McCain campaigns are doing some targeted “Google Bombing” of their own.

Is it really worth the effort?  If one or both the candidates were unknown, then “Google Bombing” would have some effect.  I think anyone is on the fence between the two isn’t going to make up his mind until after they debate a few times.

Getting past the political considerations, I just don’t see the long term value of add of messing around with how Google and other search engines index web pages.  Being able to find just anything I need on web instantly is a luxury I would not want to give up.  Using “Google Bombing” to mess with Google’s advance ranking technology has the tendency to turn valued search results into noise.  What would be considered an acceptable or desired reason to “Google Bomb”?

Adding SQL Server logins and user accounts for multiple databases in one pass

We have a few applications that include bits that are service applications.  These applications talk to SQL Server databases and they authenticate using SQL Server logins, as opposed to using Windows Authentication.  We recently changed the account that the services were using to a new account with a more robust password.  When the services are deployed, they will have an update mechanism that will add the new login account.  For internal testing, I wanted to give our testers the ability to add the server login and database user for all of their test databases in one shot.  I ended up with a script that looked like this:

   1: use [master]
   3: -- create server login if if does not already exist
   4: if not exists (SELECT 1 FROM sys.sql_logins where name = 'myservice') 
   5: create login myservice with password = 'wEEzPHUxce0xhzQFEeF8OHS2KqYYkxTA', Check_expiration = OFF
   7: -- Create a cusror that will let us iterate through a list of user 
   8: -- created databases, skipping over the system databases
   9: declare c cursor fast_forward for 
  10:   select name 
  11:   from master.dbo.sysdatabases 
  12:   where name not in ('master', 'tempdb', 'pubs', 'model', 'msdb')
  14: declare @name varchar(128)
  15: declare @sql varchar(800)
  17: open c
  19: fetch next from c into @name
  21: while @@fetch_status = 0
  22: begin
  23:   print @name -- display the name of the database
  25:   -- Drop the user and schema. this may need to be augmented depedning how you define your roles
  26:   select @sql = 'use ['+@name+'];if exists (select 1 from information_schema.tables where Table_name in (''SomeTableUniqueToMyApp'', ''AnotherTableUniqueToMyApp'')) if exists (select 1 from sys.database_principals where name = ''myservice'') begin IF EXISTS (SELECT 1 FROM sys.schemas WHERE name = ''myservice'') begin DROP SCHEMA myservice end drop user myservice end'
  27:   execute (@sql)
  29:   -- Add the user
  30:   select @sql = 'use ['+@name+'];if exists (select 1 from information_schema.tables where Table_name in (''SomeTableUniqueToMyApp'', ''AnotherTableUniqueToMyApp'')) if not exists (select 1 from sys.database_principals where name = ''myservice'') create user myservice for login myservice'
  31:   execute (@sql)
  33:   -- Define the user's role  
  34:   select @sql = 'use ['+@name+'];if exists (select 1 from sys.database_principals where name = ''myservice'') execute sp_addrolemember db_owner, myservice'
  35:   execute (@sql)
  37:   fetch next from c into @name
  38: end
  40: close c
  42: deallocate c

This script starts off in the master database and will require admin access rights to the server.  If we break down the script, we can review what each section does and why it’s doing it

Lines 4-5 will create the login if it does not already exist.  The Check_Expiration option is set to “OFF” to verify that password expiration policy will not be applied to this login account.  The BOL for SQL Server 2005 states that this option defaults to “OFF”, but I like to explicitly set that option for a couple of reasons.  One reason is that it stands out when you read the script.  Another reason would be that a future service pack or later version of SQL Server could default that setting to on.

Lines 9-12 create a cursor that provides a list of databases.  We skip over the system tables to save some processing.

Lines 17-22, 37-42 handle the mechanics of opening up the cursor and iterating through each row in the set of database names.

Lines 26-27 create a dynamic SQL statement that performs the following steps and then executes that statement:

  1. Change the database context to the current database that was located by the cursor
  2. Uses the information_schema.tables view to use this database only if contains two tables that are known to exist in my application database.  This will prevent the user from being added to the wrong database.
  3. If this user has a schema, drop the schema.
  4. Drop the user from the database.
  5. Execute the dynamically created SQL statement.

Lines 30-31 create a dynamic SQL statement that performs the following steps and then executes that statement:

  1. Change the database context to the current database that was located by the cursor
  2. Uses the information_schema.tables view to use this database only if contains two tables that are known to exist in my application database.  This will prevent the user from being added to the wrong database.
  3. Create the user and map that user to the login account created at line 4
  4. Execute the dynamically created SQL statement.

Lines 34-35 create a dynamic SQL statement that performs the following steps and then executes that statement:

  1. Change the database context to the current database that was located by the cursor
  2. Uses the information_schema.tables view to use this database only if contains two tables that are known to exist in my application database.  This will prevent the user from being added to the wrong database.
  3. Adds the user to the db_owner role.  Your application may need fewer rights for the user.
  4. Execute the dynamically created SQL statement.

We do give our customers the ability to run with just Windows Authentication, but configuring services to run under domain accounts is an additional set of steps that most of our customers prefer not to use.  It’s a much simpler OOBE if the services use SQL Server authentication.

Sign the "danah boyd proper case" petition

Jeff Atwood is on a righteous crusade against those who insist on using only lower case for their names.  He has a petition and he wants you to sign it.  It’s all in good fun, but it raises a subtle point.  There are times where you have to import data from one application to another and you may need to change the case of text coming.  You could data coming out of an old system written in COBOL, where everything was uppercase and the people using the data wants the text changed to mixed case.

Going from all upper case to mixed case is an approximation.  You are filling in details (the case of each letter), where that information did not exist before.  You can make a close approximation by assuming certain rules.  Like states are always start with the first letter of each word capitalized.  And the same goes for proper names.  The people who deviate from the rules of grammar just have to live in world where we prefer to use the proper case.

Getting back to the petition, how do you deal with people who want to use their own capitalization rules?  The bigger question is should your application even enforce the proper case?   I think you should let people type in their names in the format that they want.  If they wanted to go through life with the Caps Lock key on, that’s their prerogative.