Laden...

Forenbeiträge von caldicot Ingesamt 51 Beiträge

31.05.2012 - 00:56 Uhr

Hi,

so ich bin's nochmal.

Ich habe inzwischen selber eine Lösung gefunden.
Wenn ihr mal das selbe Problem haben solltet, ich habe es so gelöst:


using Outlook = Microsoft.Office.Interop.Outlook;

public static Outlook.MAPIFolder GetInbox()
{
            Outlook.Application app = Globals.ThisAddIn.Application;
            Outlook.MAPIFolder currentFolder = app.ActiveExplorer().CurrentFolder;
            Outlook.Account account = GetAccountForFolder(currentFolder);
            Outlook.MAPIFolder inbox = account.DeliveryStore.GetDefaultFolder (Outlook.OlDefaultFolders.olFolderInbox);
}

private static Outlook.Account GetAccountForFolder(Outlook.MAPIFolder folder)
{
            // Obtain the store on which the folder resides.
            Outlook.Store store = folder.Store;

            // Enumerate the accounts defined for the session.
            return
                Globals.ThisAddIn.Application.Session.Accounts.Cast<Outlook.Account>().FirstOrDefault(
                    account => account.DeliveryStore.StoreID == store.StoreID);
}

Die GetAccountForFolder Methode gibt's von MS. Ich habe die For Schleife mittels LINQ ausgedrückt.

Viele Grüße
caldi

30.05.2012 - 21:48 Uhr

Hi,

ich stehe mal wieder vor einem Problem.

Ich habe ein Outlook Addin mit VSTO für Outlook2010 geschrieben.
Das Addin verarbeitet die selektierte E-Mail und soll diese anschließend verschieben.

Wenn nur ein Postfach vorhanden ist, funktioniert das auch mit folgendem Code:


            Outlook.MAPIFolder inBox = 
                Globals.ThisAddIn.Application.Application.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);

Danach wird irgendwann die Move Methode des MailItems aufgerufen. Das glaube ich ist hier nicht relevant.

Das Problem tritt auf, wenn mehrere Postfächer existieren.
Es wird eine E-Mail aus dem Postfach 2 ausgewählt und verarbeitet. Es wird aber immer in den Ordner des Postfachs 1 verschoben.

Nach etwas Debuggen habe ich rausgefunden, dass die Methode ActiveExplorer noch das richtige Postfach (also in diesem Bsp Postfach 2) zurück gibt. Bei der Session Property wird aber immer das Postfach 1 verwendet.

Wie kann ich denn eine E-Mail innerhalb eines Postfachs verschieben?

Ich hoffe ihr versteht was ich meine.
Ich habe dazu auch leider nichts gefunden, sondern nur die oben genannte Möglichkeit, wie ich an den Posteingang-Ordner komme.

Danke
caldi

03.05.2012 - 17:33 Uhr

Ich glaube das stimmt so nicht.
Ich dachte, dass .NET 4.0 eine Standalone Version ist und daher nicht .NET 2.0, 3.0, 3.5 mitliefert.
.NET 3.5 ist nur ein "Update" und bringt deshalb 2.0 und 3.0 mit. Daher kann man mit .NET 3.5 auch .NET 2.0 Applikationen ausführen?

.NET 2.0 war auch eine Standalone Version und es konnten keine .NET 1.0 Applikationen ausgeführt werden?

Natürlich kann zusätzlich zu .NET 4.0 das ältere 3.5 installiert werden.
.NET 4.5 ist wieder nur ein "Update" und deswegen wird .NET 4.0 mitgeliefert.

Korrigiert mich bitte, wenn das falsch ist.
Ich dachte das mal gelesen zu haben ...

22.03.2012 - 17:18 Uhr

Hi,

ich habe ein Problem und finde Google keine Lösung.
Ich schreibe ein kleines Programm, dass mit einem SystemFileWatcher ein Verzeichnis überwacht in dem TIF Dateien abgelegt werden. Die Tif Datei soll dann in einem neuen Fenster angezeigt werden.

Dazu habe ich folgende Methoden:


        private PicViewer _picViewer;
        private void FileSystemWatcherOnCreated(object sender, FileSystemEventArgs e)
        {
            string ext = Path.GetExtension(e.FullPath);
            if(ext == null)
                return;
            ext = ext.ToLower();

            if(ext != ".tiff" && ext != ".tif")
                return;

            lock (_lockObject)
            {
                    Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => ShowPicViewer(e.FullPath)));
            }
        }

        private static void ShowPicViewer(string filename)
        {
            _picViewer = new PicViewer();
            _picViewer.ShowFullScreen(filename);
        }

PicViewer ist das neue Fenster.
Hier gibt's die Methode ShowFullScreen.


        public void ShowFullScreen(string filename)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Open))
            {
                imgPicture.Source = BitmapFrame.Create(fs, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
            }

            Show();
            Topmost = true;
            WindowState = WindowState.Maximized;
        }

Es tritt eine IOException auf im Konstruktor des FileStreams.
Hier der StackTrace:


Stapel:
   bei System.IO.__Error.WinIOError(Int32, System.String)
   bei System.IO.FileStream.Init(System.String, System.IO.FileMode, System.IO.FileAccess, Int32, Boolean, System.IO.FileShare, Int32, System.IO.FileOptions, SECURITY_ATTRIBUTES, System.String, Boolean, Boolean)
   bei System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.IO.FileAccess, System.IO.FileShare, Int32, System.IO.FileOptions, System.String, Boolean)
   bei System.IO.FileStream..ctor(System.String, System.IO.FileMode)
   bei FaxViewer.PicViewer.ShowFullScreen(System.String)
   bei FaxViewer.MainWindow.ShowPicViewer(System.String)
   bei FaxViewer.MainWindow+<>c__DisplayClass3.<FileSystemWatcherOnCreated>b__1()
   bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
   bei MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
   bei System.Windows.Threading.DispatcherOperation.InvokeImpl()
   bei System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(System.Object)
   bei System.Threading.ExecutionContext.runTryCode(System.Object)
   bei System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object)
   bei System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   bei System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   bei System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   bei System.Windows.Threading.DispatcherOperation.Invoke()
   bei System.Windows.Threading.Dispatcher.ProcessQueue()
   bei System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
   bei MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
   bei MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
   bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
   bei MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
   bei System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
   bei MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
   bei MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
   bei System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
   bei System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
   bei System.Windows.Threading.Dispatcher.Run()
   bei System.Windows.Application.RunDispatcher(System.Object)
   bei System.Windows.Application.RunInternal(System.Windows.Window)
   bei System.Windows.Application.Run(System.Windows.Window)
   bei System.Windows.Application.Run()
   bei FaxViewer.App.Main()

Das merkwürdige ist:
Ich entwickle auf einem Win7 PC mit VS2010. Hier tritt das Problem nicht auf.
Auf einem Win XP SP3 Rechner tritt die Exception nach dem 2. Mal auf.
Also das erste Bild wird angezeigt, beim Zweiten tritt die IOException auf.
Auf beiden PCs ist .NET 4.0 Extended installiert. Kompilieren tue ich das Projekt gegen das .NET 4.0 Client Profile Framework.

Ich habe auch schon mit BitmapSource mit CacheOption.OnLoad, BeginInit, EndInit.
Jedesmal das selbe Ergebnis.
Windows 7 hat's jedesmal funktioniert.

Ich hab auch schon gelesen, dass es ein Bug in der Windows Imaging Component ist. Eine Lösung habe ich dazu noch nicht gefunden.

Hat jemand eine Idee wie ich das lösen kann?
Danke
caldi

16.03.2012 - 10:14 Uhr

Hi,

ich habe erst kürzlich auch Interprozesskommunikation benötigt.

Das Zyan Framework von Rainbird kann das ebenfalls bewerkstelligen und ist in der Anwendung sehr einfach.
Ich konnte damit Kommunikation von zwei Anwendungen schnell und problemlos umsetzen.

caldi

07.03.2012 - 15:01 Uhr

Hi,

ich brauch mal wieder eure Hilfe.
Ich habe zwei unabhängige Addins mit VS2010 und VSTO für MS Outlook 2010 geschrieben.

Beide Addins sollen auf den selben Ribbon Tab, aber in unterschiedliche Gruppen dargestellt werden.
Die Ribbons habe ich bisher mit dem Designer bearbeitet und nicht in XML konvertiert.

Bisher werden 2 Ribbon Tabs angelegt, die den selben Namen haben, und auf jedem Tab gibt's eine Ribbon Gruppe für das jeweilige Addin.

Natürlich habe ich schon gegoogelt, der einzige Hinweis, den ich gefunden habe, das Problem mit dem Designer zu lösen ist hier.

Allerdings kann ich die ControlId nicht verändern.

Wisst ihr vielleicht wie ich das Problem mit dem Designer lösen kann oder muss ich wirklich das Ribbon in eine XML konvertieren?

Danke
caldi

27.02.2012 - 21:35 Uhr

Hat keiner mehr eine Idee?
Ich konnte das Problem immer noch nicht lösen?

Würde das vielleicht mit Wix besser gehen?
Ich habe damit bisher keinerlei Erfahrung?

Danke
caldi

14.02.2012 - 23:55 Uhr

Hi,

ich habe testweise die Benutzerdefinierte Aktion "Installieren" gelöscht.
Dann wird der Dienst tatsächlich nicht registriert. Getestet habe ich es ohne dass der Dienst davor installiert war.

Daher verstehe ich nicht, warum der erste Lösungsansatz von Grumbler85 nicht funktionierte.

Ich habe außerdem probiert eine Condition bei der Installieren Aktion anzulegen.
Eine MSDN-Dokumentation habe ich dazu leider nicht gefunden.
Folgende Condtions habe ich bereits probiert:*(Not Installed) OR PREVIOUSVERSIONSINSTALLED *Not Installed *NOT Installed

Ich habe gelesen, dass die Anweisung case-sensitive ist.

Vermutlich sind die Bedingungen falsch und deswegen wird die Benutzerdefinierte Aktion trotzdem ausgeführt.

Habt Ihr vielleicht eine Idee, wie die Condition richtig heißen muss?

Danke
caldi

13.02.2012 - 12:56 Uhr

Ich habe gerade auch nochmal probiert, die Commit und Install Methode mit einem return zu beenden ohne die Base Methode oder irgend einen anderen Code auszuführen.
Leider ebenfalls ohne Erfolg.
Es scheint als würde die Dienst Registrierung nicht hier statt finden.

Könnt Ihr mir weiterhelfen?

10.02.2012 - 02:04 Uhr

irgendwie scheint es gar nicht zu klappen.
Ich habe jeweils einzeln die Commit Methode und die Install Methode so überschrieben, dass die base Methode nur dann aufgerufen wird, wenn der Dienst nicht bereits installiert ist.
Ich habe es mit beiden Methoden gleichzeitig versucht.
Jedesmal habe ich die Major Versionnummer erhöht und den ProductCode verändert (UpdateCode ist gleich geblieben). Der Dienst war zum Zeitpunkt der Installation aus.
Trotzdem kam jedesmal die selbe Fehlermeldung, dass der Dienst bereits installiert sei.

Ich bin etwas ratlos, an was es noch liegen könnte?

Danke
caldi

09.02.2012 - 18:03 Uhr

Ok, danke 😃
Du hast Dich vorher so sicher angehört, da bin ich gar nicht auf die Idee gekommen, dass ich eine andere Methode probieren könnte zu überschreiben ..

Ich melde mich, wenn ichs ausprobiert habe ..

09.02.2012 - 17:43 Uhr

Hi,

danke für den Tipp, ich habe versucht das umzusetzen leider funktioniert es nicht.
Zusätzlich zur Install Methode habe ich die OnAfterInstall Methode überschrieben um den Dienst nach der Installation automatisch zu starten.
So sieht der Code aus:


    [RunInstaller(true)]
    public partial class ProjectInstaller : System.Configuration.Install.Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();
        }

        public override void Install(IDictionary stateSaver)
        {
            if(!ServiceAlreadyInstalled(serviceInstaller.ServiceName))
                base.Install(stateSaver);
        }

        private static bool ServiceAlreadyInstalled(string serviceName)
        {
            ServiceController[] allServices = ServiceController.GetServices();
            return allServices.Any(sc => sc.ServiceName == serviceName);
        }

        protected override void OnAfterInstall(IDictionary savedState)
        {
            base.OnAfterInstall(savedState);

            ServiceController sc = new ServiceController(serviceInstaller.ServiceName);
            int count = 10;

            if (sc.Status == ServiceControllerStatus.Stopped)
            {
                sc.Start();
                while (sc.Status == ServiceControllerStatus.Stopped && count > 0)
                {
                    Thread.Sleep(1000);
                    sc.Refresh();
                    count--;
                }
            }
        }

Habe ich vielleicht irgendwas falsch gemacht?
Der Fehler bleibt der Selbe...

Danke
caldi

09.02.2012 - 17:16 Uhr

Das macht das Setup Projekt für mich.
Ich habe unter Ansicht->Benutzerdefinierte Aktionen das Dienst-Projekt zu allen 4 Kategorieren (Installieren, Commit ausführen, Rollback, Deinstallieren) hinzugefügt.
Damit wird der Dienst registriert.

09.02.2012 - 16:26 Uhr

Hi,

danke für Eure Antworten.
Ich habe gerade probiert die Versionsnummer an der dritten Stelle zu erhöhen.
Den ProductCode habe ich geändert. UpgradeCode ist gleich geblieben.

Leider ohne gewünschtem Ergebnis.
Beim Installieren kommt der selbe Fehler.

Könnte ich die Dienst Registrierung mit einem CustomInstaller bei bereits vorhandener Installation überspringen?

Habt Ihr noch eine Idee?

Danke
caldicot

09.02.2012 - 12:19 Uhr

Hi,

ich habe ein Setup Projekt gemacht, das einen Windows Dienst installiert. Das klappt auch.
Bei einem Update habe ich Assembly und die Setup Version erhöht.

Folgende Eigenschaften habe ich beim Setup gesetzt:*DetectNewerInstalledVersion = True *RemovePreviousVersions = True

Wenn ich aber das geupdatete Setup auf einer Maschine ausführe, auf der bereits der Windows Dienst installiert ist, kommt während dem Setup die Fehlermeldung "Der angegebene Dienst ist bereits vorhanden".

Ich hätte gehofft, das Setup entfernt die alte Installation bevor die neue Version installiert wird.
Oder überschreibt die alte Version mit der Neuen?

Könnte mir bitte jemand weiter helfen?

Danke
caldicot

08.02.2012 - 19:30 Uhr

Vielen Dank, jetzt klappt es.
An die DefaultView Eigenschaft hatte ich nicht gedacht.
Ich hätte gehofft, dass das die BindingSource für mich erledigt..

Jetzt habe ich für das 2. Binding ein extra DataView angelegt und es funtioniert.

Danke für die Hilfe
caldi

07.02.2012 - 23:44 Uhr

Hi,

ich brauche mal wieder Eure Hilfe.

verwendetes Datenbanksystem: <MS SQL Server Compact 3.5>

Das Szenario ist wie folgt:
Ich halte Daten in einem DataTable.
Zum Einen habe ich das DataTable mittels BindingSource an ein DataGridView A gebunden.
Mit einer TextBox kann der Benutzer die Daten filtern.
Ich reagiere auf das TextChanged Event der TextBox und ändere die Filter-Eigenschaft der BindingSource.

Zum Anderen ist das DataTable (nicht die BindingSource) direkt an eine DataGridViewComboBoxColumn eines zweiten DataGridViews B gebunden.

Wenn der Benutzer einen Suchtext in die TextBox eingibt, wird wie erwartet die entsprechenden Daten im DataGridView A angezeigt.

Gleichzeitig greift der Filter aber auch in der DataGridViewComoBoxColumn.
Das ist aber nicht beabsichtigt. In der DataGridViewComboBoxColumn sollen ungefiltert alle Werte aus der DataTable angezeigt werden.

Ich hätte erwartet, dass die Filterung nur durch die BindingSource "sichtbar" ist und das DataTable unverändert bleibt.

Ich hoffe Ihr versteht, was ich meine ...
Habe ich was falsch gemacht, oder wird der Filter wirklich auf das DataTable projeziert?

Vielen Dank
caldicot

05.02.2012 - 19:10 Uhr

Warum die Wiedergabe verzögert weiß ich nicht, aber du registrierst für jeden Aufruf der PlaySound-Methode ein neues Event für LoadCompleted.
Evtl. verzögert der Player dadurch schon ...

05.02.2012 - 17:32 Uhr

Hi,

ich hatte ein ähnliches Problem und habe mir vom Conrad eine Relaiskarte gekauft.
Die Relaiskarte kannst Du mit C# ohne größere Probleme ansteuern. Die Befehle sind gut dokumentiert.

Die hier sollte auf deine Bedürfnisse zutreffen:
Relaiskarte

Ich habe die mit 24V gekauft und die ersten Tests liefen erfolgreich.

Ein Beispiel Code in VB liegt auch bei.
Der ist auch im Download Bereich beim Conrad zu finden.

Viele Grüße
Caldicot

02.01.2012 - 19:18 Uhr

Hallo Abt,

danke für Deine Antwort.

diese Lösungen hatte ich auch schon gefunden.
Nur dachte ich, dass diese nicht zum Ziel führen:
Das CMS erkennt im Moment den Typ und kann ein Preview der EMail anzeigen.
In den Beispielen werden ja nur die Eigenschaften der Email serialisiert und nicht das ganze MailItem?

Ich war der Meinung, dass das ein Unterschied ist und das CMS den Typ daher nicht erkennt?
Oder liege ich damit falsch?

Oder verstehe ich die Beispiele falsch?

Viele Grüße
caldicot

02.01.2012 - 18:19 Uhr

Hi,

danke für Deine Antwort.
Schade, ich hätte gehofft, ich könnte mir das sparen...

Dann hilfts wohl nix und ich muss es weiterhin so machen, wie bisher.

Viele Grüße
Caldicot

31.12.2011 - 18:09 Uhr

Hi,

ich brauche mal wieder eure Hilfe.

Mittels Outlook Addin soll eine Email in ein ContentManagmentSystem geladen werden.
Die API des CMS erwartet das hochzuladende Objekt als byte[].

Ich habe bisher leider nichts gefunden, wie ich ein Mailitem in ein byte[] konvertieren kann.
MailItem ist nicht mit dem Attribut Serializable gekennzeichnet.

Im Moment nutze ich die SaveAs Methode des MailItems um ein Temp-File zu schreiben, dass ich anschließend mit einem FileStream wieder einlese. Danach lese ich den Stream in ein byte[] ein.

Ich habe bei Google nur das Stichwort IPersist Interface gefunden.
Allerdings weiss ich leider überhaupt nicht, wie ich ein COM Interface implementieren kann.

Gibt es vielleicht eine leichtere Möglichkeit oder könnt ihr mir ein Tipp geben, wie ich das IPersist Interface richtig implementiere?

Vielen Dank und guten Rutsch
caldicot

13.12.2011 - 14:31 Uhr

Das liegt daran, dass Dein ListView in der Form1 den Zugriffsmodifizierer "Private" hat.
Daher kannst du nur innerhalb der Klasse Form1 auf das ListView Objekt zugreifen.

12.12.2011 - 20:25 Uhr

Hi,

ich habe eine Bibliothek geschrieben zur Lizenzierung.
Bei der Installation soll ein Eintrag in der Registry statt finden und ein Lizenzfile angelegt werden.
Das klappt auch wunderbar.

Mein Problem betrifft das ErrorHandling.
Sollte z.B. das Schreiben in die Registry fehlschlagen, dann macht das Setup nicht mehr weiter, zeigt aber auch keinerlei Fehlermeldung an.

Hier ein Codeausschnitt:
(Die Methode ist gekürzt. Es finden zusätzlich ähnliche Überprüfungen statt, die als Beispiel ohne Relevanz sind. Variablen wie file oder regPath existieren. Es geht lediglich um die Fehlermeldung, die trotz der InstallException nicht angezeigt werden.)


 public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);

            try
            {
                string file = this.Context.Parameters["FilePath"];
                if (string.IsNullOrEmpty(file))
                    throw new ArgumentException();

                RegistryKey reg = Registry.LocalMachine.CreateSubKey(regPath, RegistryKeyPermissionCheck.ReadWriteSubTree);
                if (reg == null)
                    throw new AuthenticationException("user has no admin rights"); 
            }
            catch (ArgumentException)
            {
                throw new InstallException("Fehler.");
            }
            catch (AuthenticationException)
            {
                throw new InstallException("Rechte.");
            }
            catch(Exception ex)
            {
                throw new InstallException(ex.Message);
            }
        }

Ich bin nach dem Beispiel in InstallException Class vorgegangen.
Wenn aber eine Ausnahme auftritt, dann macht der Installer nichts mehr, der Fortschnitt bleibt unverändert und es kommt keine Fehlermeldung.

Wisst Ihr vielleicht was ich hier falsch mache?
Ich sehe keinen Unterschied zum Beispiel von MSDN.

Ich habe zu Testzwecken auch direkt als erste Anweisung der Install()-Methode eine InstallException geworfen, allerdings mit dem selben Ergebnis.

Danke
caldicot

14.11.2011 - 20:48 Uhr

Empfehlen kann ich auch Zyan, das von Rainbird entwickelt wird.
Es verwendet zwar .NET Remoting als Technologie, bietet aber Einsteigern eine sehr einfache Möglichkeit ein Server/Client Szenario zu verwirklichen...

Mir hat es die Arbeit ungemein erleichtert!

10.01.2011 - 07:50 Uhr

Hi,

ich tausche eigtl. nicht das ganze DataTable aus. (oder mir ist es nicht bewusst)

hier die Methode, die den neusten Eintrag vom Server lädt:


        private void LoadLatestStatusFromServer()
        {
            // Wenn der Aufruf nicht aus dem GUI-Thread kommt ...
            if (InvokeRequired)
                // Aufruf an den GUI-Thread delegieren
                Invoke(new Action(LoadLatestStatusFromServer));
            else
            {
                // Statustabelle vom Server abrufen
                DataSet.StatusDataTable table = AppServer.Service.GetLatestStatus();

                // Vom Server abgerufene Statusdaten ins lokale DataSet laden
                this._localDataSet.Status.Merge(table);
            }
        }

Die Tabelle wird aus mit dieser Methode nie verändert. Daher finde ich es komisch, wenn die Indices nicht übereinstimmen?!

EDIT:
Also ich habe das jetzt so gelöst:
Bei dem Event, mit dem der Server den Client benachrichtigt, dass ein neues Element vorhanden ist, schreibe ich das neue Element in eine Liste (die DataRow).
In einem Timer rufe ich die List.RemoveAll() Methode auf.

Das Prädikat, das ich der RemoveAll() Methode übergebe prüft, ob die die Zeile älter als x Sekunden ist (ich speichere ein DateTime in der Zeile).
Dann suche ich die Zeile in der BindingSource anhand der Zeit und Resete dann die Zeile der BindingSource.
Dann wird eben True bzw. False zurückgegeben, damit es ein Prädikat ist.

In der Paint Cell Methode prüfe ich natürlich, ob das zu zeichnende Objekt in der Liste steht und wähle dann eine andere Farbe.

Ich hoffe, das ist keine übermäßig unsaubere Lösung 😃

Danke für Deine Hilfe, das hat mich auf die richtige Fährte gebracht ! 😃

Viele Grüße
caldi

09.01.2011 - 22:59 Uhr

Hallo,

danke für Deine Antwort.
Die Idee finde ich gut. Leider klappt das bei mir noch nicht so ganz:

Den ListChangeType.ItemAdd erhalte ich nie. Nur Reset.
Meine Server Applikation benachrichtigt alle Clients, wenn ein neuer Eintrag vorhanden ist.
Die Clients holen sich dann diesen in Form einer DataTable (mit nur 1 Eintrag; dem Neusten) und mergen das Table dann in das lokale DataSet.

Nachdem ich aber ohnehin ein Event habe, das mich über einen neuen Eintrag informiert und ich diesen dann abhole, kann ich den neuen Eintrag ja auch hier abfangen und in ein Dictionary schreiben.
Das klappt auch.
Mein Problem ist jetzt, dass ich bei der Timer Methode, das ja das Alter prüft und dann die zu alten Einträge aus dem Dictionary entfernt, nicht weiss, wie ich nur diesen einen Datensatz neuzeichnen lassen kann. Das würde mir nämlich gut gefallen, dass nicht dass ganze DGV gezeichnet werden muss, sondern eben nur die paar neuen Einträge.
Kann ich da irgendwie eine Beziehung herstellen von einer DataRow zu der entsprechenden Zeile?

Ich habe das so versucht:
Beim eintreten des neuen Eintrag-Events wird die DataRow in eine List<DataRow> geschrieben.
Der Timer tickt alle 500ms.

Die Timer Methode sieht so aus:


        private void neuerEintragTimer_Tick(object sender, EventArgs e)
        {
            foreach (DataRow dr in this.newStatus)
            {
                DateTime time = (DateTime)dr["Zeit"];
                if (time.AddSeconds(5) > DateTime.Now)
                {
                    this.newStatus.Remove(dr);
                    int index = this._localDataSet.Status.Rows.IndexOf(dr);
                    this.StatusBinding.ResetItem(index);
                }
            }
        }

Allerdings ist der index den ich erhalte immer um 1 größer als die Anzahl der BindingSource.
Das verstehe ich nicht ganz, weil der gefundene Index ziemlich klein sein sollte und die BindingSource gar nicht weniger Elemente enthalten kann als das DataSet.
Das DataSet.Status ist ja die DataSource dieser BindingSource.
Finde ich sehr merkwürdig?
Habe ich was falsch gemacht?

Danke
caldi

09.01.2011 - 18:02 Uhr

Hi,

ich habe ein Problem.
Ich möchte gerne, dass eine neue Zeile eines DataGridViews für x Sekunden farblich hervorgehoben wird.
Ich weiss nicht so recht wie ich das anstellen kann.

Das DataGridView hat ja ein RowsAdded Event.
Das würde sich ja hier anbieten?

Für jeden neuen Eintrag benötige ich einen eigenen Timer der z.B. nach 5s tickt, weil ja jede neue Zeile individuell behandelt werden soll?!
Wie kann ich jetzt beim Tick des Timers genau auf diese eine Zeile zugreifen?
Die neuste Zeile ist es ja möglicherweise nicht, weil während dieser 5s schon wieder eine Neue dazu gekommen ist.
Kann ich das den EventArgs mitgeben?
Oder übergibt man sowas z.B. in das Timer.Tag Attribut?
Die DataGridViewRowsAddedEventArgs haben ja die Eigenschaft RowIndex.
Wobei, wenn eine neue Zeile hinzugefügt wird, der RowIndex ja verfäscht wird?

Ich habe mehrere DataGridViews und möchte bei jedem die neuen Zeilen hervorheben.
Woher weiss ich in der Tick Methode des Timers, welches DGV Auslöser war?
Oder muss ich für 3 DGVs alles 3x bauen?

Oder wäre es besser ein neu Zeichnen des DGV mittels Timer alle x Sekunden auszulösen und in dem Cell Painting Event die Zeitdifferenz prüfen und dann ggf. farblich hervorheben.

Ich hoffe ihr versteht mein Problem.

Danke für Eure Hilfe
caldi

13.11.2010 - 15:58 Uhr

Hallo Rainbird,

offensichtlich habe ich doch etwas falsch gemacht.
Aufgrund Deines Tipps habe ich Dein Zyan Projekt in meine Projektmappe eingebunden und die Verweise aktualisiert.

Der Fehler tritt nicht mehr auf.
In das DataTable (das ist die DataSource des DataGridViews) wird beim Event anstandslos der Eintrag hinzugefügt. Damit habe ich auch kein Problem mit dem Zugriff auf die GUI und dem Event auslösenden Thread.

Auch wenn's nicht direkt hier her gehört:
Beim Start des Clients werden alte Einträge vom Server geschickt und in den DataTable eingetragen. Der DataGridView zeichnet das auch sofort.

Wenn ich über das Event in die DataSource den neusten Eintrag hinzufüge, dann wird das DataGridView nicht neu gezeichnet. Erst beim Scrollen wird neu gezeichnet. Der Inhalt wird aber gesetzt, weil das neue Element nachdem Neuzeichnen vorhanden ist.
Meine Frage ist jetzt, warum das so ist, bzw. wie man das löst?
Mit .Update() habe ich es versucht, aber ohne Erfolg.

Sorry, da verstehe ich das Problem leider nicht.

Ich hätte hier zuerst probiert das so zuschreiben:


OnObjectAddedEvent(NotificationEventArgs.Empty);

Allerdings meckert der Compiler, weil NotificationEventArgs.Empty den Typ EventArgs zurück gibt, aber die Methode OnObjectAddedEvent den Typ NotificationEventArgs erwartet.
Mache ich da was falsch?
Oder ist die Lösung von unten genauso sauber?

Danke
caldi

12.11.2010 - 18:43 Uhr

Hallo Rainbird,

so ganz krieg ichs noch nicht hin.

Meine Klasse, die das Event beinhaltet sieht so aus:


 private static List<myObject> m_objectHistory = new List<myObject>();

        public event EventHandler<NotificationEventArgs> ObjectAddedEvent;

        protected virtual void OnObjectAddedEvent(NotificationEventArgs e)
        {
            if (ObjectAddedEvent != null)
            {
                ObjectAddedEvent(this, e);
            }
        }

        public bool addObject(string kennung, string status)
        {
            try
            {
                m_objectHistory.Add(new myObject(kennung, status));
                
                OnObjectAddedEvent(new NotificationEventArgs("")); 
// Hier kann ich nicht NotificationEventArgs.Empty mitgeben, weil der Getter den Typ 
// EventArgs zurück gibt. Und das darf ich ja nicht?

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

Auf dem Server schaut meine Event Veröffentlichung so aus:


 HttpCustomServerProtocolSetup protocolSetup = new HttpCustomServerProtocolSetup(Properties.Settings.Default.PORT, userMng, true);
            ZyanComponentHost host = new ZyanComponentHost("Test", protocolSetup);
            host.StartNotificationService();

            history.ObjectAddedEvent += host.PublishEvent("ObjectAddedEvent");

Auf dem Client habe ich das Event abonniert:



           HttpCustomClientProtocolSetup protocolSetup = new HttpCustomClientProtocolSetup(true);
            ZyanConnection connection = new ZyanConnection("http://localhost:10000/Test", protocolSetup, credentials, true); //credentials sind weiter oben definiert, das funktioniert bereits
            history = connection.CreateProxy<IHistory>();
            connection.SubscribeEvent("ObjectAddedEvent", proxy_ObjectAddedEvent);

Die Event-Methode soll in ein DataGridView das gerade hinzugefügte Element schreiben:
Kann ich hier mittels sender auch auf das Remote Objekt History zugreifen und direkt die lastEntry.. holen?
Im Moment ist history so global definiert, dass die Methode Zugriff auf den Proxy hat.


void proxy_ObjectAddedEvent(object sender, NotificationEventArgs e)
        {
            DataTable dt = (DataTable)this.dataGridView1.DataSource;
            DataRow dr = dt.NewRow();

            myObject item = history.getLatestEntry;

            dr["Zeit"] = item.zeit;
            dr["Kennung"] = item.kennung;
            dr["Name"] = item.name;
            dt.Rows.Add(dr);

            if (item.isMine)
            {
                this.dataGridView1["Kennung", 0].Style.BackColor = Color.Aqua;
                this.dataGridView1["Name", 0].Style.BackColor = Color.Aqua;
            }
        }

Wenn ich die Event-Methode im Debug durchlaufe, dann wird keine Exception geworfen, aber am Schluss, kurz bevor die Methode beendet werden würde, kommt von VS der Hinweis, dass eine Quelldatei fehlt:


Aufruflistenort:
Zyan.COmmunication.dll!Zyan.Communication.Notification.NotificationReceiver.FireNotifyEvent(object sender, Zyan.Communication.Notification.NotificationEventArgs e) Zeile 52

Quelldateiinformationen:
Quelle für "C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" wird gesucht. Checksum: MD5 {1c 38 a5 41 bd dd 7c 84 92 85 dd 50 20 e2 ba 2a}
Die Datei "C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" ist nicht vorhanden.
"C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" wird in Skriptdokumenten gesucht...
"C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" wird in Projekten gesucht.
Die Datei wurde nicht in einem Projekt gefunden.
In Verzeichnis "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src\" wird gesucht...
In Verzeichnis "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\" wird gesucht...
In Verzeichnis "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\atlmfc\src\atl\" wird gesucht...
In Verzeichnis "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\atlmfc\include\" wird gesucht...
In den Einstellungen zum Debuggen von Quelldateien für die aktive Lösung ist angegeben, dass der Benutzer nicht zum Suchen der Datei aufgefordert wird: C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs.
Die Quelldatei "C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" wurde nicht gefunden.

Edit:
Die Fehlermeldung krieg ich auch, bei der Authenticate() Methode.
Allerdings tritt der Fehler nur dann auf, wenn die Zyan.Communication.pdb Datei im Verzeichnis liegt.
Ist diese nicht vorhanden, funktioniert die Authenticate() Methode.
Bei dem Event auf dem Client bleibt das Programm jedoch auch ohne PDB Datei stehen, nur eben ohne Fehler Hinweis.

Habe ich was falsch gemacht?

Danke
caldi

12.11.2010 - 13:21 Uhr

Hallo Rainbird,

Ich kann mich gar nicht genügend bedanken 😃
Wirklich toll, wie Du mich unterstützt.

Nachdem Zyan ein besseres Authentifizierungssysteme integriert hat, als ich jemals selber zusammen stümpern könnte, habe ich gleich versucht dieses zu integrieren. Mit Erfolg.

Sowohl das Session Managment als auch das Permission Managment wird jetzt mit Zyan behandelt.
Danke für Deine sehr hilfreiche Beschreibung.

Ein kleines Problem hab ich noch:
Wenn Zyan eine WebException schmeißt, weil der Server nicht erreichbar ist, dann fange ich die ab und die LoginForm wird mit dem Fehler Hinweis erneut aufgerufen.

Wenn der User jetzt die LoginForm schließt, dann wird bei dem FormClosing-Event Enviroment.Exit(0) aufgerufen.
Allerdings stürzt hier das Programm ab, mit dem Hinweis, dass die WebException nicht behandelt wurde.

Ich verstehe nicht ganz warum, weil die ja nur beim Instanziieren von Zyan ausgelöst wird, falls kein Server zu erreichen ist?

Danke
caldi

P.S.
Dein Notification System habe ich noch nicht geschafft zu testen, mache ich im Laufe des Tages...

12.11.2010 - 02:40 Uhr

Hallo Rainbird,

HERZLICHEN DANK!
Probiere ich gleich morgen aus!

Wahnsinn wie schnell das bei Dir geht 😃

Nochmals Danke!
Viele Grüße
caldi

12.11.2010 - 02:27 Uhr

Hallo Rainbird,

und wieder herzlichen Dank für Deine schnelle und ausführliche Antwort.

Ich habe die Klasse entsprechend deinem Vorbild angepasst.
Die schaut jetzt so aus:


    [Serializable]
    public class UserWrongPasswordException : Exception, ISerializable
    {
        public UserWrongPasswordException()
        {
        }

        public UserWrongPasswordException(string message)
            : base(message)
        {
        }

        public UserWrongPasswordException(string message, Exception innerException)
            : base(message, innerException)
        {
        }

        protected UserWrongPasswordException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }
    }

Funktioniert leider immer noch nicht.

Stack Trace:

System.Reflection.TargetInvocationException wurde nicht behandelt.
Message=Ein Aufrufziel hat einen Ausnahmefehler verursacht.
Source=Zyan.Communication
StackTrace:
Server stack trace:
bei Zyan.Communication.ComponentInvoker.Invoke(String interfaceName, ArrayList outputPinCorrelationSet, String methodName, Object[] args)
bei System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
bei System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)
Exception rethrown at [0]:
bei System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
bei System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
bei Zyan.Communication.IComponentInvoker.Invoke(String interfaceName, ArrayList outputPinCorrelationSet, String methodName, Object[] args)
bei Zyan.Communication.ZyanProxy.InvokeRemoteMethod(IMethodCallMessage methodCallMessage)
Exception rethrown at [1]:
bei System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
bei System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
bei Shared.Userverwaltung.IUserverwaltung.login(String userName, String password)
bei Login.LoginForm.checkLogin() in C:\Users...\Login\LoginForm.cs:Zeile 79.
bei Login.LoginForm.bt_login_Click(Object sender, EventArgs e) in C:\Users...\Login\LoginForm.cs:Zeile 110.
bei System.Windows.Forms.Control.OnClick(EventArgs e)
bei System.Windows.Forms.Button.OnClick(EventArgs e)
bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
bei System.Windows.Forms.Button.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms. UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.RunDialog(Form form)
bei System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
bei System.Windows.Forms.Form.ShowDialog()
bei Login.LoginForm.ShowDialog() in C:\Users...\Login\LoginForm.cs:Zeile 46.
bei Client.Form1..ctor() in C:\Users...\Client\Form1.cs:Zeile 25.
bei Client.Program.Main() in C:\Users...\Client\Program.cs:Zeile 18.
bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()
InnerException: Shared.Userverwaltung.UserWrongPasswordException
Message=Eine Ausnahme vom Typ "Shared.Userverwaltung.UserWrongPasswordException" wurde ausgelöst.
Source=Server
StackTrace:
bei Server.Userverwaltung.Userverwaltung.login(String userName, String password) in C:\Users...\Server\Userverwaltung\Userverwaltung.cs:Zeile 135.
InnerException:

Dass Zyan ein Authentifizierungssystem dabei hat, habe ich gelesen.
Leider habe ich es nicht verstanden X(
Zu meiner Verteidung muss ich sagen, dass ich erst im 3. Semester bin 😉

In der Klasse die, die registrierte Benutzer speichert, habe ich das IAuthenticationProvider implementiert und die Methode Authenticate() implementiert.

Ich hab nicht verstanden wie ich mit dem AuthRequestMessage umgehen muss.
Das Objekt beinhaltet ja die vom User angegebenen User-Daten?
Muss der Client in den HashTable User und Password setzten?
Z.B. so:


authMessage.Credentials["name"] = "myUserName";
authMessage.Credentials["pw"] = "myPassword";

entsprechend dann serverseitig die Überprüfung...

Sorry ist bestimmt die absolute n00b Frage. Ich sehs einfach nicht...

Im Moment gebe ich bei erfolgreichem Login das MyUser Objekt des eingeloggten Users zurück.
Damit ich auf dem Client die Berechtigungsstufe abfragen kann.
Wird sowas in echt anders gelöst oder wie könnte ich das mit Zyan realisiseren?

Ich steh wie immer auf dem Schlauch 🙂
Danke für Deine Hilfe UND Deine Geduld.
caldi

12.11.2010 - 00:18 Uhr

Hi,

ich bin's schon wieder 😃
Ich bin über ein neues Problem gestolpert und weiß nicht weiter.

Mittels Zyan veröffentliche ich eine Klasse die eine eigene Exception werfen kann.

Die Exception schaut so aus:


    [Serializable()]
    public class UserWrongPasswordException : ArgumentException
    {
        public UserWrongPasswordException()
            : base()
        {
        }

        public UserWrongPasswordException(string message)
            : base(message)
        {
        }

        protected UserWrongPasswordException(SerializationInfo info, StreamingContext sctxt)
            : base(info, sctxt)
        {
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }
    }

Wenn auf dem Client die Methode der Klasse aufgerufen wird, die diese Exception wirft, bekomme ich eine TargetInvocationException: "Ein Aufrufziel hat einen Ausnahmefehler verursacht".
In der InnerException steht "Der Wert liegt außerhalb des erwarteten Bereichs".
Ich kann aber mit der Fehlermeldung nichts anfangen. Welcher Wert / Bereich ist denn gemeint?

Mittels Debug sehe ich, dass die Exception Klasse aufgerufen wird, und erst danach der Fehler zustande kommt.

Wenn ich Google zu Exception und Remoting frage, finde ich nur den Hinweis, dass die Klasse Serializable sein muss, Konstuktor und GetObjectData beinhalten muss.

Hab ich irgendwas falsch gemacht?
Oder funktionieren auch Exception nicht so leicht via Remoting?

Danke für Eure Hilfe.
Caldi

10.11.2010 - 15:56 Uhr

Hallo,

ich habe mein Bug gefunden.
Es hatte NICHTS mit der Serialisierung zu tun 👅

Ich lese aus einer CSV die Namen aus.
Die CSV war ANSI Codiert, ich habe aber UTF8 gelesen eben um Umlaute zu erkennen.

Jetzt habe ich die CSV UTF8 kodiert und siehe da: Jetzt funktionieren auch Umlaute vor und nach der Serialisierung bzw. Deserialisiserung 8)

Sorry, da war ich völlig auf der falschen Fährte 🙂

Vielen Dank für Eure Hilfe
caldi

10.11.2010 - 13:00 Uhr

Hi,

hier meine Methoden zur Serialisiserung:

Konstuktor:


        public Status(SerializationInfo info, StreamingContext ctxt)
        {
            this.m_kennung = (string)info.GetValue("kennung", typeof(string));
            this.m_name = info.GetValue("name", typeof(string));
            this.m_status = (string)info.GetValue("status", typeof(string));
            this.m_farbe = (Color)info.GetValue("farbe", typeof(Color));
            this.m_isMine = proofMine();
            this.m_zeit = (DateTime)info.GetValue("zeit", typeof(DateTime));
        }

Hat er hier ein Problem mit dem Cast?
Ist info.GetString() besser?

GetObjectData:


        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("kennung", this.m_kennung);
            info.AddValue("name",  this.m_name);
            info.AddValue("status", this.m_status);
            info.AddValue("farbe", this.m_farbe);
            info.AddValue("zeit", this.m_zeit);
        }

Danke
caldi

10.11.2010 - 11:27 Uhr

Nach meiner Deserialisierung sind die Umlaute komische Zeichen.
Ich habe aber nichts an der Kodierung geändert oder ähnliches.
Ich rufe die oben gepostete Methoden auf und nach der Deserialisiserung sind eben die Umlaute weg.

10.11.2010 - 10:29 Uhr

Hi,

ich bin mir nicht 100% sicher wo die Umlaute verloren gehen.
Wenn ich serialisiert habe und mir das File mit Notepad++ anschaue, dann kann er hier keine Umlaute darstellen.

Jetzt kann natürlich auch Notepad++ falsch lesen.
Ich nehme an, dass das schon beim Schreiben passiert beim BinaryFormatter.

Wie könnte ich denn das rauskriegen, wann das passiert?
Im Debug habe ich nicht gesehen, dass ich einen Stream-Inhalt "anschauen" kann.

EDIT:
Hier meine deserialize-Methode


        public static T deserialize<T>(string file)
        {
            if (!File.Exists(file))
            {
                throw new FileNotFoundException();
            }

            T obj;
            Stream stream = File.Open(file, FileMode.Open, FileAccess.Read);
            BinaryFormatter bFormatter = new BinaryFormatter();
            obj = (T)bFormatter.Deserialize(stream);
            stream.Close();
            return obj;
        }

Danke für Deine Hilfe und sorry für die dummen Fragen 😃
caldi

10.11.2010 - 10:08 Uhr

Hi,

sorry ich steh grad aufm Schlauch.

Ich seh bei MSDN niergends, dass der FileStream eine Kodierung annimt. Nur der StreamWriter, den ich aber nicht hernehme, weil ich ja das Objekt mit dem BinaryFormatter serialisieren und ins File schreiben will.

Sorry, ich versteh grad überhaupt nix ?(

Danke
caldi

10.11.2010 - 09:09 Uhr

Hi,

danke für eine Antwort.
Allerdings komm ich trotzdem nicht so recht weiter.

Wo müsste ich denn das Encoding ändern?
Ich dachte die Strings in C# wären alle Unicode?
Und dem BinaryFormatter kann ich keine Kodierung mitgeben?

Könntest du bitte etwas genauer erklären was du meinst?

Danke
caldi

10.11.2010 - 07:39 Uhr

Hallo Rainbird,

danke für deine Hilfe.
Ich werde versuchen das anhand des Beispiels hinzukriegen. 😃

Ich versuche, ein Standard Zyan Benachrichtigungs-Feature noch bis Ende der Woche fertig zu bekommen. Wenn es fertig ist, sage ich Bescheid.

Das klingt ja super 😉

Vielen Dank für deine Mühen.
caldi

09.11.2010 - 22:43 Uhr

Hi,

ich versuche eine Klasse mit dem BinaryFormatter zu serialisieren.
Das funktioniert auch grundsätzlich.

In der Klasse habe ich einen Konstuktor zur Deserialisierung angelegt:


public Status(SerializationInfo info, StreamingContext ctxt)

und eine Methode zur Serialisierung:


public void GetObjectData(SerializationInfo info, StreamingContext ctxt)

Hier der Code der Serialisierungs-Methode:

        
public void bool serialize(string file, Object obj)
{
FileStream stream = new FileStream(file, FileMode.Create);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, obj);
stream.Close();
}

Dabei gehen aber Umlaute der String-Attribute der Klasse verloren.
Ich habe niergends einen Hinweis gefunden, wie man sowas lösen könnte.

Den XMLSerializer will ich eigtl. nicht hernehmen, da die Klasse immutabel sein soll und ich - wenn ich das richtig verstanden habe - Getter und Setter für alle serialisierbaren Attribute und einen Default-Konstuktor für die Klasse benötige.
In dem Konstuktor werden die Werte der Attribute gesetzt und deswegen will ich keinen Default-Konstruktor zulassen.

Gibt es wirklich keine andere Lösung?
Muss ich hier die XMLSerializer hernehmen.

Vielen Dank
caldi

09.11.2010 - 14:50 Uhr

Hallo Rainbird,

Danke für deine schnelle Antwort.

Wäre das ein Beispiel für das von dir beschriebene Zwischenstück?
.NET Remoting - Events, Events? Events!

oder das?

Events and Delegates in Remoting

Habe leider keine echte Idee, wie ich sowas implementieren kann. 😦

Schön zu hören, dass dieses Problem zukünftig mit Zyan leicht zu lösen sein wird 😃

Viele Grüße
caldi

09.11.2010 - 09:00 Uhr

Hi,

hier die ganze Exception.

Würde das denn grundsätzlich mit dem Event funktionieren oder ist das sowieso konzeptionell zu vermeiden?

"System.Reflection.TargetInvocationException" wurde aufgefangen.
Message=Ein Aufrufziel hat einen Ausnahmefehler verursacht.
Source=mscorlib
StackTrace:
Server stack trace:
bei System.RuntimeMethodHandle._SerializationInvoke(IRuntimeMethodInfo method, Object target, SignatureStruct& declaringTypeSig, SerializationInfo info, StreamingContext context)
bei System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
bei System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
bei System.Runtime.Serialization.ObjectManager.DoFixups()
bei System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
bei System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
bei System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryRequestMessage(String objectUri, Stream inputStream, Boolean bStrictBinding, TypeFilterLevel securityLevel)
bei System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)
Exception rethrown at [0]:
bei System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
bei System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
bei Zyan.Communication.IComponentInvoker.Invoke(String interfaceName, ArrayList outputPinCorrelationSet, String methodName, Object[] args)
bei Zyan.Communication.ZyanProxy.InvokeRemoteMethod(IMethodCallMessage methodCallMessage)
Exception rethrown at [1]:
bei System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
bei System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
bei Shared.Komponenten.ITest.add_MyEvent(EventHandler`1 value)
bei Client.Form1.Form1_Load(Object sender, EventArgs e) in C:\Users...\Client\Form1.cs:Zeile 31.
InnerException: System.IO.FileNotFoundException
Message=Die Datei oder Assembly "Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" oder eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.
Source=mscorlib
FileName=Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
FusionLog=WRN: Protokollierung der Assemblybindung ist AUS.
Sie können die Protokollierung der Assemblybindungsfehler aktivieren, indem Sie den Registrierungswert [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) auf 1 festlegen.
Hinweis: Die Protokollierung der Assemblybindungsfehler führt zu einer gewissen Leistungseinbuße.
Sie können dieses Feature deaktivieren, indem Sie den Registrierungswert [HKLM\Software\Microsoft\Fusion!EnableLog] entfernen.

   StackTrace:  
        bei System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark&amp; stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)  
        bei System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark&amp; stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)  
        bei System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark&amp; stackMark, Boolean forIntrospection, Boolean suppressSecurityChecks)  
        bei System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark&amp; stackMark, Boolean forIntrospection)  
        bei System.Reflection.Assembly.Load(String assemblyString)  
        bei System.Runtime.Serialization.FormatterServices.LoadAssemblyFromString(String assemblyName)  
        bei System.Reflection.MemberInfoSerializationHolder..ctor(SerializationInfo info, StreamingContext context)  
   InnerException: 
08.11.2010 - 16:04 Uhr

Hi,

Ich habe eine Klasse, die 2 Listen beinhaltet. Darin habe ich 2 Events implementiert (wie in [Lösung] Problem mit EventHandler beschrieben)
Für jede Liste gibt es eine Add-Methode().
Beim Aufruf der Methode wird das Event gefired.
Lokal funktioniert das wunderbar.

Die oben erwähnte Klasse publishe ich mit Rainbirds Zyan.
Die Datenübertragung funktioniert auch.
Ich kann auf die Listen zugreifen, Funktion Remote ausführen etc.
Ich hätte jetzt gerne, dass der Server dem Client mittels Event mitteilt, wenn ein neues Element in die Liste eingefügt wurde.

Leider funktioniert das nicht mehr.
Ich kann am Client dem Event kein EventHandler zuweisen.

Client Code:


HttpCustomClientProtocolSetup protocolSetup = new HttpCustomClientProtocolSetup(true);
ZyanConnection connection = new ZyanConnection("http://localhost:10000/Test", protocolSetup);

ITest proxy = connection.CreateProxy<ITest>();

//Diese Zeile funktioniert nicht mehr:
proxy.MyEvent += new EventHandler<EventArgs>(proxy_MyEvent);

Die Ausnahme TargetInvocationException wird geworfen.
Kann mir bitte jemand helfen?

Ich habe auch schon gelesen, dass Events via Remoting nicht geeignet sein sollen.
Gibt es hier eine bessere Möglichkeit dem Client aufmerksam zu machen, dass ein neues Element hinzugefügt wurde?

Ich hoffe ich habe mich klar und verständlich ausgedrückt 😃

Vielen Dank
caldi

08.10.2010 - 14:42 Uhr

Hallo,

herzlichen Dank für Deine Hilfe.

Ich werde das gleich nach Deiner Vorlage ausprobieren und Rückmeldung erstatten.

Vielen Dank und viele Grüße
caldi

EDIT:
Danke, jetzt hat's geklappt.
Ich kann leider nicht ganz nachvollziehen, warum es bei mir nicht auf Anhieb ging.

Danke für dein nettes Beispielprojekt 😃

caldi

06.10.2010 - 19:08 Uhr

Hi Zusammen,

ich habe ein Problem.
Ich habe nicht sonderlich viel Erfahrung mit Remoting, deswegen hat es mich besonders gefreut eine Klasse zu finden, die das kann: Zyan

Mit einem Objekt, habe ich das auch hingekriegt.

Allerdings möchte ich gerne mehere Objekte damit zur Verfügung stellen.
Und ich habe keine echte Idee wie das funktioniert:


ZyanComponentHost host = new ZyanComponentHost("test", 8080);
host.RegisterComponent<ImyClass, myClass>();

wie kann ich jetzt, ein weiteres Objekt publishen?
Geht das einfach indem ich ein weiteres Component registriere?


host.RegisterComponent<ImyClass2, myClass2>();

Clientseitig habe ich prinzipiell das gleiche Problem:
Das funktioniert noch:


ZyanConnection connection = new ZyanConnection("tcp://localhost:8080/test");
ImyClass proxy = connection.CreateProxy<ImyClass>();

Wie kann ich jetzt ein Proxy für das 2. Objekt machen?
So habe ich es bereits probiert, ohne Erfolg:


ImyClass2 proxy2 = connection.CreateProxy<ImyClass2>();

Ich habe es auch mit 2 Connections probiert, ebenfalls ohne Erfolg.

Kann mir bitte jemand helfen?

Vielen Dank und viele Grüße
caldi

04.10.2010 - 19:32 Uhr

Hi,

also ich habe gerade mein Problem gefunden.
Meine Klasse hieß User und mein Interface entsprechend IUser.
Anscheinend sind das "Schlüsselwörter" für C# und es wird etwas anderes damit verknüpft.
Ich habe die Klasse jetzt neu angelegt und myUser bzw myIUser genannt. Jetzt klappt es.

Eine Frage habe ich noch, die ich auf der Zyan Homepage nicht gefunden habe:
Es steht dort, dass man mehrere Objekte publishen kann.

Allerdings schaff ich das nicht.
Probiert hätte ich das einfach, indem ich noch ein host.registerComponent ausgeführt hätte.
Da bringt er auch keinen Fehler.

Aber ich weiss nicht, wie ich am Client dann 2 proxies verwenden kann.


myIUser userProxy = connection.CreateProxy<myIUser>();

zusätzlich anzugeben funktioniert nicht.

Oder muss ich für jede Componente eine eigene Connection aufbauen?

Hättest Du bitte hier ein kleines CodeSnippet da, indem ich das sehe 😃

Vielen Dank für die Hilfe
caldi

02.10.2010 - 14:17 Uhr

Hallo,

ich habe gerade Zyan getestet. Da hat es sofort funktioniert.
Ich weiss nicht woran das liegen könnte.

Vorallem habe ich es anschließend nochmal mit dem RemotingHelper probiert, da hat es dann auch geklappt...

Danke für die Hilfe

Danke
caldi

30.09.2010 - 23:36 Uhr

Danke für Deine schnelle Antwort.

Der Client wirft die Ausnahme.
Port habe ich variiert - von 9400 bis 10000.
Server und Client laufen auf dem selben PC unter dem selben Benutzer, und der ist lokaler Administrator (kein Domänen Admin)

Habe auch schon zum Test, alle Firewalls etc. ausgeschaltet. Leider ohne Erfolg.
An dem .NET Versionsunterschied kann es nicht liegen?
Firewalls habe ich eigtl. auch ausgeschlossen, da ja Dein Projekt ohne Probleme funktioniert.
Dein Projekt basiert auf .NET 2.0, wenn ich das richtig gesehen habe.
Im Moment nutze ich eben wie gesagt 4.0.

Danke für den Link, damit werde ich mich mal näher beschäftigen 😃
So groß ist mein Projekt nicht.
Ich versuche eigtl. nur mit Remoting zurecht zu kommen.
Geplant ist 2 Klassen zu publishen, die beide ein static DataSet mit je 2 Tables enthalten.

Ich probiere das Ganze nochmal mit dem Zyan Projekt.
Selbstversändlich gebe ich Rückmeldung, wenn ich Erkenntnisse habe.

Fast vergessen:
Ich nutze Windows 7 Ultimate 64bit

Danke
caldi