Tomazy’s Software Development Blog: Testing modal windows in Delphi.
Recommended reading!
–jeroen
Posted by jpluimers on 2011/08/14
Posted in Delphi, Development, Software Development | Leave a Comment »
Posted by jpluimers on 2011/08/10
Though there are API ways to add users to local groups in Delphi, you need the JwaLmAccess unit from the JEDI API library project to import those.
Sometimes that is not feasible, and sometimes you want to just script things.
For those, you can use the Windows net localgroup command (if you have sufficient privileges, you can even apply it to the local groups on your domain controller by appending it with the /domain parameter, or use the net group /domain command to execute on global domain groups instead of local groups).
Sample of using this in a cmd script:
net localgroup Guests Me Myself I ACME\BugsBunny /delete
It will remove the local users Me, MySelf and I, and remove the domain user ACME\BugsBunny from the local group Guests.
Sample source of using this in Delphi: Read the rest of this entry »
Posted in CommandLine, Delphi, Development, Software Development | 1 Comment »
Posted by jpluimers on 2011/08/04
I’ll be speaking at a few conferences this fall.
The furthest for me will be DelphiLive! 2011 in San Jose, CA, which will be held from September 12th to 14th (slightly more than a month from now).
Note that if you want to come, the early bird discount is until augusts 15!
Part of the sessions and speakers lists are already published, but it will be extended shortly (some nice Delphi XE2 sessions are in the pipeline), followed by a workshop tutorials list, and agenda.
My sessions are going to be these:
Not everything for those sessions is set in stone yet, so if you have ideas for things I should include, exclude, emphasize or understate, please let me know.
I’m looking forward to meet (often again!) a lot of attendees and speakers.
The social part of conferences is very important too.
Last year, after the conference, a few speakers, attendees and other people had a marvelous steak dinner. Great fun!
Hope to see a few of my blog readers at one conference or the other.
–jeroen
PS: Like last year, the conference will be held at Crowne Plaza Hotel San Jose Downtown, 282 Almaden Boulevard, San Jose, CA 95113, USA (it has a special room rate of USD 139 per night for conference attendees).
PS2: Some more events will follow shortly.
Posted in Conferences, Delphi, DelphiLive, Development, Event, Software Development | 1 Comment »
Posted by jpluimers on 2011/08/02
Right now there are so many ways to display text, that – depending on your physical display (CRT, LCD, etc) – all behave differently.
Even Microsoft has released a patch (see the below quote from KB 2545698 that got released last month).
This issue occurs because of a design change to how Internet Explorer 9 renders text. By default, Internet Explorer 9 uses sub-pixel positioned ClearType to render text by using DirectWrite, whereas Internet Explorer 8 uses whole-pixel positioned ClearType to render text by using the Microsoft Windows graphics device interface (GDI).
I’m wondering if there is a way to make it work ‘right’ on every type of display combination.
Do you know any?
–jeroen
Posted in .NET, Delphi, Development, Font, Power User, Software Development | 5 Comments »
Posted by jpluimers on 2011/07/27
Having proofread, I’m really glad that Marco Cantu recently announced that Delphi XE Handbook to be Available in both print and electronic forms.
Note that since the announcement, you can also get the Handbooks Collection in PDF form for something like EUR 55.
His books are always a pleasure to read, so: Great work Marco!
–jeroen
Posted in Delphi, Development, Software Development | 2 Comments »
Posted by jpluimers on 2011/07/21
On my research list: WebSphere MQ and Delphi.
The funny thing is that this Delphi MQ Series question on StackOverflow that I answered actually helped me to get going :)
A few interesting links:
The research actually is focussed to replace a APPC/CPI-C session based solution that runs on top of SNA using LU 6.2 endpoints and has round-trip response times between 50 and 150 milliseconds with a WebSphere MQ based solution having similar performance characteristics. It binds multiple client applications to multiple function entries on the AS/400 systems at the client.
The current APPC/CPI-C part is written either both a DLL and EXE in Delphi (depending on how it is used), hence the Delphi part of the research.
In many organizations, WebSphere MQ (aka MQSeries) is part of their Enterprise Service Bus. In that regard, the SNA solution was far a ahead of its time.
BTW: Back then (almost 15 years ago), the SNA solution started out as solution using AS/400 Data Queues. Even after months of trying, that didn’t work well because the mixed environment of NetSoft Router, AS/400, SNA Server and Windows NT 4 in a pretty big WAN had huge problems.
Somehow, one of the layers forced sessions to always use 2 connections at a time, which was causing huge problems when those were routed through different SNA servers. That routing was unpredictable (and it was not possible to disable/force it to use stick to one SNA server). In addition, it was memory and CPU hungry on the PC side (when you were glad to have a Pentium MMX based CPU with 32 MB RAM, it ate 20+% of the CPU power, and 25+% of the memory per session, peaking to 100% CPU and 50% of RAM per session).
Specialists from all involved parties weren’t able to pinpoint the actual cause, so we went a few steps down on the OSI layer to the APPC leve.
–jeroen
Posted in .NET, Delphi, Development, Software Development | 5 Comments »
Posted by jpluimers on 2011/07/20
This is from a long time ago, but still fun:
Sometimes simple things in life are hard do remember.
For instance, I always forgot if a file extension parameter should have a dot in it or not.
Normally it should!
But for clearing an extension, you should use a blank string.
Be aware though that empty extensions look differently depending where in the process you look at them:
C# example:
using System;
using System.IO;
public class Test
{
public static void Main()
{
string extensionLess = Path.ChangeExtension(@"C:\mydir\myfile.com.extension", "");
Console.WriteLine(extensionLess);
string extension = Path.GetExtension(extensionLess);
Console.WriteLine(extension);
}
}
Outputs:
C:\mydir\myfile.com.
Delphi example:
program Demo;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
extensionLess: string;
extension: string;
begin
extensionLess := ChangeFileExt('C:\mydir\myfile.com.extension', '');
Writeln(extensionLess);
extension := ExtractFileExt(extensionLess);
Writeln(extension);
end.
Outputs:
C:\mydir\myfile.com .com
Don’t you love differences in your platforms :)
–jeroen
Posted in .NET, C#, C# 2.0, C# 3.0, C# 4.0, Delphi, Development, Software Development | 4 Comments »
Posted by jpluimers on 2011/07/19
Recently I needed a way of concerting back and forth ISO 8601 DateTime values used in XML from Delphi.
Thoug the Delphi DateUtils unit has some ISO 8601 features for calculating week numbers, you actually need to the XSBuiltIns unit for converting back and forth to ISO 8601 text representation of a DateTime.
I remembered answering the related In Delphi is there a function to convert XML date and time to TDateTime question on StackOverflow a while ago (and forgot that this was back in 2009 <g>).
ISO 8601 dates can either include a time-zone, or be in UTC, which is not part of that answer. So lets elaborate on that answer a bit now:
UTC times in ISO 8601 format end in a Z time zone designator like this:
<Created>2011-06-29T17:01:45.505Z</Created>
The Z UTC indicator is basically a shortcut for a timezone offset of +00:00 or -00:00, effectively being a zero (or zulu) timezone.
Nonzero timezones start with an optional + or -, followed by the hours and minutes offset from UTC, for instance +01:00 for the Central European Time zone.
<Created>2011-06-29T17:01:45.505+01:00</Created>
When you want historical time zones, then you need the Delphi TZDB interface to the historical TZ database.
To do the timezone calculations, I used the TimeZoneBias function from Indy, which is either in the IdGlobal unit (Indy <= version 9) or the IdGlobalProtocols unit (Indy 10 and up).
Conversion is done by using the TXSDateTime (that like all the XS conversion classes descends from TRemotableXS in the InvokeRegistry unit).
Most of the classes descending from TRemotableXS contain two methods: NativeToXS and XSToNative doing the underlying conversions.
Since I didn’t need the historical reference in the TZDB, this is the code that I came up with:
unit Iso8601Unit;
interface
type
TIso8601 = class(TObject)
public
class function DateTimeFromIso8601(const Value: string): TDateTime; static;
class function UtcDateTimeToIso8601(const Value: TDateTime): string; static;
class function DateTimeToIso8601(const Value: TDateTime): string; static;
class function UtcNow: TDateTime; static;
class function ToUtc(const Value: TDateTime): TDateTime; static;
class function FromUtc(const Value: TDateTime): TDateTime; static;
end;
implementation
uses
IdGlobalProtocols, {IdGlobal for Index SysUtils,
XSBuiltIns;
class function TIso8601.DateTimeFromIso8601(const Value: string): TDateTime;
begin
with TXSDateTime.Create() do
try
XSToNative(value); // convert from WideString
Result := AsDateTime; // convert to TDateTime finally
finally
Free();
end;
end;
class function TIso8601.UtcDateTimeToIso8601(const Value: TDateTime): string;
begin
with TXSDateTime.Create() do
try
AsUTCDateTime := Value;
Result := NativeToXS; // convert to WideString
finally
Free();
end;
end;
class function TIso8601.DateTimeToIso8601(const Value: TDateTime): string;
begin
with TXSDateTime.Create() do
try
AsDateTime := Value; // convert from TDateTime
Result := NativeToXS; // convert to WideString
finally
Free();
end;
end;
class function TIso8601.UtcNow: TDateTime;
begin
Result := ToUtc(Now);
end;
class function TIso8601.ToUtc(const Value: TDateTime): TDateTime;
var
Bias: TDateTime;
begin
Bias := TimeZoneBias;
Result := Value + TimeZoneBias;
end;
class function TIso8601.FromUtc(const Value: TDateTime): TDateTime;
var
Bias: TDateTime;
begin
Bias := TimeZoneBias;
Result := Value - TimeZoneBias;
end;
end.
–jeroen
via In Delphi is there a function to convert XML date and time to TDateTime – Stack Overflow.
Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | 7 Comments »
Posted by jpluimers on 2011/07/14
Boy, I was wrong. Somewhere in the back of my head I knew it.
ParamStr goes from zero (the name of the EXE) through ParamCount (the last parameter). Duh :)
I’ll keep this so you can have a good laugh:
When you add double quoted arguments to the commandline of your Delphi app, strange things can happen: the first parameter seems to be gone, while it is there.
It appears that the ParamCount/ParamStr logic fails here, and cannot be repaired because of backward compatibility.
Lets look at this commandline:
“..\bin\DumpCommandLine.exe” “C:\Program Files\test.xml” “C:\Program Files\meMySelfAndI.xml”
The demo code below will output something like this:
ParamCount: 2 ParamStr(): 0 C:\develop\DumpCommandLine\bin\DumpCommandLine.exe 1 C:\Program Files\test.xml CommandLine: "..\bin\DumpCommandLine.exe" "C:\Program Files\test.xml" "C:\Program Files\meMySelfAndI.xml" CommandLineStrings.Count: 3 CommandLineStrings[]: 0 ..\bin\DumpCommandLine.exe 1 C:\Program Files\test.xml 2 C:\Program Files\meMySelfAndI.xml
You see that regular ParamCount/ParamStr calls will mis the “C:\Program Files\test.xml” parameter.
But getting it through CommandLineStrings will correctly get it.
This is the dump code:
unit CommandlineDemoUnit;
interface
procedure DumpCommandLineToConsole;
implementation
uses
Classes, CommandlineUnit;
procedure DumpCommandLineToConsole;
var
CommandLineStrings: TStrings;
I: Integer;
begin
Writeln('ParamCount:', #9, ParamCount);
Writeln('ParamStr():');
for I := 0 to ParamCount - 1 do
Writeln(I, #9, ParamStr(I));
Writeln('CommandLine:');
Writeln(CommandLine);
CommandLineStrings := CreateCommandLineStrings();
Writeln('CommandLineStrings.Count:', #9, CommandLineStrings.Count);
Writeln('CommandLineStrings[]:');
try
for I := 0 to CommandLineStrings.Count - 1 do
Writeln(I, #9, CommandLineStrings[I]);
finally
CommandLineStrings.Free;
end;
end;
end.
And this the code to get the CommandLine and CommandLineStrings, which will fill a TStrings result using the CommaText property (it uses a default QuoteChar of of double quote #34 and Delimiter of space #32, this will work nicely):
unit CommandlineUnit; interface uses Classes; function CommandLine: string; function CreateCommandLineStrings: TStrings; implementation uses Windows; function CommandLine: string; begin Result := GetCommandLine(); end; function CreateCommandLineStrings: TStrings; begin Result := TStringList.Create(); Result.CommaText := CommandLine; end; end.
Note that you need to manually free the TStrings object to avoid memory leaks.
–jeroen
Posted in Delphi, Development, Software Development | 13 Comments »
Posted by jpluimers on 2011/07/06
OSnews has an interesting view on code quality: the number of WTFs/minute.
I know it is from 2008, but it is so true, so I’m glad I re-found it.
–jeroen
via: wtfm.jpg (500×471).
Posted in .NET, Agile, Delphi, Development, Opinions, Software Development | Leave a Comment »