Laden...

Forenbeiträge von nali Ingesamt 40 Beiträge

09.06.2015 - 22:55 Uhr

Hey nali,

du musst unterscheiden zwischen "E:" und "\.\E:".
Das eine ist das Root-Verzeichnis auf der Partition E:, das andere ist die physische Diskpartition E: selbst.

Da haben wir schon das erste Problem - mein Präfix scheint nicht zu greifen. Habe jetzt mal manuell "\\.\E:" als driveLetter angeben.

The dwCreationDisposition parameter must have the OPEN_EXISTINGflag.
When opening a volume or floppy disk, the dwShareMode parameter must have the FILE_SHARE_WRITEflag.

Das habe ich auch gerade geändert.

Ergebniss: Es scheint zu laufen, zumindest bekomme ich keinen Fehler mehr und die ersten Bytes trudeln auch rein. Mit der festen Sektor-Größe habe ich berücksichtigt.

PS: CreateFile ist nicht für Sector-Copy geeignet, falls das Dein eigentliches Ziel ist.

Das klingt unschön für meinen Anwendungsfall, aber was ist denn die Alternative oder besser gesagt richtige Vorgehensweise?

08.06.2015 - 12:50 Uhr

Danke für die ausführliche Antwort, habe es jetzt mal so umgesetzt wie vorgeschlagen:


        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        internal static extern SafeFileHandle CreateFile(
             string fullName,
             [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
             [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
             IntPtr lpSecurityAttributes,
             [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
             [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
             IntPtr hTemplateFile);

Dann der Aufruf wie folgt:


        public static unsafe streamer CreateStream(string drive, FileAccess type)
        {
            streamer retVal = new streamer();
            SafeFileHandle h = CreateFile(
                /* @"\\.\"+ */drive + "",
                type,
                FileShare.None,
                IntPtr.Zero,
                FileMode.Open,
                0,
                IntPtr.Zero);
            var win32Error = Marshal.GetLastWin32Error();
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            
            if (!h.IsInvalid)
            {
              
                System.IO.Stream inPutFile = new FileStream(h, type);
                retVal.SH = h;
                retVal.STR = inPutFile;
                retVal.isERROR = false;
                return retVal;
            }
            else
            {
                retVal.isERROR = true;
                return retVal;
            }
        }

Aufgerufen wird die Funktion dann mit drive = "E:" und type = FileAccess.Read.

Als Fehlercode bekomme ich übrigens 5 - scheint also definitiv ein Berechtigungsproblem sein. Kann ich das noch genauer nachprüfen - du hast was von FileIO-Permissions anfragen geschrieben, kann die Routine in deinem Link nicht 100 % nachvollziehen bzw. diese ruft doch auch "nur" CreateFile auf - wo ist das der Unterschied zu "meinem" Aufruf?

06.06.2015 - 20:28 Uhr

Hallo zusammen,

versuche nun schon länger die kernel32 Routine CreateFile zu nutzen. Leider mit diversen Problemen.

Hintergrund: Ich möchte eine SD-Karte (sektorweise) in einem .NET Programm clonen. Einfaches Kopieren reicht nicht, da es sich um ein Linux-Dateisystem handelt, wovon Windows relativ wenig versteht und ich auch die Partitions-Tabelle nebst Bootsector benötige. Meine Idee war jetzt einfach Sektorweise die Bytes auszulesen und dann lokal in einem Image zu speichern. Anschließend dann auf eine neue SD-Karte zurückspielen. Im Prinzip das was der win32imager bzw. dd unter Unix macht.

Die CreateFile-Routine habe ich wie auf pinvoke.net beschrieben folgendermaßen eingebunden:

      
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern SafeFileHandle CreateFile(
           string lpFileName,
           EFileAccess dwDesiredAccess,
           EFileShare dwShareMode,
           IntPtr lpSecurityAttributes,
           ECreationDisposition dwCreationDisposition,
           EFileAttributes dwFlagsAndAttributes,
           IntPtr hTemplateFile);

Die Flags / Enums habe ich direkt von pinvoke.net kopiert: http://pinvoke.net/default.aspx/kernel32/CreateFile.html

Nun versuche ich Laufwerk E: (meine SD-Karte) anzusprechen:


        drive = "E:"
        tryagain:
            h = CreateFile(
                /* @"\\.\"+ */drive + "", 
                EFileAccess.GenericRead, 
                EFileShare.None,
                IntPtr.Zero, 
                ECreationDisposition.OpenAlways, 
                0,
                IntPtr.Zero);

            if (h.IsInvalid)
            {
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                retries++;
                if (retries > maxretry)
                {
                    retVal.isERROR = true;
                    return retVal;
                }
                goto tryagain;
            }

Leider bekomme ich immer folgende Fehlermeldung:

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

Ich habe im App.Manifest gesetzt:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

Beim Starten der Applikation werde ich auch nach admin-Rechten gefragt. Aber bekomme trotzdem den oberen Fehler. Das Ganze tritt auch unabhängig vom gewählten Laufwerk ab.

Hat jemand noch eine Idee wo ich ansetzen könnte?

19.07.2013 - 21:40 Uhr

Hmm, dachte gerade Vector API wäre gut.
Aber wenn ich das lese sieht´s ja nicht so toll aus.

Am Ende ist´s wohl wie geschrieben, die HW tut bei allen.
Die Details zeigen sich dann bei der Software.

Schade, dass so wenig Leute mit CAN gearbeitet haben,
andererseits auch sicher nicht alltäglich.

18.07.2013 - 20:37 Uhr

Das klingt ja ganz interessant, danke für Info.
Hast du selber mit dem Interface bzw. der API bereits gearbeitet?

18.07.2013 - 14:00 Uhr

Hallo zusammen,

ich möchte gerne ein .NET Tool schreiben was die Verwendung eines (Automotive) CAN-Busses erfordert. Dazu suche ich derzeit noch einen CAN-USB-Adapter. Idealerweise sollte dieser Adapter von Haus aus über eine gute .NET API verfügen.

Meine derzeitigen Favoriten:1.Vector VN1600 1.IXXAT USB-to-CAN-II 1.SysTec USB-CANModul2

Mit der Vector VN-Box habe ich bereits gearbeitet, allerdings noch nicht mit der .NET API. IXXAT und Systec habe ich jetzt nur aus der Suche in diesen Foren gefunden.

Was interessant wäre, falls jemand schon aus erster Hand berichten kann, wie gut sich die Interfaces bei der Verwendung der API schlagen. Gibt es größere Einschränkungen und Probleme?

Der Preis spielt wie immer auch eine Rolle. Aber im Zweifelsfall investiere ich gerne mehr, wenn das Gerät dann sauber funktioniert.

26.06.2012 - 12:30 Uhr

Der System.IO Namespace gehört endlich mal überarbeitet.

Dann ist die von mir beschriebene Situation ja eher positiv als negativ zu werten. Zumindest was die nicht-mögliche Nutzung von System.IO angeht 😉

26.06.2012 - 11:55 Uhr

Hallo zusammen,

ich versuche gerade für ein kleines Backup Programm den Volume Shadow Copy Service (VSS) in XP-7-2008 zu nutzen. Es geht um das Kopieren gesperrter Dateien.

So wie ich das jetzt durch google und Forensuche mitbekommen habe, scheint das Ansprechen des VSS in .NET recht schwierig und mit Bordmitteln komplex.

Interessante Beiträge waren jetzt:

Erster Artikel scheint aber das Problem aufzuzeigen, dass das Kopieren bzw. der Zugriff auf Schattenkopien über die Routinen in System.IO gar nicht möglich ist. D.h. man müsste wieder Umwege gehen, was wiederrum unschön wäre.

AlphaVSS scheint recht brauchbar, aber ich hätte zumindest aktuell noch den Wunsch die API selber zu schreiben.

So langsam entsteht bei mir der Eindruck das ein transparenter und einfache Erstellung und Zugriff auf Schattenkopien aus .NET heraus schwer möglich ist.

In "meiner Verzweiflung" habe ich jetzt sogar drüber nachgedacht einfach vssadmin.exe über die Kommandozeile bzw. Process.Run aus der C#-Applikation anzusprechen. Inklusive dem Zugriff auf die Schattenkopie. Wirklich komfortabel ist das allerdings nicht und im Vergleich zu den obigen beiden Lösungen verliere ich ja eher als das ich gewinne.

Hat jemand von euch vielleicht Erfahrungen im Umgang mit VSS und C#? Ist das wirklich so ein Mumpitz aktuell, die Situation scheint ja schon seit Jahren so zu bestehen.

23.04.2010 - 10:42 Uhr

Habe gerade noch ein interessantes Tool (allerdings aktuell noch in der Entwicklung) gefunden: http://www.nlocalize.net/

Ist speziell für WPF-Anwendungen gedacht.

17.01.2010 - 18:47 Uhr

Erstmal danke für die Antworten - also der Weg der Wahl scheint der Ressourcen-Manager zu sein.

Eine Sache die ich aber jetzt nicht bedacht habe: Unsere Applikation soll das **WPF ** nutzen - ist damit die Nutzung des Ressourcen-Manager draußen?

16.01.2010 - 16:54 Uhr

Hallo zusammen,

ich suche aktuell nach Informationen zur Entwicklung von Mehrsprachigen C#-Applikationen. Habe mich bei google und im Forum umgeschaut, der gewöhnliche Weg scheint wohl der Ressourcen-Manager zu sein. Dort die Strings jeweils in sprach-eigene Files ablegen. Die Lokalisierung soll die üblichen Dinge umfassen (sprich GUI-Elemente, Fehlermeldungen, Logausgabe usw.). Funktional sollte sich durch die Lokalisierung nichts ändern.

Nur scheint mir die Sache doch nicht sehr komfortabel bzw. ich habe eigentlich gedacht da gibt´s schönere Lösungen. Was ich jetzt gerne wissen würde:

Gibt es vielleicht noch zusätzliche Tools oder Addons für VS.NET welche die Entwicklung von Mehrsprachigen Applikationen vereinfachen?

Prinzipiell würde die Nutzung des Ressourcen-Managers ja ausreichen, allerdings bin ich gerne bereit für eine komfortablere Lösung zu investieren.

Über evtl. Tipps und hilfreiche Links mit weiteren Infos würde ich mich sehr freuen.

Gruß
Christian

26.08.2008 - 11:47 Uhr

Ich habe zumindest einen Verdacht. Es kann sein das die O2 PDAs nicht "wollen", dass man den COM-Port des GPS-Empfängers direkt öffnet, sondern über den GPS-Intermediate-Driver von Microsoft geht.

Siehe http://tinyurl.com/6k8qzx

Wenn ich den Treiber fertig habe, berichte ich mal...

08.08.2008 - 12:14 Uhr

wenn du sowieso Strings einlesen willst, warum nimmst du dann nicht StreamReader.ReadLine?

Ich muss die ReadFile-Funktion aus der coredll.dll verwenden.
Anders kann man nicht auf den virtuellen COM-Port des GPSID
zugreifen (habe es schon probiert...).

Und die ReadLine-Funktion ist ja eine managed-Funktion und kann
daher ebenfalls nicht auf den virtuellen COM-Port zugreifen.

Was nun? Muss ich also doch jeweils ein Byte einlesen und schauen
ob ich gerade ein Line-Break gelesen habe?

07.08.2008 - 22:37 Uhr

Hi,

die Seite war recht hilfreich. Ich bin jetzt schon soweit gekommen, dass ich die Verbindung zum GPS-Empfänger herstellen kann und die NMEA-Sätze auslesen kann.

Nur gibt´s jetzt ein anderes Problem 😉

Und zwar beim Einlesen: Hier muss ich angeben, wie viele Bytes ich in einem Rutsch lesen möchte. Testweise lese ich jetzt 10 Bytes an, wandle diese in einen String um und geben diesen zurück.

Soweit so gut. Ich möchte aber jetzt, dass jeweils beim Zeilenumbruch (quasi '\n') der String zurückgegeben wird. Die NMEA-Sätze sind aber unterschiedlich lang. Mit Einlesen einer festen Zahl von Bytes komme ich da also nicht weit. So würde ich immer zerstückelte NMEA-Sätze erhalten, nicht so schön.


        private string Read()
        {
            int InputReportByteLength = 10;
            int BytesRead = 0;
            byte[] BufBytes = new byte[InputReportByteLength];

            int ptr_read = ReadFile(
                ptr,
                BufBytes,
                InputReportByteLength,
                ref BytesRead,
                IntPtr.Zero);

            if (ptr_read == 1)
            {
                byte[] OutBytes = new byte[BytesRead];
                Array.Copy(BufBytes, OutBytes, BytesRead);

                System.Text.Encoding enc = System.Text.Encoding.ASCII;
                string myString = enc.GetString(OutBytes, 0, BytesRead);

                return myString;
            }
            else
            {
                return "";
            }
        }

Wie wäre jetzt der beste Ansatz? Also ReadFile kann wohl definitiv nur über die Anzahl zu lesender Bytes gesteuert werden. Ich habe mir jetzt folgendes gedacht:

Ich lese immer genau ein (1) Byte ein und prüfe ob es gleich '\n' ist, falls nicht hänge ich es an den aktuellen String, falls ja gebe ich den bisherigen String aus. Sollte ja theoretisch funktionieren oder?

Die Frage ist nur: Ist das ganze effizient und die "beste" Variante. War die erste, die mir eingefallen ist, ist halt die Frage ob´s auch die Sinnvollste ist 😉

Gruß
Christian

05.08.2008 - 21:54 Uhr

Hallo,

ich würde gerne den von Microsoft bereitgestellt GPS Intermediate Driver nutzen.

Es gibt zwei Möglichkeiten diesen zu nutzen

  1. Kann man geparste GPS-Datensätze lesen (d.h. die Auswertung der NMEA-Sätze erfolgt durch den Treiber, ich bekomme also direkt Angaben wie die aktuelle Position oder Geschwindigkeit).

  2. Kann man die ungeparsten GPS-Datensätze lesen (d.h. die NMEA-Sätze müssen selber ausgewertet werden).

Ich möchte und muss die 2. Variante nutzen. Finde aber nirgendwo richtig Infos bzw. ein anständiges Beispiel. Es gibt von MS eine Beispiel-Anwendung im WM 6 SKD - allerdings nur für das Einlesen der geparsten GPS-Datensätze. Das ist aber eben nicht meine Anwendung.

Auf MSDN habe ich diese Anleitung gefunden. Prinzipiell ganz gut, aber mit diesen pInvoke-Geschichten habe ich noch nie gearbeitet und bin recht unsicher wie ich da vorgehen soll.

Meine Idee - nach dem Lesen der Anleitung:

  1. Öffnen des COM-Ports über CreateFile
  2. Einlesen der NMEA-Sätze über ReadFile
  3. Schließen des GPS-Empfängers über CloseHandle

Habe dann folgende Code in mein Projekt eingefügt, um die nativen Funktionen des GPSID (Inter. Driver) nutzen zu können


        [DllImport("coredll.dll")]
        private static extern int CreateFile(
        string lpFileName,
        uint dwDesiredAccess,
        int dwShareMode,
        int lpSecurityAttributes,
        int dwCreationDisposition,
        int dwFlagsAndAttributes,
        int hTemplateFile);

        [DllImport("coredll.dll")]
        private static extern int CloseHandle(int hObject);

        [DllImport("coredll.dll")]
        private static extern int ReadFile(
        int hFile,
        byte[] lpBuffer,
        int nNumberOfBytesToRead,
        ref int lpNumberOfBytesRead,
        ref OVERLAPPED lpOverlapped);

Problem: Ich habe keinen richtigen Plan wie ich die Funktionen aufrufen soll. Klar in der Doku steht ja welcher Parameter was bewirkt. Aber die Parameter sind alle als Enum definiert (scheint jedenfalls so).

Z.B. CreateFile und der 2. Parameter "dwDesiredAccess".
Kann offenbar GENERIC_EXECUTE, GENERIC_READ oder GENERIC_WRITE sein.
Nur wie sind diese definiert - mein C#-Projekt kennt diese Enum ja nicht bzw. weiß nicht welche Flags sich dahinter verbergen.

Mir wäre sehr geholfen, wenn mir jemand kurz einen Beispiel-Aufruf für die Funktionen zeigen könnte. Und eine Aufschlüsselung der Parameter Enum's wäre auch super.

Wichtig: Das ganze soll unter dem .NET Compact Framework laufen - deshalb auch die core.dll

Vielen Dank
Christian

04.07.2008 - 13:16 Uhr

Riecht für mich nach einem Treiber-Problem.

Also ein spezifisches O2-XDA Problem, welches nicht in meinem Einflussbereich liegt?
Mit anderen Worten: Ich kann nichts machen?

03.07.2008 - 21:04 Uhr

Hallo,

habe ein ziemlich spezifisches Problem. Ich lese die Daten eines GPS-Empfängers über die serielle Schnittstelle ein (intern oder extern über Bluetooth). Soweit hat die Sache mit den verschiedensten GPS-Empfängern perfekt funktioniert.

Nun habe ich aber in letzter Zeit vermehrt Problem-Berichte beim Einsatz von den PDAs der XDA-Serie von O2 erhalten.

Die Fehlermeldung lautet hierbei immer:

OutofMemoryException

bei
System.IO.Ports.SerialPort.MaybeResize
Buffer()
bei System.IO.Ports.SerialPort.Readline()
bei my_Lib.SeriellerPort.Road()
bei my_Lib.SeriellerPort.Start()

Habe auch schon kräftig gesucht und gegoogelt. Aber leider nichts gefunden. Erschwerend kommt hinzu, dass es sich um das .NET COMPACT Framework handelt.

Hier die relevanten Code-Teile zum Auslesen der GPS-Datensätze über die serielle Schnittstelle:

Das eigentliche Einlesen der Daten vom ComPort


        /// <summary>
        /// Lese NewLine am Com-Port.
        /// </summary>
        private void Read()
        {
            while (Port.IsOpen)
            {
                try
                {
                    nmea_new = Port.ReadLine();
                   
                    /// Fire new NMEA-Sentence
                    if (newLine != null)
                    {
                        newLine(nmea_new);
                    }
                }
                catch (System.TimeoutException e)
                {
                    /// Fire TimeOut Event
                    if (Exception_TimeOut != null)
                    {
                        Exception_TimeOut();
                    }
                }
            }
        }

Hier wird der eingelesene Datensatz weitergereicht und gegebenenfalls eine Exception ausgelöst. Die Read-Funktion wird wiederrum von einer Start-Funktion aufgerufen:

**Start-Funktion **(wird einmalig aufgerufen):


        /// <summary>
        /// Starte Lesen des Com-Ports
        /// </summary>
        internal void Start()
        {
            try
            {
                if (!Port.IsOpen)
                {
                    Port.Open();
                }
                Read();
            }
            catch(System.IO.IOException e)
            {
                /// Fire WrongComPort-Event
                if (Exception_WrongComPort != null)
                {
                    Exception_WrongComPort();
                }
            }
        }

Diese beiden Funktionen befinden sich in einer gemeinsamen Klasse "SeriellerPort". Für die Verwendung des GPS-Empfängers erstelle ich nun eine Instanz der Klasse SeriellerPort und rufe dann Start auf, welche dann wiederrum Read aufruft.

Das ganze wird innerhalb eines seperaten Threads gemacht, zum Beispiel:


        /// <summary>
        /// GPS bzw. COM-Port öffnen in eigenen Thread
        /// </summary>
        /// <param name="com">COM-Port des GPS</param>
        public void Start(string com)
        {
            this.ComPort.setPort(com);

            this.thstart = new ThreadStart(ComPort.Start);
            this.th = new Thread(this.thstart);

            try
            {
                this.th.Start();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

Ich denke das dürften alle relevanten Code-Teile sein, falls nicht - ich habe noch mehr 😉 Ich denke so aus dem Nichts den oben beschriebenen Fehler zu beheben geht sicher nicht. Aber vielleicht seht ihr einen grundlegenden Fehler bei den drei Funktionen (z.B. Einlesen der Daten, Starten des Threads etc.).

Was mich halt stutzig macht ist die Fehlermeldung ansich: OutofMemory. Also irgendwo läuft ja dann was beim Einlesen der Daten über. Das Problem ist allerdings: Dieser Fehler tritt unmittelbar auf, also nicht erst nach 10min oder so. Sondern direkt zu Beginn.

Das ist für mich unverständlich, da zu Beginn ja wenige bis keine Daten vorliegen.
Aber vielleicht hat jemand eine Idee.

Hinweis: Im DeviceEmulator, auf verschiedenen PDAs usw. funktioniert das Auslesen der Daten wunderbar. Nur bei XDA-PDAs kommts zu diesem Fehler. Da ich selber kein XDA-PDA habe, kann ich das ganze auch nicht sehr weit testen.

Also bin für jede Idee dankbar.

Gruß
Christian

17.01.2008 - 12:13 Uhr

Super vielen Dank,

genau sowas habe ich gesucht - und keine Sorge, die Links habe ich mir direkt
als Favoriten gesetzt.

Danke
Christian

17.01.2008 - 00:14 Uhr

Hi,

ich suche zur Zeit eine Möglichkeiten Vektoren im .NET Compact Framework zu verwenden. Aktuell bin ich noch nicht sicher ob´s zwei- oder dreidimensionale Vektoren werden - sprich ob (x,y) oder (x,y,z).

Die Anforderung sonst sind eher gering. Z.B:

  • Vektor durch zwei bzw. drei Punkte beschreiben.
  • Abstände zwischen zwei Punkten bestimmen.
  • Prüfen ob zwei Vektoren orthogonal sind.

Auch möchte ich mein eigenes Koordinatensystem aufspannen,
aber dass sollte eigentlich im Zuge der Vektoren auch kein Problem
sein bzw. eh zwingend nötig sein.

Ich habe mich dazu ein wenig umgeschaut, konnte aber keine existierende
Klasse dieser Art für´s .NET **COMPACT **Framework finden. Es wird hier
im Forum immer wieder auf eine DirectX-Klasse verwiesen. Aber die gibt´s wohl
in dieser Form nicht im Compact Framework und ich möchte ja auch wirklich nur
Berechnung mit den Vektoren durchführen. (Vorerst) sollt hier nichts grafisch
dargestellt werden.

Bevor ich jetzt anfange mir meine eigene Vektor-Klasse zu schreiben,
wollte ich eben kurz sichergehen, dass eine solche Klasse nicht schon existiert.
Ich würde mich freuen, wenn ihr ein paar Tips bereit habt.

Danke
Christian

13.08.2007 - 23:36 Uhr

Hi,

ich versuche seid längerem eine Sounddatei (.wav) auf meinem PDA unter C# abzuspielen. Hierzu baue ich auf einem Beispielcode von Microsoft auf, leider "höre" ich aber nichts.


   public class Sound
    {
        private byte[] m_soundBytes;
        private string m_fileName;

        private enum Flags
        {
            SND_SYNC = 0x0000,  /* play synchronously (default) */
            SND_ASYNC = 0x0001,  /* play asynchronously */
            SND_NODEFAULT = 0x0002,  /* silence (!default) if sound not found */
            SND_MEMORY = 0x0004,  /* pszSound points to a memory file */
            SND_LOOP = 0x0008,  /* loop the sound until next sndPlaySound */
            SND_NOSTOP = 0x0010,  /* don't stop any currently playing sound */
            SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */
            SND_ALIAS = 0x00010000, /* name is a registry alias */
            SND_ALIAS_ID = 0x00110000, /* alias is a predefined ID */
            SND_FILENAME = 0x00020000, /* name is file name */
            SND_RESOURCE = 0x00040004  /* name is resource name or atom */
        }

        [DllImport("CoreDll.DLL", EntryPoint = "PlaySound", SetLastError = true)]
        private extern static int WCE_PlaySound(string szSound, IntPtr hMod, int flags);

        [DllImport("CoreDll.DLL", EntryPoint = "PlaySound", SetLastError = true)]
        private extern static int WCE_PlaySoundBytes(byte[] szSound, IntPtr hMod, int flags);

        /// <summary>
        /// Construct the Sound object to play sound data from the specified file.
        /// </summary>
        public Sound(string fileName)
        {
            m_fileName = fileName;
        }

        /// <summary>
        /// Construct the Sound object to play sound data from the specified stream.
        /// </summary>
        public Sound(Stream stream)
        {
            // read the data from the stream
            m_soundBytes = new byte[stream.Length];
            stream.Read(m_soundBytes, 0, (int)stream.Length);
        }

        /// <summary>
        /// Play the sound
        /// </summary>
        public void Play()
        {
            // if a file name has been registered, call WCE_PlaySound,
            //  otherwise call WCE_PlaySoundBytes
            if (m_fileName != null)
                WCE_PlaySound(m_fileName, IntPtr.Zero, (int)(Flags.SND_ASYNC | Flags.SND_FILENAME));
            else
                WCE_PlaySoundBytes(m_soundBytes, IntPtr.Zero, (int)(Flags.SND_ASYNC | Flags.SND_MEMORY));
        }
    }

Soviel zur Sound-Klasse. Das Abspielen selber geschieht dann folgendermaßen:


string lcSoundFIle = @"\\Alarm1.wav";
Sound sound = new Sound(lcSoundFIle);
sound.Play();

Führe ich die Datei aus, passiert NICHTS. Habe zuerst gedacht, dass die Pfadangabe zu Alarm1.wav nicht stimmt. Das ist aber nicht der Fall. Wird nämlich ein falscher Pfad angegeben, bemerkt das Programm bzw. die Sound-Klasse das und schmiert ab 😉

Also die Datei ist da und ein Klick auf die Datei Alarm1.wav im Datei-Explorer auf meinem PDA spielt sie auch ab - die Kodierung stimmt also auch. Hat jemand vielleicht eine Idee woran das nicht abspielen liegen könnte?

17.12.2006 - 11:41 Uhr

Habe mich mal ein bisschen eingelesen, anscheinend gibts diese Invoke-Geschichte einmal um Controls/Forms zu steuern (von einem Thread aus dem nicht die Controls/Forms "gehören") und zum anderen gibts Invokes um delegates asynchron aufzurufen.

Jetzt lese ich gerade, dass nur die erste Variante für das .NET Compact Framework verwendet werden kann. Da ich das .NET Compact Framework verwenden muss ich mich also auf diese Art der Invokes beschränken. Kann ich die gewünschte Funktionalität denn mit Controls/Forms-Invokes realisieren?

Die GPS-Bibliohtek soll ja Exceptions weiterreichen bzw. ein passendes Event Firen und weiterreichen. Eine (direkte) Einflussnahme auf meine Forms ist ja gar nicht gewünscht.

15.12.2006 - 23:19 Uhr

Hi,

folgende Situation: mein Programm benötigte eine externe Bibliothek "PocketGPSLib", welche mir als Quelltext vorliegt. Es ist eine Sammlung um mit GPS-Empfängern zu arbeiten. Die Sache funktioniert ganz gut, ist aber teilweise nicht ganz sauber ausgearbeitet:

So werden beim Öffnen des Serial-Ports (um die Verbindung zum GPS-Empfänger herzustellen) zwei Fehlerquellen nicht behandelt:1. Ein COM-Port, welcher gar nicht existiert, soll geöffnet werden (-> System.IO.IOException)

  1. Ein COM-Port, welche zwar existiert, an dem aber kein GPS-Empfänger angeschlossen ist, wird geöffnet (-> System.TimeOutException - so äußert sich diese Tatsache jedenfalls).

Habe den Code jetzt dahingehend bearbeitet, dass die Bibliothek diese beiden Fehler nun abfängt und eine passende Exception ausgibt:


/* Am COM-Port sendet kein GPS-Empfänger */
try
{
   com.Read(BufBytes, 0, nBytes);
}
catch(System.TimeoutException e)
{
   throw e;
}


/* Com-Port existiert nicht */		
try
{
   com.Open();
}
catch(System.IO.IOException e)
{
   throw e;
}

Wenn ich die Sache jetzt im Debugger teste funktioniert alles wunderbar, die Exceptions werden wie gewünscht generiert. Nun zur Problematik: die Bibliothek wird von meinen Programm verwendet, ich habe aber nicht die Möglichkeit diese Exceptions abzufangen bzw. erhalte sie nicht. Der Aufruf der Bibliothek erfolgt in MEINER Anwendung folgendermaßen:


        ...
        PocketGpsLib.GPSHandler pGPS;
        ...

        public void openGPS(string comport)
        {
            // GPS bereits geöffnet?
            if (!pGPS.IsPortOpen)
            {
                try
                {
                    // Öffne Com-Port
                    this.pGPS.Start(comport, 4800);
                }
                // Nicht existierender Port geöffnet
                catch (System.IO.IOException ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                // Falscher Port geöffnet
                catch (System.TimeoutException ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
            else
            {
                // Port war bereits offen, daher schließen
                this.pGPS.Stop(); //Close serial port
            }
        }

Ich habe gedacht, dass die von der Bibliothek generierten (und von mir hinzugefügten) Exceptions auch in meiner Anwendung "ankommen" - dafür das catch IO/TimeOut. Aber Pustekuchen, die Exceptions kommen in meiner Anwendung nicht an.

Habe jetzt viel rumprobiert und vermute, das Problem liegt daran, dass die Bibliothek einen eigenen Thread für das Öffnen des SerialPorts erstellt und die Exceptions aus diesem Thread nicht zur Main-Routine der Bibl. und damit auch nicht zu meiner Anwendung kommen. Ist sowas denkbar? Hier der Code der den Thread in der Bibl. startet:


try
{
   // Neuer Thread und GPS versuchen zu öffnen
   this.clThreadStart = new ThreadStart(GpsPort.Start);
}
catch(System.Exeception ex)
{
   // Hier kommt nichts an
   Console.WriteLine(.... usw)
}
this.clThread = new Thread(this.clThreadStart);
try
{
   this.clThread.Start();
}
catch (System.Exception ex)
{
   // Hier kommt nichts an, scheint nur für Exceptions in  
   //Zusammenhang mit dem Thread selber zu sein
   throw (ex);
}

Kernfrage also: ist es so, dass Exceptions die innerhalb eines Thread auftreten nicht an die aufrufende Umgebung weitergereicht werden? Und falls ja, gibts eine Möglichkeit die Exceptions weiter zu reichen zum Hauptprogramm und von Hauptprogramm schlussendlich zu meiner Anwendung? Ich hoffe ich habe alles gut beschrieben, ist ausführlich, aber die Situation stellt sich mir auch komplex dar.

Danke Christian

07.11.2006 - 22:01 Uhr

Habe das Problem gelöst bzw. umgangen.
Habe eine "Dummy"-Tabelle erstellt, die zur Formtierung dient.

Die enthält quasi die gleichen Werte wie die ursprüngliche Tabelle, nur sind alle
Spalten vom Format String und hier kann ich dann formatierte und angepasste Werte speichern.

Also eine Tabelle die zur reinen Datenausgabe dient und nicht als Berechnungsgrundlage für irgendwas existiert - wird nach der Ausgabe auch direkt wieder gelöscht.

Ist zwar nicht die konkrete Lösung meines Problemes, aber ich habe damit eine mehr oder minder elegante indirekte Lösung gefunden.


Nachtrag: scheint wohl ein Fehler in der Doku zu sein (kann ich mir aber nicht vorstellen) sowohl die Format-Eigenschaft, als auch DataGridBoolColumn fehlen im .NET CF.

Habe hier eine Bestätigung gefunden: Link

Auch im Objekt-Browser wo ich mir den Inhalt von Windows.Forms.Datagrid einzeigen lassen kann, fehlen diese beiden Einträge - denke also es ist definitiv so.

In diesem Fall muss man wohl auf alternative Datagrids von Drittherstellern zurückgreifen.

06.11.2006 - 00:53 Uhr

Ja, dass hätte ich vielleicht erwöhnen sollen: auf der Seite steht zwar .NET CF unterstützt es, aber bei mir scheint das wohl nicht der Fall zu sein.

Folgendes "Code-Häppchen":


            string tbPerformance= "TestTabelle";
            dg.DataSource = tablePerformance; // Die Datenquelle, eine einzelne Tabelle

            DataGridTableStyle ts1 = new DataGridTableStyle();
            ts1.MappingName = tbPerformance;

            // Ein int
            DataGridColumnStyle colType = new DataGridTextBoxColumn();
            colType.MappingName = "Type";
            colType.HeaderText = "Art";
            colType.Width = 69;
            ts1.GridColumnStyles.Add(colType);

            // Ein double, wo nur die ersten beiden Nachkommastellen relevant sein sollen
            DataGridColumnStyle colValue = new DataGridTextBoxColumn();
            colValue.MappingName = "Value";
            colValue.HeaderText = "Wert";
            colValue.Width = 40;
            ts1.GridColumnStyles.Add(colValue);

            // Datetime welches z.B. nur die Uhrzeit anzeigen soll
            DataGridColumnStyle colDatetime = new DataGridTextBoxColumn();
            colDatetime.MappingName = "Datetime";
            colDatetime.HeaderText = "Datum";
            colDatetime.Width = 100;
            ts1.GridColumnStyles.Add(colDatetime);

            dg.TableStyles.Add(ts1);

            // Jetzt soll z.B. die Ausgabe des Datums beeinflusst werden
            // hierzu folgendes:
            DataGridTextBoxColumn myGridTextBoxColumn = (DataGridTextBoxColumn)dg.TableStyles[tbPerformance].GridColumnStyles["Datetime"];
            myGridTextBoxColumn.Format = ""hh:ss" (irgendwas, was die Ausgabe des Datums beeinflusst)

Beim Kompilieren dann folgender Fehler:
Fehler 1 "System.Windows.Forms.DataGridTextBoxColumn" enthält keine Definition für "Format".

Weitere Auffälligkeit: der Konstruktor von "DataGridTextBoxColumn Constructor" ist fünffach überladen, wenn ich aber den Konstruktor aufrufe erhalten ich nur eine Auswahlmöglichkeit. Es scheint als würde die falsche Klasse aufgerufen...

05.11.2006 - 19:37 Uhr

Hi,
habe ein Problem/Frage zum DataGrid im .NET Compact Framework.
Mein DataGrid soll verschiedene Werte aus einem Dataset bzw. einer spezifischen Tabelle darstellen.

Habe es soweit hinbekommen, dass das Datagrid alles anzeigt bzw. genau die Spalten die mich interessieren (nicht alle sollen angezeigt werden).

Nun aber das Problem: es wird u.a. das Datum in dieser Tabelle gespeichert und zwar als Datetime und nicht als String oder ähnliches.

Nun würde ich halt gerne die Ausgabe des Datum im Datagrid beeinflussen, meinetwegen toShortTimeString() oder so ähnlich.

Anderes Beispiel: eine Zeile enthält double-Werte, im Datagrid soll aber nur die 2 ersten Nachkommastellen angezeigt werden.

Im .NET Framework gibt´s hierfür die Möglichkeit bei den DataGridColumnStyle auf die Format-Property zuzugreifen und dort die Ausgabe des Eintrages zu bestimmen. Diese Option ist im Compact Framework aber leider nicht vorhanden.

Siehe DataGridTextBoxColumn.Format Property

Habe schon hier im Forum gesucht und gegoogelt aber keine Lösung hierfür gefunden. Außer ein paar kostenpflichtigen Erweiterungen für das .NET Framework. Würde die Sache aber gerne per "Bordmitteln" lösen.

Gibt´s da irgendwie einen Umweg oder Möglichkeit die Ausgabe in den einzelnen Zeilen/Spalten zu beeinflussen?

25.10.2006 - 20:45 Uhr

Ich glaube nicht, dass ich einen falschen Parameter verwende,


PlaySound(filename, IntPtr.Zero, PlaySoundFlags.SND_SYNC);

Ist durchaus in Ordnung so: "filename" kann hierbei ein vordefinierter Systemsound sein (wie du es beschrieben hast, also Beep, Question, Hand usw.) aber ebenso eine eigene .wav-Datei (URL).

Außerdem funktioniert die Soundausgabe ja im Emulator, nur im echten PDA bleibt alles stumm. Habe das nochmal mit der .dll nachgeprüft - also "coredll.dll" existiert auf meinem PDA. Jedenfalls wird bei


            if (File.Exists(@"\windows\CoreDll.DLL"))
            {
                MessageBox.Show("dll existiert");
            }

die MessageBox angezeigt - also muss die Datei ja vorhanden sein. Kann den niemand den Code mal auf einem anderen PDA testen und mir sagen ob er was "hört" oder eben nicht?

24.10.2006 - 21:20 Uhr

Kennt denn keiner eine Lösung?
Ich habe nochmals intensiv bei google gesucht, aber leider nichts gefunden.

Mein PDA scheint die dll zu haben - jedenfalls sowas "ähnliches":
coredll.dll.0407 - aber das scheint wohl nicht die Richtige zu sein,
jedenfalls bleibt mein PDA stumm...

23.10.2006 - 12:57 Uhr

Original von Rainbird
Welche Windows Version hat der Pocket PC?

Windows Mobile 5.0 - also die letzte Version wenn ich da richtig informiert bin.

22.10.2006 - 19:55 Uhr

[EDIT]Abgeteilt von DllImport schlägt fehl (CF)[EDIT]

Wie gesagt der Code compiliert und funktioniert auch - jedoch nur im Pocket PC 2003 Emulator von VS.NET. Auf meinem PDA Asus A636N läuft der Code leider nicht. Also ich bekomme keine Fehlermeldung, aber es wird auch kein Sound abgespielt 😉

Die Datei "file" existiert mit Sicherheit, da beim Ausführen auf dem PDA die MessageBox nicht angezeigt wird. Also muss der Fehler wohl beim Abspielen des Sounds selber liegen. Also die Funktion "WCE_PlaySound(...)"? Dann verstehe ich aber nicht, warum mein PDA keine Fehlermeldung ausgibt.

Mein PDA ist auch nicht stummgeschaltet oder ähnliches, denn wenn ich die .wav-Datei direkt (außerhalb meines Programmes) anklicke wird sie sehr wohl abgespielt.

Gibt´s irgendwelche bekannten Probleme mit der WCE_PlaySound oder muss ich dafür noch irgendeine Dll ins Verzeichnis meines Programmes packen? Falls ja, verstehe ich aber nicht warum das im PDA-Emulator unter VS.NET nicht nötig war.


        [DllImport("CoreDll.DLL", EntryPoint = "PlaySound", SetLastError = true)]
        private extern static int WCE_PlaySound(string szSound, IntPtr hMod, int flags);

        public static void PlaySound(SoundType type)
        {
            string file = ...
            ...
            try
            {
                // if a file name has been registered, call WCE_PlaySound
                if (File.Exists(file)) {
                    WCE_PlaySound(file, IntPtr.Zero, (int)(PlaySoundFlags.SND_ASYNC | PlaySoundFlags.SND_FILENAME));
                }
                else MessageBox.Show("File existiert nicht");

            }
            catch 
            { 
            ...
            }
        }

Bin ein wenig verwirrt - weil mir ehrlich gesagt ein Anhaltspunkt zur Diagnose fehlt - halt keine Fehlermeldung oder ähnliches.

20.10.2006 - 01:43 Uhr

Top funktioniert, die Direktive fehlte einfach - danke

19.10.2006 - 19:45 Uhr

Hi,
folgende Situation möchte unter Windows Mobile 5.0 und .NET 2.0 einen Sound bzw. einen "Beep" erzeugen. Hierfür habe ich folgenden Code gefunden:


        [DllImport("coredll.dll")]
        private extern static void MessageBeep(uint BeepType);
        public static void PlayMessageBeep()
        {
            MessageBeep((uint)20);
        }

Wenn ich die Sache compiliere bekomme ich die Fehlermeldung:
"Der Typ- oder Namenspacename "DllImport" konnte nicht gefunden werden. (Fehlt eine using-Direktive oder ein Assemblyverweis?")

Soweit ich das verstanden habe, dient dieses DllImport ja dazu unmanaged Code auszuführen bzw. die in einer dll-Datei enthaltenen Funktionen. In diesem Fall die Funktion "MessageBeep".

Wo liegt jetzt der Fehler? Muss ich die Datei "Coredll.dll" dem Projekt selber hinzufügen? Und falls ja wo finde ich diese Datei? Andererseits beschwert sich ja der Compiler um den unbekannten Ausdruck "DllImport" - gibt´s dafür eine using-Anweisungen - wäre ja die einfachste Lösung des Problems.

Sorry, wenn das ein triviales Problem ist, aber ich habe sowohl die Foren- als auch Google-Suche bemüht um eine Antwort zu finden. Aber da war nichts zu finden.

Danke
Christian

03.10.2006 - 23:19 Uhr

Habe was gefunden: es scheint wohl ein Bug zu sein.

Hier weitere Infos

03.10.2006 - 00:38 Uhr

Hi,
ich habe ein kleines Problem mit den Zeitzone im PDA/Windows CE ++Emulator ++von VS .NET. Folgender Code-Abschnitt:


DateTime utcnow = DateTime.UtcNow;
DateTime now = DateTime.Now;

Und ich halte folgende Ausgaben (am 3. Oktober um 00h30):

utcnow = {03.10.06 07:30:00}
now = {03.10.06 00:30:00}

Das ist aber falsch, also wenn ich das richtig verstanden habe:
unsere (Deutschland) aktuelle Sommerzeit ist UTC+2 Stunden.
Also müsste utcnow = 02.10.06 22h30 sein.

Jetzt habe ich mir gedacht: wird wohl irgendwas mit den Zeitzonen zu tun haben. Aber im Device Emulator ist die Ländereinstellung auf "Deutschland" gestellt und die Uhrzeit auf "GMT+1 (Berlin)". Also daran kann es ja dann auch nicht liegen, und wenn ich mir

System.Globalization.CultureInfo.CurrentUICulture.Name

ausgeben lassen, bekomme ich

cultureName = "de-DE"

zurück.

Also soweit ok - jetzt aber der Punkt der nicht mehr korrekt ist:

TimeZone.CurrentTimeZone.StandardName = "Pacific Standard Time"

Das ist ja offensichtlich nicht korrekt.
Also wo muss ich diese Timezone einstellen? Im PDA selber sehe ich da keine Möglichkeit - bzw. habe ich ja mit GMT+1 bereits gemacht.

Wenn ich diese Code-Schnippsel auf einem "echten" PDA auswerte stimmen die Ergebnisse alle. Es liegt also nicht am Code, sondern mit Sicherheit am PDA-/Device-Emulator. Also weiß vielleicht jemand, wo ich dem PDA mitteile "was Sache ist"?

Danke vielmals
Christian

26.09.2006 - 12:41 Uhr

Nun ja,
herbivore hatte recht. Ich hinge definitiv 3x an dem EventHandler, wenn auch
"versteck", so dass es nicht wirklich schnell zu sehen war.

Das erklärt natürlich einiges, das hat man davon - den Fehler überall
suchen, nur nicht da, wo es eigentlich offensichtlich ist.

Ich danke euch für die zahlreichen Vorschläge.
Verwende jetzt auch eine Liste anstelle des Arrays
um die Einträge zu speichern. Das lässt sich im Nachhinein wesentlich leichter
durchlaufen.

Danke
Christian

25.09.2006 - 21:52 Uhr

So habe jetzt lange rumgesucht und den "Schuldigen" offenbar gefunden.
Es liegt wohl nicht an der Implementierung meiner Liste.
Der Liste wird ein Element zugefügt, wenn mein EventHandler "alarm" schlägt:


// Zur Diagnose einen Zähler
int count = 0;
 void pGPS_NewGPSFix(object sender, PocketGpsLib.GPSHandler.GPSEventArgs e)
        {
           // Zur Diagnose
           count++;
           MessageBox.Show("Count: " + count);
           ...
           // Neue Element in den Zwischenspeicher einfügen
           cache.addItem(item);
           ...
        }

Dabei ist mir jetzt aufgefallen, wenn ich in diesem EventHandler mal wieder meine beliebte Diagnose-MessageBox aurufe bekomme ich solche Werte.

Count: 1
Count: 1
Count: 1
Count: 2
Count: 2
Count: 2
usw...

Also der Fehler wie ganz zu Beginn, nur schon früher - außerhalb des Zwischenspeichers.

Ich verwende eine externe GPS-Bibliohtek, die offenbar auch mit Threads arbeitet.
Ich kenne mich jetzt in dem Bereich Threads überhaupt nicht aus - habe aber mal die Suche des Forums bemüht und festgestellt, dass das wohl offenbar mit Threads zusammenhängt.

Hier ist PocketGPSLib zu laden inklusive Quellcode: PocketGPS
In der Datei "GPSHandler.cs" in Zeile 40-42 steht irgendwas mit Threads,
das dürfte wohl das "Problem" sein (bin mir sicher Threads mache ich dem Zusammenhang wohl Sinn).

Also verstehe ich das richtig: PocketGPS startet mehrere Threads die alle das Event abfeuern was ich mit pGPS_NewGPSFix(...) abfange und das passiert irgendwie gleichzeitig und deshalb behalten Variablen den selben Wert bzw. ändern sich nicht passend? Das dürfte ja erklären warum ich "Count: 1 Count: 1 Count:1 Count 2: usw" ausgegeben bekomme.

Wie löse ich das Problem, habe mal probiert um das "cache.AddItem" ein lock(this) zu setzen, dass hat aber gar nichts gebracht.
Das gefällt mir nicht - was kann man da tun. Semaphore/Mutex?
Ich müsste ja nur eine Variable haben, die den Zugang zu diesem Codeabschnitt Thread-Sicher regelt.

Wäre dankbar, wenn jemand eine Idee hätte - mein gesamtes Projekt ist nämlich zum Stillstand gekommen - ohne diesen Cache kann ich leider nicht weiterarbeiten.
Und das der Fehler offenbar (IMHO) an einer externen Sache/Code liegt, macht
die Sache nur noch schlimmer.

P.S: Bitte für Codehinweise beachten - ich nutze das .NET CF Framework - ich glaube da gibts keine Semaphore?

25.09.2006 - 01:41 Uhr

Original von Borg
Mir sind ein paar Sachen aufgefallen.
1.) Cache.size bleibt bei dir immer 0, da die Zeile size = size; im Konstruktor nur die lokale Variable ändert (bzw. gleichlässt).
2.) Wenn du auf Überlauf testest, solltest du mit if (last ≥ size) testen.
3.) Momentan würdest du in eine Exception laufen (Array Index out of range).
4.) Du benötigst size gar nicht, das du ja speicher.Length abfragen kannst.
5.) speicher sollte nicht public sein. Schreib dir zwei public Methoden, die Werte lesen und schreiben. Wenn du magst, kannst du dazu auch setter und getter nutzen.

Punkt 1) und 5) sind in der Tat fehlerhaft, aber auch nur hier im Beitrag - habe wohl eine alte Fassung in den Beitrag kopiert. Habe den Beitrag entsprechend korrigiert.

Punkt 2-4 sind ebenfalls gute Hinweise, habe ich in der Eile auch nicht bedacht.
Aber wie du selber schon sagetest - daran dürfte das 3-malige Aufrufen nicht liegen.

Ich werde die Korrekturen einarbeiten und den Quelltext nochmal durchsehen,
dann melde ich die Ergebnisse hier.

24.09.2006 - 23:16 Uhr

Hi,
habe mal versucht eure Ideen umzusetzen.
Also weder mit lock noch mit Listen oder synchronisierten queues kann ich das Problem lösen.
Auch hier werden die Einträge mehrfach eingefügt - nur halt jetzt nicht mehr in meiner Klasse Cache, sondern eben in eine Liste oder Queue.

Das verwirrt mich jetzt sehr, wie kann sowas sein?
Es muss also das "Einfügen" mehrfach und zeitgleich ausgeführt worden sein.
Aber sowas wie lock() verhindert doch gerade, dass ein solches Einfügen von einem anderen Einfügen unterbrochen wird.

Ich bin jetzt echt verwirrt - werde mir die Sache morgen nochmal in Ruhe anschauen.
Falls ich keine Lösung finden werden (wovon ich ausgehe), werde ich wohl noch etwas Code posten, um die aufrufenden Funktionen zu beschreiben.

24.09.2006 - 20:20 Uhr

Hi,
ich habe folgendes Problem: ich möchte eine Art Zwischenspeicher, im folgenden Cache genannt, für eine regelmässig (jede Sekunde) eintreffende Wertemenge erstellen. Hierzu habe ich mir ein Objekt "Cache" erstellt, welches als Array über die zu speichernden Werte realisiert ist.


    public class Cache
    {
        private CacheItem[] speicher;
        // Wie groß wird der Cache
        int size = 0;
        // aktuelle Zelle im Array
        int last = 0;

        public Cache(int size)
        {
            this.size   	= size;
            speicher = new CacheItem[size];
            last        = 0;
        }

        public void addItem(CacheItem item)
        {
            // Überlauf?
            if (size == last)
            {
                last = 0;
            }
            //MessageBox.Show("Position: " + last);
            speicher[last] = item;
            last++;
        }
    }

Die Definition von CacheItem lass ich hier mal aussen vor, da sie wohl kein Problem darstellen wird. Nun folgende Idee hinter dieser Realisierung. Eine Cache wird mit einer festen Größe erstellt. Z.B. new Cache(30) - erzeugt mir einen Cache der 30 Elemente maximal aufnehmen kann. Wenn ich beim letzten Element des Array angekommen bin, möchte ich wieder von vorne anfangen, also das Element in der 1. Zelle überschreiben. D.h. der Zeiger "last" zeigt immer auf das aktuelle freie bzw. zu überschreibene Element im Array.

Leider habe ich jetzt das Problem, dass dieser Zugriff wohl nicht atomar läuft - wundert mich auch nicht wirklich. Die Funktion addItem() wird von verschiedenen externen Funktionen oftmals aufgerufen und es kommt vor, dass ein Element eingefügt wird, das nächste Element diese Element aber direkt überschreibt - weil der Zeiger last nicht schnell genug um eins erhöht wird/wurde.

Daher meine prinzipielle Frage: ist die Implementierung mittels Arrays hier überhaupt sinnvoll? Ich bräuchte sowas wie eine undliche bzw. zyklische Liste fester Länge. Sobald ich ans Ende angekommen bin, sollte wieder vorne eingefügt bzw. überschrieben werden.

Was meint Ihr - ist mein Ansatz zu gebrauchen oder soll ich eine andere Datenspeicherungmethode wählen?

P.S: Als Diagnose haben ich den(auskommentierten) MessageBox-Dialog genutzt. Lass ich mein Programm laufen kommen dann Dialogboxen mit

Position: 0
Position: 0
Position: 0
Position: 1
Position: 1
Position: 1
Position: 2
usw...

d.h. jede Zelle wird 3 mal hintereinander beschrieben.

16.08.2006 - 12:19 Uhr

Habs jetzt so versucht:


              DataRow myRow = myDS.myTable.NewRow();
                myRow["Name"] = tbName.Text;
                myRow["Vorname"] = tbVorname.Text;
                myRow["Telefon"] = tbTelefon.Text;
                usw....
                myRow["active"] = true;
myDS.myTable.Rows.Add(myRow);
myDS.myTable.AcceptChanges();

Bringt jedoch keine Besserung, außerdem würde ich es gerne mit dem obigen Befehl arbeiten, also

myDS.myTable.AddmyTableRow(string param1, string param2, usw.)

Denn in diesem Fall werden mir die benötigten Parameter per Intellisense angezeigt und kürzer ist es auch.

Mal davon abgesehen würde ich das Problem lösen und nicht umgehen - ok zur "Diagnose" macht es ja Sinn einen anderen Befehl zu nutzen/testen. Aber offenbar stimmt ja was mit dem Dataset nicht?

Ich weiß ehrlich nicht mehr weiter, habe die ganze Nacht drüber gegrübbelt.

15.08.2006 - 23:21 Uhr

Hi,
folgende Aufbau: .NET Compact Framework in der Version 2.0 und eine SQL Mobile Datenbank. Habe mit VS.NET 2005 bzw. dem Assistenten das Dataset entsprechend eingerichtet und es scheint auch zu funktionieren.

Kann zum Beispiel per myDS.myTable.Select(); entsprechende Zeilen auslesen und zum Beispiel an eine Combobox binden bzw. einfügen.

Nun möchte ich eine Zeile in die Tabelle myTable eintragen,
dass klappt leider nicht. Mein Code sieht wie folgt aus:


myDS.myTable.AddmyTableRow(string param1, string param2, usw.)

Der Befehl "AddmyTableRow()" scheint dynamisch von VS.NET generiert worden zu sein, es wird mir jedenfalls per Intellisense vorgeschlagen ist aber in der Doku nicht aufgeführt.

Der Code compiliert und wird auch ohne zu Mucken ausgeführt, nur leider wird die Zeile nicht eingetragen, jedenfalls zeigt ein entsprechendes Datagrid keinen erfolgreichen Eintrag.

Ich habe gedacht, ein DS stellt den Abgleich zu seiner Quell-Datenbank immer automatisch her. Scheint aber nicht so, sonst wäre die Zeile ja eingefügt.
Also füge ich noch folgendes hinzu

myDS.myTable.AcceptChanges();

da bringt aber auch keine Verbesserung.

Weiß jemand wo der Fehler liegt - mir ist klar, dass ich mit zwei Zeilen Code nichts großes Erwarten kann - aber vielleicht hat jemand von einem ähnlichen Fehler gelesen.

Das Dataset ansich scheint nämlich wunderbar zu funktionieren - Select funktioniert ja wie gesagt und vorhandene Daten werdem in einem Datagrid auch korrekt angezeigt. Nur das einfügen von neuen Zeilen klappt halt nicht - was ich ja verstehen würde, wenn ich eine Fehlermeldung bekomme, aber ich bekomme ja keine. Hängt das vielleicht irgendwie mit der Synchronisation des Datasets mit der Datenbank zusammen?