Das habe ich auch schon ausprobiert mit
Set objMessageItem2 = objArchive.GetArchiveEntries("default")
gibts bei mir ein Fehler. Egal ob ich default in die Klammer schreibe oder 0 für DvFilterNone
Das habe ich auch schon ausprobiert mit
Set objMessageItem2 = objArchive.GetArchiveEntries("default")
gibts bei mir ein Fehler. Egal ob ich default in die Klammer schreibe oder 0 für DvFilterNone
Vor allem übergibst Du hier ja auch die Anzahl und nicht die ID...oder sehe ich das falsch? Er erwartet aber den Pfad und den Dateinamen ohne Endung (ID) von Dir.
Stimmt da hab ich wohl etwas falsch verstanden. Obwohl in der Doku "//Get entry based on filename" steht. Na dann werd ich mir jetzt einmal Gedanken machen wie ich an den Dateinamen ran komme.
Gruß Janosch
EDIT:
Leider klappt es mit Datei und Pfadnamen bei mir nicht
hier mal ein Auszug aus der API-Doku, wobei oItem das MessageItem2 sein soll und ich bei mir natürlich noch den Servernamen eingetragen habe und "in" mit "out" ausgetauscht habe und dazu ein existierenden Filenamen mir rausgesucht habe.
ZitatSet oItem = oArchive.GetArchiveEntryByID (“\\Server\david\archive\user\10004000\in\filename.001”)
Wenn möglich sollte man immer das MessageItem2 nutzen, dass ist ca. um den Faktor 10 schneller als das MailItem/MessageItem.
Welche Infos bekommt man aus dem MessageItem2 nicht, die man aus dem MailItem bekommt?
Wie gesagt ist mein tool hier eine Anzeige von Terminen (also Kalendereinträge). Die Position eines Termins bekomme ich, wie erwähnt, nur über die MessageItem2 heraus, da ich nur hier das RecNo "finden" konnte. Die eigentlichen Terminoptionen wie Ort, Datum, Uhrzeit, ob ein Reminder eingeschaltet ist, usw, bekomme ich über die MessageItem2 nicht heraus.
Da musste ich dann wieder gezielt MessageItem verwenden und in meiner Schleife dann quasi sowas wie
foreach MessageItem AS CalendarItem
...
verwenden, um an diese informationen zu kommen. Also Datum usw...
Gleiches Problem hatte ich aber auch bei einem anderen tool, wo ich alle Attachments in einem Archiv mit einem Rutsch exportiere. auch hier musste ich mittels MessageItem AS MailItem mir erst das MailItem herholen, um an die attachments zu kommen.
CalendarItem und MailItem lassen sich jedoch leider nicht aus MessageItem2abfragen, sondern nur MessageItem. aus diesem Grund gehe ich bei meinem Termintool beides durch.
MessageItem2 halt nur wegen der Pos in der archive.dat, um in der anzeige einen termin klickbar zu machen um den dann in David direkt anzeigen zu können.
Leider klappt es mit Datei und Pfadnamen bei mir nicht
hier mal ein Auszug aus der API-Doku, wobei oItem das MessageItem2 sein soll und ich bei mir natürlich noch den Servernamen eingetragen habe und "in" mit "out" ausgetauscht habe und dazu ein existierenden Filenamen mir rausgesucht habe.
GetArchiveEntryByID<--- !!
Ein unc-Pfad zu einem Eintrag ist kein ID.
Hier mal mein Code (etwas zusammengeschnitten um die Stellen rauszunehmen, die hier nicht relevant sind):
procedure Tfrmtermine.reloadTimer(Sender: TObject);
var oArchive : Archive;
oMessageItems : MessageItems;
oMsg: CalendarItem;
oMessageItems2 : MessageItems2;
oMessageItem2 : MessageItem2;
oFields : Fields;
oField : Field;
oStartTime, oEndTime: TDateTime;
vorschau: TDateTime;
recno, last, subject: string;
tage, tag, i, o, pos, count, terminzeilen : integer;
begin
oApp := CreateOLEObject('DVOBJAPILIB.DvISEAPI') as IApplication;
oAccount := oApp.Logon('server', username, passwd, Unassigned, Unassigned, 'AUTH');
try
oArchive := oAccount.GetSpecialArchive(DvArchivePersonalCalendar);
Caption := 'Meine Termine ('+oAccount.User.Name +')';
oMessageItems := oArchive.AllItems;
oMessageItems2 := oArchive.GetArchiveEntries('default');
vorschau := DateUtils.IncWeek(now,2);
pos := 0;
count := 0;
terminzeilen := 0;
for i := 0 to oMessageItems.Count-1 do begin
oMsg := oMessageItems.Item(i) AS CalendarItem;
oMessageItem2 := oMessageItems2.Item(i);
recno := '';
oFields := oMessageItem2.Fields AS Fields;
for o := 0 to oFields.Count - 1 do begin
oField := oFields.Item(o);
if oField.Name = 'RecNo' then
recno := VarToStr(oField.Value);
end;
oStartTime := oMsg.StartTime;
oEndTime := oMsg.StopTime;
subject := oMsg.Subject;
end;
finally
end;
end;
Alles anzeigen
Wie Du sehen kannst hole ich mir BEIDE Typen.
oMessageItems := oArchive.AllItems;
oMessageItems2 := oArchive.GetArchiveEntries('default');
Dann gehe ich die MessageItems durch um an den CalendarItem zu kommen (könntest du bei dir weg lassen)
for i := 0 to oMessageItems.Count-1 do begin
oMsg := oMessageItems.Item(i) AS CalendarItem; // könntest du bei dir weg lassen
Dann hole ich mir das gleiche Item (schleife i) aus MessageItem2
oMessageItem2 := oMessageItems2.Item(i);
und ermittele die RecNo...
recno := '';
oFields := oMessageItem2.Fields AS Fields;
for o := 0 to oFields.Count - 1 do begin
oField := oFields.Item(o);
if oField.Name = 'RecNo' then
recno := VarToStr(oField.Value);
end;
Der Aufruf ist bei mir dann z.B.
'dvwin32.exe \\server\david\archive\user\1001c000\cal /POS='+RecNo
Gleiches Problem hatte ich aber auch bei einem anderen tool, wo ich alle Attachments in einem Archiv mit einem Rutsch exportiere. auch hier musste ich mittels MessageItem AS MailItem mir erst das MailItem herholen, um an die attachments zu kommen.
Ich habe mir vor einiger Zeit mal ein kleines Tool zum testen programmiert. In erster Linie ging es mir dabei um den Geschwindigkeitsvergleich. Dabei kann ich wahlweise über das MailItem (also MessageItem) oder das MessageItem2 auslesen. Ich bekomme über beide Varianten sowohl die RecNo als auch Datum und andere Felder.
Werde da nachher nochmal reinschauen und dann hier den Code posten.
Ein unc-Pfad zu einem Eintrag ist kein ID.
Beim David sehr wohl. Du kannst hier eine Nummer übergeben oder aber den FullPath, so steht es auch in der API Hilfe:
GetArchiveEntryByID (Archive)GetArchiveEntryByID
Returns a object of IMessageItem2 type, based on the ID of the object.
Example: //Get entry based on filename:
Dim oAccount as DvApi32.Account
Dim oArchive as DvApi32.Archive
Dim oItem as DvApi32.MessageItem2
Set oArchive = oAccount.GetSpecialArchive(DvArchivePersonalIn)
Set oItem = oArchive.GetArchiveEntryByID (“\\Server\david\archive\user\10004000\in\filename.001”)
//Get entry based on ID:
Dim oAccount as DvApi32.Account
Dim oArchive as DvApi32.Archive
Dim oItem as DvApi32.MessageItem2
Dim oID as Long
oID = 5
Set oArchive = oAccount.GetSpecialArchive(DvArchivePersonalIn)
Set oItem = oArchive.GetArchiveEntryByID (oID)
Alles anzeigen
So, hier mal ein bisschen Code (C#.NET) und die Screenshots zum Beweis.
Bei dem Tool kann man wie gesagt wählen, ob man ein Verzeichnis per MailItem oder MessageItem2 auslesen will. Bei ersterem hat man dann noch die Wahl über die Fields zu gehen, oder direkt auf die Felder und Methoden vom MailItem zuzugreifen.
Da ich noch einige andere Sachen eingebaut habe, wie z.B. die Option den Vorgang als Thread zu starten, werde ich den Code aufs wesentliche kürzen.
Zunächst mal mein Code für Logon und Archive auslesen.
dvsrv = "server";
path = "\\david\\archive\\user\\10004000\\in";
//DvAPI Logon
oApp = new DavidAPIClass();
oApp.LoginOptions = DvLoginOptions.DvLoginForceAsyncDuplicate;
oAcc = oApp.Logon(dvsrv, "", "", "", "", "NOAUTH");
oArchive = oAcc.ArchiveFromID("\\\\" + dvsrv + "\\" + path.Replace("\\","\\\\"));
// Archive einlesen
oMessageItems = oArchive.AllItems;
oMessageItems2 = oArchive.GetArchiveEntries(DvItemFilterBits.DvFilterOnlyEMail);
if (mailitem == true)
{
itemcount = oMessageItems.Count;
} else {
itemcount = oMessageItems2.Count;
}
// Hier folgt dann eine for-Schleifenanweisung anhand von itemcount
// weiter wird dann geprüft, welche Optionen eingestellt wurden.
Alles anzeigen
Die erste Variante ist das MailItem ohne Fields
if (oMessageItems.Item(i).Type == DvItemTypes.DvEMailItem)
{
oMailItem = (MailItem)oMessageItems.Item(i);
oFields = (Fields)oMailItem.Fields;
oFrom = (Address)oMailItem.From;
lvi = new ListViewItem(oMailItem.Subject);
lvi.SubItems.Add(oFrom.EMail);
lvi.SubItems.Add(oMailItem._ID.ToString());
lvi.SubItems.Add(oMailItem.StatusTime.ToString());
}
Alles anzeigen
Die zweite Variante ist das MailItem mit Fields
if (oMessageItems.Item(i).Type == DvItemTypes.DvEMailItem)
{
oMailItem = (MailItem)oMessageItems.Item(i);
oFields = (Fields)oMailItem.Fields;
oFrom = (Address)oMailItem.From;
lvi = new ListViewItem(oMailItem.Subject);
lvi.SubItems.Add(oFields.Item("SRFrom").Value.ToString());
lvi.SubItems.Add(oFields.Item("RecNo").Value.ToString());
lvi.SubItems.Add(oFields.Item("StatusTime").Value.ToString());
}
Alles anzeigen
Die dritte Variante ist über das MessageItem2
if (oMessageItems2.Item(i).Type == DvItemTypes.DvEMailItem)
{
oMessageItem2 = (MessageItem2)oMessageItems2.Item(i);
oFields = (Fields)oMessageItem2.Fields;
lvi = new ListViewItem(oMessageItem2.Subject);
lvi.SubItems.Add(oFields.Item("SRFrom").Value.ToString());
lvi.SubItems.Add(oFields.Item("RecNo").Value.ToString());
lvi.SubItems.Add(oFields.Item("StatusTime").Value.ToString());
}
Alles anzeigen
Wie gesagt komme ich so über das MessageItem2 an so gut wie alle Informationen heran.
Gruß Jens
Hallo,
ich lese gerade alle Adressen eines David Server aus. Un möchte danach eine Adresskarte öffnen lassen mit folgendem befehl:
\\server\david\Clients\Windows\DVWIN32\DVWIN32.EXE /POS=???? /SA=34
ich komme nur nicht an die richtige /POS
Das _ID und UID funktioniert nicht, wie komme ich denn an die "RecNO" ?
habs rot markiert
mein Code in vb.net
Dim book As New List(Of adress_book.st_adresses)
Dim oApp As DvApi32.DavidAPI
Dim oAcc As DvApi32.Account = Nothing
Dim oArchive As DvApi32.Archive
' Dim oAddress As DvApi32.Address
Dim oAddressbook As DvApi32.AddressBook
Dim nc As New adress_book.st_adresses
TryoApp = CType(CreateObject("DVOBJAPILib.DvISEAPI"), DvApi32.DavidAPI)
oApp.LoginOptions = DvApi32.DvLoginOptions.DvLoginForceAsyncDuplicateoAcc = oApp.Logon("", "", "", "", "", "AUTH")
If pfad = "" Then Exit Sub
oArchive = oAcc.GetArchive(pfad)
oAddressbook = oArchive.AddressBook
If oAddressbook.Count = 0 Or Nothing Then
Exit Sub
End IfDim ac As Integer = 1000For Each c As DvApi32.Address In oAddressbook
ac += 1
nc.fax = c.AddressItem.FaxNumber
nc.firma = c.AddressItem.Company
nc.firstname = c.AddressItem.FirstName
nc.name = c.DisplayName
nc.ort = c.AddressItem.City
nc.plz = c.AddressItem.ZipCode
nc.tel_gesch = c.AddressItem.PhoneOffice
nc.tel_handy = c.AddressItem.PhoneMobile
nc.tel_home = c.AddressItem.PhonePrivate
nc.street = c.AddressItem.Street
nc.mail = c.AddressItem.EMail
nc.owner = "david"
nc.adress_time = Now.ToString
nc.david_id = c.AddressItem._ID.ToString
nc.david_id2 = c.UID.ToString
'c.Account.
Try
If IsNothing(c.AddressItem.Picture) = False Thennc.bild = Image.FromFile(CStr(c.AddressItem.Picture))
End If
Catch ex As Exception
nc.bild = Nothing
End Try
nc.id = ac
book.Add(nc)
Next
adress.adress_adddavidbook(book, pfad)
oAcc.Logoff()Me.Close()
Catch ex As Exceptionexep.send_error("error in d_import", "", ex.Message)
If Not oAcc Is Nothing Then
oAcc.Logoff()
End If
Exit SubEnd Try
Alles anzeigen
Hallo,
_ID kann in VB soweit ich weiß nicht funktionieren, da es ein Zeilentrenner ist, oder?
Die UID ist die User ID denke ich. Existiert aber nur, wenn Du die Address vom lokalen Adressbuch generierst.
Zumal die auch aus der Address und nicht dem AddressItem kommt, das sind unterschiedliche Objekte. Die Address bezieht sich nicht auf einen physikalischen Eintrag. AddressItem ist das womit Du arbeiten musst.
Die _ID bzw. RecNo ist eine fortlaufende Zahl die die Position des Eintrages im Archive wiederspiegelt. Diese kann sich durch Änderungen im Archive aber ändern. D.h. wird der Eintrag an Pos 5 gelöscht, hat man eine Lücke, die 5 gibt es nicht mehr. Bis zur nächsten Datenbereinigung, dann wird die _ID neu durchnummeriert von 1-n.
An die RecNo kommst Du über die API Fields.
Ich versuch mich mal in VB:
Gruß Jens
P.S.: Du solltest mal Deine Objektnamen überdenken (c, ac, nc, ...), das verbessert die Leserlichkeit ungemein, vor allem auch wenn Du nach längerer Zeit mal an den Code ran musst.
P.P.S.: Steht aber auch schon oben in dem Beispielcode von mir, da allerdings in C#.
Doch das ._ID Funktioniert kommt der selber wert heraus wie bei c.AddressItem.Fields.Item("RecNo").Value
Es ist erst ein Zeilentrenner wenn ein leezeichen vor dem unterstrich ist.
//Edit hat sich erledigt.
Hallo,
das _ID und RecNo das gleiche ist, ist klar.
Was war denn Dein Problem?
Gruß Jens
Ich wollte durch die dvwin32.exe eine adresskarte anzeigen lassen. Nur wenn ich ihm die recno per /POS
Übergebe sagt mir David das es die Position in David archive nicht gibt.
P.s. Die objektnamen sind schon gewohnheit weil ich zu lange mit assembler gearbeitet habe. Aber ich komm
Gut klar damit.
Hi,
das ursprüngliche Problem ist mir schon klar gewesen, das hast Du oben ja schon geschrieben.
Ich meinte auch eher, was Dein Problem war, dass es mit der POS nicht klappte. Aber ich vermute es lag an dem fehlenden Pfad, oder?
Man sollte die Lösung des eigenen Problems immer posten, da andere User ein ähnliches Problem haben könnten.
Habe das ganze eben mal in C# mit Adressen getestet, folgender Aufruf klappt einwandfrei:
Process.Start("\\\\server\\david\\clients\\windows\\dvwin32\\dvwin32.exe",
"\\\\server\\david\\archive\\address /POS=id /SA=34");
Also wie in der KB beschrieben zuerst den Pfad zur Client EXE (kann natürlich genauso gut auf die lokale Installation zeigen, den Pfad könnte man sich aus der Registry holen), dann den Pfad zum Ordner in dem die Adresse / die Nachricht liegt, dann die Angabe der ID oder der RecNo für den Parameter /POS. Das /SA=34 wird so 1:1 übernommen.
Die "id" habe ich in diesem Beispiel aus einer DataGridView-Zelle die vorher mit eingelesenen Daten aus David befüllt wurde. Die ID wurde dabei über "AddressItem._ID" eingelesen. Über die Fields mit der RecNo sollte das genauso funktionieren.
Gruß Jens
Ich habe dasselbe Problem wie Don Manfred und bytefresser, die Bestimmung von Recnos für den /Pos Parameter zum Aufruf des TIC für eine beliebige ältere Nachricht.
Während Don Manfred mit seiner Lösung theoretisch schon richtig liegt, ist bytefresser m.E. auf deren praktischen Schwachpunkt gestoßen: "verschobene" Recnos durch gelöschte Records.
Das ist auch bei mir das Problem, d.h. viele (nicht alle) von Don Manfreds Methode gelieferte Recnos sind nicht korrekt. Das hat zur Folge, dass man entweder eine falsche Nachricht öffnet oder man bekommt die Meldung "API-Fehler: Invalid Position in Archiv.dat".
Irgendwer gab den Rat, dass man auch jedesmal die komplette oMessageItems2 durchlaufen und den Betreff vergleichen könne um die passende Recno zu finden. Da es aber mehrere Nachrichten mit identischem Subject geben kann, müßte zusätzlich noch die Zeit verglichen werden und dazu müssen erst Datumsformate gecastet werden. Etwas mühsam also.
Weiß wirklich niemand eine bessere Lösung für die zuverlässige und effiziente Bestimmung des Recnos mit Delphi?
Gruß,
Steffen
Hallo Steffen,
das hängt ja davon ab, was genau Du machen willst.
Wenn Du "JETZT" das Archive durchläufst und mit den RecNo arbeitest, ist doch alles gut.
Problematisch wird es nur, wenn Du die Daten speichern willst - aber warum solltest Du das tun?
Und dann kannst Du immer noch auf den FileName gehen und Dir damit dann die RecNo holen.
Die Verschiebung der RecNo passiert ja auch erst nachdem die Datenbereinigung durchgelaufen ist, also quasi am nächsten Tag.
Nochmal:
RecNo ist für die temporäre Nutzung vollkommen in Ordnung, für die langfristige Speicherung sollte man den FileName oder eine eigene Property nutzen.
Gruß Jens
PS: Beschreib doch mal Deine Anforderung.
Hallo Jens,
ich schreibe in Delphi ein Tool, das Kalendereinträge (inkl. Gruppenkalendern) anzeigt und ausdruckt.
Klappt soweit alles sehr gut - zum Teil Dank deiner Hilfe.
Daneben soll durch Doppelklick auf einen Termin dieser im TIC zur Bearbeitung geöffnet werden können.
Dazu verwende ich zur Ermittlung des /POS= Parameters DonManfreds Code:
oMsg := oMessageItems.Item(i) as CalendarItem;oMessageItem2 := oMessageItems2.Item(i);
oFields := oMessageItem2.Fields as Fields;
for n := 0 to oFields.Count - 1 do
begin
oField := oFields.Item(n);
if oField.Name = 'RecNo' then
begin
recno := VarToStr(oField.Value)
end;
end;
Alles anzeigen
Wie gesagt liege ich mit dieser Ermittlung des Recnos in vielen Fällen daneben, interessanterweise aber nie weiter als 1.
D.h. die "echte" Recno (die, mit der ich den gewünschten Termin öffnen kann) liegt um 1 höher als die vom o.g. Code ermittelte Recno.
Ich verstehe einfach nicht wieso.
Gruß,
Steffen
Hallo Steffen,
wenn Du die Daten "live" einliest dürfte das eigentlich nicht passieren...
Warum machst Du eigentlich eine Schleife durch die Fields? Kann man mit Delphi nicht direkt auf die Fields zugreifen?
Bei C# ginge das so:
Das Du so oft daneben liegst kann ich mir nicht erklären. Denn wie erwähnt, bevor die Datenbereinigung nicht gelaufen ist, stimmen die Werte immer noch überein, selbst wenn ein Eintrag gelöscht wurde. Die Neusortierung wird durch die nächtliche Datenbereinigung initialisiert (läuft die bei euch vielleicht tagsüber? Kontrolliere mal die Einstellungen im Admin)
Gruß Jens
Hallo Jens,
ich weiss nicht wieso aber Recno und _ID sind NICHT in allen Fällen gleich.
Kann das Datenkorruption sein?
Egal, jedenfalls bekomme ich so stets die korrekte Recno:
oMsg := oMessageItems.Item(i) as CalendarItem;
recno := oMSG._ID; // NICHT so: recno := Item('Recno').Value;
Gruß,
Steffen
Hallo Steffen,
wirklich seltsam. Lt. API Doku ist recNo = der ID des MessageItem.
Sogar der Hinweis auf die automatische Bereinigung ist bei allen dreien (MessageItem.get__ID, MessageItem2.get__ID und Field_RecNo) gleich:
ZitatAfter the autom. Archive Purge the ID can have another RecNo (ID). The ID (RecNo) isn't fixed.
Allerdings habe ich ehrlich gesagt bisher auch nicht beide gegenübergestellt, da ich meistens mit dem FileName arbeite und dann mit der _ID.
Gruß Jens
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!