Monday, June 30, 2008

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?



or



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\<username>\.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 .<Random#A> directories from your User Home (directory name will start with a . and contain 6 or 7 random numbers and letters)


  6. Remove the .<Random#>.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.

Friday, June 27, 2008

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.

/*
* FF3.0, FORCE BIGGER DISPLAY OF FOLDER TREE WITHIN 'BOOKMARK THIS PAGE' POP-UP
*/
#editBMPanel_folderTree
{
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.

Thursday, June 26, 2008

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.

Tuesday, June 24, 2008

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.

Monday, June 23, 2008

I really want a Dalek surveillance cam for my office

I saw this linked to on Boing Boing, a remote control Dalek toy outfitted with a pinhole security camera with wireless transmitter. It will transmit decent quality video up to 100m.

It’s not cheap, but the really cool toys never are. 

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"?

Friday, June 20, 2008

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]


   2:  


   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


   6:  


   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')


  13:  


  14: declare @name varchar(128)


  15: declare @sql varchar(800)


  16:  


  17: open c


  18:  


  19: fetch next from c into @name


  20:  


  21: while @@fetch_status = 0


  22: begin


  23:   print @name -- display the name of the database


  24:  


  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)


  28:   


  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)


  32:  


  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)


  36:   


  37:   fetch next from c into @name


  38: end


  39:  


  40: close c


  41:  


  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.

Wednesday, June 18, 2008

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.

Tuesday, June 17, 2008

Migrating Delphi versions with DevExpress

I usually run on the latest version of Delphi while the other Delphi developers in our department run a version or two back.  I’m the pretty much the sole Delphi developer on our .NET projects and I switch between VS 2008 and Delphi 2007 as needed.  The core Delphi team is on Delphi 2006 because of how our product development and testing cycles work.  We don’t switch compiler versions without coordinating with our QA department.

The core team is moving up to Delphi 2007 later this year for the next release cycle.  The current version of the product will stay in Delphi 2006 and the versions of the 3rd party components will be locked.  While development on the next release goes on, we may need to release updates to the current version.  So we lock the 3rd party components so that QA only needs to test the code specific to the update, plus general regression across the application.

With some component vendors, this makes upgrading more challenging.  We use the Developer Express components for Delphi Win32 and for .NET.  DevExpress has wonderful components, but they use monolithic installers that install everything for each compiler per platform.  If I install the latest version of the DevExpress components for Delphi 2007, I’m also going to get the latest version for Delphi 2006.  You can’t install them separately, not without seriously confusing their installer.  Installer technology is scary enough, the last thing you want to is mess areound with the installer.  I wanted something robust, hand tweaking my system to manipulate the installer would be to fragile to have an entire team try it.

After a few emails with DevExpress support, I came with another method.  I wrote a Delphi app that would manually downgrade a DevExpress install for a specific compiler.  You would run this app after running the DevExpress installer and it would rip out the DevExpress current installed bits and replace them with a cached copy of the version that we need to stay at.  It does the following steps:

  1. Check to see if Delphi 2006 is running and stop with a warning message if it’s running.  Here’s how to check to see if Delphi 2006 is running:
    function IsDephi2006Running: boolean;
    var
    handler: THandle;
    data: TProcessEntry32;
    Delphi2006IsRunning: boolean;
    function GetName: string;
    var
    i: byte;
    s: string;
    begin
    result := '';
    i := 0;
    while data.szExeFile[i] <> '' do begin
    result := result + data.szExeFile[i];

    if uppercase(result) = 'BDS.EXE' then begin
    s := uppercase(ProcessFileName(data.th32ProcessID));

    Delphi2006IsRunning := pos('BDS\4.0\BIN\BDS.EXE', s) > 0;
    end;
    inc(i);
    end;
    end;
    begin
    Delphi2006IsRunning := false;
    handler := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);

    if Process32First(handler, data) then begin
    GetName();
    while Process32Next(handler, data) do begin
    if Delphi2006IsRunning then
    break;
    GetName();
    end;
    end;

    result := Delphi2006IsRunning;
    end;




  2. See if the Package Cache key, HKEY_CURRENT_USER\Software\Borland\BDS\4.0\Package Cache, exists in the registry.  If it does rename it.


  3. Deregister the DevExpress components from the IDE. 
    In Delphi 2006, the component packages are registered in HKEY_CURRENT_USER\Software\Borland\BDS\4.0\Known Packages.  The rollback program has a list of list of every DevExpress 5 and 6 package.  My code rips them all out. Before they are removed, their location is cached as this is the folder where the compiled library files are located.  For Delphi 2006, this defaults to “C:\Program Files\Developer Express.VCL\Library\Delphi10”.


  4. Using the location the library folder for the DevExpress compiled units, we delete all of the files in that folder.  If you want to be extra cautious, you could just rename that folder and create a new one with the original name.


  5. Copy the cached copy of the rollback version of the DevExpress compiled units to the library folder.  I keep a clean copy of the library folder in a protected location on our network.  If you need to rollback your DevExpress components, you’ll want to cache those fiels before doing anything else.  You will also need to cache the list of packages to install.


  6. Register the rollback packages into the Known Packages key used in step 3.


  7. Copy the runtime packages to the bin folder.  You can get the location of the bin folder by reading the value of RootDir in HKEY_CURRENT_USER\Software\Borland\BDS\4.0.  I keep a cached set of the runtime packages in the same folder that I keep the cached library files.



This process goes on the assumption that the DevExpress source code is not your Delphi search paths.  We typically leave the source code of the 3rd party components off the search path and just use the compiled units.  You get a faster compile and you don’t have to see other vendors compiler hint and warning messages.  If you want the source code on the search path, the you will need to cache all of the source code files.  At that point, it would be easier to cache the entire “\Program Files\Developer Express.VCL” folder.  And that’s how we upgrade selcted portions of our development environment.

Proof by lack of evidence

CNET’s Matt Asay wrote an article for CNET’s News.com that was just so bad, it gets the “Epic Failtag.  You can get the gist of how bad it is by the first few lines:

Vista's big problem: 92 percent of developers ignoring it

And to think Microsoft used to be popular with the developer crowd...

Not anymore. A recent report from Evans Data shows fewer than one in 10 software developers writing applications for Windows Vista this year. Eight percent. This is perhaps made even worse by the corresponding data that shows 49 percent of developers writing applications for Windows XP.

Wow, I’m not sure where to start on this one.  I started by visiting the Evans Data web site that Asay refered via this link.  It was vague and provide no actual metrics.  How that “one in 10” number was arrived that was never specified.  Sounds pretty bogus to me.

What they did say was this:

Only eight percent of North American software developers are currently writing applications to run on Microsoft's Vista operating system, while half are still writing programs for XP, according to Evans Data's Spring 2008, North American Development Survey. These same developers forecast a fragmented Windows market in 2009 with only 24 percent expecting to target Vista and 29% expecting to continue with XP.

8% of what?  Is that 8% of all developers writing for the Windows Desktop or is 8% of all North American software developers.  The former is a subset of the latter.  Did they exclude web developers from that count?

The other question is what do they mean by writing for Vista?  Does that mean writing for features specific to the Vista platform or does it mean writing the code so that it behaves under Vista?  Did they break that out by managed code as compared to unmanaged code?  If you are writing managed code like for the .NET Framework or Java, then you are not targeting an OS, you target the managed code framework.

Since Matt conveniently left out any actual numbers, I can use myself as a sample set.  A sample size of 1 is just as relevant and/or meaningless as an undefined sample size. I write shrink-wrapped applications for the Windows desktop market.  I do both Win32 coding (with Delphi 2007) and for the .NET Framework (with Visual Studio 2008).  All of my code is tested on XP, Vista, Server 2003, and Server 2008. 

With the .NET Framework, I have no code that is OS specific and I didn’t have to change any of it for Vista or Server 2008.  For the Delphi code, some minor changes were made to account for the location of the local application data folder.  That was all we had to do.  It’s something like 5 lines of Delphi code out 500,000+.  Of course by using Delphi 2007, we get the benefit of the Delphi VCL being Vista aware.  We get the Aero Glass effects and the new UI for dialogs without any code changes.

Does that mean we are not targeting Vista?  No, it just means for our applications, that Windows XP and every OS that comes after it is tested and supported.  That leads back to the critical failure point of Matt Asay’s article.  He’s making broad assumptions based on no evidence.  I’m reminded of that old quote by Leonard H. Courtney, “There are three kinds of lies: lies, damned lies, and statistics.”

I don’t usually read news.com anymore, in fact I came across Matt Asay’s article in a blog post by Steve Trefethen.  So I’m not familiar with Matt Asay’s body of work.  I don’t know if he wrote this out of ignorance out or as Steve put it: “written for no other reason than to generate traffic for c|net.”  I would like to know how much actual research Matt performed for his article.

The title of this post comes from the “You Are Wrong Because” portion of Scott Adams book, “The Joy of Work: Dilbert's Guide to Finding Happiness at the Expense of Your Co-Workers”.  The context was that Adams has stated that irrational people are easily persuaded by anything that has been published.  I think that’s applicable with with Matt Asay’s article.

{updated on 6/23/08]
I removed the link to Matt Asay’s article because I didn’t want to give him any more traffic.  It’s not that there would be a lot coming from my blog, it’s more of a principle thing.  I had originally included a link so that people could make up their own mind, but I think I have enough of his article to make my point.  And if you really want to read it, you know where to find it.

Monday, June 16, 2008

What’s the deal with the idiots wearing Bluetooth earpieces at a dance recital?

On the Saturday that just passed, our family was at the Palace Theatre for our daughters dance recital.  They had a lot of fun and really enjoyed their time performing on stage.  One thing that annoyed me were the people who insisted on wearing their Bluetooth headsets during the performance.  With the lights lowered, the blue lights blinking were a major distraction.

Don’t these people know that they look like dorks wearing their blue light idiot badges in a performance hall?  You wouldn’t answer the phone (well, you shouldn’t) at a dance recital, that would be rude and disrespectful to the performers and their family and friends.  One of the mothers in my younger daughter’s class was wearing one.  I kept thinking, “Are you out of your mind?”.  I had to stand near her because all of the girls had rows assigned to their classes.  Out of the corner of my eye, I kept seeing this blue light blinking and it was very distracting.

Blue LEDs are brighter than other colors and in a dark room, they will draw your attention.  Our brains are wired that way.  In my home office, my PC’s case has a couple of blue LED’s and they light up the room.  No need for night lights in my office.  Between the brightness and how our eyes perceive the color blue, bright blue LEDs can cause eye strain.

I have a Bluetooth headpiece, but I only use it in the car.  I don’t have anything against Bluetooth technology, but there is a time and place for everything.  And a dance recital is neither the time nor the place.  Think about it for a minute, it’s not practical to use a Bluetooth earpiece in performance hall.  If someone calls you, you wouldn’t want to take the call in your seat, you would walk out to the lobby to take the call.  You would be better off just to set the phone to vibrate and keep it in your pocket.

Unless they are wearing the earpiece as a fashion accessory.  “Hey, look at me!  I have a device embedded in my ear advertising my dorkness every two seconds”.  Come on, if you want to carry a techno device to look cool, you’re 4 years too late with Bluetooth.  If that’s what you want, then get an iPhone, it’s new enough to make you look cool. 

As a side note, a few weeks ago I saw some guy with Bluetooth earpieces in both ears.  We called it “Double-dorking”.

Sunday, June 15, 2008

Tim Russert, 1950-2008

I was shocked to hear about the passing of Tim Russert.  I always enjoyed watching "Meet the Press" and I should have watched it more.  I've been kicking myself forgetting to TiVo this morning's show.  On this morning's "Meet The Press", Tom Brokaw hosted a tribute to Tim Russert.  Fortunately, the show is available on the MSNBC site, and I'm grateful for that.  I don't know know it will be available, but the following link should work right now.

 

If you want to view a larger version, even fullscreen, try the following: http://www.msnbc.msn.com/id/21134540/vp/25173667#25173667.

He was the master of the interview, his show was not the one to do if you were looking for softball questions.  Even though he came out of politics, first with the late Senator Daniel Patrick Moynihan, then with the Governor of NY, Mario Cuomo, Tim Russert was non-partisan and fair.  His untimely departure leaves a great void and he will be missed.

Thursday, June 12, 2008

At least I passed the robot test

Name That Robot 

That's almost as important as knowing how long I could survive in the vacuum of space?

 How long could you survive in the vacuum of space?

File this under "end of the day diversions"...

Unblocking attachments with Outlook

Today, one of the other programmers needed to send me some odd registry entries that were on his machine.  So I asked him to export the registry settings to a .reg file from regedit and then and email me the .reg file.  Outlook blocked the file attachment because the .reg file extension is on the Outlook equivalent of the “No Fly” list.  Outlook has two levels of attachment security, Level 1 and Level 2.  Level 2 attachments will prompt you to save the file to your hard disk.  Level 1 attachments are blocked at the client by Outlook and can not be accessed.  The list of file types classified as Level 1 are listed here.  It has the usual suspects and this include .reg files.

That’s annoying.  I wanted that .reg file.  Fortunately, you can white-list specific file types in the Level 1 list and allow access to them.  I found the following instructions on the HowTo-Outlook web site at this page.

  1. Make sure Outlook is closed.
  2. Open your registry editor by opening the Run command and type regedit (regedt32 for Windows 2000)
  3. Locate the following key
    Outlook 2000 [HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Outlook\Security]
    Outlook 2002 [HKEY_CURRENT_USER\Software\Microsoft\Office\10.0\Outlook\Security]
    Outlook 2003 [HKEY_CURRENT_USER\Software\Microsoft\Office\11.0\Outlook\Security]
    Outlook 2007 [HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Outlook\Security]
  4. Go to Edit-> New-> String Value and name the value Level1Remove (case sensitive!)
  5. Double-click on the newly created value and enter the extension including the “dot” that you want to open in Outlook. For instance .exe
    If you need to enter more than one extension you’ll have to type separate them by a semicolon like this; .exe;.bat;.url
  6. Press OK on the input box and close the registry editor
  7. When you open Outlook the attachments which hold those extensions aren’t blocked by Outlook anymore.

In my case, I just used ".reg" as the file extension.  To go back to blocking the extensions, just remove or rename the Level1Remove string value from that registry key.

This isn't that hard to do, but it's a pain to have start and stop Outlook just to get the new settings to take affact.  I can understand why the restart is required, it prevents malicious code from changing the setting without you being aware of some going on with Outlook.

When chicken bombs are outlawed, only outlaws will have chicken bombs

From the The Hartford Courant:

...A motorist on Powder Forest Drive Friday morning noticed what looked like a whole chicken — the kind bought at grocery stores for roasting — with a pipe bomb stuffed inside, police said Monday.

When they arrived on the scene around 9 a.m. officers found the roaster had an improvised explosive device where the fowl's innards should have been.

They closed the road for part of the morning as the Hartford Police Department's bomb squad was called to detonate the device, police said.

The full article can be read here.  Are chicken bombs the latest meme?  I saw references to this story on bunch of sites.  One of more entertaining links is here, scroll down through the comments.

Wednesday, June 11, 2008

Backing up your Blogger hosted posts

This blog is hosted on Google's Blogger platform.  It has it's own domain name, but it's still on Blogger.  While I have faith in our Google Overlords, I still like keeping a local backup of the blog posts.  There's a nice open source Blogger backup utility named "Blogger Backup".  It's written in C# in VB.NET and is hosted on CodePlex.

When it's running, you'll see a window that looks like this:


Sell photos on photrade | By Chris Miller

You save each post as it's own file, or put them all inside one big, honkin' file.  The posts are saved as XML to make it easier to process.  You can use Blogger Backup to restore the posts back to your blog.  That would be handy if you accidentally delete a blog post.  You could also use the saved XML files to port your blog to another platform.  While I have no intention of moving this blog off of Blogger, it's good to know that I would have a way of migrating all of my posts to a new platform.

Blogger Backup is a .NET application, you'll need to have the .NET Framework 2.0 installed.  To communicate with Blogger, it uses the GData.Net (Google Data API for .NET) library.  I wasn't familiar with GData, it's a Apache licensed API that provides programmable access to many of Google's services:

  • Base
  • Blogger
  • Calendar
  • Spreadsheets
  • Google Apps Provisioning
  • Code Search
  • Notebook
  • Picasa Web Albums
  • Document Feed
  • Contacts
  • YouTube
  • Google Health

GMail is not on the list, but that would be asking for trouble.  The last thing we need is a Google API for sending spam through GMail.  The API is not limited to .NET, they have versions for Python, Java, and Objective-C.  I think you could do some interesting things with the GData API and their Calendar.

If you are wondering about the screenshot, I'm playing around with the beta for Photrade.  It has some cool features, it's worth checking out.

[Updated on 6/12/2008]
For some reason I thought Blogger Backup was written in C#, when it’s actually VB.NET.

Photrade has updated their license agreement for everyone's benefit

Yesterday, I posted about a new site called Photrade and it's license agreement.  Basically, section F of their license gave them the permanent right to do anything to your images with out compensation.

Their site looks cool and it provides features that I haven't seen anywhere else, but the license was too broad for my comfort.  Within 4 hours, they had revised their license.  The updated license gives Photrade the rights to use your images in order to operate the web site and to provide the functionality that the web site gives you.

That's really cool.  The updated license is completely appropriate for their business needs with out reserving any permissions that they would not need to operate their site.  The change in the agreement is very similar to the changes that Adobe made with licensing for Photoshop Express, except that Photrade revised the license with 4 hours. 

From the comments posted to my earlier post, it sounds like the original license was drawn up by lawyers seeking to provide the greatest level of protection to their client.  My guess is that no one looked at section F too close enough to realize how broad the rights were that were being granted to Photrade.  I'm sure that the people behind Photrade had no intention on reselling the images, but since the original license gave them that right in perpetuity, that part needed to be revised.  And it was revised in under 4 hours.  For revising and publishing a legal contract, that turn around time is very impressive.  Without knowing the people behind Photrade, the speed in which they revised their license says a lot about their character.

Now that I'm comfortable with the license agreement, I'm looking forward to trying Photrade.  For more information about Photrade, take a look at their site tour video.

Tuesday, June 10, 2008

Photrade lets you sell your photos online but retains perpetual and royalty-free license to your images

I have updated this post with additional details about how Photrade has revised their license agreement.  I also put additional comments in a new post.

I'm still playing around with Twitter and one of the accounts that I follow is photojojo.  The photojojo site is pretty cool and has some decent photography tips.  A little while ago, Photojojo tweeted a free invite code to the beta of www.photrade.com.

Hmm, a site where I could sell my images.  There a few ways of earning money on their site.  From their FAQ page:

There are 3 different ways to earn ad revenue:
1) From banner ads on your Photrade galleries. Earn every time someone sees your galleries.
2) From Photrades unique Patent-Pending Picture-in-Picture advertising (during our Beta test this ad space is donated to charity and/or used for test ads), where the ads are directly IN the photo when it gets shared. Earn Ad revenue every time someone sees your photo on ANY website (ie. in your blog or on your myspace).
3) From ads on a splash screen where users land when they click on your photos from another site. Earn ad revenue every time someone clicks on your photo when it iss hosted on another site.

You can sell your images and add a markup.  There is a base price for images and you can set a mark up value and collect the difference between the base price and the markup.  Plus you can sell licenses as stock images.   The idea of generating ad revenue by using your own artwork in blog postings looks intriguing.  If someone hotlinks your image, they would be hotlinking your advertising.

Sounds cool, but I declined to complete the membership form.  To complete the sign up process, you have to agree to the terms of the Photrade License Agreement.  Never agree to a license agreement without reading it.  That is really important when your own intellectual property is involved.  Most of the license is common boiler plate code, but I stopped when I hit section (F).  The following is section F in it's entirety:

(F) Company does not claim ownership in Your Content. At all times, You retain all rights in Your Content. However, each time You upload Your Content, You irrevocably grant to Company, its parent, subsidiaries, affiliates, and advertising or other partners a non-exclusive, perpetual, worldwide, royalty-free license in and to Your Content and intellectual property rights therein. Such license shall include, without limitation, the right in perpetuity, without any credit or compensation to You, to use, reuse, modify, alter, display, backup, archive, publish, sub-license, perform, reproduce, disclose, transmit, broadcast, post, sell, translate, create derivative works of, distribute and use for advertising, marketing, publicity and promotional purposes, all or any portion of Your Content, and Your name, voice, likeness and other identifying information, in any form, media, software or technology of any kind now known or developed in the future for any purposes whatsoever including, without limitation, developing, manufacturing and marketing products or services using Your Content. Intellectual property rights shall include all patents, trademarks, service marks, trade names, trade identities, copyrights, trade secrets, rights of publicity, logos, domain names, know-how, source code and object code, mask-work rights, inventions, moral rights, author's rights, goodwill and other intellectual property and proprietary rights whatsoever. You hereby waive any moral rights You may have in and to any of Your Content, even if such material is altered or changed in a manner not agreeable to You.

I marked in bold the part where I lost interest in signing up.  Basically, anything you upload becomes freely available to Photrade and they can do anything they want with it.  If you upload a spectacular snapshot of a sunset from your vacation, Photrade can sell it and they don't have to share any of the revenues with you.   That's the same sort of nonsense that Adobe tried to pull when they release Photoshop Express.  That didn't go over too well and Adobe revised their terms of service to make it clear they wouldn't sell the images.

Photrade's license looks pretty evil.  Their intentions may be pure (and I am assuming that they are), but that license allows them to anything to your images and your personal information forever.  And that's a mighty long time time, according to Prince.  I would consider signing up if they revamp that license to make it more like Adobe's.  It would be nice if you could license your images with a Creative Commons license like Flickr does.  The concept looks good, but that scary fine print make it a non-starter for me.

[Updated on June 11th, 2008]

As noted in the comments, Photrade has revised their license.  The new section F is more more reasonable:

(F) Company does not claim ownership of Your Content. At all times, You retain all ownership rights in Your Content. However, we do need certain rights from you, with respect to Your Content, in order to operate the Website and in order to enable you to do all the things this Website affords you the ability to do. Therefore, by uploading or transmitting Your Content to Website, you grant Company a worldwide, royalty-free, non-exclusive, fully sublicensable license to use, reproduce and modify Your Content solely for the purposes of operating the Website and enabling your use of the Website. To the extent that you choose to make Your Content available for sale or licensing to Users, you additionally grant Company the rights to distribute, publicly perform and publicly display Your Content (in whole or in part) for the sole purposes of operating the Website and enabling your use of the Website and to sublicense Your Content to other Users.

Basically, this gives Photrade a license to your images in order to present them on their site and enable the usage of the image.  This gives Photrade the legal protection that they need to run their site while still protecting the users.

I'm impressed, they made this change in just a few hours.  That's not an easy task to pull off when you are changing the contents and coverage of a legal document.

Thursday, June 05, 2008

Displaying what your TiVo recorded as a blog badge

There have been some people blogging about having what was recorded on TiVo being displayed on their blog.  Something like how you have display what you have been listening to with Last.FM.  Personally, I wouldn't want the world to know what was just recorded on my TiVos.  One TiVo gets filled up with cooking shows and NY Mets baseball, the other one gets an eclectic collection of kid shows and the SciFi channel, with some Animal Planet for extra seasoning.

The programmer in me keeps thinking about from a how to build it viewpoint.  There are some scripts out there that will pull the recorded show information from the TiVo mini web server.  That part is pretty easy.  Getting it to your blog is another story.  Unless you host your own blog, you need some place to store the data so a blog widget can render it in Web 2.0 approved colors (plus the bottom reflection with alpha channel blending goodness).  Since your TiVo is behind a firewall (well, it should be behind one), your blog can't pull the data directly form the TiVo.  And you really don't want to pull the data, that's too much traffic.

What you want to do is to push the data up once you find a place to host the data.  Since we don't want to hack the TiVo, the TiVo wont be pushing the data.  You'll need a home PC to query the recorded show history and push the data up.  A pretty simple task, but if you step back and think a little more about the whole TiVo experience, there is a better way.

Your TiVo box is connecting back to the TiVo mothership on a regular basis.  It gets program updates, verifies that it's subscription is still good, sends usage data back to TiVo.  Other than creating the infrastructure, it would be pretty easy for the TiVo company to supply to you what your TiVo has recorded.  That's where Louis Gray was heading with his article about TiVo adding social network related functionality.

I wonder if anyone at TiVo has thought of doing this.  They already have the hardware and networking stuff in place.  It's basically just taking the data that TiVo is already sending back and allowing the users to display and share that data.  It adds a coolness factor that you wont get with a cable company DVR.  I mean TiVo spent resources enabling you to program your TiVo from a mobile phone, why not social networking?

Wednesday, June 04, 2008

Not a fan of Vibrant Media's intellitxt popups (and how to get rid of them)

I was reading a blog about pulling an XML feed from my TiVo and I kept being distracted by popup ads over key words in the article.  You've probably seen them on other sites, the words have a double underline and they are not actually links. 

In the middle of a sentence, you see a word like this Internet and it looks almost like a regular link.  Except the color is wrong and the underline is not the same a regular link.  When your mouse hovers over them, a popup ad that has some contextual relationship to the text appears.  In the fake link above, nothing will happen when you mouse over it.  I just used an inline CSS style to do the double underlining.

Vibrant Media calls it "in-text advertising".  I call it a popup and I want it to go away.  As in go away right now.

I can understand the desire to have ads on your blog and I have them here myself.  I'm using Google to supply the ads on this blog and they are pretty unobtrusive.  I don't have any beef with web based advertising as long as it doesn't get in the way of the reading the web page.  I don't like popups and if I can avoid them, I will. 

In this case it was pretty easy.  I am using Firefox 2, so I installed the Adblock Plus addin.  That little gem will give you fine control over what ads you will see and experience.  For Vibrant based popups, it's pretty easy.  For a web site to use Vibrant's popups, they need to register an account with Vibrant and add some code to their web page that scans the text and creates something funky with Javascript when the page is rendered.  The web site author gets a url that includes their blog name on the intellitxt.com domain.  With AdBlock Plus, I just added a filter for the text http://*.intellitxt.* and after I refreshed the web page the popups were gone.  For Opera users, this link will show you how to block Intellitxt popups.

I would prefer not using AdBlock Pro. When I installed it, it prompted me to pick a subscription for automatically picking up ad filters.  When I did this, it took out most of the ads on every page.  And I don't have a problem with Google Ads or other ads that don't interfere with the consuming of the content.  So I yanked the subscription list out.  From here on out, I'm just going to kill the popups and leave the other ads in place.

One more reason why I'll never go back to Time Warner Road Runner

Time Warner Cable is implementing metered broad band Internet usage in a few test markets.  I switched to FiOS the day it was available and it's been a positive experience.  I'm paying less money for more bandwidth.  And it's consistent bandwidth.  I usually get a little over 20 Mbs for downloads and 5 Mbps for uploads.  When I dropped Road Runner, about two years ago, I was getting 5 Mbs down and 384 Kps up.  The fun part was watching the bandwidth performance drop when neighborhood kids came home from school.  We shared the same Road Runner pipe and the more people that joined, the slower it got.  FiOS doesn't have the problem.

I think the 5 Mbps upload speed has been the biggest benefit.  If I upload photos to my SmugMug account, it takes seconds where with Road Runner it would take minutes.

Time Warner's meter usage would allow 40 gb of traffic a month for their 15 mbps account.  That sounds like a lot but if you are downloading movies that you have bought from iTunes, Amazon UnBox, Tivo's TivoCast, or NetFlex; then you'll go through that 40 gb fairly quickly.