Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   .NET-Framework (managed code) (https://www.delphipraxis.net/79-net-framework-managed-code/)
-   -   C# Programm läuft nicht ohne Visual Studio (https://www.delphipraxis.net/156749-programm-laeuft-nicht-ohne-visual-studio.html)

jfheins 13. Dez 2010 18:51

Programm läuft nicht ohne Visual Studio
 
Hallo,
ich habe ein ganz tolles Programm geschrieben. Auf meinem Entwicklungsrechner läuft das auch sehr schön. Nur leider fast überall anders nicht.
Ich habe es auf 2 Rechnern getestet, die mit WinXP liefen, ohne VS. Geht nicht. Auf einem Win7 Rechner mit VS - lief. in meiner VM mit Vista und .net 4 aber ohne VS läuft es wieder nicht.
Ich könnte natürlich zu den Systemvorraussetzungen ein "Visual Studio 2010 oder höher" schreiben, aber das will ich nicht :stupid:

Zum Code: (denn ich weis, wie gerne ihr ein "läuft nicht" hört)

Code:
        private void files_lv_MouseClick(object sender, MouseEventArgs e)
        {
            const int centerradius = 15;
            var centerpen = new Pen(Color.Red, 5);
            var axis = new Pen(Color.Green, 4);
            var thickness = new Pen(Color.Red, 4);
            var roughlevel = new Pen(Color.Blue, 2) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dash };


            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                var lvitem = files_lv.GetItemAt(e.X, e.Y);
                if (lvitem != null)
                {
                    try
                    {
                        // Bild laden, und in 32 bit Bitmap konvertieren
                        var img = new Bitmap(Files[lvitem.Index].File.FullName);
                        var rect = new Rectangle(0, 0, img.Width, img.Height);
                        Bitmap bmp = img.Clone(rect, PixelFormat.Format32bppArgb);

                        // Bilddaten werden gesperrt
                        BitmapData bmpData = bmp.LockBits(
                                rect,
                                System.Drawing.Imaging.ImageLockMode.ReadWrite,
                                bmp.PixelFormat
                            );

                        try
                        {
                            // Array für die Farbwerte
                            int size = bmp.Width * bmp.Height;
                            int[] rgbArray = new int[size];

                            // Die Farbwerte in ein Array kopieren
                            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, rgbArray, 0, size);

                            var calcitem = new CalcInfo { rgbValues = rgbArray, color = colorDialog1.Color.ToArgb(), Width = bmp.Width, Height = bmp.Height };

                            // Hier sind dann win paar Berechnungen

                            bmp.UnlockBits(bmpData);

                            using (var g = Graphics.FromImage(bmp))
                            {
                                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                                // auf g malen
                            }
                            pictureBox.Image = bmp;
                            pictureBox.BringToFront();
                            pictureBox.Show();
                        }
                        finally
                        {
                            // Sperre aufheben
                            bmpData = null;
                            img.Dispose();
                        }
                    }
                    catch (DivideByZeroException)
                    {
                        MessageBox.Show(this, "Das Bild enthält keine farbigen Pixel.", "Bild kann nicht geöffnet werden", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    catch (SystemException)
                    {
                        MessageBox.Show(this, "Das Bild hat ein unbekanntes Format und kann deshalb nicht geöffnet werden.", "Bild kann nicht geöffnet werden", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(this, "Das Bild kann aus einem unbekannten Grund nicht verarbeitet werden.\n" + ex.ToString(), "Bild kann nicht geöffnet werden", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }
Bzw. hier mit Syntax Highlighting: http://clipboard.to/18c24

Die Fehlermeldung:
Zitat:

---------------------------
Bild kann nicht geöffnet werden
---------------------------
Das Bild hat ein unbekanntes Format und kann deshalb nicht geöffnet werden.

Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
---------------------------
OK
---------------------------
Was ist bei PC's mit VS anders als bei solchen, wo nur das Frameworkt drauf ist?

Das Bild, das geladen wird ist ein PNG (bzw. mit vielen PNG's getestet, auf meinem gehen alle auf den anderen geht keines)
Doof ist eben, dass ich nicht einfach VS installieren kann um zu debuggen ... :-/

Wisst ihr Rat?

Phoenix 13. Dez 2010 19:36

AW: Programm läuft nicht ohne Visual Studio
 
Ein bisschen mehr Info wäre hilfreich ;-)

Fang doch mal die System.SystemException ab und geb die Message der Meldung aus:
Code:
...
catch (SystemException ex)
{
   MessageBox.Show(this,
      "Das Bild hat ein unbekanntes Format und kann deshalb nicht geöffnet werden. " + ex.Message,
      "Bild kann nicht geöffnet werden", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
...
Das dürfte ein wenig mehr helfen.

Dann schreibst Du zwar von .NET 4.0, aber hast Du im Projekt auch wirklich das Target-Framework entsprechend eingestellt?
Sonst wären ein paar mehr Meldungen mehr ziemlich wichtig.
Du kannst ja mal nach jedem Einzelschritt mittels Trace.Write() (System.Diagnostics) infos rausschreiben und in der App.config noch einen TraceListener (TextWriterTraceListener) reinpacken, so dass Du ohne großartigen Aufwand noch ein ziemlich aussagekräftiges Log hast und den Fehler auf die Zeile runtertracken kannst.

jfheins 13. Dez 2010 19:38

AW: Programm läuft nicht ohne Visual Studio
 
Ja, die eine Idee hatte ich auch schon, siehe Fehlermeldung:
Zitat:

---------------------------
Bild kann nicht geöffnet werden
---------------------------
Das Bild hat ein unbekanntes Format und kann deshalb nicht geöffnet werden.

Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
---------------------------
OK
---------------------------
Zielframework ist auf .net 2.0 - ich guck mal ob sich da was tut wenn ich das ändere, mom.

Der Rest ... ich schau mal ob ich das hinbekomme :)

jfheins 13. Dez 2010 19:53

AW: Programm läuft nicht ohne Visual Studio
 
Na toll, wenn ich das Ziel auf .net 4 Client Profile ändere (welches auf dem Testlaptop neben mir auch installiert ist) dann kommt "Programm xyz hat ein Problem festgestellt und muss beendet werden" :|

Mit dem 3.5 Framework kommt wieder die Schutzverletzung.

Phoenix 13. Dez 2010 20:01

AW: Programm läuft nicht ohne Visual Studio
 
Ach, hervorragend. 2.0. Der Klassiker ;-)

Du hast bei Dir amit VS2010 .NET 3.5 SP1 drauf, was auch .NET 2.0 SP1 installiert. Auf den XP-Maschinen wahrscheinlich nur .NET 2.0 ohne SP1. Auf der Vista-Kiste wahrscheinlich auch. Will heissen das SP fehlt dort mit an Sicherheit grenzender Wahrscheinlichkeit.

Da das ganze Bitmap-Gelade in GDI+ passiert, und das Native ist, hast Du hier unter der Haube mit einer Menge von P/Invoke zu tun. Und die P/Invoke aufrufe sind auf Deiner Maschine mit SP1 leicht anders als die ohne SP, da sich genau an der Stelle im SP was geändert hat.

Dewegen verschwurbeln sich da wohl ein paar Bytegrenzen, und der Fehler wird ausgelöst. Das Problem ist auch andersrum da: Packst Du das .NET SDK auf eine der anderen Maschinen und kompilierst das Programm dort, läuft es dort, aber nicht bei Dir.

Hintergrundinfos mit weiterführenden Links gibts hier: http://www.danielmoth.com/Blog/net-framework-35.aspx

Phoenix 13. Dez 2010 20:16

AW: Programm läuft nicht ohne Visual Studio
 
Ah, hab ihn :)

Es ist unter Garantie das Marshal.Copy. Je nach SP Version hat das ausgelesene Bitmap voraussichtlich ne andere Größe die nicht unbedingt der Breite*Höhe entspricht. Im übrigens sollten die Farbwerte ein Byte[] sein und kein int[] - schliesslich kann sich int je nach Plattform ändern.

Probier mal folgende Hotfixes aus, oder sorge eben dafür dass überall die gleichen SP's da sind:
http://support.microsoft.com/kb/923028
http://support.microsoft.com/kb/971030
(Auch wenn die Fehlerbeschreibung nicht unbedingt passt - das ist alles die gleiche Thematik).

jfheins 13. Dez 2010 20:25

AW: Programm läuft nicht ohne Visual Studio
 
Hallo Sebastian,
danke schonmal für die ausgiebige Hilfe.

Ja, dass es das Copy ist habe ich auch gerade rausgefunden (dank deinem Tipp, das mit dem Trace muss ich mir merken :-) )

Zitat:

Test output Bild laden
Bild Format ändern
Bilddaten sperren
Stride: 17472
Width: 4368
Bildwerte ins Array kopieren
Zeug berechnen
Bilddaten entsperren
Malen
Anzeigen
finally
vs
Zitat:

Test output Bild laden
Bild Format ändern
Bilddaten sperren
Stride: 13104
Width: 4368
Bildwerte ins Array kopieren
finally
System.AccessViolationException: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
bei System.Runtime.InteropServices.Marshal.CopyToManag ed(IntPtr source, Object destination, Int32 startIndex, Int32 length)
bei System.Runtime.InteropServices.Marshal.Copy(IntPtr source, Int32[] destination, Int32 startIndex, Int32 length)
bei SA_Auswertung.Form1.files_lv_MouseClick(Object sender, MouseEventArgs e)
Daraus schließe ich, die PC mit Fehler nehmen meine "Aufforderung" nach 32 bit pro Pixel nicht richtig Ernst ...
Code:
                Bitmap bmp = img.Clone(rect, PixelFormat.Format32bppArgb);
Das mit den integers hat Performance-Gründe. Das verarbeiten ging so schneller als mit den Bytes.

Grüße,
Julius

------------------------------------------
Edit:

Problem gelöst. Neuer Code:
Code:
Bitmap bmp = new Bitmap(img.Width, img.Height, PixelFormat.Format32bppArgb);
                        using (Graphics g = Graphics.FromImage(bmp))
                        {
                            g.DrawImage(img, new Rectangle(Point.Empty, img.Size));
                        }
Fragt mich nicht warum, aber anscheinend ist .Clone() nicht verlässlich, wenn man das Pixelformat ändern möchte.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:07 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz