Laden...
D
DickesB myCSharp.de - Member
Azubi zum Fachinformatiker Treis in Hessen Dabei seit 11.11.2009 68 Beiträge
Benutzerbeschreibung

Forenbeiträge von DickesB Ingesamt 68 Beiträge

15.02.2011 - 13:36 Uhr

Hi Oli,

denke dabei sollte dir das Überladen des == Operators deiner Qualität helfen.
Siehe dazu überladbare Operatoren

Also dann entweder den Qualität == string oder Qualität == Qualität, was dir besser gefällt...

MfG

DickesB

02.02.2011 - 19:11 Uhr

hallo leute,

ich hätte mal wieder eine frage.

und zwar habe ich ein programm geschrieben, das mithilfe von Castle Project auf eine datenbank (mysql) im internet zugreift. das funktioniert alles prima und ist sehr komfortabel. der user kann sich die daten anzeigen lassen und sie verändern. soweit so gut.
jetzt würde ich das programm aber gerne an einige ausgewählte leute verteilen, die dann auch auf diese datenbank zugreifen würden. mein problem dabei ist nur die synchronisation der zugriffe. ich zerbreche mir seit tagen den kopf darüber, wie und vor allem ob sowas überhaupt ohne server möglich ist, aber leider führen alle wege in eine sackgasse.

hier mal meine bisherigen überlegungen:

  1. alle herkömmlichen techniken ala lock oder monitor fallen ja sowieso weg, weil die programme auf verschiedenen rechnern laufen

  2. über flags zur bearbeitung in der datenbank wird das ganze wohl auch nicht funktionieren

  3. die rechner könnten die synchronisation z.b. über wcf selbst regeln. da habe ich aber von verschiedenen quellen im netz gehört, dass das ohne server bzw. port-forwarding schonmal überhaupt nicht geht (also die direkte kommunikation übers internet)

so, und da bin ich auch schon mit meinem latein am ende. ich kenne mich leider auch mit mysql datenbanken nicht sehr gut aus. jedenfalls habe ich über google nichts gefunden, dass die etwas anbieten, um zugriffe zu synchronisieren.

jetzt dann mal endlich meine frage 😉: weiß jemand eine möglichkeit, den datenbankzugriff übers intrernet zu synchronisieren, wenn ein programm von verschiedenen rechnern darauf zugreift?

vielen dank schonmal für eure mühe!

MfG,

DickesB

07.12.2010 - 11:09 Uhr

Hallo Leute,

ich bin mal wieder am verzweifeln und brauche eure Hilfe.
Ich habe folgendes Problem:
Innerhalb eines Outlook 2007 AddIns (erstellt mit Visual Studio 2010 und VSTO) muss ich eine Email in einen anderen Ordner verschieben. Das hatte bis Freitag auch super funktioniert. Seit gestern wirft allerdings die Methode MailItem.Move eine COMException mit der wunderbar aufschlußreichen Meldung "Die Elemente können nicht verschoben werden".
Und jetzt das kuriose: Es gibt zwei Möglichkeiten, wie ein verschieben angestoßen werden kann. Einmal per WCF durch ein anderes OutlookAddIn und einmal per Event vom selben Outlook. Das Verschieben durch WCF schlägt fehl, das vom eigenen Outlook funktioniert ohne Probleme.
Dazu ist noch zu sagen, dass es sich um ein Exchange Postfach handelt, auf das mehrere Benutzer Zugriff haben.

Durch längeres Googlen habe ich herausgefunden, dass es entweder daran liegen könnte, dass das MailItem noch irgendwo referenziert ist oder die Outlook.pst defekt ist.
Ersteres schließe ich aus, da ein Marshal.ReleaseComObject direkt vor dem besagten Fehler 0 zurückliefert. Zweiteres, da die Ordner auf einem Exchange-Server liegen und das Verschieben per Drag'n'Drop bzw. vom selben Client aus angestoßen funktioniert.

Jetzt bin ich mit meinem Latein am Ende. Ich habe seit Freitag nicht sehr viel geändert und habe versucht, auf den Stand von Freitag zurückzusetzen, was ich meiner Meinung nach auch geschafft habe, leider ohne Erfolg.
Weiterhin habe ich versucht, das Verschieben im Hauptthread des AddIns laufen zu lassen(so wie wenn die Funktion vom eigenen Client ausgelöst wird), das hat aber auch nichts geholfen.


public bool uebertrageTechsoft(string subject)
{
bool ret = false;
//Für alle Emails im Techsoft-Ordner
                for (int i = serviceInboxFolderMails.Count; i > 0; i--)
                {
                    //MailItem referenzieren
                    Outlook._MailItem item = (Outlook.MailItem)serviceInboxFolderMails[i];
                    //Herausfinden, ob der Betreff übereinstimmt
                    bool contains = String.IsNullOrEmpty(subject) ? String.IsNullOrEmpty(item.Subject) : item.Subject == subject;
                    if (contains)
                    {
                        //Wenn ja:
                        try
                        {
                            Settings settings = Settings.GetInstance();
                            //Zeitstempel der Email sichern (Move-Methode überschreibt ihn)
                            DateTime receivedTime = item.ReceivedTime;
                            //Mailobjekt in den Archivordner verschieben
                            Outlook.MailItem item2 = (Outlook.MailItem)item.Move(serviceArchivFolder);
                            //Als ungelesen markieren
                            item2.UnRead = true;
                            //Kategorie setzen
                            item2.Categories = Category.GetCategory(settings.Category);
                            //Speichern
                            item2.Save();
                            //Kopie anfertigen
                            Outlook.MailItem copy = (Outlook.MailItem)item.Copy();
                            //Kopie in den Serviceeingang des Users verschieben
                            copy.Move(userServiceInboxFolder);
                            //Emailtext im Archiv verändern
                            item.Body = "TECHSOFT-SERVICE-MAIL\r\nAbgerufen von " + settings.Token + " am " + DateTime.Now.ToLongDateString() + " um " + DateTime.Now.ToLongTimeString() + "\r\nEmpfangen am " + receivedTime.ToLongDateString() + " um " + receivedTime.ToLongTimeString();
                            //Anhänge im Archiv löschen
                            Outlook.Attachments attachments = item.Attachments;
                            while (attachments.Count > 0)
                            {
                                attachments.Remove(1);
                            }
                            //Als gelesen markieren
                            item.UnRead = false;
                            //Speichern
                            item.Save();
                            ret = true;
                        }
                        catch (Exception ex)
                        {
                            Logger.LogException(ex);
                        }

                        break;
                    }

                }
     return ret;
}

Weiß jemand vielleicht eine Lösung? Vielen dank schonmal!!!

MfG

DickesB

20.08.2010 - 15:07 Uhr

das ist ja das problem, die collection liefert object über den indexer und GetType() liefert bei dem object System.Com_Object...

also so funktioniert es:


		private static void Delete(Outlook.MAPIFolder mapiFolder)
		{
			for (int i = mapiFolder.Items.Count; i > 0; i--)
			{
				object DeleteItem = mapiFolder.Items[i];
				try
				{
					if (DeleteItem != null)
					{
						DeleteItem.GetType().InvokeMember("Delete", System.Reflection.BindingFlags.InvokeMethod, null, DeleteItem, null);
					}
				}
				catch (System.Exception ex)
				{
					System.Windows.Forms.MessageBox.Show(ex.ToString());
				}
			}
		}

ist allerdings widerlich langsam, kommt darauf an, wieviele elemente das pro durchlauf sind...

20.08.2010 - 09:56 Uhr

moin,

hmmm, find das mit dem folder auch grad nicht mehr 😃 habe das eben auch mal versucht und habs auch nicht hinbekommen mit dem cast, schade.

dann kann ich dir nicht weiterhelfen und du musst wohl doch eine der anderen methoden oben benutzen...

MfG

DickesB

19.08.2010 - 15:17 Uhr

is ja nur ein interface, was du in c# bekommst, war mein fehler, sorry.

aber in diesem fall sind beide eh gleich zu benutzen...


        private void Delete(Outlook.MAPIFolder mapiFolder)
        {
            Folder DeleteItem;

            for (int i = mapiFolder.Items.Count; i > 0; i--)
            {
                DeleteItem = mapiFolder.Items[i];

                try
                {
                    if (DeleteItem != null)
                    {
                        DeleteItem.Delete();
                    }
                }
                catch (System.Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(ex.ToString());
                }
            }
        }

so sollte es jetzt funzen...

MfG

DickesB

19.08.2010 - 08:55 Uhr

ok, hab jetzt nochmal ein wenig in der msdn recherchiert und Sebastian.Lange hat recht, die gemeinsame basisklasse heißt Folder...

18.08.2010 - 22:58 Uhr

du könntest die methode per reflection aufrufen, siehe dazu: Dynamisches Laden und Verwenden von Typen

das wird dann halt aber ziemlich langsam. ansonsten fällt mir grad auch nix ein. ein gemeinsames interface wäre prima...

hier ein beispiel(ungetestet):


foreach (object item in inboxFolder.Items) {

Trace.WriteLine (item.GetType ().InvokeMember ("Subject", BindingFlags.GetProperty, null, item, null));

} 

18.08.2010 - 16:08 Uhr

hmmm, also soweit ich weiß gibt es kein gemeinsames interface, das die ganzen outlook-items verbindet, von daher müsstest du mit nem switch case oder mit if abfragen unterscheiden. das würde den code allerdings noch ziemlich aufblähen...

mit welcher c# version bist du unterwegs? ab 3.0 gibt es ja die var deklaration, wo der typ einer variable erst vom compiler bestimmt wird. denke mal, das alle items eine Delete()-methode besitzen. das könntest du nochmal probieren, ist aber ungetestet...


        private void Delete(Outlook.MAPIFolder mapiFolder)
        {
            for (int i = mapiFolder.Items.Count; i > 0; i--)
            {
                var DeleteItem = mapiFolder.Items[i];

                try
                {
                    if (DeleteItem != null)
                    {
                        DeleteItem.Delete();
                    }
                }
                catch (System.Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(ex.ToString());
                }
                releaseCom(DeleteItem);
            }

        }

//EDIT: vergiss es, items_ liefert object, da bräuchtest du dann doch nen cast auf ein gemeinsames interface. btw: wie geht der code bei dir ohne cast durch den compiler?


DeleteItem = mapiFolder.Items[i];

ansonsten sieht dein code jetzt schon ganz gut aus, denk ich...

MfG

DickesB

18.08.2010 - 08:15 Uhr

das ist ne klasse aus System.Runtime.InteropServices.
und die statische methode ReleaseComObject() brauchst du zum freigeben einer COM referenz...

17.08.2010 - 12:45 Uhr

Das Problem: Wenn jemand ein Word-Dokument über das Managementsystem anlegt und dann das Managementsystem schließt ohne vorher das Dokument geschlossen zu haben, bekommt die Anwedung davon nichts mehr mit.

ich versteh immer noch nicht, was jetzt dein problem ist. einfach das schließen des managementsystems abfangen und gucken ob noch ein prozess läuft. wenn ja, speichern und warten bis er zuende ist, danach schließen.

17.08.2010 - 12:21 Uhr

ich kenn mich mit asp.net nicht aus, aber gibt es da nicht events wie z.b. page_load, in denen du eine instanz der klasse presenter erstellen könntest? oder wo macht man sowas bei asp?

gegenseitig referenzieren dürfen die beiden auf keinen fall, das würde dem mvp wiedersprechen. da sollte eigentlich nur der presenter die model und view kennen und (eigentlich über schnittstellen, aber machs erstmal so) die kommunikation zischen den beiden regeln.

übung macht eben den meister 😉

17.08.2010 - 12:06 Uhr

ich glaube, du musst nochmal etwas mehr zu deinem aufbau erklären.

ich dachte, es geht um den fall, dass der benutzer dein programm schließt, falls noch eine operation läuft. wenn er es schließt, arbeitet er bestimmt nicht mehr an dokumenten 😉

17.08.2010 - 11:47 Uhr

achso, der titel hat mich dann wohl in die irre geleitet. hört sich so an, als sollte dein programm warten...

ich würde das trotzdem so machen, nur dann eben die form im form_closing schonmal verstecken. ist denk ich das beste für den user, denn wenn du dein programm beendest und die wordverarbeitung im hintergrund weiterläuft, kannst du auf keinerlei fehler mehr reagieren. das erscheint mir eher sehr schlecht...

17.08.2010 - 11:26 Uhr

Hallo Rahvin,

verhindere das schließen deiner Anwendung, z.B. im Form_Closing event und setze ein flag, das du dann im DocumentBeforeClose auswertest. wenn es gesetzt ist, beendest du deine anwendung...

MfG

DickesB

17.08.2010 - 10:48 Uhr

wieso weist du die eventhandler nicht im konstruktor zu?


        _Default defaultsite;

        public Presenter()
        {
             defaultsite = new _Default();
             defaultsite.ButtonGeklicked += new _Default.LogHandlerdef(Process);
             defaultsite.ButtonGeklicked += new _Default.LogHandlerdef(Process2);
        }

du musst defaultsite sowieso zur Klassenvariable machen, da sie ansonsten nach ausführung der methode M1 vom GC weggeräumt wird...

und wieso hat die methode ButtonWurdeVerändert die signatur eines Eventhandlers, wenn du sie doch einfach so aufrufst?

17.08.2010 - 08:17 Uhr

moin Key-Concept,

der eventhandler M1 wird nie aufgerufen, deshalb ist ButtonGeklicked natürlich noch null. das solltest du vorher prüfen...

MfG

DickesB

13.08.2010 - 09:24 Uhr

moin,

joa, das ist weil das keine mailitems sind, sondern ContactItems, AppointmentItems, usw.
schau dir das am besten mai in der outlook developer reference an, du musst dann halt nach typ unterscheiden. bei dir wirft im moment die zuweisung von mailItem eine exception, wenn das element kein mailitem sondern ein anderes ist...

btw: da du ja beinahe zweimal denselben code in der methode hast, sollteste eine draus machen und als parameter den ordner übergeben...

MfG

DickesB

13.08.2010 - 09:16 Uhr

denke mal weil schowdialog() die form modal aufruft, d.h. erst nach bestätigung des dialogs gehts mit dem nachfolgenden code weiter...

12.08.2010 - 15:10 Uhr

wie wärs mit ein wenig code?

12.08.2010 - 14:20 Uhr

Hallo Timur Zanagar,

das liegt bestimmt daran, dass die standard .net richtextbox bei komplexeren rtf-datein schon ziemlich schwächelt(z.b. bei verschachtelten tabellen).
stand auchmal vor dem problem und habe da auch eine neuere version der dll dem richtextbox-wrapper per LoadLibrary untergeschoben. das hat aber auch nur zur anzeige funktioniert und die richtextbox hat sich danach sehr komisch verhalten(z.B. waren TextLength und Text.Length danach immer verschieden und wenn man den SelectedIndex auf knapp unter diese werte gesetzt hat, gabs ne ArgumentOutOfrangeException)

die vorgehensweise is also alles andere als das wahre. bei mir war das allerdings auch nicht für einen kunden.

@Pedro_15: ich denke auch, dass du die dll auf keinen fall mitliefern darfst. könntest halt höchstens sicherstellen, dass überall office installiert ist, aber das ist sicherlich auch nicht sinn der sache...

MfG

DickesB

12.08.2010 - 08:06 Uhr

Hallo XenoLith,

zum einen kannst du dir die äußere if-bedingung sparen, das erreichst du auch, wenn du die bedingung der for-schleife auf i>0 änderst.

und du solltest nach der benutzung die COM-objekte wieder freigeben, so wie hier. da gehts zwar um excel, das prinzip ist aber dasselbe...

MfG

DickesB

11.08.2010 - 13:33 Uhr

Hallo scrabbl,

das komische objektmodell vom office kann einem schon manchmal kopfschmerzen bereiten.


Excel.Axis xlAxis = (Excel.Axis)xlChart.Axes(Excel.XlAxisType.xlValue, Excel.XlAxisGroup.xlPrimary);
xlAxis.HasTitle = true;
Excel.AxisTitle xlTitle = xlAxis.AxisTitle;
xlTitle.Text = "bla";

so sollte es eigentlich funktionieren.
Mache das bei mir so mit nem ChartTitle, müsste dann wohl am HasTitle = true liegen...

MfG

DickesB

11.08.2010 - 08:27 Uhr

Moin XenoLith,

ich würde mal drauf tippen, dass es daran liegt, dass du ne foreach benutzt...

das erste element wird gelöscht -> zweites rutscht an erste stelle, drittes an zweites, usw.
das zwiete element wird gelöscht und ist eigentlich das dritte...

ich würde ne for-schleife benutzen und die rückwärts laufen lassen.


for (int i = mapiFolder2.Items.Count - 1; i >= 0; i--)
{
    //Mailitem loschen
}

MfG

DickesB

09.08.2010 - 13:49 Uhr

hi frankuc45,

ups, war nur schnell hier reingeschrieben.

der indexer gibt hier ein object zurück, deshalb musst du analog zu den mapifoldern nach mailitem casten.


MailItem item = (MailItem)items[1];

schau dir mal bitte Compilerfehler selbst lösen an, die fehlermeldung war jetzt schon ziemlich eindeutig...

MfG

DickesB

06.08.2010 - 15:30 Uhr

oh, sorry, dann hab ich dich wohl falsch verstanden.

die frameworkmacher haben demnach wahrscheinlich einfach den 1.1.1930 als stichtag gewählt, die funktion kann ja auch schlecht hellsehen, welches jahr(hundert) der benutzer in dem genauen fall meint...

aber gut zu wissen, also am besten die jahreszahl vierstellig speichern 😃

06.08.2010 - 15:21 Uhr

hab das auch mal getestet und sobald die jahreszahl 30 oder höher ist, wird von 1900 ausgegangen...

also sind beim übergang von 39 zu 40 usw. beide datumswerte im 20. jahrhundert.

kannst du nicht einfach die 20 vor dem parsen in den string einfügen?

06.08.2010 - 09:23 Uhr

Wenn überall Word vorhanden ist, kannst du das mit den Primary Interop Assemblies machen. Und zwar mit der PrintOut-Methode im Document-Objekt...

Beachte auch bitte Wie poste ich richtig - Punkt 1.1, denn wenn ich nach 'c# word dokument drucken' google, kommt der Thread Word Drucken mit angabe der zu druckenden Seiten als erster Treffer...

05.08.2010 - 08:32 Uhr

benutze bitte die code-tags...


MAPIFolder inboxFolder = (MAPIFolder)olNS.Folders["Maschine"];
MAPIFolder subFolder = (MAPIFolder)inboxFolder.Folders["Archiv"]
Items items = subFolder.Items
MailItem item = items[1];
Attachments att = item.Attachments;

vergiss am ende nicht für jedes COM-Objekt Marshal.ReleaseComObject() aufzurufen...

05.08.2010 - 08:13 Uhr

zu empfehlen ist dafür auch immer das Regex-Tutorial und herbivores Regex-Lab...

02.08.2010 - 11:08 Uhr

meine Excel - Instanz erst mit Beenden der Applikation geschlossen wird

8o Ja aber so soll das doch ?

ich glaube er hätte die instanz gerne schon früher geschlossen...

prinzipiell sollte die vorgehensweise so sein:

  1. jedes com-objekt einzeln referenzieren, d.h. nicht

Range xlRange = xlWorkbook.Worksheets["Tabelle1"].Cells[1,1]

sondern


Worksheets xlWorksheets = xlWorkbook.Worksheets
Worksheet xlWorksheet = xlWorksheets["Tabelle1"]
Range xlRange = xlWorksheet.Cells[1,1]

dann nach der Benutzung jedes(!) com-objekt freigeben, ich mach das immer so:


private void releaseCom(object o)
{
	if (o != null)
	{
		Marshal.ReleaseComObject(o);
		o = null;
	}
}

leider hatte ich trotz dieser vorgehensweise schon manchmal das problem, dass erst ein GC.Collect() die Instanz beendet hat.

ich hoffe das hilft dir weiter.

MfG

DickesB

30.07.2010 - 12:19 Uhr

hast du die primary interop assemblies auf dem server installiert?

22.07.2010 - 10:50 Uhr

Mit Assembly.Load kannst du eine dll auch aus den Ressourcen laden, sofern es sich um eine .NET dll handelt...

[EDIT]du brauchst dazu noch den ResourceManager, um dir die Ressource als byte[] zu holen[/EDIT]

01.02.2010 - 10:36 Uhr

Hallo absolut,

die ArrayList gehört in die Mottenkiste.

Ich würde dir ein Dictionary<string, int[]> empfehlen. Da musst du nicht mehr casten und kannst dir per TryGetValue die Werte anhand des Bezeichners holen...

MfG

DickesB

20.01.2010 - 14:03 Uhr

Hallo calabrese,

sollte dieser Mechanismus nicht innerhalb deines Controls ablaufen? D.h. du abonnierst das TextChanged-Event der TextBox und lässt darin dann den Text aktualisieren...

Wenn du das Event wirklich nach außen brauchst, schreib dir nen EventHandler in dein Control, der im TextChanged-Event deiner TextBox gefeuert wird...

EDIT: ok, zu spät 🙁

MfG

DickesB

19.01.2010 - 16:28 Uhr

Hallo herbivore,

danke erstmal für deine Antwort. Irgendwie stand ich da auf der Leitung 😉

Leider hab ich bei dem Versuch, den Aufruf des Konstruktors in einen anderen Thread auszulagern Probleme bekommen. Da wurden ja die Controls der Form in einem anderen Thread erstellt und somit gabs InvalidCrossThreadCalls als später meine Form auf die Controls zugriff X(

Hab dann einfach im Konstruktor meiner Form nen Thread gestartet, der die SplashForm per ShowDialog() zeigt. Am Ende vom FormLoad beende ich diesen mit Abort(). ABER: Problem war dasselbe.

Jetzt hab ich einfach die API bemüht und SetForegroundWindow benutzt 8) Damit hat sich das Problem erledigt, auch wenns so nicht ganz die feine Art is...

MfG

DickesB

19.01.2010 - 14:25 Uhr

Hallo,

ich habe glaub ich ein ähnliches Problem. Ich lasse einen Splashscreen anzeigen, bevor die Form sich zeigt, weil der Konstruktor der Form schonmal 2 bis 4 sekunden braucht.

gelöst hab ich das ganze in der main so:


                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Form1 frmMain;
                using (frmSplash frmsplash = new frmSplash())
                {
                    frmsplash.ShowInTaskbar = false;
                    Thread t = new Thread(new ParameterizedThreadStart(runForm));
                    t.Start(frmsplash);
                    frmMain = new Form1();
                    frmsplash.Invoke(new DelVoidNone(frmsplash.Close));
                }
                Application.Run(frmMain);

meine runForm-Methode:


        private static void runForm(object form)
        {
            Application.Run((Form)form);
        }

Das funktioniert auch super soweit, aber wenn die MainForm gezeigt wird ist sie immer im Hintergrund und ich muss sie erst in der Taskleiste anklicken. Es ist aber nicht minimiert, habe den WindowState gecheckt, der ist normal. Woran könnte das liegen?
Ohne Splashscreen und einfach nur mit Application.Run(new Form1()) kommt das Fenster im Vordergrund hoch.

Vielen Dank schonmal im Vorraus!

MfG

DickesB

13.01.2010 - 11:52 Uhr

Zu den escape-Sequenzen:

Was bedeutet das @ vor strings

18.12.2009 - 15:17 Uhr

Hallo herbivore,

ich finde es auch wirklich wundesam. Wenn ich mir während der Laufzeit den SelectionStart-Wert ausgeben lasse, sehe ich dass der größtmögliche Index 65305 ist, also wie die TextLengt-Property.
Wenn ich mir aber den Text hole, ist der nur 64653 Zeichen (=Text.Length)
lang. Also gibt es dabei tatsächlich eine Abweichung! Ich hab aber irgendwie keinen Plan, wie ich diese beiden Werte unter einen Hut kriegen kann. Noch dazu zu sagen ist, dass ich den Text niemals verändere, sondern er wird nur angezeigt.

Ich habe irgendwie die Vermutung, dass es an der RichtextBox liegt, weil ich ja keine "normale" benutze. Ich muss die aber so nehmen, weil darin ein Rtf mit teilweise verschachtelten Tabellen angezeigt werden soll und das kriegt die normale leider nicht hin. Ist aber ja auch eigentlich verständlich, dass da was nicht passt, weil ich ja der .Net Wrapperklasse einfach eine neuere Version des Controls unterschiebe. Mit Aufwärtskompatibilität ist das ja so ne sache...

Ich habe jetzt TextLength überschrieben und gebe Text.Length zurück. Dann fliegt keine Exception mehr aber die Find-Methode gibt -1 zurück. (logisch, weil sie denk ich nur bis zu TextLength sucht)

Und die Find-Methode benutze ich nur als Workaround, weil mir schon vorher aufgefallen ist, dass die Indices nicht passen. Je weiter man nach unten kommt um so größer wird die Abweichung, ABER die Indices waren sonst immer kleiner als die echten Werte. So konnte ich mit Find und dem Index das Wort trotzdem schnell markieren (auch ohne den genauen Index zu kennen)...

MfG

DickesB

18.12.2009 - 10:23 Uhr

bei input deinen text von oben eingetragen?
bei pattern mein pattern?
dann zeigt er bei mir unten die korrekten groups...

und der codeschnipsel funktioniert bei mir auch wie gewünscht!

18.12.2009 - 10:02 Uhr

was meinst du mit in einem eintrag? im match.Value? oder in match.Groups[0].Value? falls es so ist dann is ja klar...

teste das am besten doch nochmal mit dem Regex-Lab

damit hab ich das pattern erstellt und wie gesagt stehen die keys dann in Group[1] und die values in Group[2]...

also so ungefähr:


            Regex matcher = new Regex(@"([A-Za-z]+):(.+?(?=(?<!\[.+),|}))");
            foreach (Match m in matcher.Matches(input))
            {
                string key = m.Groups[1].Value;
                string value = m.Groups[2].Value;
            }

18.12.2009 - 09:28 Uhr

du kannst doch in der schleife die id und alles was du noch so brauchst setzen, oder?

und in dem anderen thread ging es doch glaub ich darum, dass man keine controls nach ihrem namen ansprechen sollte, der in einem string vorliegt. und dass machst du ja mit dem array nicht mehr...

18.12.2009 - 09:20 Uhr

Hallo herbivore,

du hast natürlich Recht! War nur so schnell dahingedacht...

Hallo Toem99,

mit diesem Pattern sollte das so gehn, wie herbivore gesagthat: ([A-Za-z]+):(.+?(?=(?<![.+),|}))

da kannst du dann aus match.Group[1] den Key holen und aus match.Group[2] den Value...

MfG

DickesB

18.12.2009 - 08:55 Uhr

Moin schuppsi,

erstell ein array mit länge 10 von deinen controls, dann kannst du sie iterativ initialisieren und auch über den index ansprechen...


    MyControl[] arr = new MyControl[10];
    for (int i = 0; i < arr.Length; i++)
    {
        arr[i] = new MyControl();
    }

MfG

DickesB

18.12.2009 - 08:39 Uhr

Moin Toem99,

ich würde die {} per Trim() entfernen, dann Regex.Split() nach , oder :
dann hast du die elemente getrennt.


        string input = DEINTEXT.ToCharArray());
        string[] arr = Regex.Split(input,",|:"); 

Das einzige problem ist halt, dass deine tags auch durch kommas getrennt sind, aber so hast du jedenfalls schon mal ein array ind dem im ersten feld ein key und im zweiten feld der zugehörige value steht usw. (bis auf die tags halt)...

EDIT: das problem mit den kommas in den tags könntest du lösen, indem du die kommas in den tags z.b. durch ; ersetzt:


    input = Regex.Replace(input, @"(?<=\[.+),", ";");

einfach zwischen die beiden zeilen oben...

MfG

DickesB

17.12.2009 - 13:27 Uhr

Hallo herbivore,

danke erstmal für deine Antwort und ja, genau so mach ichs.

Auf die Idee mit den Zeilenumbrüchen bin ich auch schon gekommen, deshalb lasse ich den Regex erst auf den Text los, nachdem ich die Zeilenumbrüche (soweit ich weiß nur linefeed in der RichTextBox) durch Leerstrings ersetze. Dadurch wurden meine Indices ja wiederum kleiner, aber das Problem blieb bestehen...

Den Debugger habe ich auch schon öfter dazu befragt und dabei ist mir etwas aufgefallen:
Index wenn die Exception fliegt: 63165
rtb.TextLength: 65305
rtb.Text.Length: 64653
Wenn ich selbst über die Lines iteriere und die Länge addiere: 63180
Länge des Patterns: 10

Das müsste ja eigentlich in jedem Fall passen, zumal doch theoretisch bei der Anzeige in der Box doch nur Zeichen hinzukommen dürften.
Wenn ich jetzt aber bei der Exception den Wert von index ändere, egal wie klein ich ihn mache (sogar bei null), kommt die Exception wieder wenn ich F5 drücke...
Wenn ich nen simplen try-catch-block um den Find-Aufruf packe, passiert eben bei diesem Suchvorgang nichts, drücke ich dann aber nochmal Weitersuchen gehts ganz normal oben wieder weiter!

Irgendwas ist da doch faul oder steh ich total aufm Schlauch?

17.12.2009 - 12:14 Uhr

Hallo Leute,

ich habe mir aus der .Net RichTextBox zwecks besserer Rtf-Darstellung ein RichEdit 6.0 gebastelt (RichEdit v 6.0). Nach dem Einbinden der riched20.dll von Office 2007 wollte das Programm zur Laufzeit ebenfalls noch die msptls.dll (ebenfalls Office 2007, Beschreibung: Office component) haben. Die hab ich dann auf die gleiche Weise eingebunden. Soweit hat auch alles super funktioniert und funktioniert auch immer noch. Nur bin ich jetzt auf ein echt verwirrendes Problem gestoßen:

Ich habe eine Volltextsuche implementiert, bei der es zu Problemen kommt, wenn man nach Text am Ende des angezeigten Dokuments sucht (bzw. wenn man nach mehrmaligem Weitersuchen einen Treffer am Ende hat).
Ich matche bei jeder Suche zuerst per Regex und merke mir die Indices der Matches. Dann gehe ich beim Weitersuchen-Buttons nur noch die verschiedenen Indices durch.

Das geschieht in folgender Methode (restlicher Code auskommentiert, Fehler kommt trotzdem):


        private void find(int index)
        {
            int position = this.Find(this.searchPattern, index, RichTextBoxFinds.None);
        }

Von der Find-Methode der RichTextBox wird eine ArgumentOutOfRangeException ("startIndex darf nicht länger als die Länge der Zeichenfolge sein. Parametername: startIndex") geworfen, obwohl TextLength und Text.Length noch über dem index liegen 8o Auch in der Text-Eigenschaft steht noch der komplette Text drin, mit(!) meinem gesuchten Begriff ziemlich am Ende...

Hab mir die Find-Methode im Reflector mal angesehen und die Exception muss an folgender Stelle fliegen:


    int textLength = this.TextLength;
    if ((start < 0) || (start > textLength))
    {
        throw new ArgumentOutOfRangeException("start", SR.GetString("InvalidBoundArgument", new object[] { "start", start, 0, textLength }));
    }

So nun meine Frage:
Wie kann es sein, dass diese Exception geworfen wird, obwohl der StartIndex eigentlich stimmt?

Ich hoffe mir kann jemand weiterhelfen, hänge jetzt schon seit gestern da dran und langsam zeigt mir google nurnoch besuchte Links an 8)
Vielen Dank schonmal im Vorraus!

MfG

DickesB

16.12.2009 - 19:20 Uhr

Hi siedlerchr,

hinter deiner methode im ParametrizedThreadStart-Delegat durfen keine klammern hin, das ist punkt 1...

außerdem nimmt der delegat nur eine methode mit object als parameter.


[ComVisibleAttribute(false)]
public delegate void ParameterizedThreadStart(
	Object obj
)

müsstest dir also ne containerklasse für deine 4 daten bauen und die nach object caten und übergeben. in der methode musst du dann wieder auf deine containerklasse casten und kannst die daten dann verwenden.

MfG

DickesB

16.12.2009 - 14:17 Uhr

also funktionieren sollte das schon, weil sich bei RemoveAt(index) der count der liste ja automatisch um 1 verringert...

ich hab das mal getestet:


            List<string> list = new List<string>();
            list.Add("1");
            list.Add("2");
            list.Add("3");
            list.Add("4");
            list.Add("5");
            for (int i = 0; i < list.Count; i++)
            {
                MessageBox.Show(list[i]);
                if (i == 2)
                {
                    list.RemoveAt(i);
                }
            }

dabei kommt allerdings ein ganz anderes problem zum vorschein, und zwar wird jedesmal wenn du ein element löschst das nächste in der liste übersprungen, da sich der index aller folgenden elemente ja um eins verringert. der index von i+1 wird also i und der ist schon durchlaufen...

warum merkst du dir nicht die zu löschenden indices und löschst alle nach der schleife?

EDIT: sth_Weird hat recht, hab den wald vor lauter bäumen nicht gesehen 😃

MfG

DickesB

16.12.2009 - 08:22 Uhr

vor deine klassendefinition schreibst du die attribute in eckigen klammern durch komma getrennt...


[ComVisible(true), ClassInterface(ClassInterfaceType.XXX), Guid("XXX")]
public class ABC
{
    ....
}

bei classinterface weiß ich net mehr, was da genau hinmusste, google am besten mal! und bei guid muss ein eindeutiger schlüssel hin, den kannste dir aber glaub ich vom vs erstellen lassen. am besten ebenfalls dr. google fragen...