yoy.be "Why-o-Why"

2005 ...

januari februari maart april (1) mei juni (16) juli augustus september (12) oktober (14) november (8) december (3)

run COM from an NT-Service

2005-10-04 16:39  i282  delphi  [permalink]

I've been searching on this for a while, and still I'm not sure I'm there all the way yet. For now I'll put a summary here of how to set op COM-object(s) from an NT-service.


Create a new NT-Service project in Delphi.
Add dependency "RpcSs".

Add a Type Library and COM-Objects (or Automation objects or anything COM/ActiveX really).
The objects need to be instancing type MultiInstance.

Add these registry keys (I'll use the regedit export notation for now, with a little imagination you can guess what the Delphi code might look like), replace {AppID} with the full class GUID of your main object (or a unique AppID if you already have one), and ServiceName is the name of your service (Name property of your TService).

[HKEY_CLASSES_ROOT\AppID\{AppID}]
"LocalService"="ServiceName"

[HKEY_CLASSES_ROOT\CLSID\{AppID}]
"AppID"="{AppID}"

Optionally you might rig the TService.AfterInstall/TService.AfterUninstall to call the DllRegisterServer/DllUnregisterServer calls, or vice versa (with overriding TAutoObjectFactory.UpdateRegistry).
Or be sure to have an install(/uninstall) program that does both.

Then, in the TService.ServiceStart include this:

CoInitializeSecurity(@CLASS_MyObject,-1,nil,nil,0,0,nil,8,nil);

Where CLASS_MyObject is the constant value for the same AppID GUID as described above.

When you want the service to run on a Windows Server 2003 computer, you need to fix one more thing. By default two internal system calls get mixed up. To fix this on older Delphi versions open the project's dpr, and move Application.Initialize; to the TService.OnStart event handler. Newer versions of Delphi apparently have a notice in comment in the dpr, and also have a Application.DelayInitialization property specifically for running COM objects from an NTService


Refresh Desktop

2005-10-06 14:25  i285  delphi  [permalink]

Let's say you just registered a new NameSpace object on the desktop, by entering it into the registry here:

HKEY_LOCAL_MACHINE
  SOFTWARE
    Microsoft
      Windows
        CurrentVersion
          Explorer
            Desktop
              NameSpace
                {MyGUID}

It doesn't show straight away. It does if you focus the desktop (minimize all, or click on the desktop somewhere), and hit F5. Or use this code to do just that programatically: (include the unit ShlObj in the uses clause, pidl is a variable of type PItemIDList)

  SHGetSpecialFolderLocation(GetDesktopWindow,CSIDL_DESKTOP,pidl);
  SHChangeNotify(SHCNE_UPDATEDIR,SHCNF_IDLIST,pidl,nil);

Ro IRC Client

2005-10-07 19:44  ro  freeware  [permalink]

[Ro icon]Ro is my second attempt at an easy-to-use IRC client, without too much of feature bloat and extra's. My first attempt, used Delphi's TListView with ViewStyle:=vsReport, but that wasn't stable, used up a lot of memory and GDI handles... And the colums weren't really what I was looking for. A while later I worked with InterExplorer's embeddable WebBrowser component a bit more, and thought of using HTML to output the IRC conversation transscript... It turns out to work quite nice, work nicely fast and use less memory and resources! Hope you like it also.

If (that's a big if) I ever work further on this one, these are a few things I thought of already:

Update: this project has gone open source! (in fact I don't really intend to put more work in). See this NLDelphi post, svn

Update 2015-07-08: for your convenience, I've also put it up on github: https://github.com/stijnsanders/ro#ro 

freeware/RoInstall.exe

Ro IRC Client

2005-10-07 19:50  r174  freeware  [permalink]

Ro IRC Client

[Ro icon]IRC is dead, long live IRC clients. Look beyond that slow limited Java IRC thing you get served on some website (did you even know it worked on IRC?), and get hold of a real thing to chat into the world.

DATEPART: The 'real' datepart

2005-10-10 16:42  i292  coding  [permalink]

Let's say you have a table where events were registered, with a datetime field, filled with the current time of the event. Now, how to get a new query that returns the totals per day...

In other languages, it's generally easy to extract only the 'date part' or the 'time part' from a DateTime type of variable. Some languages store the date+time as a floating point variable, the integer part denotes a number of days since a certain day in the past (e.g. 1900-01-01), and the fraction part denotes how far in the day the time part is.

But SQL (at least Microsoft SQL Server) doesn't really have that. There's a DatePart function, but that returns the day of the month, the month of the year...

After a bit of searching around this is apparently the most performant way to get only the date parts (actually, re-work the datetime values to have 'time part' '00:00:00.000'):

CAST(DATEDIFF([DAY], 0, datefield1) AS datetime)

siggma.net is gedaan!

2005-10-12 22:23  i298  weblog  [permalink]

De hosting is gestopt voor siggma.net. Ik had er mooi alles opgeruimd. De spam bleef tot op het laatste toekomen in mijn mailbox daar... Ik heb het domain nog voor wat langer, ik kijk of ik die ook naar hier kan krijgen zonder te veel kleurscheuren. Maar voor de rest is het hier te doen vanaf nu!

Telenet Group Holding Stock

2005-10-13 10:51  i299  beurs  [permalink]

TNET.BR: Basic Chart for TELENET GROUP HOLD - Yahoo! Finance

he hij staat er hier al bij...


date and time excedes 2038

2005-10-14 20:13  i305  coding  [permalink]

oops! Ik dacht dat we nog tot 2137 of zo hadden...

Cookies object, ASP 0200-2147467259
The date and time given for 'Expires' precedes Jan 1, 1980 or excedes Jan 19, 2038, 3:14:07 GMT.
Out of Range 'Expires' attribute


TreeBrowse

2005-10-14 23:11  r206  freeware  [permalink]

TreeBrowse

New version online! v1.0.2.20
This time with a self-installer! As I was suspecting it was a bit of a hassle to extract TB.exe to a suitable directory...

New in this version is a WhiteList, that does allow PopUp's on the sites listed on a file 'whitelist.txt'. You need to create the file yourself, and remind to write the URL's with "http://" to make sure they match the first part of longer URL's the browser gets.

I also got to work on the pop-up windows, and the strange behaviour with minimize, restore and switching from another application to them. It should all be in order now.

Feel free to add feature proposals, bug-reports or any suggestions. I might import the list of idea's I have already some time soon also.


IMDb: Born in Belgium

2005-10-18 14:23  i325  film tv  [permalink]

IMDb biography search

grappig om te zien! Zelfs de koning zit er tussen!


Delay a file copy until the next reboot

2005-10-21 10:43  i327  delphi  [permalink]

I have been looking for a while how to 'delay' a file-copy until the next reboot.
In searching the [[Microsoft Windows]] documentation, I have found the SetupApi functions, and they appear to be just what I need to make it work. Ported to Delphi, the code looks a little like this. The code I first had had some more exception-raising code in stead of a return value of boolean here, but feel free to build it up some more. I also provide a callBack routine that does a little more than absolutely neccessary, but that might come in handy of you want to do more with this single FileQueue. Note that I chose not to use the default callback routine here, which would handle all events with the proper dialogs and UI things.

interface uses Windows; type HSPFILEQ = THandle; function SetupOpenFileQueue: HSPFILEQ stdcall; function SetupCloseFileQueue(QueueHandle: HSPFILEQ): BOOL stdcall; function SetupQueueCopy(QueueHandle: HSPFILEQ; SourceRootPath: PChar; SourcePath: PChar; //optional SourceFilename: PChar; SourceDescription: PChar; SourceTagfile: PChar; //optional TargetDirectory: PChar; //optional TargetFileName: PChar; //optional CopyStyle: DWORD ) : BOOL stdcall; type PSP_FILE_CALLBACK_A=function(CONTEXT:pointer;NOTIFICATION:cardinal;PARAM1:cardinal;PARAM2:cardinal):cardinal stdcall; function SetupCommitFileQueue(Owner: HWND; QueueHandle: HSPFILEQ; //optional MsgHandler: PSP_FILE_CALLBACK_A; Context: pointer): BOOL stdcall; implementation function SetupOpenFileQueue; external 'setupapi.dll'; function SetupCloseFileQueue; external 'setupapi.dll'; function SetupQueueCopy; external 'setupapi.dll' name 'SetupQueueCopyA'; function SetupCommitFileQueue; external 'setupapi.dll' name 'SetupCommitFileQueue'; // CopyStyle values for copy and queue-related APIs const SP_COPY_DELETESOURCE = $0000001; // delete source file on successful copy SP_COPY_REPLACEONLY = $0000002; // copy only if target file already present SP_COPY_NEWER = $0000004; // copy only if source newer than or same as target SP_COPY_NEWER_OR_SAME = SP_COPY_NEWER; SP_COPY_NOOVERWRITE = $0000008; // copy only if target doesn't exist SP_COPY_NODECOMP = $0000010; // don't decompress source file while copying SP_COPY_LANGUAGEAWARE = $0000020; // don't overwrite file of different language SP_COPY_SOURCE_ABSOLUTE = $0000040; // SourceFile is a full source path SP_COPY_SOURCEPATH_ABSOLUTE = $0000080; // SourcePathRoot is the full path SP_COPY_IN_USE_NEEDS_REBOOT = $0000100; // System needs reboot if file in use SP_COPY_FORCE_IN_USE = $0000200; // Force target-in-use behavior SP_COPY_NOSKIP = $0000400; // Skip is disallowed for this file or section SP_FLAG_CABINETCONTINUATION = $0000800; // Used with need media notification SP_COPY_FORCE_NOOVERWRITE = $0001000; // like NOOVERWRITE but no callback nofitication SP_COPY_FORCE_NEWER = $0002000; // like NEWER but no callback nofitication SP_COPY_WARNIFSKIP = $0004000; // system critical file: warn if user tries to skip SP_COPY_NOBROWSE = $0008000; // Browsing is disallowed for this file or section SP_COPY_NEWER_ONLY = $0010000; // copy only if source file newer than target SP_COPY_SOURCE_SIS_MASTER = $0020000; // source is single-instance store master SP_COPY_OEMINF_CATALOG_ONLY = $0040000; // (SetupCopyOEMInf only) don't copy INF--just catalog SP_COPY_REPLACE_BOOT_FILE = $0080000; // file must be present upon reboot (i.e., it's needed by the loader); this flag implies a reboot SP_COPY_NOPRUNE = $0100000; {// never prune this file} // Operation/queue start/end notification. These are ordinal values. const SPFILENOTIFY_STARTQUEUE = $00000001; SPFILENOTIFY_ENDQUEUE = $00000002; SPFILENOTIFY_STARTSUBQUEUE = $00000003; SPFILENOTIFY_ENDSUBQUEUE = $00000004; SPFILENOTIFY_STARTDELETE = $00000005; SPFILENOTIFY_ENDDELETE = $00000006; SPFILENOTIFY_DELETEERROR = $00000007; SPFILENOTIFY_STARTRENAME = $00000008; SPFILENOTIFY_ENDRENAME = $00000009; SPFILENOTIFY_RENAMEERROR = $0000000a; SPFILENOTIFY_STARTCOPY = $0000000b; SPFILENOTIFY_ENDCOPY = $0000000c; SPFILENOTIFY_COPYERROR = $0000000d; SPFILENOTIFY_NEEDMEDIA = $0000000e; SPFILENOTIFY_QUEUESCAN = $0000000; // These are used with SetupIterateCabinet(). SPFILENOTIFY_CABINETINFO = $00000010; SPFILENOTIFY_FILEINCABINET = $00000011; SPFILENOTIFY_NEEDNEWCABINET = $00000012; SPFILENOTIFY_FILEEXTRACTED = $00000013; SPFILENOTIFY_FILEOPDELAYED = $00000014; // These are used for backup operations SPFILENOTIFY_STARTBACKUP = $00000015; SPFILENOTIFY_BACKUPERROR = $00000016; SPFILENOTIFY_ENDBACKUP = $00000017; // Extended notification for SetupScanFileQueue(Flags=SPQ_SCAN_USE_CALLBACKEX) SPFILENOTIFY_QUEUESCAN_EX = $00000018; SPFILENOTIFY_STARTREGISTRATION = $00000019; SPFILENOTIFY_ENDREGISTRATION = $00000020; //IFDEF _SETUPAPI_VER >= $0501 // Extended notification for SetupScanFileQueue(Flags=SPQ_SCAN_USE_CALLBACK_SIGNERINFO) SPFILENOTIFY_QUEUESCAN_SIGNERINFO = $00000040; //ENDIF // Copy notification. These are bit flags that may be combined. SPFILENOTIFY_LANGMISMATCH = $00010000; SPFILENOTIFY_TARGETEXISTS = $00020000; SPFILENOTIFY_TARGETNEWER = $00040000; // File operation codes and callback outcomes. const FILEOP_COPY = 0; FILEOP_RENAME = 1; FILEOP_DELETE = 2; FILEOP_BACKUP = 3; FILEOP_ABORT = 0; FILEOP_DOIT = 1; FILEOP_SKIP = 2; FILEOP_RETRY = FILEOP_DOIT; FILEOP_NEWPATH = 4; //callback context type TCallBackRaiseError=( cbrNone, cbrCopyError, cbrSourceNotFound, cbrDeleteError, cbrRenameError); TCallBackContext=record MediaNeededOnce,DelaySuccess:boolean; RaiseError:TCallBackRaiseError; end; function QueueFileCopyCallBack(Context: pointer; Notification: cardinal; Param1: cardinal; Param2: cardinal): cardinal stdcall; var ctx:^TCallBAckContext; begin ctx:=Context; case Notification of SPFILENOTIFY_DELETEERROR: begin ctx.RaiseError:=cbrDeleteError; Result:=FILEOP_ABORT; end; SPFILENOTIFY_RENAMEERROR: begin ctx.RaiseError:=cbrRenameError; Result:=FILEOP_ABORT; end; SPFILENOTIFY_COPYERROR: begin ctx.RaiseError:=cbrCopyError; Result:=FILEOP_ABORT; end; SPFILENOTIFY_NEEDMEDIA: begin if ctx.MediaNeededOnce then begin ctx.RaiseError:=cbrSourceNotFound; Result:=FILEOP_ABORT; end else begin ctx.MediaNeededOnce:=true; Result:=FILEOP_DOIT; end; end; SPFILENOTIFY_FILEOPDELAYED: begin ctx.DelaySuccess:=true; Result:=FILEOP_DOIT; end; else Result:=FILEOP_DOIT;//default: continue end; end; function QueueFileCopy(SrcPath,SrcFile,DestPath,DestFile:string; DeleteSource:boolean):boolean; var fq:HSPFILEQ; c:cardinal; ctx:TCallBackContext; begin //init callback context ctx.MediaNeededOnce:=false; ctx.DelaySuccess:=false; ctx.RaiseError:=cbrNone; fq:=SetupOpenFileQueue; c:= //SP_COPY_REPLACEONLY or SP_COPY_SOURCE_ABSOLUTE or //SP_COPY_FORCE_IN_USE or //SP_COPY_IN_USE_NEEDS_REBOOT or SP_COPY_NOSKIP; if DeleteSource then c:=c or SP_COPY_DELETESOURCE; if not(SetupQueueCopy( fq, PChar(SrcPath), nil, PChar(SrcFile), nil, nil, PChar(DestPath), PChar(DestFile), c ) ) then RaiseLastOSError; SetupCommitFileQueue(GetDesktopWindow,fq,@QueueFileCopyCallBack,@ctx);<BR>  //returns false on abort! don't RaiseLastOSError;<BR>  SetupCloseFileQueue(fq); Result:=ctx.RaiseError=cbrNone; end;

 


A (little) bit about 'diff'

2005-10-27 20:59  i332  coding  [permalink]

What is 'diff'? Let's say you want to know the differences between two text files. A most frequent real-life example: two versions of the same source file, for example each with updates from another user. But how to merge them.

Nice tools like ExamDiff Pro - Visual Diff Tool for File and Directory Compare are handy, but often not free. There's one provided in Visual Studio: Visual SourceSafe also, have a look at the history of a file, select two items in the list and hit difference...

But, inquisitive like we are, we need to get to the bottom of it. I want to have done it myself.

You might think, OK, two lists of lines, search a line on the 'left' in the list on the 'right', and if you find any, just forward the list on the right to that line, showing a piece of the list as 'not in the version on the right', and vice versa.

Not.

The best way to go at it is to get the best set of biggest chunks of data that's present in both documents. At least, I found out after [[Google]]ing my way onto Joe White's Blog, having a great set of enlightening exposees on his discovery of the diff algorithm.

A bit of Googling further, I found out which algoritm Perl's Algorithm::Diff was using, and used that and the original in SmallTalk, to get to this attempt in Delphi:

    start1:=0;
    finish1:=ls1.Count-1;
    start2:=0;
    finish2:=ls2.Count-1;
 
    SetLength(matchVector,ls1.Count);
    matches:=TMatchList.Create(Eq);
    links:=TLinkList.Create;
    //first prune
    while (start1<=finish1) and (start2<=finish2) and
      Eq(ls1[start1],ls2[start2]) do
     begin
      matchVector[start1]:=start2;
      inc(start1);
      inc(start2);
     end;
    while (start1<=finish1) and (start2<=finish2) and
      Eq(ls1[finish1],ls2[finish2]) do
     begin
      matchVector[finish1]:=finish2;
      dec(finish1);
      dec(finish2);
     end;
    for a1:=start1 to finish1 do matchVector[a1]:=-1;
 
    //with positions of interval (ls2,start2,finish2);
    for a2:=start2 to finish2 do matches.NoteMatch(ls2[a2],a2);
 
    SetLength(entries,finish2-start2+1);
    entryMax:=start2;
    for a2:=0 to finish2-start2 do entries[a2].Link:=-1;
 
    for a1:=start1 to finish1 do
     begin
      m:=matches.GetMatch(ls1[a1]);
      if Assigned(m) then
       begin
        b2:=-1;
        for mi:=m.Count-1 downto 0 do
         begin
          b1:=m[mi];
 
          if not(b2=-1) and (entries[b2-start2].tr>b1) and (entries[b2-start2-1].tr<b1) then
            entries[b2-start2].tr:=b1
          else
           begin
            b2x:=start2;
            while (b2x<entryMax) and (entries[b2x-start2].tr<b1) do inc(b2x);
 
            if (b2x<entryMax) then with entries[b2x-start2] do
             begin
              if tr=b1 then b2:=-1 else
               begin
                //assert tr>b1
                tr:=b1;
                b2:=b2x+1;
               end;
             end
            else
             begin
              //add!
              entries[entryMax-start2].tr:=b1;
              inc(entryMax);
              b2:=entryMax;
             end;
           end;
 
          //
          if not(b2=-1) then
           begin
            if b2<start2 then nl:=-1 else nl:=entries[b2-start2-1].Link;
            entries[b2-start2].Link:=links.AddLink(nl,a1,b1);
           end;
         end;
       end;
     end;
 
    if entryMax>start2 then
     begin
      nl:=entries[entryMax-start2-1].Link;
      while not(nl=-1) do
       begin
        links.GetLink(nl,a1,a2);
        matchVector[a1]:=a2;
       end;
     end;

voedselagentschap: cartografie vogelpest

2005-10-27 23:59  i335  actueel tv  [permalink]

oeioei

http://www.ngi.be/ai-ia/

[[death by slashdot]], maar dan op zijn Belgisch vermoed ik? Dan kom je eens op het nieuws, wordt je platgesurft...


A (little) bit about 'diff'

2005-10-31 22:34  r226  coding  [permalink]

A (little) bit about 'diff'

the first problems arise, with using this some more... I'll have a go at re-writing the last part (display loop) some time soon, to pick the largest chunk first, and then the largest left before and after, and again and again... (Unless you want to have a go at it!)