Laden...

Forenbeiträge von Lumbra Ingesamt 115 Beiträge

10.08.2009 - 22:28 Uhr

Auch wenn ich nicht unbedingt aus der Ecke komme meine ich, dass besser sei, über die A67 zu fahren.

09.08.2009 - 17:42 Uhr

Google, der erste Eintrag... RSS Feed erstellen

09.08.2009 - 16:02 Uhr

Schau mal, der erste Eintrag...C# Windows Firewall

09.08.2009 - 01:02 Uhr

War ja auch nur eine Idee - aber ich gebs zu - DARAUF hatte ich dann nicht geachtet... 😉

09.08.2009 - 00:44 Uhr

Ok, das einzige, was ich auf die schnelle gefunden habe ist dies hier

Symphony IMAP Backup

Ob das die Mails allerdings im XML-Format speichert wage ich zu bezweifeln, allerdings hat es eine Synchronisierungsfunktion, die permanent mitläuft - dazu ist es Freeware...

09.08.2009 - 00:37 Uhr

Willst Du das Backup Server- oder Clientseitig durchführen?

09.08.2009 - 00:27 Uhr

--- Anmerkung: Das ganze Thema ist für mich (noch) zu hoch, aber einen Frage hab ich da doch ---

@dein.Tod:

  1. Du sagst, es soll ein Browsergame werden - inwieweit macht es da noch Sinn wirklich die Millisekunden zu beachten? Allein die Latenz zwischen User, also Browser und Server dürfte da doch schon größer sein, oder irre ich mich da?

  2. Warum liest Du alle Events aus, die in den nächsten 15 Minuten stattfinden - würden da nicht auch die nächsten 30 Sekunden reichen? Von aussen betrachtet sieht mir das nach doppelter Arbeit aus...

08.08.2009 - 19:42 Uhr

Hab zwar keine Ahnung, ob die was taugt, aber hier mal ein Link:

NotesForGallery

08.08.2009 - 11:15 Uhr

Du kannst dir aber das Leben mit einem netten Makro für Regionen erleichtern.

Das ist mal ein feines Makro 😃 Habs direkt mal übernommen. Danke!

07.08.2009 - 22:03 Uhr

Hmm, ich hab grad mal durchgezählt - meine Methode, aus der dieser Codeschnipsel stammt hat insgesamt 87 Zeilen - mit Leerzeilen - da frag ich mich jetzt aber schon, wie ich das noch kürzer bekomme... Aber das ist ein anderes Thema...

Regions allerdings benutze ich schon - hauptsächlich um Methodengruppen zu organisieren...

07.08.2009 - 21:48 Uhr

Ja, die Sache mit den Regions ist mir schon bekannt - nur um mal eben was wegen der "besseren" Übersicht mit Regions zu falten, finde ich schon was aufwändig.

Da das ja auch wieder nur zusätzlicher Code ist, wirds dann in der nicht gefallteten Version nur noch unübersichtlicher...

07.08.2009 - 21:39 Uhr

für Schleifen wie z.B. FOR oder für Abfrage wie z.B. IF wären solche automatische Falten schon sinnvoll, denn diese besitzten ja einen definierten Anfangs- und Endpunkt ( meist "{" + "}").

Genau das meine ich...

In VS gibts die Falten ja standardmäßig nur bei Methoden und Klassen(soweit ich weiß).

Ja, und das ist ein bisserl wenig...

07.08.2009 - 21:37 Uhr

Sowas hier meine ich:


do                <-Code-Falte beginnt
{
    if (!fStopThread)                <-Code-Falte beginnt....
    {
        String line;
        line = sr.ReadLine();
        if (line.Contains(suchstring))
        {
            for (int j = 0; j < zuLesendeZeilen; ++j)
            {
                //if (line.Contains(suchstring) && j >= 0)
                //{
                //    if (j == 1)
                //    {
                //        j = 0;
                //    }
                //    else
                //    {
                //        j = 1;
                //    }
                //}
                w.WriteLine(line);
                line = sr.ReadLine();
            }
            w.WriteLine(line);
            w.WriteLine("");
        }
    }                <-Code-Falte endet
    else
    {
        return;
    }
}
while (!sr.EndOfStream);                <-Code-Falte endet

Das gibt natürlich sehr viele Code-Faltungen - aber vielleicht gibts ja etwas, dass innerhalb der Methoden die nächsten zwei oder drei Ebenen falten kann...

07.08.2009 - 21:02 Uhr

Hallo zusammen,

ich habe schon ein paar mal nach einer Funktion gesucht, die es mir ermöglicht sowohl Kommentare als auch Schleifen etc. mit Code-Falten zu versehen. Ich hab nicht unbedingt Lust an allen möglichen Stellen, regions einzufügen.

Ich hab schon mal das Addin SmartOutline ausprobiert, aber es ist nicht das, was ich Suche. Ich kann da zwar Regions einfügen, aber das ist mir in der Form zu umständlich...

Vielleicht habt Ihr ja eine Idee für mich?

04.08.2009 - 23:55 Uhr

Dito

Windows Vista 32bit
2048 x 1152

04.08.2009 - 23:49 Uhr

Habs geändert und es geht jetzt! Welche Bedeutung hat die "updates.xml" in der ZIP-Datei eigentlich? Da steht auch noch ein c drinne...

04.08.2009 - 21:44 Uhr

Deine GUI hängt weil der Thread in dem moemnt auf die Antwort des Webservers wartet. Pack das ganze am besten in einen eigenen Thread oder in einen Background Worker dann hast du das Problem nicht mehr.

Ja das hab ich mir schon gedacht. Allerdings wollte ich das Threading in meinem Projekt sowieso nochmal komplett überarbeiten.

ThreadPool BackgroundWorker etc...

04.08.2009 - 21:28 Uhr

Hmm, hab das Visual Studio nochmal neu gestartet - komischerweise kommt da auch keine mehr... Aber der Check schlägt fehl - keine Updates vorhanden, obwohl eines drauf ist...

Und irgendwie hängt die Applikation kurz, sobald der Check läuft...

04.08.2009 - 19:02 Uhr

@Zony, danke für den Code - hat mir weitergeholfen

@EvilMM, ja, ich hab die alte verwendet - hatte nicht mehr geschaut, ob da eine neue DLL dabei war...

Allerdings bin ich nach einigem Rumprobieren immer noch nicht weiter. Bei mir schlägt der Check() auf neue Updates mit eine NullReferenceException fehl. Das einzige was in meinem Objekt aber "null" ist, sind die AuthorizationValues.

Was muss ich denn da reinschreiben? Hier mal mein Code:


            SelfUpdate SUpdate = new SelfUpdate();
            DataTypes.ProxyServer Proxy = new DataTypes.ProxyServer();
            DataTypes.ReleaseInfo CurrentAppVersion = new DataTypes.ReleaseInfo();
            DataTypes.UpdateCheckResult UpdateCheckResult = new DataTypes.UpdateCheckResult();

            Proxy.Address = "http://www-proxy.netcologne.de";
            Proxy.Port = 8080;
            Proxy.Username = "";
            Proxy.Password = "";
            Proxy.Type = DataTypes.ProxyType.Http;

            CurrentAppVersion.VersionNumber = Assembly.GetExecutingAssembly().GetName().Version.ToString();

            SUpdate.CurrentReleaseInfo.VersionNumber = CurrentAppVersion.VersionNumber;
            SUpdate.GuiLanguage = DataTypes.Language.German;
            SUpdate.UpdatePath = "http://meinServer/meineAnwendung";

            SUpdate.ServerAuthentication.Mode = DataTypes.ServerAuthenticationMode.HttpBasic;
            SUpdate.ServerAuthentication.Username = "meinUser";
            SUpdate.ServerAuthentication.Password = "meinPasswort";
            SUpdate.Proxy = Proxy;

            SUpdate.Check();

04.08.2009 - 00:25 Uhr

Hallo EvilMM,

sehr feines Tool - funktioniert bei mir (fast) reibungslos!

Nur mit den Proxy-Einstellungen zum Update hab ich ein Problem:

Nach den Informationen des alten Wiki hab ich dann folgendes gemacht.....


KSettings.Proxy = @"http://www-proxy.netcologne.de:8080";
KSettings.ProxyUsername = "";
KSettings.ProxyPassword = "";

Trotzdem bekomm ich dann die anghängte Fehlermeldung. Dieses Problem hatte ich übrigens schon mit dem K_Updater.

Was brauchst Du jetzt für Infos von mir, um das Problem nachvollziehen zu können?

01.08.2009 - 22:17 Uhr
  
//Parametriesierter Start eines Threads  
//StartReading ist die Methode die im neuen Thread ausgeführt wird,  
//dateien ist das Objekt, dass an die Methode übergeben wird  
new Thread(StartReading).Start(dateien);  

Wie gesagt: Lieber den ThreadPool verwenden!

Das mit dem Parametrisierten Thread gefällt mir auch nicht so. Siehe mein Edit weiter oben

01.08.2009 - 22:09 Uhr

Hallo sbirg,

genau damit hab ich mich in der letzten Zeit auch beschäftigt. Neben den Turotials hier findest Du auch beim Codeproject eine ziemlich umfrangreiche Einleitung zu Threads und co... Thread-Tutorial auf CodeProject

Ich hab das bei mir wie folgt gelöst. In meinem Form wähle ich Dateien aus die verarbeitet werden sollen. Die Verarbeitung beginnt nach einem Klick auf "Start":

(Der Code funktioniert so natürlich nicht, da ich fast alles rausgeschmissen hab, was fürs Threading unwesentlich ist)


private void StartButton_Click(object sender, EventArgs e)
{
    progressBarMarquee.Style = ProgressBarStyle.Marquee;
    progressBarMarquee.MarqueeAnimationSpeed = 1;

    progressBarFiles.Style = ProgressBarStyle.Continuous;
    progressBarFiles.Minimum = 0;
    progressBarFiles.Maximum = completeSize;
    progressBarFiles.Value = 0;

    //Parametriesierter Start eines Threads
    //StartReading ist die Methode die im neuen Thread ausgeführt wird,
    //dateien ist das Objekt, dass an die Methode übergeben wird
    new Thread(StartReading).Start(dateien); 
}

...

// Methode, die im Thread ausgeführt wird.
private void StartReading(object container)
{
    // Ich hab hier jeweils Quell- und Zieldatei in einem Dictionary gespeichert.
    Dictionary<string, string> temp = new Dictionary<string, string>();

    temp = (Dictionary<string, string>)container;

    foreach (KeyValuePair<string, string> pair in temp)
    {
        try
        {
            string ziel = pair.Value;
            string quelle = pair.Key;

            do
            {
                // Wenn die Anwendung während der Bearbeitung des Threads gschlossen
                // wird, verlasse ich mit RETURN den Thread
                if (!fStopThread)
                {
                    //macht was mit den Dateien
                    String line;
                    line = sr.ReadLine();
                }
                else
                {
                    return;
                }
            }
            while (!sr.EndOfStream);

            // Hier wird die ProgressBar in Deiner MainForm aktualiesiert
            //Invoke deshalb, weil direkte Zugriffe auf Teile der Form von einem anderen
            //Thread aus nicht zulässig sind
            // ChangeProgressFiles ist dabei die Methode, die die Änderung durchführt
            this.Invoke(new MethodInvoker(ChangeProgressFiles));
        }
    }
}

private void ChangeProgressFiles()
{
     progressBarFiles.Value += Convert.ToInt32(countSize);
}

--Edit--
Was ich leider noch nicht rausgefunden habe ist, wie ich benannte Threads mit Parametern starten kann. Das würde das kontrollierte beenden der Anwendung deutlich sicherer machen. Ob das nämlich mit meinem boolschen Wer so funktioniert, kann ich nicht sagen.
Vor der Einfügung ging das Beenden mal mit, mal ohne Exception.

01.08.2009 - 21:48 Uhr

Bei den "Internet-Informationsdiensten" sollte das zu finden sein. Da ich hier keinen IIS installiert habe, kann ich Dir leider nicht sagen, welcher Reiter das ist, aber es sollte schnell zu finden sein.

Deine virtuellen Verzeichnisse findest Du in der Regel in der Standardwebseite...

01.08.2009 - 21:42 Uhr

Falls Du mal rausfinden willst, warum Deine Schleife nicht funktioniert - verlager mal das "line = sr.ReadLine()" vor die selbige - vielleicht siehst Du dann ja, was da passiert...

01.08.2009 - 21:03 Uhr

(Ich will den Beitrag jetzt nicht nochmal editieren, daher noch eine Ergänzung...)


do
{
    String line;
    line = sr.ReadLine();

    if (line == null)
    {
        break;
    }

    ... Der Rest Deines Code - ohne 'break' und ohne 'sr.Close()'
}
while (!sr.EndOfStream);

Wenn der Stream also von vornherein leer ist, wird die Schleife sofrot abgebrochen - ansonsten wird Dein Code ausgeführt.

Das sr.close() solltest Du dann aber unterlassen, sonst passt Deine Abbruchbedingung nicht mehr (sag ich jetzt ohne das ausprobiert zu haben).

Das break solltest Du ebenfalls in Deiner if-else-Verzweigung weglassen, falls Du mehrere IP-Adressen hinzufügen willst.

Wenn Du aber immer nur eine IP hinzufügen willst, dann brauchst Du aber nicht wirklich die Schleife. Dann reicht Dein Code...

(Alternativ geht statt do-while auch ein foreach)

01.08.2009 - 20:54 Uhr

Hallo xHelper,

  
            while ((line = sr.ReadLine()) != null)  
            { ...  
  

Ich kann da auf anhieb auch keinen Fehler feststellen. Probier doch statt dessen mal ein Do-While-Schleife. Da wird der erste Schleifenduchgang ja auf jeden Fall durchlaufen.

Dann kannst Du im Debugger auch wenigstens mal vernünftig sehen, welche Werte in Deine Variable geschrieben werden.

Doch, wegen des breaks und sr.Close() in if und else.

Er sagt doch, dass if und else gar nicht ausgeführt wird! Ausserdem hat er ja schon seinen Wert aus dem StreamReader in eine Variable geschrieben. Von daher macht das sr.Close() ja keinen Unsinn...

31.07.2009 - 00:40 Uhr

Dann aber mit doppelter ProgressBar 😉
Auch dann solltest du die Berechnung von der Dateigröße abhängig machen 😉.

Dann macht es aber auch wirklich Sinn - um den ungefähren Zeitfortschritt einschätzen zu können...

30.07.2009 - 21:41 Uhr

Ich würde da einfach eine Ladeanimation und einen Text "Bitte warten" anzeigen, solange der Vorgang läuft.

Ich hab mir nochmal die ProgressBar-Klasse angesehen und das "Marquee-Design" für mich entdeckt. Nachdem ich das mal schnell ausprobier habe, ist die Geschwindigkeit um etwa den Faktor 20 höher... Die Rechnerei hab ich aber auch wahrscheinlich etwas "dümmlich" realisiert 😉

die Verwendung eines Timers hat auf jeden Fall den Vorteil, dass die Berechnung garantiert ausreichend selten durchgeführt werden.

Ja, das war auch der Grund weshalb ich darüber nachgedacht habe. Aber im das Problem mit den Ausgangswerten hab ich damit noch nicht so ganz gelöst...
Ausserdem habe ich im Moment damit Probleme, das Timer-Event der Form-Klasse aus dem Thread heraus aufzurufen.

Deshalb bin ich bei den Marquee-Design der Progress-Bar gelandet. Für den Zweck reicht es allemal...

wenn es sich tatsächlich um dateiEN handelt, könntest du einfach die dateianzahl in die processbar reinschreiben und beispielsweise mit der dateigröße gewichten.

Es handelt sich tatsächlich um Dateien, aber die Abarbeitung erfolgt "manuell" nacheinander. Sind ja nicht grad hunderte. So um die 10 werden es maximal mal sein... Aber wenn es mehr werden, dann macht es durchaus Sinn. Dann aber mit doppelter ProgressBar 😉

30.07.2009 - 20:43 Uhr

Hallo zusammen,

ich bin gerade dabei ein kleines Progrämmchen zu basteln, dass mir aus Text-Dateien einen String heraussuchen und die betreffende Zeile sowie die X folgenden in eine neue Datei kopieren soll.

Zuerst hab ich das Programm ohne Threading geschrieben und das hat auch soweit funktioniert. Nur blockiert verständlicherweise die GUI, da die Dateien teilweise 2 Millionen (ja, 2 Millionen) Zeilen haben. (Im Prinzip ein "Log-File-Analysator", in dem dann nach Verbindungsabbrüchen gesucht wird.)

Jetzt möchte ich aber ein ProgressBar einbauen, da die Bearbeitung doch recht lange dauern kann - abhängig davon wie oft der Suchstring gefunden wurde.

Mein Problem ist jetzt folgendes:

Die ProgressBar akzeptiert als Grenzwerte nur Int32. Wenn ich nun die Zeichen der Datei über FileInfo auslese, bin ich da locker ausserhalb des Wertebreiches. Um das zu verhindern mache ich derzeit folgendes (nur die meiner Ansicht nach wesentlichen Elemente):


private void Startbutton_Click(object sender, EventArgs e)
{
     progressBar1.Maximum = Convert.ToInt32(myInfo.Length/10000);
     progressBar1.Minimum = 0;
}

...

void StartReading()
{
     if (bearbeiteteZeichen % 10000 == 0)
     {
          wert = bearbeiteteZeichen / 10000;
          this.Invoke(new MethodInvoker(FillProgressBar));
     }
}

...

private void FillProgressBar()
{
     progressBar1.Value = Convert.ToInt32(wert);
}

Könnt Ihr mir einen Tipp zu einem Lösungsansatz geben, wie ich das Füllen der ProgressBar vernünftig hinbekomme? Der Zeitaufwand für das Auslesen und Kopieren hat sich durch die ganze Rechnerei nämlich ziemlich deutlich erhöht...

Ich selbst habe schon über folgende Dinge nachgedacht:1.Ermittlung, wie lange der Vorgang dauern wird und dann entsprechend die ProgressBar füllen (falls das irgendwie möglich sein sollte, was ich aber bezweifle). 1.Mit Timern arbeiten und alle 100ms den Stand (bearbeitete Zeichen) abfragen und die ProgressBar füllen.

Letztere Variante wäre für mich auch ohne Hilfe zu realisieren. Trotzdem würde ich gerne wissen, wie Ihr vorgehen würdet.

21.07.2009 - 15:03 Uhr

Hallo zusammen,

hat jemand von Euch eigentlich schon mal mit dem oben genannten Toolkit zusammen mit C# gearbeitet?

17.07.2009 - 19:10 Uhr

Leider sind die Dateien im Startposting nicht mehr verfügbar. Gibt es eine neue URL?

29.05.2009 - 11:16 Uhr

Such mal nach "gpedit". Da solltest Du einiges finden können...

15.05.2009 - 19:50 Uhr

Hallo Gepro,

ausserdem solltest Du beachten, dass Telefonnummern nach internationalem Standard (ITU) inklusive Landesvorwahl maximal 15 Stellen lang sein dürfen. Wikipedia

Also: 0049 - 123 - 12345678

Selbst wenn Du die ersten beiden Nullen weglässt bist Du immer noch nicht im speicherbaren Zahlenraum des int32 (4294967295).

Von daher bleibt Dir, wenn Du die Rufnummern korrekt abspeichern willst, nichts anderes übrig, als Strings zu verwenden.

Wenn Du mit einer Datenbank arbeitest, dann würde ich evtl. überlegen, ob ich nicht für die Landesvorwahl, die Ortsvorwahl und die Durchwahl ein eigenes Feld reservieren würde. Aber das ist Ansichtssache...

14.05.2009 - 11:13 Uhr

Hier auch nochmal ein Link aus dem Heise-Software-Verzeichnis. Dort ist auch ein Screenshot der Oberfläche der Software verlinkt...

com0com im Heise-Software-Verzeichnis

14.05.2009 - 11:07 Uhr

Hallo lindesbs,

es gibt da schon die eine oder andere Software-Lösung für.

Unter anderem com0com, das unter der GPL veröffentlicht wurde.

Ich selbst benutze es auch und die Funktion ist einwandfrei...

06.05.2009 - 14:14 Uhr

Erst mal Danke für Eure Antworten! Mittlerweile war ich beim Kunden und die Datei System.Security.dll ist vorhanden. (Betriebssystem ist übrigens Windows Server 2003 R2)

Nachdem ich das Framework neu installiert (eher repariert) habe, bekomme ich aber immer noch die gleiche Fehlermeldung.

Der Witz ist, dass auf einem Windows XP System, mit Framework (Redist) und OPC-Core-Komponenten alles sofort und auf Anhieb funktioniert. Mein Programm scheint also richtig zu funktionieren.

Trotzdem finde ich dieses Verhalten nach wie vor eigenartig.

30.04.2009 - 13:41 Uhr

Hallo zusammen,

ich hoffe ich bin mit meinem Problem im richtigen Foren-Bereich gelandet.

Seit kurzem produziert eine von mir geschriebene Anwendung folgenden Fehler (basiert auf .NET 2.0):

System.Security.Cryptography.CryptographicException: Das System kann die angegebene Datei nicht finden.

Ich selbst verwende diese Bibliothek jedoch gar nicht, aber eine DLL verweist darauf, soweit ich den Reflector da richtig verstanden habe.

Das Problem ist nun, dass seit der Installation alles eigentlich einwandfrei funktioniert hat. Seit ein paar Tagen lässt sich das Programm aber nicht mehr starten und gibt stattdessen ins Log die oben genannte Fehlermeldung aus.

Da ich selbst bisher nicht bei meinem Kunden vor Ort war, muss ich mich auf die Aussagen meiner Kollegen verlassen und glauben, dass am betreffenden Rechner NICHTS verändert worden ist.

Daher frage ich mich, woher der Fehler kommen kann. Ist es möglich, dass da irgendwas mit der Registrierung des .NET-Freamworks nicht mehr in Ordnung ist? Kann sowas überhaupt so mir nichts dir nichts passieren?

Ich hoffe Ihr könnt mir einen Tipp geben, in welcher Richtung ich suchen soll. Falls bis Montag noch keiner geantwortet hat, werde ich auf jeden Fall mal versuchen, die Runtime des .NET-Frameworks neu zu installieren.

Danke schon mal für Eure Antworten.

06.02.2009 - 23:43 Uhr

verwendetes Datenbanksystem: <MS SQL (Desktop Engine), MS SQL Server Express 2008>

Hallo zusammen,

vor einiger Zeit habe ich mal angefangen ein kleines Tool zu schreiben, dass ein Datenbankbackup wiederherstellen sollte, hab es allerdings aus Zeitgründen wieder aufgegeben und den Quelltext auch nicht mehr.

Folgendes Szenario gilt:*Auf dem Server liegt sowohl die Datenbank, als auch in einem separatem Verzeichnis das Backup *Das Backup soll in eine neue Datenbank wiederhergestellt werden *Das Restore wird von meinem Tool von einem anderen PC (Client) aus gestartet

Folgendes Problem hatte ich damals:
Ich habe die Konfiguration auf dem Client in einer XML-Datei gespeichert. Als ich jedoch den Speicherordner des Backups mit aufnehmen wollte, bin ich daran gescheitert, den Backup-Ordner, der sich von Installation zu Installation unterscheiden kann auf dem Server über einen Konfigurationsdialog auszuwählen. Es ist an den Berechtigungen gescheitert. Ich hatte nie einem Möglichkeit gefunden, die Netzwerkberechtigungen entsprechend zu übertragen, ohne, dass der gleiche User auf dem Client eingerichtet werden musste.

Nun die Konzeptfrage:*Kann ich überhaupt die Datenbank wiederherstellen, wenn die Konfigurationsdaten, inkl. Ordnerangaben, durch den Client ausgewählt werden sollen? *Muss ich ein Client-Server-Modell dafür entwickeln? *Kann ich die Netzwerkanmeldung automatisiert durch mein Programm erledigen lassen?

26.01.2009 - 10:12 Uhr

Hallo zusammen,

mittlerweile hab ich einen Thread gefunden der unter Umständen für mich einen Lösungsansatz beinhalten könnte: mehrere Programminstanzen verhindern?

Die Frage die sich mir jetzt nur noch stellt ist, ob man über ein Mutex auch realisieren kann, dass ein OPC-Client auf eine bestehende Server-Instanz zugreift. Auch, wenn noch kein anderer OPC-Client mit diesem verbunden ist.

Edit: Ich sollte vielleicht noch anmerken, dass die Server-Client-Verbindung über COM/DCOM aufgebaut wird.

24.01.2009 - 00:17 Uhr

Ok, ich merke gerade, dass ich es falsch beschrieben habe was ich vorhabe.

Für das beschriebene Problem habe ich allerdings in der MSDN unter MSDN: RegistrationServices.RegisterTypeForComClients Method die Lösung gefunden.

Das was ich aber eigentlich wollte, habe ich nicht damit hinbekommen.

Ich muss folgendes machen:

  1. Ein OPC-Client verbindet sich mit dem Server
  2. Der OPC-Server wird durch den Client gestartet.
  3. Der Client verliert (warum auch immer, z.B. Neustart der Client-Anwendung) die Verbindung
  4. Der Server wird NICHT beendet
  5. Der OPC-Client verbindet sich mit der bestehenden Instanz des Servers.

Jemand eine Idee, wie sowas geht?

23.01.2009 - 18:18 Uhr

Hallo zusammen,

da bin ich mal wieder mit einer für mich ziemlich kniffligen Geschichte.

Ich bin gerade einen OPC-Server am programmieren und habe den bisher als kleine Windows-Anwendung als OutProc realisiert (mit der Softing .Net-Toolbox).

Wenn ich den Server im Debugger starte, kann ich mich mit beliebige vielen Clients mit ihm verbinden. Sobald er jedoch durch einen Client gestartet wird, kann nur dieser eine auf den Server zugreifen. Jeder andere Client startet eine neue Instanz des OPC-Servers. DCOM ist aber soweit nach den Vorgaben von Softing eingerichtet. Daran kann es eigentlich nicht liegen.

Die Toolbox selbst liefert keine Methode oder Klasse, die das Verbindungsverhalten steuert.

Womit kann ich das überhaupt beeinflussen?

23.01.2009 - 18:06 Uhr

So, ich habs drangegeben und erstelle jetzt für jeden Kameratyp den ich habe eine eigene XML-Datei. Ebenso für die Konfiguration...

Also quasi /close von meiner Seite aus...

14.01.2009 - 17:09 Uhr

Ah, habe gerade bei Code-Project was gefunden, dass denke ich die Lösung sein könnte.

Ich werde das heute Abend mal implementieren und wenn es funktioniert den Thread auf gelöst setzen...

Load and save objects to XML using serialization

14.01.2009 - 17:05 Uhr

Probier mal obs mit dem XmlAnyAttribute geht.

Damit funktioniert dann auch mein bisher laufendes Code-Fragment nicht.

Ich habe daher mal anstatt XmlElement das XmlArray ausprobiert und komme damit immerhin schon mal einen Schritt im Code weiter.

Allerdings bricht es dann bei

s.Serialize(w, configData);

mit der Fehlermeldung "InvalidOperationException" ab. Der Inhalt lautet:

"Mindestens ein Element im Quellarray konnte nicht in den Zielarraytyp umgewandelt werden."

---edit---

Muss ich da etwa jede Klasse einzeln serialisieren?

14.01.2009 - 16:18 Uhr

Hallo zusammen,

ich beschäftige mich gerade mit der Serialisierung von Daten in eine XML-Datei. Ich habe mir dafür eine "Vorlage" im Netz gesucht, und auf meine Bedürfnisse angepasst. Leider funktioniert die Serialisierung aber nicht, sobald ich den Teil des Codes ab "[XmlElement("Severity", IsNullable = true)]" mit in den Programmablauf aufnehme.

Die Fehlermeldung lautet:
"configData.Severities" hat eine Ausnahme vom Typ "System.InvalidCastException" verursacht.

Eigentlich ist mir soweit klar, warum dies passiert. Ich versuche zwei unterschiedliche Datentypen mit in das Array aufzunehmen.

Leider komme ich aber selbst nicht auf die Lösung und in der Forensuche habe ich auch nichts gefunden, was mir weitergeholfen hat.

"Darf" ich als Array überhaupt die ArrayList verwenden oder sollte ich besser eine List<T> nehmen?

Ich wäre Euch über den einen oder anderen Tipp oder Link dankbar...

Hier mein Code:


    [Serializable]
    [XmlRoot("OPCConfig")]
    public class GetConfigData
    {
        private ArrayList configData = new ArrayList();

        public GetConfigData()
        {
        }

        [XmlElement("Camera")]
        public Camera[] Cameras
        {
            get
            {
                Camera[] cameras = new Camera[configData.Count];
                configData.CopyTo(cameras);
                return cameras;
            }
            set
            {
                Camera[] cameras = (Camera[])value;
                configData.Clear();
                foreach (Camera i in cameras)
                    configData.Add(i);
            }
        }

        public void AddCamera(Camera camera)
        {
            configData.Add(camera);
        }

        public Camera this[string cameraName]
        {
            get
            {
                foreach (Camera i in configData)
                    if (i.cameraName == cameraName)
                        return i;
                throw (new Exception("Camera not found"));
            }
        }

        [XmlElement("Severity", IsNullable = true)]
        public Severity[] Severities
        {
            get
            {
                Severity[] severities = new Severity[configData.Count];
                configData.CopyTo(severities);
                return severities;
            }
            set
            {
                Severity[] severities = (Severity[])value;
                configData.Clear();
                foreach (Severity i in severities)
                    configData.Add(i);
            }
        }

        public void AddSeverity(Severity severity)
        {
            configData.Add(severity);
        }

        public Severity this[string severityName, int severityValue]
        {
            get
            {
                foreach (Severity i in configData)
                {
                    if (i.severityName == severityName)
                        return i;
                    if (i.severityValue == severityValue)
                        return i;
                }
                throw (new Exception("Severity not found"));
            }
        }
    }

    public class Camera
    {
        [XmlAttribute("cameraName")]
        public string cameraName;

        public Camera() { }

        public Camera(string cameraName)
        {
            this.cameraName = cameraName;
        }
    }

    public class Severity
    {
        [XmlAttribute("severityName")]
        public string severityName;

        [XmlAttribute("severityValue", typeof(int))]
        public int severityValue;

        public Severity() { }

        public Severity(string severityName, int severityValue)
        {
            this.severityName = severityName;
            this.severityValue = severityValue;
        }
    }

Im Hauptprogramm werden dann folgende Daten hinzugefügt und sollen serialisiert werden.


GetConfigData configData = new GetConfigData();

configData.AddCamera(new Camera("Kamera 1"));
configData.AddCamera(new Camera("Kamera 2"));
configData.AddCamera(new Camera("Kamera 3"));
configData.AddCamera(new Camera("Kamera 4"));

configData.AddSeverity(new Severity("1", 1));

XmlSerializer s = new XmlSerializer(typeof(GetConfigData)); //hier ist der Fehler

TextWriter w = new StreamWriter("configData.xml");
s.Serialize(w, configData);
w.Close();

Das Ergebnis, das ich erwarte soll wie folgt aussehen:


<?xml version="1.0" encoding="utf-8"?>
<OPCConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Camera cameraName="Kamera 1" />
  <Camera cameraName="Kamera 2" />
  <Camera cameraName="Kamera 3" />
  <Camera cameraName="Kamera 4" />
  <Severity sevrityName="1" severityValue="1" />  //ob das wirklich so aussieht, weiß ich leider nicht wirklich...
</OPCConfig>

06.01.2009 - 16:44 Uhr

Nachdem ich in der Zwischenzeit immer noch weiter im Internet gesucht habe, bin ich dann doch noch fündig geworden:


public delegate void WriteNotificationDelegate(
    IntPtr tagHandle,
    ref object newValue,
    UInt32 deviceError);

Das Objekt musste als Verweis ref übergeben werden.

06.01.2009 - 14:08 Uhr

Nein, steh ich eindeutig nicht drauf, aber die DLL ist nunmal als Lizenz schon vorhanden und erprobt. Ich bin jetzt halt der "Dumme" der damit einen OPC-Server auf C#-Basis schreiben darf...

06.01.2009 - 13:37 Uhr

Hallo zusammen und ein frohes neues Jahr erst mal.

Ich beschäftige mich derzeit mit der Einbindung einer OPC-Server-DLL (unmanaged C++) in eine C#-Anwendung.

Probleme bereiten mir die Callbacks aus der DLL, die z. B. die Item-Änderungen an meine Anwendung zurückmelden sollen.

Die Funktionen sind der OPC-DLL-Dokumentation wie folgt beschrieben:


BOOL EnableWriteNotification (WRITENOTIFYPROC lpCallback, BOOL ConvertToNativeType)

// lpCallback zeigt auf folgenden Funtkionsaufruf

void CALLBACK EXPORT NotificationHandler (HANDLE handle, VARIANT *pNewValue, DWORD *pDeviceError)

Das Delegate für den Callback und das Platform Invoke hab ich soweit:


public delegate void WriteNotificationDelegate(
	IntPtr tagHandle,
	Object newValue,
	UInt32 deviceError);

//Innerhalb der Klasse

/// <summary>
/// Callback-Routine, die durch die WTOPCSvr.dll ausgelöst wird, sobald ein OPC-Client
/// auf ein definiertes Item schreibt.
/// Im Normalfall ist die DLL so konfiguriert, dass die Werte in den nativen Datentyp 
/// des Items konvertiert werden. In einigen Fällen kann es jedoch erforderlich sein, 
/// dass die Anwendung selbst eine Typumwandlung durchführt.
/// </summary>
/// <param name="lpCallback">Callback-Aufruf</param>
/// <param name="ConvertToNativeType">"true" wenn automatisch Konvertiert werden soll, sonst false</param>
/// <returns></returns>
[DllImport(@"WtOPCSvr.dll", SetLastError = true, EntryPoint = "_EnableWriteNotification@8")]
public static extern Int32 EnableWriteNotification(WriteNotificationDelegate lpCallback, int ConvertToNativeType);

Mein Problem ist, dass ich beim Debuggen bei einer Item-Änderung folgenden Fehler erhalte:

InvalidVariant wurde erkannt.
Message: Beim Konvertieren einer nicht verwalteten VARIANT in ein verwaltetes
Objekt wurde eine ungültige VARIANT gefunden. Wenn ungültige VARIANTs an die
CLR übergeben werden, kann dies unerwartete Ausnahmen, Datenbeschädigung
oder -verlust zur Folge haben.

Ich vermute dass ich "Object newValue" aus meinem Delegate irgendwie anders marshallen muss - nur hab ich gerade keinen Schimmer wie. Folgendes hatte ich schon mal ausprobiert, aber das produziert dann den Fehler "System.ExecutionEngineException"

public delegate void WriteNotificationDelegate(
	IntPtr tagHandle,
	[MarshalAs(UnmanagedType.IDispatch)] Object newValue,
	UInt32 deviceError);

Ein Möglichkeit VARIANTs in ein Object zu konvertieren - und zwar so, dass es von unmanaged nach managed-Zugriffen gültig ist habe ich leider nicht gefunden.

Habt Ihr einen Tipp für mich?

02.12.2008 - 16:00 Uhr

Hallo kleines_eichhoernchen,

so wie es aussieht, ist es eben KEINE COM-Bibliothek. Sowohl das hinzufügen als Verweis noch das umwandeln mit tlbimp.exe funktioniert. Hier die Fehlermeldung vom tlbimp.exe

TlbImp : error TI0000 : The input file 'WtOPCSvr.dll' is not a valid type library.

An und für sich ist das aber auch nicht unbedingt problematisch - wie ich mit pinvoke die dll einbinde ist klar, die EntryPoints habe ich auch alle - nur habe ich halt bei manchen Typen so meine Probleme.

Auf jeden Fall werde ich aber z.B. ein WORD als System.UInt16 usw. kennzeichnen.

Trotzdem danke für den Hinweis - in der Zukunft kann das sicher mal nützlich sein...;)

02.12.2008 - 14:48 Uhr

Hallo Mystique,

danke Dir, auf die Idee nach Platform Invoke zu suchen bin ich natürlich nicht gekommen.

Das geht aber auf jeden Fall schon mal ganz stark in die Richtung, die ich brauche.

Leider stehen da aber noch nicht alle Datentypen drin, die in meiner DLL vorkommen (WinTech OPC-Server siehe Abschnitt Creating Porcess Tags). Aber da wird wohl ein wenig basteln angesagt sein - oder wie Überstze ich VARIANT korrekt?