Laden...

Forenbeiträge von mosspower Ingesamt 456 Beiträge

07.01.2009 - 16:39 Uhr
  
Thread serviceThread =new Thread( ((IThreadClass)serviceInstance).Run);  

?

ja, hatte ich doch tatsächlich vergessen. Lustig ist schon, dass ich es erst oben richtig geposted hatte. Ich hab keine Ahnung, was mit mir heute los ist.

Vielen Dank euch allen ... aus 25 Zeilen 1 gemacht 👍

07.01.2009 - 16:20 Uhr

Hm,

jetzt wollte ich das bei mir einbauen.

Das Objekt serviceInstance ist generisch erstellt worden (Activator.CreateInstance), jetzt dachte ich, dass ich folgendermaßen vorgehen kann:


// Ich muss jetzt hier ja casten
Thread serviceThread = ((IThreadClass)serviceInstance).Run;

Das funzzt aber nicht, wegen dem Cast, würde ich MyThreadClass erstellen, dann würde es gehen. Wie mache ich denn das jetzt?

Die Fehlermeldung lautet:
Cannot convert method group Run to none delegate type Thread
Hm, genau wegen dieser Fehlermeldung hatte ich die "Hilfsklasse" gecoded.

07.01.2009 - 15:55 Uhr

OK,

das wieder mal ein Thread von mir, den man gleich wieder vergessen kann 😉 ... ohne eure Hilfe wäre das natürlich nicht möglich gewesen. Ich bedanke mich (ein bißchen beschämt 😉) bei euch für die Unterstützung.

Es geht mit folgendem Code ...


MyThreadClass myThreadClass = new MyThreadClass();
Thread thread = new Thread(((IThreadClass)myThreadClass).Run);
thread.Start();

Dafür braucht man natürlich keine Hilfsklasse

07.01.2009 - 15:31 Uhr

Es MUSS natürlich nicht Reflection sein, jedoch hatte ich die Klasse entwickelt, um die Threads generisch erstellen zu können. ([EDIT]=herbivore] ... wofür, wie sich ja oben gezeigt hat, gar keine Reflection notwendig ist.[/EDIT]

07.01.2009 - 14:50 Uhr

@ErfinderDesRades ,

hast schon Recht, nur der Hintergrund ist, dass die Threads dynamisch mittels Reflection gestartet werden sollen 😉

Trotzdem Danke

07.01.2009 - 11:44 Uhr

@myCSharp.de-Poweruser ,

danke, werde mich da mal einlesen (wenn ich dazukomme)

@herbivore,

stimmt, Du hast recht, vielen Dank. Interface übergeben und auf ThreadStart verzichten. Vielen Dank Leute, hier lernt man wirklich was 👍

07.01.2009 - 10:19 Uhr

[EDIT=herbivore]Dieser Thread war als Snippet gedacht, aber weiter unten zeigt sich, dass es einfacher geht, weshalb man das Snippet nicht benötigt. Deshalb verschoben nach Basistechnologien.[/EDIT]

Beschreibung:

Hier eine Utility-Klasse, mit der es möglich ist (wie in z.B. Java) Threads in Klassen zu kapseln.


using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Reflection;

namespace Util.ThreadClass {
  /// <summary>
  /// Utility class for handling thread class issues
  /// </summary>
  public class ThreadClassUtil {
    /// <summary>
    /// Gets a Thread object for the passed object
    /// </summary>
    /// <param name="threadClassInstance">The Thread object, must implement
    /// <see cref="ThreadClass.IThreadClass"/></param>
    /// <returns>The Thread object</returns>
    /// <exception cref="Exception">All possible reflection exceptions</exception>
    /// <exception cref="ArgumentException">If instance is passed null</exception>
    public static Thread GetThread(Object threadClassInstance) {
      Thread thread = null;
        
      try {
        // Check null
        if(threadClassInstance == null) {
          throw new ArgumentException("Parameter threadClassInstance was passed null");
        }

        // Check thread interface
        if(threadClassInstance.GetType().GetInterface(typeof(IThreadClass).FullName) == null) {
          throw new ArgumentException(String.Format("Type '{0}' does not implement mandatory interface '{1}'", 
            new Object[] { threadClassInstance.GetType().FullName, typeof(IThreadClass).FullName }));
        }

        MethodInfo methodInfo = threadClassInstance.GetType().GetMethod("Run");
        ThreadStart threadStart = (ThreadStart)Delegate.
          CreateDelegate(typeof(ThreadStart), threadClassInstance, methodInfo);
        thread = new Thread(threadStart);
      }
      catch(Exception) {
        throw;
      }

      return thread;
    }
  }
}

Hier das Interface


namespace Util.ThreadClass {
  /// <summary>
  /// Interface for using class threads
  /// </summary>
  public interface IThreadClass {
    /// <summary>
    /// The running thread method
    /// </summary>
    void Run();
  }
}

Verwendet kann das dann so werden:


MyThreadClass myThreadClass = new MyThreadClass(); // Must implement IThreadClass
Thread thread = ThreadClassUtil.GetThread(myThreadClass);
thread.Start(); // Run method in MyThreadClass will be invoked

Schlagwörter: Threadklasse, Thread

Viel Spass damit

Grüße

06.01.2009 - 23:03 Uhr

Hallo,

also mir würde auch sofort Serialisierung einfallen. Wenn die Variablen den gleichen Datentyp haben, z.B. String, dann einfach in eine List gepackt und serialisieren, bzw. deserializieren oder ggf. eigenes serialisierbares Objekt schreiben.

Gruß

06.01.2009 - 21:15 Uhr

Hallo "Kollegen",

anbei ein Screenshot von der Ordnerstruktur meiner Utilityklassen. Die Struktur ist zusammengefasst in ein Library Projekt mit dem Namen Util. Nun ist es aber mitlerweile so, dass das Teil 2.9 MB groß ist (ohne bin und obj Ordner). Das blöde ist jetzt, dass wenn man mal schnell eine Consoleanwendung ect. macht und 3 oder 4 Methoden aus dem Utilitypack braucht, dass ich immer das Projekt eingebunden habe, was aber jetzt schon sehr nach mit Kanonen auf Spatzen aussieht. Naja, was ich vermeiden möchte ist, dass ich immer den Code rauskopiere. Ich könnte jetzt das nochmals "zerbröseln" und aus jedem Oberordner, z.B. Database, DLL, EDI ect ein eigenes Projekt machen und die dann einbinden, nur habe ich hier auch schon "Überkreuzungen" 😛, da die sich teilweise auch widerum gegenseitig referenzieren würden. Wie habt ihr das denn gelöst? Wie sieht das bei euch aus?

Da fällt mir gerade noch was ein. Ich komme ursprünglich von der Java-Schiene, da war ich es gewohnt, einen Ordner src zu machen und da die Sourcecodes. Hätte ich gerne auch gemacht in C#, nur das Problem ist, wenn ich in VS Klassen neu anlege, dann müsste ich immer den Namespace manuell anpassen (Löschen von src in den Namespaceangaben). Gibt es hier einen Workaround? Vielleicht kann ich irgendwo VS mitteilen, dass meine Sourcen in einem bestimmten Ordner sind (wie auch bei Eclipse) - leider habe ich sowas bisher nicht gefunden. Ist halt immer noch für mich irgendwie ungewohnt, wenn bin und z.B. lib auf gleicher Ebene liegen, wie die Klassenpakete. Gibt es hier eine Lösung?

OK, das war es dann schon wieder.
Danke schon mal im Voraus für eure Antworten und Anregungen.

Gruß

06.01.2009 - 17:22 Uhr

und wartet auf Ereignisse
Wie sieht denn bei dir solch ein Ereigniss aus bzw. nenn einfach mal ein Beispiel aus der entsprechenden Klasse.

Sorry, ist ein bißchen später, ich hatte den Thread leider aus den Augen verloren.

Beispiele wären:

Ein bestimmtes Datum für Generierung von Rechnungen oder Erinnerungsmails werden verschickt für bevorstehende Prozesse. Files werden in Verzeichnissen gefunden, die dann Import werden, bzw. "aufgeräumt" werden. Tägliche Abgleiche über andere Datenbank usw.

Hört sich alles sehr unterschiedlich an, ist es ja auch, aber dies wird alles für einen Kunden im Rahmen des Warehousings durchgeführt, also gehören die thematisch schon zusammen.

Ich möchte halt einen Service und nicht zig andere Anwendungen (gegenwärtig noch teilweise in drei verschiedenen Programmiersprachen entwickelt). Das wird alles zusammengeführt.

@GarlandGreene,
wegen der Komplexität habe ich ja ein kleines "Services-In-Services"-Framework geschrieben, so dass man nur im Konfigfile den Klassennamen angeben braucht, mittels Reflection wird dann die Run-Methode aufgerufen und man kann gleich zum Coden loslegen, ohne sich um das ganze "Service-Gedöns" zu kümmern - auch können mehrere Coder so unabhängig Teilservices implementieren. Wenn einer natürlich Schrott baut, dann zieht das nicht den ganzen Service mit runter, sondern der Thread raucht halt ab und ja, bei Änderrungen muss der Service neu gestartet werden, das ist aber bei Anwendungen auch nicht anders, die müssen auch neu gestartet werden.

Gruß

06.01.2009 - 06:52 Uhr

Gegenwärtig ist die Console erst mal so, wie ich sie brauche, jedoch werde ich später folgende Funktionalitäten auch noch brauchen:

**Freeze pane **(wenn viel und häufig gelogged wird, dass man das Einfrieren kann und die Messages auch lesen, denn die Console springt standardmäßig immer ans Ende, nach einem Logvorgang)
Filterfunktionalität Filtern nach Type, Datum und Source
Kontenxtmenu Hier können dann diese Funktionalitäten ausgewählt werden + weitere, wie z.B. To Clipboard, select all ect.

OK, hier dann noch abschließend der Quellcode (mit 3.5 kompiliert, sollte aber ohne Probleme auch mit 2.0 kompiliert werden können)

Gruß

06.01.2009 - 06:45 Uhr

Hier noch einer mit "HTML-Spielerei" 🙂 ...

06.01.2009 - 06:44 Uhr

Kurze Erklärungen zu den Properties (der Code ist ausführlichst dokumentiert)

Selection: kann aktiviert werden (inklusive Browser-Kontextmenu)
UTC Time: Zeit kann als UTC registriert werden, dann werden (wenn angegeben im Formatter) die Zeitangaben als UTC gelogged.
Timeout: Kleine Spielerei von mir. Der Text wird als Ticker geschrieben, und nicht als Ganzes (natürlich nur, wenn man das möchte), hier kann man den (JavaScript) Timeout einstellen
Chars pro Interval: Die Anzahl der darzustellenden Zeichen der Gesamtmessage pro Funktionsaufruf im JavaScript Intervall, wenn die Message gezeichnet wird. Will man also die Message sofort sehen (ohne Tickerfunktionalität), dann Timeout auf 1 und Chars / Interval auf 1000 (sollte reichen)
Log Pattern:: Wird kein Pattern angegeben, dann wird "nur" die Message gelogged.

In diesem Pattern sind widerum vier konstante Werte bekannt:
**Datum Key ${date[(format)]}: ** Das Datum wird gelogged, existiert unmittelbar hinter dem Datum Key ${date} ein Ausdruck in runden Klammern, dann wird das Datum mit diesem Format gelogged, ansonsten HH:mm:ss
Type Key ${type}: Der Type name, innerhalb des Objektes ConsoleLoggerConfig definiert, hier z.B. INFO, WARNING, PROCESSING und ERROR
Source Key ${source}: Der Ursprung der Logmeldung
Message Key ${message} Die Logmeldung

Hier kann man natürlich "rumspielen". Die Keys sind nicht mandatory. Wie gesagt, wenn kein Pattern angegeben, wird nur die Message gelogged, wichtig ist aber, dass z.B. in einem Pattern schon die Message ${message} stehen sollte, denn z.B. das Pattern

${date} Bla blub bla würde nur folgendes loggen:

HH:mm:ss Bla blub bla

OK, zu guter letzt noch. Wie wird gelogged: Es gibt die überladenen Methoden LogMessage, welcher man immer die Nachricht und das ConsoleLoggerConfig Objekt übergeben muss. Dieses Objekt besteht lediglich aus dem Type (String) und der Schriftfarbe (Color).

Bei Fragen einfach an mich wenden.

Hier noch ein Screenshot, wie man die Konsole jetzt locker mit Doppelklick aufklappen kann ohne die störenden, bzw. häßlichen Textselektionen

06.01.2009 - 06:21 Uhr

Beschreibung:

Hi folks,
Hintergrund für die Entwicklung des eigenen Controls war dieser Thread. Ich habe es nicht (performant) hinbekommen, dass ich den Cursor ausschalte, in verschiedenen Farben loggen (was über Select geht) kann und dann auch noch Selectionen als Ganzes deaktivieren kann, denn beim Vergrößern solcher Consolen mittels Doppelklick wird dann immer Text selektiert, was total nervig ist, bzw. häßlich aussieht. Bei "meiner Lösung mit der RichTextBox" hatte ich zum Schluß bei sieben Ereignissen den Aufruf für die API-Function HideCaret drinnen und beim Mausmove-Ereignis innerhalb der RichTextBox hatte ich zeitweise 20 Prozent CPU-Auslastung und die Selections waren auch nicht ganz verschwunden und hin und wieder tauchte der Cursor immer noch auf. Also habe ich mich entschiedenen ein eigenes Control zu bauen. Ich benutze jetzt immer (vorher auch schon mit der RichTextBox) in meinen Projekten solche Consolen, weil ich diese Popup-Fenster einfach hasse und mit diesen Consolen ist sichergestellt, dass man z.B. bei Programmen, die auf Servers laufen, am z.B. nächsten Tag mal schnell in die Console schaut und nicht immer den Umweg über Popup-Fenster oder Logfiles gehen muss (oder nicht geht, weil man keine Fenster implementiert hat oder nicht gerade weiß, wo sich das Logfile befindet, bzw. nicht vorhanden ist ... auch habe ich oft mit Programmen zu tun, wo kein Mensch mehr weiß, was die überhaupt machen, ich bekomme dann immer nur zur Antwort, das es nicht mehr so geht wie immer .. und manchmal am Ende einer Operation ein Fenster mit dem Hinweis "Fertig !" erscheint ... LOL .. echt kein Witz, alles schon gehabt ...

OK, wie wird das nun benutzt,
die Console besteht aus einem WebBrowser Control, so ist sichergestellt, dass man auch hin und wieder mal HTML-Code (Bilder oder Tabellen ect.) loggen kann, bzw. auch formatierte Ausgaben durchführen kann (HTML-Style). Das Webbrowser Control habe ich public gemacht, so kann man eben damit machen was man will (Formulare, AJAX ect.).

Das loggen ist total simple. Control einfach wie gewohnt auf ein Formular ziehen und die Methode LogMessage aufrufen. Es gibt vier vordefinierte ConsoleLoggerConfig Objekte, die aber ignoriert oder überschrieben werden können - natürlich können auch eigene angelegt werden.

Hier mal ein Screenshot von der Testform für das Control ...

Schlagwörter: Console, Logger, ConsoleLogger

05.01.2009 - 01:54 Uhr

Hat sich erledigt, ist Gott sei Dank implementiert, nämlich hier ...

this.browser.Document.Body.DoubleClick += bla ...
05.01.2009 - 00:27 Uhr

Hallo "Kollegen",

wie kann ich bei einem Control (hier speziell das WebBrowserControl) ein Doppelklick-Event implementieren, da keins vorhanden ist, leider. Ich brauche unbedingt dieses Ereignis. Wie stellt man das jetzt an? Ich müsste auf Systemebene einen Doppelklick abfangen und dann nachsehen ob sich die Koordinaten in dem Control befinden? Braucht es dazu wirklich so einen "Overhead"?

Danke für eure Hinweise und Anregungen schon einmal im Voraus.

Gruß

04.01.2009 - 21:37 Uhr

@zommi,

vielen Dank 😁 .. man bin ich blöde - fuck!
Man lernt nie aus.

Gruß

04.01.2009 - 21:26 Uhr

Hallo "Kollegen",

ich habe ein sog. "Greedy-Problem" mit der folgenden Regular Expression:

.?(${date})(((.+)))?.?

Nach ${date} darf ein Ausdruck von (.+) kommen (mit den Klammern) .. wie mache ich das jetzt, wenn später auch noch mal eine Klammer kommt?
Ich möchte drei Gruppierungen als Rückgabewert haben

  1. $date
  2. nach ${date} mit der Klammer bis zur ersten Klammer zu )
  3. alles innerhalb dieser Klammern nach $date oder anders ausgedrückt, wie 2 nur ohne die öffnende und die schließende Klammer

z.B. wird alles (die Gruppierungen) richtig erkannt bei
[${date}(HH:mm:ss) > ${type}]: ${message}bla blums drums ... bla

jedoch nicht mehr, wenn später noch eine Klammer kommt, z.B.
[${date}(HH:mm:ss) > ${type}]: ${message}<script alert("bla");</script>

Kann mir da jemand weiterhelfen, ich bin bei den RegEx jetzt nicht so total tief drinnen.

Danke schon mal für Hilfe im Voraus.

Gruß

03.01.2009 - 17:58 Uhr

... Eine andere Möglichkeit wäre, das SelectionChanged-Event zu abonnieren und damit nach jedem Markieren die SelectionLength auf 0 zu setzen.

Hallo rechner,

dann kann ich aber keine unterschiedlichen Farben mehr verwenden, da die ja nur bei einer Selektion gesetzt werden kann - das hatte ich schon drinnen, dann war eben die Schriftfarbe immer gleich.

Ich habe schon angefangen, eine mit HTML zu machen, die kann ich dann nach meinen Wünschen anpassen. Ich werde die dann hier als Control zur Verfügung stellen - hier kann ich dann später auch mal HTML-Tabellen on the fly mit reinmachen, Icon-Links reinbauen, mit JavaScript "rumspielen", Filter einbauen ect. ist imo viel flexibler.

Gruß und Danke für die Hilfe

03.01.2009 - 11:53 Uhr

Hallo "Kollegen",

gleich nochmal ein Problem. Wie ihr im Anhang sehen könnt, möchte ich so eine Art Konsole nachbilden, wobei die Meldungen, je nach Typ, farblich unterschiedlich dargestellt werden. Das funzzt auch alles wunderbar, nur, dass ich den Text selektieren kann, dies möchte ich vermeiden. Die Konsole kann man aufklappen, siehe hier Screenshot aus anderen Thread, mit einem Doppelklick, nur dann wird immer etwas selektiert (automatisch) und das sieht nicht schön aus. Gibt es hier einen Workaround? Ich habe schon ewig "rumgespielt", bis ich den "blöden" Cursor rausbekommen habe. Naja, vielleicht mache ich dann ein Browserelement rein, und schreibe die Nachrichten mit "Plain old HTML" ... das wäre dann wieder mal wie mit Kanonen auf Spatzen schießen .. aber wenn es nicht anders geht 😜 🙁 ... oder doch?

Gruß und danke schon mal im Voraus für etwaige Antworten.

03.01.2009 - 10:00 Uhr

Hallo "Kollegen",

mir ist in VS, Version 2008, English, SP1, jetzt schon desöfteren aufgefallen, dass nach einem Build (Build.BuildSolution) welcher mit dem globalen Shortcut durchgeführt wurde, die ausgeführte Exe-Datei, sei es mittels Doppelklick auf Exe-Datei oder direkt aus der IDE (Start Debug) nicht aktualisiert wird (obwohl die IDE anzeigt, dass der Compile erfolgreich verlaufen ist). Kenn jemand diese Problematik? Das geht einen aber voll auf die Nerven. Erst denkt man, dass man etwas falsch gecoded hat, dann spielt man da rum, bis man letztendlich total genervt einen expliziten Clean durchführt und dann ein Recompile (was, wenn man es immer macht, total zeitaufwendig wäre). Wie kann ich das umgehen?

Danke schon mal für etwaige Hilfe im Voraus.

Gruß

P.S. Es war auch vor dem SP1 schon so 🙁 ... bei VS 2005 ist mir das bisher noch nie aufgefallen.

03.01.2009 - 05:42 Uhr

@norman_timo,

kein Problem, ist ja etwas "umständlich" beschrieben, bzw. nicht ganz so trivial. Ich habe mal ein paar Screenshots rein (farblich angepasst).

siehe erster Anhang

Kurze Erklärung:

3 Panels (1 = Einbahnstraßenschild, 2 = Menupanel (gelb, innerhalb gedocktes Browserelement, auch ohne Tabstop und Tabindex = 0) und 3 = Contentpanel (dunkelblau)
1 GroupBox (hellblau)
1 RichTextBox (Console schwarz, TabIndex = 50)
1 UserControl (mit dem jeweiligen Content, abhängig von der Menuauswahl, hellgrau)

Das Problem ist, dass auf allen Panels TabIndex = 0 und Tabstop = false ist. Auch auf der GroupBox ist das so. Wenn ich jetzt "durchtabbe", dann fängt der bei der Console an (ist auch so gewollt) und dann stept er alle durch bis zum Save-Button, dann jedoch "verläuft" er sich und springt erst beim übernächsten Mal wieder in die Console rein.

Beim zweiten Beispiel ist es noch kurioser. Hier habe ich einen Menupunkt ausgewählt, wo hinter dem eingebundenen UserControl noch kein Control (TextBox ect.) eingebunden ist. Hier setzt er immer zweimal! aus 8o, d.h. ich fange wieder mit der Console an und muss zweimal "übersteppen". Was ist denn das? Das komische ist, dass ich das gleiche Konzept bei meiner vorherigen Anwendung auch eingesetzt habe (ohne Browsermenu), und das funzzt da wie erwartet.

siehe zweiter Anhang

Das ganze geht einen ziemlich "auf den Sack" .. ist aber jetzt nicht "überlebenswichtig" 😁

Danke für etwaige Hilfe schon einmal im Voraus.

03.01.2009 - 05:42 Uhr

.

01.01.2009 - 13:01 Uhr

Hallo "Kollegen", willkommen im neuen Jahr,

gleich zu Beginn habe ich ein nervenaufreibendes Problem - bin jetzt 1 3/4 Stunden über dieses "Popelproblem" drüber und kann mir keinen Reim draus machen. Es geht um Tabindices. Ich habe eine Hauptform, in dieser befinden sich 3 Panels (jeweils Tabindex auf 0 und Tabstop auf false) und eine Richtextbox (Tabindex = 10). Ferner gibt es noch eine GroupBox (Tabindex = 0, Tabstop auf false). Jetzt werden in dem einen Panel (innerhalb der GroupBox) UserControls eingebunden (mit Controls.Add) und zwar immer eins, je nachdem, was im Menu ausgewählt wurde. Jetzt tauchen aber immer zwei Probleme auf.

1.) Wenn ich alles "durchgetabbed" habe, dann ist der Tab auf einmal nicht sichtbar, soll heißen, der geht auf einen "leeren Tab". Warum macht der das?

2.) Wenn ich in ein eingebundenes Unsercontrol zu Testzwecken überhaupt kein Control einfüge (Textbox ect.), dann setzt er zweimal aus, d.h. immer von Richtextbox auf leer, auf leer und wieder auf Richtextbox.

... das kann doch nicht wahr sein. Ich habe definitiv keine "versteckten Elemente", die ich ggf. nicht sehen kann. Es muss an der GroupBox liegen, denn wenn ich hier den Tabindex auf 999 setze, dann kommt der "Aussetzer" unmittelbar nach der RichtextBox, sonst vorher.

Problem ist, dass ich genauso nach diesem Schema eine andere Anwendung programmiert habe, hier habe ich keinerlei Probleme mit den Tabindices, da funzzt also alles. Ich habe auch schon clean gemacht und natürlich auch den Rechner neu gestartet ... jetzt bin ich mit meinem "Latein" am Ende.

Vielleicht kennt ja jemand dieses "saublöde" Problem und kann mir helfen. Danke schon einmal im Voraus.

Gruß

Nachtrag: Kann man vielleicht irgendwie tracen oder loggen (welches Ereignis überhaupt?), welches das aktive Control ist, bzw. wo der Tabindex drauf steht?

29.12.2008 - 13:48 Uhr

Hallo "Kollegen",

gibt es mittels C# (Open Source wäre nicht schlecht) die Möglichkeit, automatisch Anrufe durchzuführen mit verschiedenen Textansagen, die in Audiodateien vorliegen? Hintergrund ist, dass ich eine Anwendung laufen habe, die mit sehr viel Geld "hantiert". Jetzt gibt es hier ca. 10 Totalausnahmen (Server unten, Internet (länger) weg, Anbieter nicht erreichbar ect.). Wenn ich jetzt mal längere Zeit nicht zu Hause bin, möchte ich aber trotzdem das Programm laufen lassen - läuft eigentlich 24 Stunden. Jetzt dachte ich mir, dass mich die Anwendung bei Ausnahmen auf meinem Handy anruft und mir den Fehlertext aufsagt, so dass ich ggf. schnell reagieren kann. Ist dies möglich mittels C#? Welche APIs gibt es, wie hoch sind die Kosten?

Danke schon mal für eure Antworten im Voraus.

12.12.2008 - 10:27 Uhr

Vielen Dank, genau das suche ich. Ich hatte nicht genau gewusst, nach was ich suchen soll. 👍

11.12.2008 - 23:08 Uhr

Hallo "Kollegen",

ich hätte einmal zwei Fragen:

  1. Ist es möglich, einen XML-Knoten (also ein Teil eines XML-Dokumentes, bzw. Knoten von XML-Dokumenten) gegen ein Schema mittels C# prüfen zu lassen und wenn ja, wie? Also nicht ein ganzes XML-Dokument, sondern nur ein Teil (oder Teile) davon?

  2. Ist es möchlich in einem Schemafile eine Referenz anzugeben auf ein anderes Schemafile? ... mal ein Beispiel mit XML ...


<a-outer>
  <aa-outer>
    <b-inner-other-schema>
      <bb-inner-other-schema>Bla</bb-inner-other-schema>
    </b-inner-other-schema>
  </aa-outer>
</a-outer>

Ist es möglich, z.B. ab bb-innerXXX in einem Schemafile gegen ein anderes Schemafile laufen zu lassen, bzw. eine Referenz auf dieses andere anzugeben (also im "Hauptschemafile" Referenz auf anderes Schemafile für die Beschreibung ab b-innerXXX)?

Ich hoffe, ich habe mich einigermaßen verständlich ausgedrückt 😁 ... vielen Dank schon einmal für etwaige Antworten.

Gruß

04.12.2008 - 23:58 Uhr

Da kann ich gleich einfach die Zugriffe lassen und dort die Exceptions abfangen. Gibts denn echt keine Möglichkeit festzustellen ob ein config "anwesend" ist?

if(File.Exists(Assembly.GetExecutingAssembly().ManifestModule.Name + ".config")) ...
29.11.2008 - 14:07 Uhr

@Tomot,

Danke für Deine Antwort.

Also mit Preprozessor -Anweisungen kann ich gar nix anfangen - die möchte ich einfach nicht (ist halt Geschmackssache).

Die Anregung von Dir ist ja ganz gut, nur garantiert mir diese Lösung nicht, dass eine getestete Umgebung auch Live läuft, wenn ich nämlich mal hin und wieder eine Einstellung vergessen habe. Du musst Dir vorstellen, dass ich jetzt (am Anfang) schon über 100 Einstellungen (Keys in Configfile) habe. Das werden viel mehr - und diese müssen doppelt gepflegt werden - da ist imo Inkonsistenz vorprogrammiert. Irgendwie sollte ich die alle in einem File haben und daraus das benötigte generieren, so muss ich das zentral nur an einer Stelle pflegen ... vielleicht so ...

<config>
  <key name="my.key.name" test-value="test" live-value="live" />
  <key name="my.key.name2" common-value="equal live and test" />
</config>
...
29.11.2008 - 13:44 Uhr

Hallo "Kollegen",

ich bin gerade dabei, mir ein Konzept zu überlegen, wie ich die ewige Problematik umgehen kann, dass ich Konfigurationen (Datenbank, Netzwerkzugriffe, Passwörter, EMailadressen ect.) unterschiedlich benötige, nämlich abhängig von der Test- und Liveumgebung.

Als erstes dachte ich, dass ich einfach zwei Configfiles (App-Live.config und App-Test.config) anlege und dann je nach Bedarf die benötigte umbenenne (App.config). Dies ist aber viel zu umständlich, da ich sehr viel in die Configdatei auslagern möchte. Funzzt jetzt meine Testumgebung, dann bedeutet das noch lange nicht, dass die Liveumgebung läuft, denn ich könnte ja die ein oder andere Einstellung in der Livedatei vergessen haben (KeyNotFoundException ect.).

OK, ich könnte beim Hochfahren der Anwendung die beiden Configfiles vergleichen, ob die beide die gleichen Elemente + Attribute besitzen. Wie macht man das eigentlich? Gibt es dafür eine schnelle Lösung mit dem XmlDocument-Objekt? Die Lösung ist aber eigentlich auch nicht optimal.

Dann dachte ich daran, dass ich ein komplett neues Configfile mache, mit jeweils beiden Einträgen (Test- und Laufzeitumgebung), so dass ich alle Einstellungen in einem File habe. Bei einem Deployment (Test- oder Liveumgebung) kann ich dann soz. on the fly aus dem einen File die App.config generieren, mit den Daten, die ich halt benötige (Test- oder Liveumgebung) - also soz. als Template benutzen.

Nun meine Frage. Gibt es dafür schon Lösungen, bzw. wie umgeht ihr die Problematik?

29.11.2008 - 13:29 Uhr

Hallo "Kollegen",

ich suche eine Möglichkeit, möglichst schnell und komfortabel eine geänderte Programmversion (Windowsservice) auf den Ausführungsserver zu stellen.

Optimallösung wäre:

  1. Kompilierung geändertes Projekt
  2. Herunterfahren des Services auf dem Server
  3. Kopieren der notwendigen neuen Dateien auf den Server
  4. Starten des Services auf dem Server

Gibt es hierfür Lösungen (fern ab vom Foundation Server, den wir nicht einsetzen?)

Bekommt man das mit MSBuild und / oder NAnt hin? Wie löst ihr diese Problematik? Mir geht nämlich das ewige Hin- und Herkopieren auf den Geist.

Danke schon mal für etwaige Antworten und Anregungen im Voraus.

29.11.2008 - 00:22 Uhr

Hallo,

erst mal vielen Dank für eure Anregungen ...

Nachteile:

  • Umständliche Programmieren
  • Kompliziertes Debugging
  • Threading ist unbedingt nötig (und Threading ist kompliziert 😜 )

Ja, weil es umständlich (Debugging, Logging, Exceptionhandling ect.) ist, habe ich alles aus der Serviceklasse ausgelagert. Das bedeutet, dass die Start-Methode nur einen Thread startet, der sich dann um alles weitere kümmert. So kann ich lokal die Threads einzeln oder den ganzen Service komplett in einer Consolenanwendung testen und debuggen. Entwickelt wird natürlich auch mit der Consolenanwendung.

Mein Serviceklasse ist also sehr schlank .. sieht lediglich so aus:

namespace LoeweService {
  public partial class Service : ServiceBase {
    /// <summary>
    /// The service main class
    /// </summary>
    public Service() {
      InitializeComponent();
    }

    private LoeweServiceManager loeweServiceManager = null;

    /// <summary>
    /// Starting service point
    /// </summary>
    protected override void OnStart(String[] args) {
      this.loeweServiceManager = new LoeweServiceManager();
      this.loeweServiceManager.severe += this.Servere;
      this.loeweServiceManager.Run();
    }

    /// <summary>
    /// Ending service point
    /// </summary>
    protected override void OnStop() {
      this.loeweServiceManager.Stop();
    }

    /// <summary>
    /// Severe event from LoeweServiceManager object has been fired
    /// </summary>
    private void Servere(Exception ex) {
      base.Stop();
    }

    /// <summary>
    /// System is shutting down
    /// </summary>
    protected override void OnShutdown() {
      this.loeweServiceManager.Stop();
    }
  }
}
  1. verwende bitte kein Thread.Sleep, sondern steig auf WaitHandle(AutoResetEvent, ManualResetEvent, Semaphore) oder Monitor.Wait/Pulse um.

Also, ich bin ja (noch) nicht so tief in Sachen Threads drinnen gewesen, bzw. weiß nicht genau ob ich das hier brauche, bzw. wie ich das einsetzen soll. Ich erkläre einmal kurz, wie ich meine Anwendung aufgebaut habe.

Im Configfile gibt es einen Sectionhandler, hier können Services angemeldet werden, z.B. mit display-name="BlaService" class="BlaServiceClass" ...

Der Hauptservice Instanziert einen ThreadManager (hier LoeweServiceManager). Diese Klasse (Methode) läuft andauernd mit einem Thread.Sleep(1000) und wartet auf Ereignisse (Logging, Errors, Mailinganforderungen, Messages ect.). Bei der Initialisierung dieser Klasse werden die Services aus dem Configfile gelesen und in einem bestimmten Verzeichnis nach den Klassen (Attribut class) gesucht. Hier wird dann mittels Reflection eine Instanz von dieser Klasse gebildet und die jeweilige implementierte Run-Methode wird als Thread aufgerufen.

Sieht dann in einem Beispiel so aus ...

public class OrdersMatchingService : BaseThread, IThreadClass { ...


 public void Run() {
      
      try {
        while(!base.AbortRequest) {
          // Do some work
         Thread.Sleep(1000);
        } ...

Ich habe absolut keine Performanceprobleme und das gezeigte funktioniert auch ohne Probleme. Nur will ich ja dazulernen. Was würdet ihr an dieser "Architektur" verbessern? Es wird von den Threads nicht auf Resourcen (im Speicher) zugegriffen, die auch von anderen Threads benötigt werden - die Threads laufen alle völlig autark. Also weiss ich nicht, wie ich hier Monitor oder Waithandles einsetzen soll oder könnte, hier fehlt mir leider der Background oder aber ich brauche die für meine "Problematik" überhaupt nicht (zumindest verstehe ich das jetzt so). Danke schon mal im Voraus für Hilfe.

27.11.2008 - 20:33 Uhr

Hallo "Kollegen",

ich habe neu in einer Firma angefangen, die noch in der "Steinzeit" lebt - das ist ja nichts neues. Es gibt ganz viele verschiedene Programme (meisst Access), die halt etwas machen. Totales Chaos eben. Nun portiere ich die Funktionalität der Programme nach C#. Ich habe nun angefangen einen einzigen Service zu machen, der wiederum für jede Routine einen eigenen Thread startet. Es können locker insgesamt 50 Routinen werden. Gleichzeitig im Dauereinsatz sind max. fünf Threads, die anderen Routinen starten entweder nach Request oder einmal am Tag. Später ist dann vorgesehen, eine kleine WCF-Anwendungs-GUI zu erstellen, um die Threads (also die Routinen) kontrollieren (ein/ausschalten) zu können und den Service als Ganzes pfegen zu können.
Gegenwärtig bin ich bei 11 Threads (Routinen). Nun stelle ich mir die Frage, ob es hier Grenzen gibt (was ich nicht glaube) oder aber ob der Aufbau so richtig ist. Wie würdet ihr das ganze angehen? Bin ich auf dem "richtigen Weg"? Ich möchte halt weg von zig kleinen Anwendungen (die dann auch noch net mal gekapselt auf der Datenbank "rumrödeln"), sondern eine Anwendung haben, die das Zentral macht. Was hat es denn mit den Threads so auf sich? Ist doch eigentlich egal, wieviele ich gleichzeitig laufen lasse (solange ein Thread.Sleep(1000) bei allen drinnen ist - jeweils nach einer Prozessroutine), sollte es doch keine Performanceprobleme geben, oder?

Wäre nett, wenn sich der ein oder andere hier mal zu Wort meldet, um mir Feedback zu geben. Danke schon mal im voraus hierfür.

Gruß

P.S. Alle Routinen benötigen (i.d.R.) keine GUI

23.11.2008 - 00:31 Uhr

Vielen Dank für eure Antworten. Ich hatte ursprünglich die Lösung (binär) von vbprogger bevorzugt, musste dann aber feststellen, dass dies im MSIE nicht funzzt. Da aber alle Mails an Outlook gehen, ist die Lösung von manunidi optimal.

Vielen Dank für die gewonnenen Einsichten 👍

22.11.2008 - 17:17 Uhr

Hallo Kollegen,

ist es möglich, eine Mail (im HTML-Format) mit einem generierten Bild zu senden, ohne dieses auf einem Webserver zur Verfügung zu stellen? Hintergrund ist der, dass ich ein Bild generiere und dieses dann in einer Mail verwenden möchte (nicht als Anhang, sondern als HTML in der Mail). Nun kann ich dieses generierte Bild ja auf den Webserver schieben und in der Mail "festverdrahtet" referenzieren, wäre ja kein Problem. Frage ist nur, ob man das nicht auch so einstellen kann, dass er das Bild gleich "live" überträgt.

Ich habe das gerade mit Thunderbird ausprobiert, wenn ich hier eine HTML-Mail mit Bild verschicke, dann funzzt das, dann kann ich auf lokales Bild referenzieren - wenn ich das mit C# via SmtpClient mache, dann nicht, also muss es eine Lösung geben, denn Thunderbird ist ja auch gecoded worden 😉

Danke schon mal für etwaige Antworten.

28.10.2008 - 09:13 Uhr

OK, erst mal Danke. Ich suche natürlich selbst, bis ich mich entschließe, einen Eintrag hier zu schreiben. Ich habe bisher leider nichts gefunden (weder hier noch in Google). Die Sourcen sind definitiv frei. Auf meinem lokalem System (IIS 5.1) funktioniert das und auf dem Server (IIS 6.0) bekomme ich die besagte Fehlermeldung. Wie gesagt, auf dem Server kann ich aber ohne weiteres Files erstellen und löschen, jedoch nicht verschieben. Hat jemand eine Idee?

27.10.2008 - 17:25 Uhr

Hallo,

ich bekomme bei einer ASP.NET Webanwendung immer den Fehler "UnauthorizedAccessException: Access to the path is denied", wenn ich ein File verschieben möchte. Probiere ich das lokal aus, dann funktioniert das auch. Auch kann ich auf dem Server Dateien erstellen und löschen (ohne Probleme) - auch habe ich dem ASP.NET-User und dem IUSR die vollen Berechtigungen gegeben aber der Fehler kommt immer wieder (auch wenn ich ein komplett neuen Ordner auf dem Server erstelle - ich kann da einfach keine Dateien hinschieben). Die Dateieen sind nicht geöffnet, also die Resourcen sind frei. Was kann denn das sein? Kann mir jemand helfen?

Gruß

18.10.2008 - 16:02 Uhr

Vielen Dank. Es war noch ein kleiner Fehler drinnen. Die Lösung sieht nun so aus:

 public class MyThread : IThread {
    public void Run() {
      while(true) {
        Console.WriteLine("Thread is running ...");
        Thread.Sleep(1000);
      }
    }
  }
  
  public class Program {
    public static void Main() {
      try {
        Object serviceInstance = Activator.CreateInstance(typeof(MyThread));
        Type type = serviceInstance.GetType();
        MethodInfo methodInfo = type.GetMethod("Run");

        ThreadStart threadStart = (ThreadStart)Delegate.
          CreateDelegate(typeof(ThreadStart), serviceInstance, methodInfo);
        Thread thread = new Thread(threadStart);
        thread.Start();
      }
      catch(Exception ex) {
        Console.WriteLine(ex.GetType().FullName + ex.Message + ex.StackTrace);
      }

      Console.WriteLine("Exit");
      Console.ReadLine();
    }

Jetzt kann ich Thrads so benutzen wie in Java (ist halt schöner gekapselt)

Gruß

18.10.2008 - 01:21 Uhr

Hallo "Kollegen",

folgender Quellcode:

public class MyThread {

    public MyThread() {

    }

    public void Run() {
      while(true) {
        Console.WriteLine("Thread is running ...");
        Thread.Sleep(1000);
      }
    }
  }
 
  public class Program {
    public static void Main() {
      try {
        Object serviceInstance = Activator.CreateInstance(typeof(MyThread).GetType());
        Type type = serviceInstance.GetType();
        MethodInfo methodInfo = type.GetMethod("Run");

        ThreadStart threadStart = (ThreadStart)
          Delegate.CreateDelegate(type, serviceInstance, methodInfo);

        Thread thread = new Thread(threadStart);
        thread.Start();

      }
      catch(Exception ex) {
        Console.WriteLine(ex.Message + ex.StackTrace);
      }

      Console.WriteLine("Exit");
      Console.ReadLine();
    }

Fehlermeldung (gleich in der ersten Zeile bei CreateInstance)

No parameterless constructor defined for this object

Ist es jetzt zu spät oder worauf stehe ich jetzt? Ich habe doch einen Konstruktor drinnen und bin da jetzt schon über eine Stunde drüber ... ich mag heute erst mal nicht mehr. Vielleicht kann mir jemand helfen oder morgen früh fällt es mir wie Schuppen von den Haaren.

Gute N8 und vielen Dank für evtl. Antworten

18.10.2008 - 01:15 Uhr

Nochmals vielen Dank für eure Tips - ich glaube ich habe da einen 3/4 Tag verbraten, nur wegen dem Oracle. Problem war, dass ich vorher den DBVis installiert hatte mit dem JDBC-Treiber (jar) ... ist ratz fatz gegangen wie immer und dann kam C# dran ... ich habe da nix gefunden bis ich letztendlich völlig generft eine ODBC (ich brauche nur zwei Selects) eingebaut hatte - die ist dann auch nicht gelaufen, weil ich beim Oracle-Client das Passwort bei der Installation für den Dienst falsch eingegeben habe - aber die ODBC-verbindung ist gelaufen, nach Testbutton 8o .. d.h., wenn ich auf die referenziert hatte, dann ging es aus dem Programm nicht aber über ODBC mit dem Button Test Connection .. war wirklich verrückt - naja, jetzt wieder schnell zürück zu SQL-Server 🙂 ... und danke nochmal für eure Antworten.

14.10.2008 - 15:14 Uhr

Ich habe jetzt lokal den Client installiert und eine ODBC-Verbindung (ja, ODBC) eingestellt, mit dem Namen stillmms, das funktioniert auch (Test-Button) ... wie kann ich nun im Quellcode an diese Verbindung rankommen ... ich kriege das einfach nicht gebacken:

OdbcConnection connectin = new OdbcConnection("?????");

Ich habe schon allerhand ausprobiert und war natürlich auch schon auf http://www.connectionstrings.com

Danke für eure Hilfe schon einmal im Voraus

14.10.2008 - 12:51 Uhr

OK, vielen Dank für Deine Ausführungen. Ich gehe jetzt einfach mal davon aus, dass Du Recht hast. Ich bekomme nun die Fehlermeldung ...

ORA-12705: Cannot access NLS data files or invalid environment specified

jetzt muss ich da wohl ein bißchen "rumsuchen", an was das liegt.

14.10.2008 - 12:39 Uhr

Ich habe irgendwie das Gefühl, dass wir aneinander vorbei reden.

Gut, nehmen wir das Beispiel ODBC her ... bei jeder x-beliebigen Datenbank (SQL-Server, Acces, mysql) kann ich einen ODBC-Eintrag erstellen und dann auf die Datenbank zugreifen, jedoch geht das bei Oracle nicht so einfach - hier müssen dann Minimalinstallationen (lokal) durchgeführt werden um überhaupt an eine Oracle-Datenbank (im Netz) zu kommen - zumindest habe ich das bisher so verstanden. Oder habe ich das jetzt völlig falsch verstanden. Wenn das so einfach ist, was wähle ich denn dan aus, wenn ich eine neue ODBC-Verbindung erstellen will?

14.10.2008 - 12:28 Uhr

aber da brauche ich doch den Client, oder etwa nicht? Bei einer ODBC-Verbindung brauche ich doch lokal (oder überall, wo die Anwendung laufen soll) einen Client, das ist doch mein Problem. Bei SQL-Server oder MySQL ist das ja kein Problem, bei Oracle jedoch schon - leider

14.10.2008 - 12:00 Uhr

Ich habe mir jetzt den Instant Client gezogen. Hier habe ich die vier DLLs in mein Startup-Path copiert (oraociei11.dll, oci.dll, orannzsbb11.dll, oracci11.dll)

... dann im Code ...

OracleConnection oracleConnection = new OracleConnection();

        string CONNECTION_STRING =
          "User Id=bla;Password=bla;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.4.13)(PORT=1521))(CONNECT_DATA=(SID=stillmms)));";

        oracleConnection.ConnectionString = CONNECTION_STRING;
        oracleConnection.Open();

        oracleConnection.Close();

Jetzt bekomme ich die Fehlermeldung:

ORA-12705: Cannot access NLS data files or invalid environment specified

Was bedeutet dies? Ich möchte auf eine 9i-Datenbank, bzw. muss ich noch etwas lokal einstellen?

14.10.2008 - 09:48 Uhr

.Vielen Dank - ich schaue da gleich mal rein ...
.
.
OK, sorry, ich habe da keinerlei Erfahrung.

Was muss ich da alles installieren?

Es gibt folgende Auswahlmöglichkeiten
Oracle Services For Microsoft Transaction Server
Oracle ODBC Driver
Oracle Provider for OLE DB
Oracle Objects for OLE
Oracle Data Provider for .NET

????

Ich habe jetzt mal Oracle Data Provider for .NET installiert. Was muss ich jetzt machen, bzw. wo bekomme ich nähere Informationen.

Hatte leider bisher mit Oracle nie etwas zu tun, wenn, dann nur mit Java und hier nur als Client - Datenbank war immer schon eingerichtet.

Gruß

14.10.2008 - 09:23 Uhr

verwendetes Datenbanksystem: Oracle 9
Hallo Kollegen,

ich habe jetzt schon mehrere Stunden damit verbracht, eine Lösung zu finden um einen "stink normalen Select" auf eine Oracle-Datenbank mit C# durchzuführen. Ich komme da einfach nicht weiter. Ich will nicht den Client installieren. Ich bekomme da keine einheitlichen Informationen. Gibt es denn sowas wie bei Java, wo ein ganz normales JAR-File als Client ausreicht. Leider komme ich hier mit der Suchfunktion auch nicht weiter. Was soll ich machen?

Mein Connectionstring (Java - JDBC) lautet: jdbc:oracle:thin:user/password@URL : PORT : SID

03.10.2008 - 02:12 Uhr

Hallo "Kollegen",

ich bin jetzt nicht so tief drinnen in Schematas aber ich wollte einfach einmal nachfragen, ob es möglich ist bei Elementen, die Text enthalten (müssen) von vornherein zu prüfen, ob der Inhalt, nach einem Trim nicht ein Leerstring ist? Ist das mittels XSD möglich? Ich möchte keine (extra) Validierung durchführen und auf Empty nach einem Trim prüfen.

Die zweite Frage ist, ob man in einem Schema referenzieren kann. Mal angenommen ich habe 5 verschiedene Elemente (aus welchen Gründen auch immer) und die müssen alle gegen einen gleichen regulären Ausdruck laufen - muss ich dann dies wirklich explizit für jedes Element angeben oder gibt es da eine Möglichkeit der Referenzierung?

Danke schon einmal für eure Antworten.

22.09.2008 - 11:42 Uhr

@juetho,

ja, es handelt sich natürlich um ein GridView. Wenn ich das ganze für eine Spalte machen soll, dann ist das kein Problem, jedoch komme ich nicht weiter, wenn alle (oder meherer) Spalten sortiert werden können. Ich komme in dem Ereignis Sorting mit dem EventArgs-Objekt DataGridSortCommandEventArgs einfach nicht an die Spalte. Das ist mein Problem. Ich habe natürlich schon vorher im Web oder MSDN nachgesehen.

Gruß

P.S. Das Forum ist hier viel zu gut um zu "klagen". Ich wollte einfach nochmals nachfragen, so dass der Thread nicht ganz "untergeht".

22.09.2008 - 09:27 Uhr

Hat wirklich keiner eine Idee oder habe ich mich einfach nicht verständlich genug ausgedrückt? Das kann doch nicht sein, dass das Sortereignis auftritt, mit den jeweiligen Properties von Sortexpression und Sortdirection aber ich dann nicht auf den zu sortierenden Spaltenindex komme. Anybody?