The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,862 other subscribers

Archive for October, 2009

XP embedded – .NET Framework 3.0

Posted by jpluimers on 2009/10/27

The “out of the box” .NET 3.0 component in Windows XP Embedded drags way too many required components (like the System Restore Core) into your image.

So most people build their own .NET 3.0 component.

If you get errors like this when you make your own, then you didn’t get your dependencies right.

These are the dependencies for the .NET 3.0 framework:

  • .NET Framework 2.0
  • ASP.NET 2.0

These are the error messages you get when you forget the ASP.NET 2.0 dependency:

Of course I always get all my dependencies right :-)
(yeah right, not this time)

–jeroen

Posted in Development, XP-embedded | Leave a Comment »

Delphi – for … in on enumerated data types

Posted by jpluimers on 2009/10/27

I like [Wayback/Archive] enumerated type a lot.
The allow you to perfectly describe what the members of such a type actually mean, much more readable than a bunch of integer constants!

Given an enumerated type like TTraphicLightColors

type
  TTraphicLightColors = (Red, Orange, Green);

I always wondered why  – since the for ... in statement was added to the [Wayback/Archivestructured statements part of the Delphi language – it is not possible to use a for … in statement like the this:

</span>
<pre>var
  TraphicLightColor: TTraphicLightColors;
begin
  try
    for TraphicLightColor in TraphicLightColor do
      ShowValueAsTraphicLightColor(Ord(Value));
    // [DCC Error] EnumerationEnumeratorDemoProcedures.dpr(63): E2430 for-in statement cannot operate on collection type 'TTraphicLightColors'
end;

Somehow, for ... in [Wayback/Archiveexpects a collection type.
A request for [WayBack/Archive] the for … in do on enumerated types compiler feature is in QC, but it is closed with reason “Won’t do”.

Back in Delphi 2007, I tried working around this by writing a type implementing the GetEnumerator pattern myself, but got [WayBack/Archive] Internal Errors when compiling anything but the most basic sample.

Until today, where I found how I could get that most basic sample to work!
It is an example on how you could implement this: it is research, so you decide if you find the result practical enough to use yourself.

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Development, Event, F2084, QC, Software Development | 20 Comments »

Delphi operator overloading: table of operators, names, and some notes on usage and ‘glitches’

Posted by jpluimers on 2009/10/19

Operator overloading is a very nice feature of the Delphi language.
However. the Delphi documentation on Operator overloading is not completely right.

Below is my table of what I found out so far, and some notes.

It is part of my “Nullable types in Delphi” session that I gave on some conferences.
The downloads for that session contain more detailed information.

This is just an abstract to get you going and a try to answer this operator overloading question on Stackoverflow.
Download the full presentation to get more in depth information.

Let me know if you need more information.

Notes

Operator overloading

Add your own “behaviour” to operators

  • Win32: Works only for records, not classes!
  • An operator and the operand(s)
    are being implemented worden by a “class operator”;
    this is a kind of class method with name and argumen(s)

Example:

  • Multiplication X : = A * B;
  • Operator: *
  • Name: Multiply
  • Operands: 2 -> two parameters
type
  TMyRecord = record
    class operator Multiply(A, B: TMyRecord): TMyRecord;
  end;

Documentation is not correct!

Combining the rules of operator and result types, you can do magical things like Dances with XML | Australian Delphi User Group Members.

Do not use Delphi 2006 with operator overloading

Delphi 2007 fixed a number of bugs including this one: Delphi 2006 wont allow const parameters of type record within record method? – Stack Overflow.

10+ years later: maybe assignment operator?

It might be that in 2019, a new Delphi version gets assignment operator overloading: [WayBack] Operator Overloading Explained – Code Partners

Watch the result type of comparison operators!

Tips:

  • Some operators should be overloaded pair-wise
    = and <>
    shl and shr
    < and >=
    > and <=
    dec and inc
    + and –
    / and *
    div and mod
  • Prefer Explicit over Implicit operators
    • Beware of the built-in type coercion (implicit operators)
    • e.g
      • Byte to Integer;
      • Integer to Double;
      • Variants from/to anything!

Table of operators

operator # usage name cagetory *
and 2 R := A and B; BitwiseAnd bit
not 1 R := not A; //BitwiseNot bit glitch: does not exist!
or 2 R := A or B; BitwiseOr bit
xor 2 R := A xor B; BitwiseXor bit
() cast 1 R := TValue(A); Explicit conversion
:= 1 R := A; Implicit conversion
operator # usage name category *
round 1 R := Round(A); Round function
trunc 1 R := Trunc(A); Trunc function
and 2 R := A and B; LogicalAnd logical
not 1 R := not A; LogicalNot logical
or 2 R := A or B; LogicalOr logical
xor 2 R := A xor B; LogicalXor logical
operator # usage name category *
+ 2 R := A + B; Add binary
/ 2 R := A / B; Divide binary
div 2 R := A div B; IntDivide binary
mod 2 R := A mod B; Modulus binary
* 2 R := A * B; Multiply binary
2 R := A – B; Subtract binary
operator # usage name category *
shl 2 R := A shl B; LeftShift binary name is confusing
shr 2 R := A shr B; RightShift binary name is confusing
1 R := -A; Negative binary
+ 1 R := +A; Positive binary
dec 1 Dec(A); Dec self
inc 1 Inc(A); Inc self
operator # usage name category *
= 2 R := A = B; Equal comparison
> 2 R := A > B; GreaterThan comparison
>= 2 R := A >= B; GreaterThanOrEqual comparison
< 2 R := A < B; LessThan comparison
<= 2 R := A <= B; LessThanOrEqual comparison
<> 2 R := A <> B; NotEqual comparison
operator # usage name category *
in 2 R := A in B; In set

–jeroen

Posted in Conferences, Delphi, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi XE, Delphi XE2, Delphi XE3, Development, Event, Software Development | 6 Comments »

Delphi – list of posts about hidden registry entries

Posted by jpluimers on 2009/10/15

There are quite a few registry tricks that you can perform to influence the Delphi IDE.

If you have any registry settings to share, please let me know by posting a comment below, or filling out the contact form.

This summary will be enhanced over time:

Have fun with them!

–jeroen

Posted in Delphi, Development, Software Development | 2 Comments »

Delphi – finding the VERxxx define for a particular Delphi version: use JEDI.INC

Posted by jpluimers on 2009/10/15

Edit 20140822 since originally posting, JEDI moved to a GIT repository, so I changed some URLs and added that it is up to date until Delphi XE7.

Finding the correct VERxxx conditional define for a particular Delphi version is asked by a lot of people.

Even the first link in the above search, does not contain the full list!
But: JCL comes to the rescue

The JCL file JEDI.INC usually (read: like 99.999% of the time) is up to that with that information soon.
Currently, it contains all the defines starting with Delphi 1, up to Delphi 2010 XE7.

You can always browse the to JEDI.INC with this link to the sourceforge trunk. link to the GitHub master version.

In fact that file contains a lot more useful defines.
Actually, having the JCL and/or JVCL at hand is a very good practice: it is filled with high quality code that solves a lot of everyday problems.

Note:

VER190 (by some people attributed to the wrong Delphi version) is only used by Delphi 2007 for .NET (Delphi 2007 for Win32 used VER185 by itself and shares VER180 with Delphi 2006 for Win32).

The number 13 (in between Delphi 2009 aka Delphi 12, and Delphi 2010 aka Delphi 14) was never used as a Delphi version number
Since Delphi is mainly developed in the USA, and since a lot people there have Triskaidekaphobia, they showed mercy to those and skipped Delphi 13.

–jeroen

Posted in Delphi, Delphi 1, Delphi 2, Delphi 2005, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 3, Delphi 4, Delphi 5, Delphi 6, Delphi 7, Delphi 8, Delphi x64, Delphi XE, Delphi XE2, Delphi XE3, Delphi XE4, Delphi XE5, Delphi XE6, Delphi XE7, Development, Software Development | 9 Comments »

Delphi – hardcore debugging the intialization of your app, dlls and packages

Posted by jpluimers on 2009/10/15

Recently we got involved with a client having a large and complex application that (historically) consists of

  1. A main .EXE that loads
  2. Many DLLs
  3. Underlying BPLs

One of the biggest problems is debugging the startup sequence.
Somehow, when the Delphi IDE loads DLLs in the initialization sequences of units, it looses its ability symbol tables.

This article describes a few tips on how to debug those, especially where to put breakpoints.
Read the rest of this entry »

Posted in Conference Topics, Conferences, Debugging, Delphi, Development, Event, Software Development | 3 Comments »

Te Waka o Delphi · Absolute for Beginners

Posted by jpluimers on 2009/10/15

Jolyon Smith just published a great article about using the absolute keyword in Delphi.

When used with care (just like the with or goto keywords), absolute can make your code much easier to maintain.

Recommended reading!

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

Ancient history – found back one of my earliest email messages dated in februari 1989!

Posted by jpluimers on 2009/10/12

I found back one of my earliest mail messages: it is dated back in februari 1989.

Wow – ain’t search engines nice!

Today, messages like those seem totally irrelevant.

But back then, getting in touch with other people through email could be a real challenge.

The internet was forming (out of UUNET, DECnet, BITNET, Usenet, EARN, ARPANET and others), and not everything was completely interconnected yet, let alone connected on-line 24/7.
For instance, newsgroups were limited to the usenet portion of the internet, and not available on the bitnet portion. Read the rest of this entry »

Posted in //e, About, Apple, Apple Pascal, Apple ][, DEC Pascal, Development, History, Pascal, Personal, Power User, Software Development, UCSD Pascal | 9 Comments »

C# / .NET – setting or clearing the Password Never Expires flag for a user

Posted by jpluimers on 2009/10/11

Recently, I had to change the “Password Never Expires” flag for some users on Windows systems.

In the past, there used to be a netuser tool available from WindowsITPro where you could use the pwnexp flag to set or clear that flag.
That tool seems to be vanished, so I was searching for alternatives.

Most alternatives I found depend on some  kind of scripting, or the use of the WMIC WMI command line interface: that was “out” because this particular setup is running on Windows XP Embedded, which is trimmed down very much.
The only C# example I found was on CodeProject, but it does

  • not take into account the existing flags correctly,
  • have  hard coded literals without any references where they are from,
  • use bit flag arithmetic without letting the C# compiler do its magic with enums,
  • use a call to the deprecated  InvokeGet method,
  • use the Invoke(“Put”, … way of calling that so many people use (which actually should have been an – also deprecated – InvokeSet method),
  • use COM Interop

Hence the solution below:
C#, with the proper ADS_USER_FLAG_ENUM enum from the MSDN documentation and no COM Interop, it also moves all literals to constants.

Read the rest of this entry »

Posted in .NET, C#, C# 2.0, CommandLine, Development, Software Development, XP-embedded | Leave a Comment »

Vista SP2 update: error E_FAIL(0x80004005) caused by SYSHIPER 0x80071a91- solved!

Posted by jpluimers on 2009/10/08

It took me almost 2 days to find out the cause of this one:

When performing a Service Pack 2 update on Vista (in this case a machine that was upgraded from Vista Home to Vista Ultimate), I would always get this very descriptive error message:

E_FAIL (0x80004005)

This is the relevant portion of the CBS.LOG file (%SystemRoot%\Logs\CBS\CBS.log):

2009-10-08 12:50:16, Info CSI 000008d2 Begin executing advanced installer phase 38 (0x00000026) index 1500 (0x000005dc) (sequence 1539)
Old component: (null)
New component: Microsoft-Windows-VistaServicePack-SysHiper-SP1, Version = 6.0.6002.18005, pA = PROCESSOR_ARCHITECTURE_INTEL (0), Culture neutral, VersionScope = 1 nonSxS, PublicKeyToken = {l:8 b:31bf3856ad364e35}, Type neutral, TypeName neutral, PublicKey neutral
Install mode: install
Installer ID: {81a34a10-4256-436a-89d6-794b97ca407c}
Installer name: [15]"Generic Command"
2009-10-08 12:50:16, Info CSI 000008d3 Performing 1 operations; 1 are not lock/unlock and follow:
LockComponentPath (10): flags: 0 comp: {l:16 b:95113b1f0548ca013e07000004058805} pathid: {l:16 b:95113b1f0548ca013f07000004058805} path: [l:206{103}]"\SystemRoot\WinSxS\x86_microsoft-windows-syshiper_31bf3856ad364e35_6.0.6002.18005_none_77fb27ec5025e18b" pid: 504 starttime: 128994722438561151 (0x01ca480440d9bd7f)
2009-10-08 12:50:16, Info CSI 000008d4 Calling generic command executable (sequence 53 (0x00000035)): [115]"C:\Windows\WinSxS\x86_microsoft-windows-syshiper_31bf3856ad364e35_6.0.6002.18005_none_77fb27ec5025e18b\syshiper.exe"
CmdLine: [211]""C:\Windows\WinSxS\x86_microsoft-windows-syshiper_31bf3856ad364e35_6.0.6002.18005_none_77fb27ec5025e18b\syshiper.exe" /install:VistaSP1-KB936330~31bf3856ad364e35~x86~~6.0.0.18000 /hide /permanent /ignorenotexist"
2009-10-08 12:50:17, Info CSI 000008d5 Done with generic command 53 (0x00000035); CreateProcess returned 0, CPAW returned S_OK
Process exit code 0 resulted in success? TRUE
Process output: [l:358 [358]"SYSHIPER: Initialized with following command parameters: /install:VistaSP1-KB936330~31bf3856ad364e35~x86~~6.0.0.18000 /hide /permanent /ignorenotexist

SYSHIPER: Failed with error hr: 0x80070002

SYSHIPER: Failed to open registry key for read

SYSHIPER: CBS key does not exist and ignoring operation for VistaSP1-KB936330~31bf3856ad364e35~x86~~6.0.0.18000

"]
2009-10-08 12:50:17, Info CSI 000008d6 Performing 1 operations; 1 are not lock/unlock and follow:
LockComponentPath (10): flags: 0 comp: {l:16 b:951c4e1f0548ca014007000004058805} pathid: {l:16 b:951c4e1f0548ca014107000004058805} path: [l:206{103}]"\SystemRoot\WinSxS\x86_microsoft-windows-syshiper_31bf3856ad364e35_6.0.6002.18005_none_77fb27ec5025e18b" pid: 504 starttime: 128994722438561151 (0x01ca480440d9bd7f)
2009-10-08 12:50:17, Info CSI 000008d7 Calling generic command executable (sequence 54 (0x00000036)): [115]"C:\Windows\WinSxS\x86_microsoft-windows-syshiper_31bf3856ad364e35_6.0.6002.18005_none_77fb27ec5025e18b\syshiper.exe"
CmdLine: [211]""C:\Windows\WinSxS\x86_microsoft-windows-syshiper_31bf3856ad364e35_6.0.6002.18005_none_77fb27ec5025e18b\syshiper.exe" /install:VistaSP1-KB936330~31bf3856ad364e35~x86~~6.0.1.18000 /hide /permanent /ignorenotexist"
2009-10-08 12:50:17, Info CSI 000008d8 Performing 1 operations; 1 are not lock/unlock and follow:
LockComponentPath (10): flags: 0 comp: {l:16 b:951c4e1f0548ca014207000004058805} pathid: {l:16 b:951c4e1f0548ca014307000004058805} path: [l:234{117}]"\SystemRoot\WinSxS\x86_microsoft.windows.s..ation.badcomponents_31bf3856ad364e35_6.0.6001.18000_none_3891bf6bc31ec194" pid: 504 starttime: 128994722438561151 (0x01ca480440d9bd7f)
2009-10-08 12:50:17, Info CSI 000008d9 Creating NT transaction (seq 1), objectname [6]"(null)"
2009-10-08 12:50:17, Info CSI 000008da Created NT transaction (seq 1) result 0x00000000, handle @0x6b20
2009-10-08 12:50:17, Info CSI 000008db@2009/10/8:10:50:17.182 CSI perf trace:
CSIPERF:TXCOMMIT;5
2009-10-08 12:50:17, Error CSI 000008dc (F) Done with generic command 54 (0x00000036); CreateProcess returned 0, CPAW returned S_OK
Process exit code 6801 (0x00001a91) resulted in success? FALSE
Process output: [l:287 [287]"SYSHIPER: Initialized with following command parameters: /install:VistaSP1-KB936330~31bf3856ad364e35~x86~~6.0.1.18000 /hide /permanent /ignorenotexist

SYSHIPER: Failed with error hr: 0x80071a91

SYSHIPER: Failed to open registry key for write

SYSHIPER: Failed to backup registry key

"][gle=0x80004005]
2009-10-08 12:50:17, Info CSI 000008dd@2009/10/8:10:50:17.182 CSI Advanced installer perf trace:
CSIPERF:AIDONE;{81a34a10-4256-436a-89d6-794b97ca407c};Microsoft-Windows-VistaServicePack-SysHiper-SP1, Version = 6.0.6002.18005, pA = PROCESSOR_ARCHITECTURE_INTEL (0), Culture neutral, VersionScope = 1 nonSxS, PublicKeyToken = {l:8 b:31bf3856ad364e35}, Type neutral, TypeName neutral, PublicKey neutral;240239
2009-10-08 12:50:17, Error CSI 000008de (F) Failed execution of queue item Installer: Generic Command ({81a34a10-4256-436a-89d6-794b97ca407c}) with HRESULT HRESULT_FROM_WIN32(14109). Failure will not be ignored: A rollback will be initiated after all the operations in the installer queue are completed; installer is reliable (2)[gle=0x80004005]
2009-10-08 12:51:08, Info CSI 000008df End executing advanced installer (sequence 1539)
Completion status: HRESULT_FROM_WIN32(ERROR_ADVANCED_INSTALLER_FAILED)

Since the install and rollback of SP2 takes a very long time, it took me almost 2 days to find out the cause:

All normal solutions for issues with 0x80004005, 0x80070002 or 0x80071a91 failed.
I finally found the solution in a thread on vistax64.com.

This registry key was missing:

HKLM\Software\Microsoft\Windows\CurrentVersion\SysHiper

After adding that key in RegEdit, SP2 installed fine (and much faster too).

Many thanks user veldthui!

Back to normal work!

–jeroen

Posted in Development, Vista | 13 Comments »