Laden...

Forenbeiträge von Kingkook Ingesamt 69 Beiträge

06.04.2013 - 16:13 Uhr

Hallo ErfinderDesRades,

danke für deine Hilfe, habe deine Lösung etwas abgewandelt übernommen. Ich arbeite weiterhin mit dem ObjectDataProvider, statt dem Color[] KnownColors.
Eigentlich hat ein zusätzliches Attribut gereicht, um die Datenbindung zu setzten :

Source={x:Static props:Settings.Default}

Ich bin mir zwar nicht sicher, warum er diese Sourceangabe benötigt, da die anderen Controls auch keinen Source Eintrag verlangen, aber es funktioniert jetzt ohne Probleme 😃

Danke nochmal, und kann gern geschlossen werden!

Gruß Kooki

02.04.2013 - 19:08 Uhr

du brauchst nicht einen Converter, der aus einem enumerable eine enumerable<Color> macht, sondern einen Converter, der aus genau einem PropertyInfo genau eine Color macht.

Ja, das sehe ich ein. Aber meine ComboBox enthält jetzt eine Liste mit Werten vom Typ Color. SelectedValue ist demnach ja auch vom Typ Color. wenn ich zum Beispiel folgendes xaml habe :

                                <ComboBox x:Name="comboBoxNotificationColor" ItemsSource="{Binding Source={StaticResource colorPropertiesOdp}, Converter={StaticResource PropertyConverter}}" SelectedValue="{Binding Path=Default.NotificationColor, Converter={StaticResource TestConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">

und hinter "TestConverter" folgender Code steckt :

    public class TestConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }
    }

Dann sehe ich beim debuggen, dass der "value" beim Convert als auch beim ConvertBack vom typ Color ist. Ich habe auch überlegt gehabt, ein Viewmodel einzubinden, aber die Settings selbst reagieren doch auf PropertyChanged. Es klappt ja bei allen anderen Werten, und auch bei der Combobox werden jetzt Colors rein und rausgereicht. Brauch ich denn dafür wirklich zwangsläufig noch ein extra Viewmodel?

02.04.2013 - 02:45 Uhr

Sehr gutes Argument 😉

Ich habe jetzt einen Converter hinzugefügt, um aus den PropertyInfo's eine List<Color> zu erstellen.


    public class PropertyInfo2ColorListConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            List<Color> colors = new List<Color>();

            if (value == null)
                return null;

            System.Collections.IEnumerator enumerator = ((System.Collections.IEnumerable)value).GetEnumerator();
            while (enumerator.MoveNext())
            {
                Object current = ((PropertyInfo)enumerator.Current).GetValue(enumerator.Current, null);
                colors.Add((Color)current);
            }
            return colors;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException(); 
        }
    }

Damit habe ich weiterhin alle Farben in der ComboBox.
Leider wird bei der Auswahl einer neuen Farbe immernoch nicht die Konfiguration geändert. Fehlt noch was?

Gruß Kooki

30.03.2013 - 21:00 Uhr

Liebe Com,

ich habe für meine Anwendung folgende ApplicationSettings :

MySetting.settings


Name      Type                         Value
myColor   System.Windows.Media.Color   #FFFFFF

AutoGenerated Code :

MySettings.Desinger.cs

    [global::System.Configuration.UserScopedSettingAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Configuration.DefaultSettingValueAttribute("#FFFFFFFF")]
    public global::System.Windows.Media.Color myColor {
        get {
            return ((global::System.Windows.Media.Color)(this["myColor"]));
        }
        set {
            this["myColor"] = value;
        }
    }

Diesen Wert will ich in einem Einstellungsfenster verändern:

configWindow.xaml

<Window x:Class="myApp.configWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:properties="clr-namespace:myApp.Properties"
    xmlns:converter="clr-namespace:myApp.Converter"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"      
    Title="myApp" Height="557" Width="626">
<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    <converter:myColorConverter x:Key="ColorConverter"/>
    <properties:MySettings x:Key="config"/>
    <ObjectDataProvider ObjectInstance="{x:Type Colors}" MethodName="GetProperties" x:Key="colorPropertiesOdp" />
</Window.Resources>
<Grid Height="524" Width="615" DataContext="{StaticResource config}">
    <TabControl Height="508" HorizontalAlignment="Left" Name="tabControl1" VerticalAlignment="Top" Width="616" BorderThickness="0" Margin="1,11,0,0">
        <TabItem Header="options" Name="tabItemOptions">
            <Grid Height="484">
                <GroupBoxHeight="330" Margin="6,149,15,0" Name="groupBox2" >
                    <Grid Height="313">
                        <ComboBox x:Name="comboBoxMyColor" Height="23" HorizontalAlignment="Left" Margin="302,34,0,0" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Source={StaticResource colorPropertiesOdp}}" SelectedItem="{Binding Path=Default.myColor, Converter={StaticResource ColorConverter}, Mode=TwoWay}">
                            <ComboBox.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal">
                                        <Label Background="{Binding Path=Name}" Content="{Binding Path=Name}" Height="{Binding ActualHeight, ElementName=comboBoxNotificationColor}" Width="{Binding ActualWidth, ElementName=comboBoxNotificationColor}"/>
                                    </StackPanel>
                                </DataTemplate>
                            </ComboBox.ItemTemplate>
                        </ComboBox>
                    </Grid>
                </GroupBox>
            </Grid>
        </TabItem>
    </TabControl>
</Grid>

Doch wenn ich den Wert in der Combobox ändere, werden die Einstellungen nicht verändert. Bei anderen Controls (z.B. Slider,Checkbox...) funktioniert es ohne Probleme.Wo liegt mein Fehler?

Gruß und Danke
Kooki

22.01.2013 - 08:26 Uhr

Hätte ich auch gedacht, jedoch selbst wenn ich die Assembly parallel zu der geladenen Assembly zur Verfügung stelle, kommt die Exception.

22.01.2013 - 07:19 Uhr

Hallo Sparkle,

die LoaderException(s) besagen, dass eine Assembly ( die zu durchsuchende verweist auf darauf) nicht gefunden wird/wurde. Wo muss diese denn liegen, damit Sie erkannt wird?

21.01.2013 - 16:05 Uhr

Liebe Com,

ich bekomme bei dem Versuch, eine Dll durch Reflection nach einem bestimmten Attribut zu durchsuchen eine ReflectionTypeLoadException. Die Assembly stammt aus einem früherren Projekt von mir. Bereits bei dem alten Projekt habe ich die Assembly auf gleiche Art durchsucht, damals immer mit erfolg. Bei dem neueren Projekt, wollte ich die gleiche vorgehensweise benutzen.

Ausgelöst wir die Exception schon beim Aufruf von assembly.GetTypes().

Fehlermeldung:
HRESULT : -2146232830
Stack :
bei System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
bei System.Reflection.RuntimeModule.GetTypes()
bei System.Reflection.Assembly.GetTypes()
bei AutomaticTestGUI.ObservableTestPlanFile.ConvertToTestplanFile(String pPath) in Pfad\ObservableTestPlanFile.cs:Zeile 88.

Codeauszug :

            Assembly toCheck = Assembly.LoadFile(pPath);
            try
            {
                foreach(Type _type in toCheck.GetTypes())
                {
                    Console.Write("");
                }
            }
            catch(ReflectionTypeLoadException e)
            {
            }

Woran kann es liegen, dass ich eine dll in einem Projekt perfekt durchsuchen kann, in einem anderen aber nicht.

Gruß Kooki

Edit :

Diesen Log erhalte ich, wenn ich direkt auf die Assembly assembly.GetCustomAttributes(false) aufrufe> Fehlermeldung:

FusionLog :
=== Zustandsinformationen vor Bindung ===
LOG: Benutzer = user
LOG: DisplayName = TestAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///Pfad
LOG: Ursprünglicher PrivatePath = NULL
Aufruf von Assembly : (Unknown).
===
LOG: Diese Bindung startet im default-Load-Kontext.
LOG: Die Anwendungskonfigurationsdatei wird verwendet: Pfad\Test.vshost.exe.Config
LOG: Die Hostkonfigurationsdatei wird verwendet:
LOG: Die Computerkonfigurationsdatei von C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config wird verwendet.
LOG: Die Richtlinie wird derzeit nicht auf den Verweis angewendet (private, benutzerdefinierte, teilweise oder pfadbasierte Assemblybindung)
LOG: Die gleiche Bindung ist bereits aufgetreten und hat den Fehler hr = 0x80070002 verursacht.

02.10.2012 - 17:14 Uhr

Nach Projektumstellung scheint es zu funktionieren...danke für eure Hilfe 😃

Könnte geschlossen werden 😃

02.10.2012 - 16:33 Uhr

@ gfoidl:

Mit minimalen Testprojekt habe ich folgende Ergebnisse :

Wenn ich nur den Service und einen Installer hinzufüge, ohne etwas zu verändern, fragt er mich bei der Dienstinstallation nach Name/PW.Wenn ich dort meinen angemeldeten Domänenbenutzer (in der Gruppe lokale Admins vorhanden) eintrage und das pw eingebe, installiert er den Service, startet aber nicht mit der gleichen Fehlermeldung wie immer.

Wenn ich in der ProjectInstaller.Designer.cs folgende Zeile hinzufüge/editiere kommen teilweise andere Ergebnisse :
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService; --> Zugriff verweigert

this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService; --> Der Dienst antwortete nicht rechtzeitig auf die Start- oder Steuerungsanforderung

this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User; --> Verhalten wie bei Default ( fragt nach Username/PW)

Auch wenn ich statt meines Domänenusers den lokalen Admin wähle ("RECHNERNAME\Administrator") und dessen PW eingebe, bekomme ich die Fehlermeldung

Der Dienst antwortete nicht rechtzeitig auf die Start- oder Steuerungsanforderung.

@ujr:

Ja, die beiden Dienstnamen sind zu testzwecken, jenachdem ob ich als Debug oder Release ausführe, damit hängt es nicht zusammen...
Und wieder ja, die Werte unter [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services]
sind alle richtig (für beide Services)

EDIT 2:
Ein noch minimaleres Testprojekt hat ergeben, wenn ich ein Projekt NUR mit Service+Installer erstelle, funktioniert es ohne Probleme, denke jetzt also dass das Problem daran liegt, dass die WPF-Form in der gleichen Klasse liegt, wie der Service.

02.10.2012 - 15:32 Uhr

Hastrecht xD Console war blöde Idee, aber auch der EventLog und Trace sagen kein Wort zu mir...

02.10.2012 - 14:47 Uhr

Nein, ist ein eigener Logger, habe aber auch Console.WriteLine() probiert, auch da schreibt er mir nicht.Habe das Gefühl die OnStart wird bei mir nie betreten...

02.10.2012 - 14:26 Uhr

Wie in den CodeSnippets oben zu sehen ist, logge ich wenn der Service gestartet wird bzw bei einer Exception


        protected override void OnStart(string[] args)
        {
            try
            {
                serviceThreadStart = new ThreadStart(StartService);
                serviceThread = new Thread(serviceThreadStart);
                serviceThread.Start();
            }
            catch(Exception ex)
            {
                Logger.ErrorWrite(ex);
            }
        }

        private static void StartService()
        {
            Logger.InfoWrite("Service started");
            RssTimedJob.Start();
            RssSendJob.SendJob.Start();
        }

Aber soweit kommt er scheinbar garnicht, da weder der catch-Block, noch irgendwas anderes erreicht wird...

02.10.2012 - 14:08 Uhr

Die Exceptions sind "gewollt" und fliegen durch fehlerhafte Konfiguration beim versenden von SmtpMails (zB fehlender Empfänger, falscher SmtpHost/Port).

Aber die Exceptions haben ja nichts damit zu tun, ob der Dienst starten sollte oder nicht.Oder sehe ich das falsch?

Gruß Kooki

02.10.2012 - 13:50 Uhr

Also es fliegen zwar einige Exceptions aber die werden alle abgefangen, also das Programm läuft normal durch.

02.10.2012 - 13:28 Uhr

Wie gesagt, mehr Informationen habe ich nicht, obwohl ich AutoLog aktiv habe und davon ausgehe, dass er eigentlich mehr loggen sollte...

Edit:

kann dir nur noch meinen Fehlerlog bieten, der ist aber auch nichtssagend (meiner Meinung nach)

Fehlermeldung:
Message :
Der Dienst MailGeneratorServiceDebug kann nicht auf dem Computer . gestartet werden.
StackTrace :
bei System.ServiceProcess.ServiceController.Start(String[] args)
bei System.ServiceProcess.ServiceController.Start()
bei MailGenerator.MainWindow.StartServiceClick(Object sender, RoutedEventArgs e) in c:\Users\ich\Documents\Visual Studio 2012\Projects\MailGeneratorProject\MailGenerator\GUI\MainWindow.xaml.cs:Zeile 96.
Source :
System.ServiceProcess

02.10.2012 - 13:10 Uhr

Hi gfoidl,

leider nicht, habe ich auch schon versucht, dort steht aber leider auch nur :

Fehlermeldung:
Das Zeitlimit (30000 ms) wurde beim Verbindungsversuch mit dem Dienst MailGeneratorServiceDebug erreicht.

und

Fehlermeldung:
Der Dienst "MailGeneratorServiceDebug" wurde aufgrund folgenden Fehlers nicht gestartet:
Der Dienst antwortete nicht rechtzeitig auf die Start- oder Steuerungsanforderung.

02.10.2012 - 11:49 Uhr

Liebe Com,

ich verzweifel gerade an meinem WindowsService.Folgender Hintergrund:

Ich ahbe ein Dienst, welcher wenn er gestartet ist in gewissen Zeitabständen Mails verschicken soll. Was er dabei verschicken soll und an wen kann auf einer GUI festgelegt werden ( von da kann man auch den Dienst de/installieren und startet).
Wenn ich aber jetzt versuche den Dienst zu starten, kommt immer die Fehlermeldung:> Fehlermeldung:

Der Dienst MailGeneratorServiceDebug kann nicht auf dem Computer . gestartet werden.

Hier ein paar Snippets:
Starten des Dienstes


        private void StartServiceClick(object sender, RoutedEventArgs e)
        {
            try
            {
                ServiceController serviceChecker = new ServiceController("MailGeneratorService");
#if DEBUG
                serviceChecker = new ServiceController("MailGeneratorServiceDebug");
#endif
                if(serviceChecker.Status != ServiceControllerStatus.Running)
                {
                    serviceChecker.Start();
                    serviceChecker.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMilliseconds(200));
                }
            }
            catch(Exception ex)
            {
                Logger.ErrorWrite(ex);
            }
        }

MailGeneratorService - Klasse :


        protected override void OnStart(string[] args)
        {
            try
            {
                serviceThreadStart = new ThreadStart(StartService);
                serviceThread = new Thread(serviceThreadStart);
                serviceThread.Start();
            }
            catch(Exception ex)
            {
                Logger.ErrorWrite(ex);
            }
        }

        private static void StartService()
        {
            Logger.InfoWrite("Service started");
            RssTimedJob.Start();
            RssSendJob.SendJob.Start();
        }

Habt ihr eine Idee, woran es liegen kann, oder wie ich mehr Informationen bekommen kann als die nichtssagende Exception?

Gruß Kooki

03.08.2012 - 14:03 Uhr

Hallo Sparkle,

das habe ich gerade auch gemerkt 😉 Habe jetzt auf RTBox umgestellt.Und wie funktioniert das mit der RTBox?

Gruß Kooki

03.08.2012 - 13:29 Uhr

Liebe Com,

ich will für meine WFP-Application eine Textbox haben, die der MailempfängerTextbox von Outlook ähnelt.Dafür will ich bei jeder Textänderung überprüfen, ob die Textbox valide Mail-Adressen enthält.Diese Überprüfung bekomme ich hin, was ich leider nicht weiß, ob es geht (und wenn ja wie), dass ich nur bestimmten Text in einer Textbox unterstreiche, und den Rest nicht.

Gibt es dafür eine Möglichkeit?

Gruß Kooki

30.07.2012 - 10:48 Uhr

Ich habe auch befürchtet, dass es nicht möglich ist, auch wenn ich immernoch der Meinung bin, dass es theoretisch eigentlich kein Ding der unmöglichkeit sein sollte. Helfen würde jetzt jemand, der sich gfoidl's Signatur

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!" zu Herzen nehmen würde...

28.07.2012 - 20:45 Uhr

e.Sourcegibt mir Infos über das DataGrid in das ich den Text droppe :

e.Source
{System.Windows.Controls.DataGrid Items.Count:0}

e.OriginalSource gibt diese Infos :

e.OriginalSource
{System.Windows.Controls.ScrollViewer}
    base {System.Windows.Controls.ContentControl}: {System.Windows.Controls.ScrollViewer}
    CanContentScroll: true
    ComputedHorizontalScrollBarVisibility: Collapsed
    ComputedVerticalScrollBarVisibility: Collapsed
    ContentHorizontalOffset: 0.0
    ContentVerticalOffset: 0.0
    ExtentHeight: 0.0
    ExtentWidth: 0.0
    HorizontalOffset: 0.0
    HorizontalScrollBarVisibility: Auto
    IsDeferredScrollingEnabled: false
    PanningDeceleration: 0.001
    PanningMode: Both
    PanningRatio: 1.0
    ScrollableHeight: 0.0
    ScrollableWidth: 0.0
    VerticalOffset: 0.0
    VerticalScrollBarVisibility: Auto
    ViewportHeight: 0.0
    ViewportWidth: 651.0

Gruß Kooki

27.07.2012 - 09:28 Uhr

Liebe Com,

ich habe ein DataGrid, welches Drag and Drop für Texte unterstützt.Dieser Text soll der gedropped wird, kommt aus einer .txt-Datei, welche zB mit Notepad++ geöffnet ist( da dieser dragging unterstützt).Wenn ich diesen Text jetzt in mein Datagrid droppe, würde ich dort gern herausfinen können, aus welcher Datei der Text eigentlich kommt, oder wenigstens von welcher Anwendung.Gibt es irgendwelche Möglichkeiten über die DragEventArgs an solche Infos zu kommen?

Gruß Kooki

20.07.2012 - 15:42 Uhr

Hallo gfoidl,

danke dir erstmal für deine Infos.Vllt habe ich es blöd beschrieben oder es ist von der Architektur her wirklich ähnlich aber meiner Meinung nach brauche ich schon was anderes als ein Chat.Es geht darum, dass ich ein Programm habe, welches sich mit einem Server verbinden soll.Dieser Server soll mehrere Verbindungen in verschiedenen Threads halten, so dass er jederzeit mit jedem beliebigen verbundenen Client kommunizieren kann.Diese Kommunikation soll aber durch eine Android-App ausgelöst werden.Zum Beispiel.

Ich habe auf meinem Rechner die Anwendung ( C# ) laufen, die eine eindeutige ID hat (zB abc123def).Alle anderen die die Anwendung auch benutzen haben dementsprechend eine andere ID.Jetzt soll sich meine gestartete Anwendung mit dem Server verbinden.Dieser kennt dann meine IP und den Port von dem aus ich mich verbunden hab, zusätzlich noch meinen Hostname oder was auch immer und natürlich meine ID.Diese Verbindung soll der Server jetzt aufrecht erhalten, solange der Client noch erreichbar ist.
Wenn ich jetzt auf meinem Handy meine App starte, habe ich dort die möglichkeit eine ID einzugeben.Ich gebe ihm also die ID abc123def.Jetzt drücke ich auf der App zB den Button "Client beenden". Die App soll dann an den Server einen String schicken (zB "close:abc123def") und der Server soll dann anhand der übermittelten ID wissen, an welchen der verbundenen C#-Anwendungen er den Befehl schicken soll, sich zu beenden.

Ich habe inzwischen ein wenig getestet, und mir ein kleines Client-Server Programm geschrieben, in der ich per Socket.Send(byte[]) Strings o.ä. verschicken kann.Meine Frage ist jetzt nur, ob ich diesen Multithread Server irgendwie als WebService o.ä. laufen lassen kann, um dann von Android aus vllt nur eine gewisse URL aufrufen zu müssen, in der alle Parameter stehen und der Server dann arbeitet.Oder ist das erforderliche Multithreading nur als .exe möglich.

Bitte um ein wenig Aufklärung, wie man sowas löst 😃

Danke dir/euch vielmals
Kooki

17.07.2012 - 19:51 Uhr

Liebe Com,

ich bin noch recht unerfahren im Bereich der Client-Server Programmierung und brauche daher eine kleine Starthilfe, wie ich eigentlich vorangehen soll.Ich habe mir eine kleine WPF-Applikation geschrieben.Jetzt will ich (ohne sinnvolles Projekt, eher zum üben) gern eine kleine Android-App programmieren,mit der ich zum Beispiel eine kleine Nachricht an die WPF-Applikation schicken kann.Wie die Androidapp zu erstellen ist, ist erstmal nicht relevant.Meine Frage ist eher, welche "Art" von Server ich dazwischenklemme.ich dachte mir, dass ich zum Beispiel aus Android heraus eine Bestimmte URL aufrufe, in der ich zB einen beliebigen String übergeben kann.Der WebService soll diese gesendete URL auswerten (muss zB auch eine ID enthalten um den richtigen CLient zu finden) und soll diese Nachricht dann an den entsprechenden C#-Client weiterleiten.

Aber wie genau mache ich sowas?Brauche ich dafür im VisualStudio ewine ASP.NET Anwendung, oder WCF oder wie genau starte ich am besten? Und was ist der Unterschied zwischen ASP.Net WebANWENDUNG und ASP.Net WebDIENST ( und warum kann ich den im VisualStudio bei "neues Projekt" nicht auswählen)

Hoffe ihr könnt mir ein paar kleine Startschubser geben...

Vielen Dank im vorraus... Kooki

11.07.2012 - 13:24 Uhr

Liebe Com,

ich bin noch unerfahren auf im WPF-Umfeld, bei WinForms war das irgendwie einfacher 😃.

Ich habe ein DataGrid mit einem Textfeld und einer ComboBox. Ich will lediglich, dass wenn der Benutzer in der ComboBox eine Haken setzt oder entfernt, dass die gebundene Collection den entsprechenden Wert auch ändert. Aber leider tut sie weder das, noch ändert das Grid irgendwas.Immer wenn ich was anklicke wird die Row nur markiert ( und jede weitere in der ich was ändere). An der Source ändert sich aber nichts.Wenn ich dann zB die Spalten sortiere per klick auf einen Header, dann sind die Markierungen weg, die veränderten Werte auch und ich muss neu anfangen ( dann markiert er aber auch nicht mehr blau sondern setzt den Haken gleich)...

Kann mir das mal einer erklären, was zu tun ist, um einfach immer wenn sich ein Wert ändert ein Event zu erhalten, um die Source zu updaten?

Gruß Kooki

18.04.2012 - 14:08 Uhr

@DaMoe80

Initialisiert wird er, wenn auch das WPF-Fenster initialisiert wird, jedoch wird er wie gesagt in einer Methode gestartet, welche von einem Event aufgerufen wurde.

@FZelle

Mit einem Timer habe ich es vorher getestet, hat aber nicht funktioniert 😦
Mit dem Wertebereich kann es aber nichts zu tun haben, der wird erstens eingehalten und ausserdem funktioniert die ganze BGW Geschichte auch, wenn ich zB direkt bei der Initialisierung RunWorkerAsynch() aufrufe.Nur wenn ich diesen Startin einem Event aufrufe, kommt die Fehlermeldung...

18.04.2012 - 11:20 Uhr

Danke erstmal,
den Artikel habe ich vorher bereits gelesen aber folgenden Absatz so verstanden, dass es bei mir eigentlich gehen sollte.

BackgroundWorker

Statt mit extra Threads und Control.Invoke, kann man auch mit der BackgroundWorker-Klasse ungültige threadübergreifende Vorgänge vermeiden. Dazu müssen bei BackgroundWorker alle Zugriffe auf das GUI einfach aus den ProgressChanged- oder RunWorkerCompleted-EventHandlern durchgeführt werden. Wenn man sich daran hält, ist explizites Control.Invoke bei BackgroundWorker nicht erforderlich, denn die genannten EventHandler werden hinter den Kulissen automatisch per Control.BeginInvoke aufgerufen.

Alles vorausgesetzt, der BackgroundWorker wurde korrekt initialisiert, so dass er insbesondere einen passenden SynchronizationContext verwendet. Wenn der BGW unter Verwendung von VS im GUI-/Main-Thread erzeugt wurde, sollte das automatisch der Fall sein.

Meiner Meinung nach sollte es doch bei mir funzen, wenn der BGW bei Erstellung der WPF-Form initialisiert wird, und Events angehängt bekommt.Da ich die GUI-Manipulation erst im Changed Event ausführe, sollte doch alles stimmen oder?

18.04.2012 - 08:41 Uhr

Liebe Com,

ich für meine Form ein BackgroundWorker, der meine GUI nach und nach Transparent machen soll.Dafür habe ich ihm im Konstruktor der Klasse die nötigen Events angehängt.


                taskbarWorker = new BackgroundWorker();
                taskbarWorker.DoWork += new DoWorkEventHandler(TaskbarDoWork);
                taskbarWorker.ProgressChanged += new ProgressChangedEventHandler(TaskbarChanged);
                taskbarWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(TaskbarCompleted);

Jetzt wartet die GUI darauf, von einer anderen Klasse ein Event zu erhalten.Wenn dieses Event gefeuert wird, wird der Worker gestartet.Er arbeitet sich normal durch, aber wenn er etwas an der GUI verändern soll, kommt eine InvalidOperationException.
Woran könnte das liegen?

Hier der BGW-Code:


        private void TaskbarDoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            worker.WorkerReportsProgress = true;
            for(int _opacity = 100 ; _opacity > 0 ; _opacity--)
            {
                worker.ReportProgress(_opacity);
                System.Threading.Thread.Sleep(100);
            }
            e.Result = e.Argument;
        }

        private void TaskbarChanged(object sender, ProgressChangedEventArgs e)
        {
            Logger.InfoWrite("Changed to {0}", e.ProgressPercentage);
            float newOpacity = (float)e.ProgressPercentage;
            this.volumeBar.Opacity = newOpacity;
        }

        private void TaskbarCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Logger.InfoWrite("Completed");
        }

Danke im voraus... Kooki 😃

16.04.2012 - 12:19 Uhr

Danke genau das habe ich gesucht DaumenHoch

PS : Kann geschlossen werden g

16.04.2012 - 11:54 Uhr

Auf dem Bild im Anhang sieht man den Rahmen, den ich meine.Vllt hilft dir/euch das weiter 😃

Edit: oberer Teil zeigt Screen aus dem Studio, der untere zeigt den Screen des gestarteten Programms

16.04.2012 - 11:45 Uhr

Das habe ich auch mal gedacht 😃
Darum bin ich auf "None" gegangen, der Rahmen ist aber anwesend...

16.04.2012 - 11:40 Uhr

Liebe Com,

ich will für ein Programm, dass der User lediglich eine Progressbar sieht, wenn ein gewisses Ereignis ausgelöst wird.
Momentan habe ich also ein eigenes WPF-Form, welches nur eine Progressbar enthält.Leider hat diese immer einen Rahmen von der eigentlichen Form.Gibt es eine Möglichkeit, dass wirklich nur die Progressbar zu sehen ist, und der Rest der Form völlig unsichtbar und auch unbenutzbar ist?

Gruß Kooki

29.03.2012 - 16:02 Uhr

Hi,

daran habe ich auch mal gedacht, aber ich will keine GUI darum brauche ich keinen Fortschrittsbalken.Auch wenn ich damit vllt nicht wirklich schneller werde, würde ich trotzdem schon aus lerngründen gern wissen, wie ich mein "Problem" lösen könnte, also den ThreadPool immer wieder vollzupacken, sobald ein Element fertig ist.

Gruß Kooki

29.03.2012 - 15:44 Uhr

Liebe Com,

ich beschäftige mich zum ersten mal mit dem Thema Multithreading und habe mir dafür ein kleines Programm gebaut.Dieses sucht auf der Festplatte auf einem bestimmtem Pfad alle Datein, sortiert diese nach einem Muster und fängt dann an diese Datein zu kopieren.Das mache ich momentan mit einem ThreadPool:


            try
            {
                DateTime start = DateTime.Now;
                Logger.InfoWrite("Start storing for 64 of {0} elements ({1} MB)", toCopy.Count,(((toCopy.Size / 1024) / 1024)));
                for(int i = 0 ; i < doneEvents.Length ; i++)
                {
                    Logger.DebugWrite("Start Thread for file {0}/64", i+1);
                    doneEvents[i] = new ManualResetEvent(false);
                    USBStorer storer = new USBStorer(toCopy[i], doneEvents[i]);
                    ThreadPool.QueueUserWorkItem(storer.Store, i);
                    toCopy.Remove(toCopy[i]);
                }

                WaitHandle.WaitAll(doneEvents);
                if(toCopy.Count > 0)
                    StartCopy(toCopy);
                TimeSpan span = DateTime.Now - start;
                Logger.InfoWrite("Ready with storing after {0} seconds({1} MB/sec)...", span.TotalSeconds, (((toCopy.Size / 1024) / 1024) / span.TotalSeconds));
            }
            catch(Exception e)
            {
                Logger.ErrorWrite("error while storing : {0}", e.StackTrace);
            }

Wobei der Pool aufruft :


        public void Store(Object threadContext)
        {
            int threadIndex = (int)threadContext;
            try
            {
                Logger.DebugWrite(String.Format("Start : Copy file #{0}({1}) -- {2}[{3}] MB]", threadIndex, targetFile.FileNumber, targetFile.FileName, ((targetFile.FileSize/1024)/1024)));
                File.Copy(targetFile.FilePath, @"E:\" + targetFile.FileName, true);
                Logger.DebugWrite(String.Format("Ready : Copy file #{0}({1}) -- {2}[{3}] MB]", threadIndex, targetFile.FileNumber, targetFile.FileName, ((targetFile.FileSize / 1024) / 1024)));
                doneEvent.Set();
            }
            catch(Exception e)
            {
                Logger.ErrorWrite("error while copying : {0}", e.StackTrace);
                doneEvent.Set();
            }
        }

Das ganze läuft auch soweit, auch wenn ich manchmal Exceptions bekomme, die ich nciht ganz verstehe, das tut aber erstmal nicht weh.
So wie ich die ganze Sache verstehe, arbeite ich momentan nach dem Prinzip :

Queue vollpacken und warten bis alle fertig sind, dann weitermachen.
Dabei bin ich aber wenn ich rund 200MB kopiere ( braucht rund 2min) 30 sek langsamer als wenn ich die Datein per Strg+C / Strg+V kopiere.
Ich weiß zwar nicht ob ich das schneller schaffen könnte (kann ich mir fast nicht vorstellen...), aber ich denke ich könnte meine Zeit verbessern, indem ich statt auf alle Events warte, immer warte bis ein Thread fertig ist, und den sofort wieder befülle und Neustarte.Jedoch weiß ich nicht wie ich das realisieren kann....

Könnt ihr mir eine kleine Starthilfe geben?

Gruß Kooki

24.01.2012 - 15:24 Uhr

Die Klasse MyElement erbt von einer BaseKlasse


public class MyElement : MyElementBase

diese hat folgenden Konstruktor:

public MyElementBase(Collector pParentCollector)

ich will also schon : base(pCollector) aufrufen...

Ja ich weiß, dass es Grundlagen sind aber ich bin mir gerade nicht im klaren darüber, warum er es nicht will 😦

24.01.2012 - 15:15 Uhr

Liebe Com,

folgender Fehler ist mir gerade unverständlich:

Konstruktorüberladung 1

public MyElement(Collector pCollector, AutomationItem pStart, AutomationItem pTarge, MyDockPoint pStartDockPosition = MyDockPoint.East, MyDockPoint pTargetDockPosition = MyDockPoint.East):base(pCollector)

Konstruktorüberladung 2

public MyElement(Collector pCollector, MyDockPointpStartDockPosition = MyDockPoint.East, MyDockPointpTargetDockPosition = MyDockPoint.East, params String[] pSearchParams)
            : base(pCollector)

Das Studio sagt mir bei folgendem Aufruf, dass> Fehlermeldung:

Die beste Übereinstimmung für die überladene Methode hat einige ungültige Argumente.

Aufruf :


MyElement  test = new MyElement (collector, "start", "to", "ende");

aber eigentlich sollte er doch die zweite Überladung nehmen können oder?
Wie kann ich den Fehler vermeiden?

Liebe Grüße Kooki

04.01.2012 - 16:05 Uhr

Danke schonmal für die Hilfe,

aber warum kann ich dann zb folgendes nicht tun?


    public class TileMapBase
    {
        public struct FieldCell
        {
            private int fieldID;
            public int FieldID
            {
                get { return fieldID; }
                set { fieldID = value; }
            }

            public FieldCell(int pFieldID)
            {
                fieldID = pFieldID;
            }
        } 

        public struct MapRow
        {
            public List<FieldCell> Column = new List<FieldCell>();
        }
        private int mapWidht;
        private int mapHeight;
        private List<MapRow> row;

        private const int DEFAULT_FIELD_CELL = 0;
        public int MapWidht
        {
            get { return mapWidht; }
            set { mapWidht = value; }
        }

        public int MapHeight
        {
            get { return mapHeight; }
            set { mapHeight = value; }
        }

        public List<MapRow> Row
        {
            get { return row; }
            set { row = value; }
        }

        public TileMapBase(int pMapWidht = 50, int pMapHeight = 50)
        {
            MapWidht = pMapWidht;
            MapHeight = pMapHeight;

            Row = new List<MapRow>();
            GenerateMap(MapWidht, MapHeight);
        }
        private void GenerateMap(int pMapWidht, int pMapHeight)
        {
            for(int _heightPosition = 0 ; _heightPosition < pMapWidht ; _heightPosition++)
            {
                MapRow tmpRow = new MapRow();
                for(int _widhtPosition = 0 ; _widhtPosition < pMapWidht ; _widhtPosition++)
                {
                    tmpRow.Column.Add(new FieldCell(DEFAULT_FIELD_CELL));
                }
                Row.Add(tmpRow);
            }


            Row[0].Column[0].FieldID = 2;

in der letzten Zeile Kann ich der FieldID keinen Wert zuweisen ( keine Variable), sobald ich aber aus


        public struct FieldCell
        {
            private int fieldID;
            public int FieldID
            {
                get { return fieldID; }
                set { fieldID = value; }
            }

            public FieldCell(int pFieldID)
            {
                fieldID = pFieldID;
            }
        }

ein

        public class FieldCell
        {
            private int fieldID;
            public int FieldID
            {
                get { return fieldID; }
                set { fieldID = value; }
            }

            public FieldCell(int pFieldID)
            {
                fieldID = pFieldID;
            }
        }

mache funzt es...??

*doof*

*edit : Copy/Paste-Fehler 😉

04.01.2012 - 13:24 Uhr

Liebe Com,

ich lese gerade ein Tut zum Thema XNA-Spieleprogrammierung / Kartenerstellung, in der eine TileMap Karte folgendermaßen aufgebaut ist:

    class MapCell
    {
        public int TileID { get; set; }

        public MapCell(int tileID)
        {
            TileID = tileID;
        }
    }

    class MapRow
    {
        public List<MapCell> Columns = new List<MapCell>();
    }

und in einer kompletten Karte werden dann beliebig viele Reihen erstellt, welche jeweils eine beliebe anzahl an Spalten haben -> in jedem Feld ist eine MapCell welche eine ID besitzt.

Ist dieser Weg wie dort vorgenommen wird der einfachste?Oder wäre es nicht besser MapCell als struct zu speichern statt class zu verwenden??

Grüße Kooki

07.12.2011 - 14:31 Uhr

Nein es handelt sich um eine eigene dll, in der Bilder enthalten sind.Wenn ich diese im Projekt als Verweis hinzufüge, kann ich sie auslesen.Wenn ich sie aber aus dem Projektverweis entferne, manuell in den Ordner schiebe und sie mit Assembly.LoadFrom(path) öffne, macht er das zwar, aber wenn ich mein ResourceSet erstelle, fällt er auseinaner.

07.12.2011 - 09:28 Uhr

Liebe Com,

ich habe folgendes Problem.
Für eine Überprüfungsklasse möchte ich eine "Fremd"-Dll in meiner .net-Anwendung einlesen, um alle Resourcen, die in dieser dll enthalten sind herauszufischen.Das klappt auch alles super, solang ich die dll in den Verweisen aufführe, und dann folgendermaßen benutze:


        public static List<Object> GetAssemblyFiles()
        {
            List<Object> resources = new List<Object>();
            foreach(String _path in Directory.GetFiles(Application.StartupPath + @"\"))
            {
                if(_path.EndsWith(".dll"))
                {
                    try
                    {
                        System.Reflection.Assembly asm = System.Reflection.Assembly.LoadFrom(_path);
                        System.Globalization.CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture;
                        String resourceName = asm.GetName().Name + ".g";
                        System.Resources.ResourceManager rm = new System.Resources.ResourceManager(resourceName, asm);
                        System.Resources.ResourceSet resourceSet = rm.GetResourceSet(culture,true, true);
                        foreach(System.Collections.DictionaryEntry resource in resourceSet)
                        {
                            try
                            {
                                resources.Add ((System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream ((UnmanagedMemoryStream)resource.Value));
                            }
                            catch(Exception)
                            { }
                        }
                        rm.ReleaseAllResources();
                    }
                    catch(Exception)
                    { }
                }
            }
            return resources;
        }

Das klappt auch alles soweit gut, ich finde alle Bilder und kann sie speichern.Wenn ich die entsprechende Assembly aber aus den verweisen entferne, und sie lediglich manuell in einen Ordner packe um sie dann zu benutzen, fällt die Sache immer mit einer MissingSatelliteAssemblyException auseinander:

Fehlermeldung:
bei System.Resources.ManifestBasedResourceGroveler.HandleResourceStreamMissing (String fileName)
bei System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(CultureInfo culture, Dictionary`2 localResourceSets, Boolean tryParents, Boolean createIfNotExists, StackCrawlMark& stackMark)
bei System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture, Boolean createIfNotExists, Boolean tryParents, StackCrawlMark& stackMark)
bei System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
bei System.Resources.ResourceManager.GetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
bei AutomaticTestCore.Reflector.GetAssemblyFiles() in XXX

Kann mir jemand sagen woran das liegt??

Grüße Kooki

28.11.2011 - 14:38 Uhr

Hallo liebe Com,

ist es möglich, ein switch auf einen String anzuwenden, der seine cases per .contains() entscheidet?Also ungefähr:


switch(meinString)
{
case meinString.contains("fall1"): break;
case meinString.contains("fall2"): break;
case meinString.contains("fall3"): break;
}

Geht sowas irgendwie?

Grüße Kooki

27.10.2011 - 16:05 Uhr

Ah ok 😃
Vielen Dank dN!3L für das tolle TuT!!

Aber was ich leider nicht weiß, ist wie mann nur Methoden mit bestimmten Attributen auflistet 0o...könnt ihr mir noch einen Tipp geben wie ich zB hier nur nach
TestMethods suche, sprich eine Abfrage die am ende nur Method1 liefert?


private class Test
{
    public int Field;
    private static string property { get; set; }
    [TestMethod]
    public void Method1() 
    { 
       Console.WriteLine("Hello!"); 
    }
    //Keine TestMethod
    public void Method2() 
    { 
       Console.WriteLine("Hello2!"); 
    }
    public int Method(int value) { return value; }
}

27.10.2011 - 15:25 Uhr

Liebe Com,

ich habe ein kleines WIndowsForm-Programm, welches mir auf Knopfdruck GUI-Tests durchführt.Momentan habe ich eine gewisse Menge x an Testfällen, die nacheinander abgearbeitet werden.Nun möchte ich aber, falls ein Fehler auftritt, das der entsprechende Testfall abgebrochen wird, und er den nächsten startet.Da ich aber ständig neue Testfälle hinzufüge, möchte ich nicht ständig irgendwelche Stringarray o.ä. ändern, um da einen Testfall einzufügen.Gibt es eine möglichkeit, zB bei der Initialisierung einer Klasse alle Methoden dieser Klasse auf ( zB [TestMethod] ) Attribute zu prüfen, und für jeden gefundenen einen Zähler zu erhöhen, um so jederzeit zu wisse, wie viele Testfälle es gibt, und um dann zB per foreach jeden Testfall automatisch zu starten.

Liebe Grüße Kooki

24.10.2011 - 07:46 Uhr

Ja, du hast natürlich Recht, dass es zwei verschiedene Technologien sind.
Ein cast kam mir nur in den Sinn, da ich eventuell noch mehr Informationen über dass Element gebraucht hätte, zB ob es **fett **oder nicht ist, ob es _kursiv _oder nicht ist und so weiter.
Gibt es für solche Feinheiten denn andere Möglichkeiten?

21.10.2011 - 15:52 Uhr

Liebe Com,

um an mehr Information eines Elementes zu gelangen, möchte ich aus einem Vorhandenem AutomationElement ein UIControl casten, um auf WPF-Propertys zugreifen zu können.
Habe dafür Die UITestControlFactory probiert, aber die schmeißt mir immer eine Exception.
Hat jemand Erfahrungen, wie ich aus einem AutomationElement ein UIControl casten kann?

lg Kooki

17.10.2011 - 13:10 Uhr

Liebe Com,

ich habe mir einen kleinen Logger geschrieben.Momentan erstelle ich in jeder Klasse, der diesen benutzt einen neuen LogWriter, welcher dann in die gewünschte Datei schreibt. Jetzt will ich diese Prozedur aber umstellen, so dass es nur noch eine einzige Instanz dieses Loggers gibt, und all meine Klassen auf diese zugreifen können.Irgendwie hab ich aber keine Ahnung wie ich das am besten und schönsten löse.
Habt ihr einen Ansatz/ eine Hilfe für mich?

Danke im vorraus Kooki!!

14.10.2011 - 11:20 Uhr

Falls jemand mal auf ähnlich Probleme trifft, könnte dieser Ansatz helfen, Elemente zu finden, die als Property IsControlElement == false haben:


        private void WalkTreeItems(AutomationElement rootNodeElemente, TreeNode rootTreeNode)
        {
            AutomationElement childNodeElement = TreeWalker.RawViewWalker.GetFirstChild(rootNodeElemente);

            while(childNodeElement != null)
            {
                TreeNode childTreeNode = rootTreeNode.Nodes.Add(childNodeElement.Current.ControlType.LocalizedControlType);
                WalkTreeItems(childNodeElement, childTreeNode);
                childNodeElement = TreeWalker.RawViewWalker.GetNextSibling(childNodeElement);
            }
        }

Aufgerufen durch


AutomationElement rootNodeElemente= rootNodeElementParent
     .FindFirst(TreeScope.Children, new System.Windows.Automation.PropertyCondition(AutomationElement.ClassNameProperty, "TreeViewItem"));  
TreeNode rootTreeNode= new TreeNode(string.Format("{0}.{1}", rootNodeElemente.Current.LocalizedControlType, rootNodeElemente.Current.Name));
rootTreeNode.Tag = rootNodeElemente.GetRuntimeId();
WalkTreeItems(rootNodeElemente, rootTreeNode);

Damit findet man auch Elemente,die kein ControlElement sind.Innerhalb der

private void WalkTreeItems(AutomationElement rootNodeElemente, TreeNode rootTreeNode) 

Methode, kann man sich entsprechende Elemente zB in einer Collection speichern, um diese wiederzuverwenden.

Danke für die mithilfe und Grüße
Kooki

14.10.2011 - 08:29 Uhr

Die inspect.exe hat zwei verschiedene Arbeitsweisen.Im "MSAA"-Mode und den "UI Automation"-Mode.Sagt dir dass vielleicht was?Und wie ich auf diesen unterschied bei mir im Code eingehen kann?

13.10.2011 - 11:09 Uhr

Kleiner Nachtrag:

ich habe einmal nach allen ChildElementen gesucht, welche mein TopParent beinhaltet.Dabei finde ich alle Elemente, welche auch Inspect findet (auch diverse TextFelder (TextBlock)), ausser die,die ich Suche.Laut Inspect exe ist die einzige Property, die bei allen nicht gefunden TextFeldern anders ist als bei denen, die gefunden werden die IsControlElement Property.Diese ist bei allen gefundenen Elementen "true" bei allen die ich nicht finde "false".Leider weiß ich nicht, warum ausderechnet diese nicht gefunden werden...

13.10.2011 - 09:17 Uhr

Gibt mir die Funktion wirklich alles, vom Main Window bishin zum kleinsten Textfeld etc und wenn ja kann ich mir so auch Namen,ProcessID's etc ausgeben lassen ?