Wenn Du mit dBase zufrieden bist... Wieso migrierst du nicht einfach auf die
MSDE... Man muss ja nicht gleich alle features nutzen?
Zu Deinem Problem mit dem Exklusivzugriff: Du kannst ja bei einem Fehler eine Message an alle Nutzer schicken (per 'mail' broadcast). Die kappen die Verbindung, Du reparierst den Müll, dann eine Mail, das Du fertig bist und fertig...
Zum Thema mail (geht nur bei Domänen, soweit ich weiss):
Der Empfänger erzeugt ein mail-hande, indem er ein 'mailslot' mit irgendeinem Namen (Hier: "Client") erzeugt.
Delphi-Quellcode:
Procedure TMailReceiver.CreateMailSlot;
Begin
aPath := '\\.\mailslot\Client';
fHandle := CreateMailSlot(PChar(aPath), 0, MAILSLOT_WAIT_FOREVER, nil);
End;
Offiziel geht der Empfang so: Ich eröffne den mailslot *nicht* mit MAILSLOT_WAIT_FOREVER, sondern mit einem Timeout und schaue dann immer wieder nach, ob was angekommen ist. Die Anzahl der Bytes wird zurückgeliefert. Dann hole ich die Daten ab. Das hat den Vorteil, das ich beliebig lange Nachrichten verschicken kann, aber den Nachteil, das ich eben 'pollen' muss.
Ich mache das Anders: Ich setze mich einfach auf das
Handle und vereinbare eine maximale Länge. Sobald was angekommen ist, weiss ich auch, wieviele Bytes die Nachricht enthält...
Delphi-Quellcode:
procedure TMailReceiver.Execute;
Var
aSize : DWord;
begin
While Not Terminated Do Begin
SetLength (fMessage, fMaxLength); // fMessage ist ein privates String-Feld...
if ReadFile(fHandle, PChar(fMessage)^, fMaxLength, aSize, nil) Then Begin
If not terminated Then Begin
SetLength (fMessage, aSize);
Synchronize (DoOnMailReceived);
End
End
end;
Der Sender macht Folgendes:
Delphi-Quellcode:
Procedure SendMail (aComputer, aSlotName, aMessage : String);
var
Bytes: DWord;
aPath : String;
aHandle : THandle;
begin
If aComputer = '' Then Exit;
aPath := '\\' + aComputer + '\mailslot\' + aSlotName;
aHandle := CreateFile(PChar(aPath), GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
try
if aHandle = INVALID_HANDLE_VALUE then
If aComputer='*' Then
SendMail('.',aSlotName, aMessage)
Else
Raise EInOutError.CreateFmt('Cannot create mailslot %s\%s',[aComputer,aSlotName])
else
If not WriteFile(aHandle, Pointer(aMessage)^, Length(aMessage), Bytes, nil) Then
If aComputer='*' Then
SendMail('.',aSlotName, aMessage)
Else
Raise EInOutError.CreateFmt('Cannot write to mailslot %s\%s',[aComputer,aSlotName]);
finally
if aHandle <> INVALID_HANDLE_VALUE Then
CloseHandle(aHandle);
end;
end;
Wenn ich als Computernamen ein '*' übergebe, wird die Nachricht an ALLE Computer in der Domäne verschickt. Um also, an den Computer 'FOO' (der ein mailslot mit Namen 'BAR' erzeugt hat und wartet...) eine Nachricht zu schicken, rufe ich einfach
"Sendmail ('FOO','BAR','Hello foo')" auf. Um eine Nachricht an ALLE Computer zu schicken, benutze ich "Sendmail ('*','BAR','Hello foo')".
Bevor ich hier gepeitscht werde: Es geht auch mit UDP, aber ich habs nunmal mit den mailslots gemacht