Laden...
E
Easyrider myCSharp.de - Member
Anwendungsentwickler Bayern Dabei seit 18.12.2006 200 Beiträge
Benutzerbeschreibung

Forenbeiträge von Easyrider Ingesamt 200 Beiträge

22.02.2008 - 09:13 Uhr

Hallo Golo,

danke für die schnelle Antwort. Hast du zufällig ein gutes Beispiel dazu? Habe mit Templates noch nicht gearbeitet.

mfg

Easy

22.02.2008 - 08:52 Uhr

Hallo zusammen,

nach langer C-Abwesenheit meld ich mich mal zurück, leider mit einem kleinen Problem. Folgendes:

Meine Basisklasse stellt eine Vorlage für einen Editor dar. Darin sollen neben einigen virtuellen Funktionen auch ein paar Events ausprogrammiert werden. So sieht sie derzeit aus (stark gekürzt):


    [Serializable]
    public class EditorFrame : ProgramFrame
    {

...

        private void EditorFrame_Activated(object sender, EventArgs e)
        {
            this.MainForm.SetEditor(this);
            MessageBox.Show("Test");
        }

        private void EditorFrame_Load(object sender, EventArgs e)
        {
            this.savePath = this.TabText;
        }

        private void EditorFrame_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
            this.Save();
            this.MainForm.OnEditorClose();
        }

...


        public virtual void Undo()
        { }
        public virtual void Redo()
        { }
        public virtual void Cut()
        { }

...

Wenn ich nun eine Kindklasse von meiner Basisklasse ableiten lasse, möchte ich das die Events der Basisklasse automatisch in der Kindklasse mit ausgeführt werden sollen. Das hat einen sicherheitsspezifischen Aspekt, da ein Entwickler somit das manuelle Auslösen des Events nicht machen muss.

1.) Das Problem ist, das diese Events gar nicht ausgeführt werden. Es werden nur die Events der Kindklasse gestartet, die der Basisklasse nicht.

2.) Würde ich doch wieder die manuelle Variante wählen (Fehlerquelle Mensch), kann ich nicht base.On... aufrufen. Vor allem nicht bei base.OnActivated(e) und base.OnLoad(e). Dies resultiert in einem Stackoverflow, weil es eine Endlosschleife ist...

Lösungsvorschläge? Denkansätze? Neues Klassenmodell?

mfg

Easy

29.11.2007 - 09:28 Uhr

Um deinen direkten Start umzusetzen müsste ich somit jeden Befehl der Windows-Console in eine eigene Exe-Datei auslagern und diese starten. Hört sich nach ganz schön viel arbeit an, wenn das überhaupt geht... Muss mich mal ein wenig schlau machen.

Vielleicht kannst du deinen Code nicht 1:1 auf das direkte Starten umsetzen. Aber gehen tut es. Auch wenn cd benutzt wird.

Kannst du mir mal ein Beispiel nennen? Ich habe das Gefühl, wir reden knapp aneinander vorbei, weil ich nicht wirklich verstehe wie du das meinst. 🤔

mfg

Stefan

P.S.: Bin jetzt für den Rest des Tages unterwegs, kann dir leider erst Abends antworten.

29.11.2007 - 08:34 Uhr

Danke für die Antwort herbi,

wie meinst du das mit "den Befehl direkt starten"? Die interne .NET-Ping-Klasse?

Über Process.Start starte ich eine Windows-Console, welche die ganze Zeit im Hintergrund mitläuft. Die einzelnen Befehle werden dann an die Konsole geschickt.

Für jeden Befehl eine eigene Konsole starten, ist weder performant noch sinnvoll, da ein Befehl bei mir über mehrere Einzelbefehle gehen kann. Baut nun eine Lösung auf die andere auf, wirds kompliziert. Und manche sachen wie "cd" machen somit keinen Sinn mehr. Ergo fällt die Lösung mit Process.WaitForExit weg, leider.

Ach ja, das mit Ping war nur ein Beispiel, es könnte auch "net use" sein oder sonst irgendein unterstützter Befehl. Der einzelne Befehl selbst ist egal. Mir gehts nur darum festzustellen, wann der Befehl abgearbeitet ist.

Noch weitere Ideen?

mfg

Stefan

28.11.2007 - 21:03 Uhr

Hallo zusammen,

habe ein kleines Problem mit der Windows-Console, und finde leider mit der Suche hier und in google nix brauchbares.

Mein Programm startet eine Windows-Console im Hintergrund. Danach werden Befehle an diese Console geschickt, welche mein Programm dann ausgeben / auswerten soll.

Beispiel:

Mein Programm sendet an die Konsole: "ping google.de"
Im Event WindowsConsole_OutputDataReceived bekomme ich die gewünschten Daten wieder. Soweit sogut. Nur wie kann ich überprüfen, ob die Konsole immer noch an dem Befehl arbeitet? Ich könnte ja ein "ping google.de /t" machen, oder der Ping braucht 2-5 Sekunden zum antworten. Über die ankommenden Daten kann ich es nicht machen, da ich ja nicht weiß wann und welche Daten ich erhalte. Blos wie dann? 🤔

Stehe leider ziemlich auf dem Schlauch, und mein Programm kann erst dann weiterarbeiten, wenn alle Daten da sind. X(

Ich hoffe jemand von euch hat eine Antwort darauf.

mfg

Stefan

19.11.2007 - 09:22 Uhr

Programmierer sind keine guten Gamer. Zumindest nicht in Spielen wo es um schnelligkeit und Reaktion geht.

Wie definierst du "gut"? Reicht es, wenn man einigermaßen Mitspielen kann, oder muss man schon fast professionell sein um gut zu sein?

Ich persönlich passe nicht wirklich in dein Schema. Strategiespiele sind mir viel zu langweilig. Wenn dann will ich selbst zielen und feuern, und das nicht einem Computer überlassen.

Zu deiner Umfrage: ESL CS:S 5on5 Top 100, Stammkneipe Liga 4f, jeweils mit TNB. Denke schon das wir einigermaßen gut sind. Wenn es dich genauer interessiert such einfach bei beiden Ligen mal unter Easyrider.
Genaueres kann ich es dir in zwei Wochen sagen, weil dann die MTA ist, wo wir mit vier Häusern vertreten sind.

Wir sehen uns :evil:

12.10.2007 - 08:01 Uhr

Morgen zusammen,

ich hoffe doch mal das ich bei Google jemanden finden kann, der neue Ideen sammelt. Das sie tonnenweise eigene Ideen haben ist klar, sonst wären sie niemals so schnell so groß geworden, oder herbi? 😉

Das mit der Werbung ist mir auch schon eingefallen el_panter. Zwar etwas anders, aber recht ähnlich. Aber ich habe das Thema am Anfang bewusst weggelassen, da es bei meiner Version zu unübersichtlich geworden wäre. Wenn man die Blase aber erst beim Mouseover anzeigen lassen würde, wäre die Werbung sogar erträglich. Und die Firma hat ein weiteres Geschäftsfeld.

Derzeit existieren bereits "vereinzelt" Wikipedialinks auf Google Earth, aber die sind für meinen Geschmack einfach noch viel zu selten gesäht. Wenn ich mir mit Google Earth ein bestimmte Stadt ansehen will und ein interessantes Gebäude entdecke, möchte ich auch wissen was es ist und warum es da steht. Aber nur auf der Karte, ohne Namen und Links ist es einfach schwer, so etwas auf Wikipedia zu finden.

Bitte / Danke weitere Kommentare, solche Ideen wie die von el_panter helfen mir weiter. 👍

11.10.2007 - 16:05 Uhr

@ el_panter: Das ganze privat zu realisieren war nie meine Absicht, da es selbst mit zehn Entwicklern in absehbarer Zeit nicht umsetzbar ist. Im Endeffekt möchte ich die Idee natürlich bei Google selbst vortragen. Diese Leute hätten das Geld und die personelle Möglichkeiten, sowas zu machen.
Und wieviele Leute es nutzen? Theoretisch jeder, der bei Wikipedia nach etwas nachsieht, zu dem Daten für Google Earth vorhanden sind. Oder möchtest du vorm Urlaub nicht sehen, wohin du fährst?

@ Grouser: Das mit der Finanzierung sollte nicht das Problem sein. Wenn es Google nicht bezahlen könnte, wer dann? Und die 5-10 Entwickler, die zur Wartung der Datenbank abgestellt werden müssen sind auch nicht das Problem. Schau dir mal die Google-Interne Arbeitsweise an, dann weißt du was ich meine.

Und zum Anreiz für Google: Durch die intensivere Nutzung von Google Earth hat die Firma eine breitere Basis für Google Plus, Pro oder Enterprise. Damit könnten schon viele Kunden gewonnen werden. So könnte sich ein Teil der Kosten wieder ammortisieren.

Nochmal für alle: Mir geht es hier rein um theoretische Möglichkeiten. Also nach dem Prinzip der Synergien. Je mehr Leute sich hier äußern und versuchen die Idee weiter zu entwickeln, desto besser wird es. Jedwede Art von Anreiz kann den anderen wieder weiterbringen. Probiert's einfach, traut euch 😉

*edit: Eins hab ich vergessen: Wikipedia und Google Earth sind derzeit kostenlos, wieso sollte dann die Kombination draus nicht kostenlos sein?

11.10.2007 - 10:45 Uhr

*edit: deletet, habe überlesen das es VPC war...

11.10.2007 - 10:31 Uhr

Servus zusammen,

ich hatte da heute morgen eine Idee, die mich einfach nicht mehr loslässt. Da ich aber gerne andere Meinungen mit einbeziehen möchte stelle ich sie hier mal kurz vor.

Es geht konkret darum, die riesige Wissensdatenbank Wikipedia stärker mit Google Earth zu verknüpfen. Durch diese Verknüpfung wäre die Suche, geografische Lokalisierung und Dichte der Informationen viel höher als derzeit.

Beispiele:

Wenn ich in Google Earth Deutschland markiere, bekomme ich die Informationen von Wikipedia über Deutschland. Zoome ich jetzt weiter rein und wähle Berlin aus, bekomme ich die Informationen über Berlin. Genauso soll es funktionieren, wenn man das Berliner Rathaus selektiert.

Umgekehrt wären auch die Wikipedia-Artikel zu erweitern. Dabei wären neben Gebäude und Denkmäler auch Flüsse oder Berge grafisch als 3D-Modelle darzustellen. Genauso sollte es einfach möglich sein ein Objekt (z.B. Eiffelturm) direkt von der Homepage aus anzufliegen. Also so ähnlich wie wenn ich mir eine KML-Datei downloade, blos ohne den Aufwand des Downloadens.
Mit Sketchup erstellte 3D-Modelle von Objekten sollten in Wikipedia eingegliedert werden, genauso wie Touren zu bestimmten Personen oder Ereignissen. Als Beispiel möchte ich hier den Lebenslauf von Mozart sowie seine einzelnen Stationen nennen.
Das alles sollte nicht auf Google-Servern liegen, sondern direkt in Wikipedia integriert werden, um die Modifizierbarkeit und Transparenz zu erhöhen. Somit ist eine gewissen Sicherheit gewährleistet.

Es gibt bestimmt noch viele Möglichkeiten, wie man diese Engine erweitern und für die Allgemeinheit verbessern könnte. Die Grundidee bleibt aber die gleiche: Wissensdatenbank mit geografischem Tool verbinden.

Der Aufwand dafür wäre enorm, da neben der grafischen Anzeige die Datenbank und die komplette Kommunikation zwischen den Servern gemacht werden müsste. Aber die Chancen machen diesen Aufwand mehr als wett!

Was haltet ihr davon? Würdet ihr sowas benutzen? Oder würdet ihr sogar Artikel / Modelle / Texturen dafür erstellen? Ich freue mich auf eure Meinungen.

mfg

Easy

P.S.: Natürlich muss ich davon ausgehen, das Google eine Erweiterung bzw. sowas wie eine SDK dafür zur Verfügung stellen würde. Nur mit KML ist nur ein Teil möglich. Aber dafür habe ich auch schon einige Argumente 😉

10.10.2007 - 07:44 Uhr

Hallo,

@ regen: Weglassen kann ich leider nix, auch wenn ich auf maximale Zoomstufe gehe. DirectX ist auch eine Möglichkeit, die aber eingeschränkt ist: Alle Computer ohne DirectX fallen weg. Das ist bei mir nicht erwünscht.

@ herbivore: thx für den Link, sieht vielversprechend aus. Das ich den nicht gefunden habe? O_o Egal, werde mich jetzt erst mal einlesen.

mfg

Easy

09.10.2007 - 16:25 Uhr

Hallo zusammen,

ich habe ein logisches Problem. Folgende Aufgabenstellung:

  • Picturebox mit einem Bild im Hintergrund
  • Im Vordergrund werden im Paint-Ereignis Polygone auf ein zweites Bild gezeichnet, das dann darüber gelegt wird
  • Die Picturebox ist zoombar und bewegbar, so das immer nur ein Teil der Polygone sichtbar ist
  • Anzahl der Länder: ~ 200
  • 1 bis 100 Polygone pro Land
  • Anzahl der Koordinaten aller Polygone: ~ 20.000

Jedes "Land" besitzt ein Array von Objekten des Typs "Region". Diese wiederum besitzen ein Array mit "Koordinaten". Im Code weiter unten kann man sehen, wie diese Funktionen aufgerufen werden. Zuerst wird Land.Draw aufgerufen, dieses leitet es dann weiter an die Regionen, also Region.Draw. In der Funktion wird dann erst das richtige Zeichnen ausgeführt.


Picturebox:
private void pcbPicture_Paint(object sender, PaintEventArgs e)
{

    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

    if (this.myLaender.Count > 0)
    {
         foreach (clsLand Land in this.myLaender)
         {
             Land.Draw(e.Graphics, this.myZoomRate);
         }
     }

     DrawNewCountry(e.Graphics);
        
}

clsLand:
internal void Draw(Graphics graph, double ZoomRate)
{
    this.myGraphic = graph;
    this.ZoomRate = ZoomRate;

    for (int i = 0; i < this.myRegionen.Count; i++)
    {
         ((clsRegion)this.myRegionen[i]).RecalcGraphicsPath();
         ((clsRegion)this.myRegionen[i]).Draw(this.myGraphic, ZoomRate);
    }

}

clsRegion:
- Berechnung
- Zeichnung
- Graphicspath füllen


Mein Problem ist nun, das das mit zunehmender Größe der Länder und Anzahl der Regionen / Koordinaten das Zeichnen einfach zu lange dauert. Wenn ich bei jedem Invalidate alle Regionen neu zeichnen lassen muss schaffe ich so höchstens ein paar Bilder pro Sekunde.

Ich habe mir nun gedacht, einen Algorithmus zu entwickeln, um nur die benötigten Koordinaten neu zeichnen zu müssen. Aber dazu müssen bei einem verschieben der Picturebox alle Koordinaten neu berechnet werden. Dies ist ungefähr genauso langsam wie das neuzeichnen.

Weiß jemand sonst noch Lösungswege, oder bleibt mir nur das einfache Zeichnen übrig? Oder hat jemand andere Ideen oder Anregungen zu diesem Dilemma? Ich freue mich über jede konstruktive Antwort!

mfg

Stefan

10.07.2007 - 16:07 Uhr

Aye, ich ziehe die Picturebox. Ich verändere Größe und Position.

Und ja, ich nehme alles mal Faktor. Das stellt aber nicht das Problem dar, wie dir dieses Beispiel erläuter soll:

Left = -1500, LeftWithoutZoom = 1000, Faktor = 1.50

-> Faktor wird auf 1.55 erhöht. -1000 * 1.55 = -1550

Mein Hauptproblem derzeit ist, das ich immer noch den zentralen Punkt meines Zooms in der linken oberen Ecke der Anzeige habe. Diesen möchte ich in die Mitte bringen. Aber ich stell mich echt zu doof an, den Wert korrekt auszurechnen, den ich vom Left noch abziehen muss.

Die Fehler mit den Sprüngen kannst du erstmal ignorieren, da ich das Layout komplett auf ein Koordinatensystem umgestellt habe. Scheiß auf Rundungsdifferenzen, sonst wirds zu kompliziert. Der Zoom hat atm Priorität.

Im Anhang findest du ein Bild, wie man es sich etwa vorstellen kann. Das große gelbe ist die Picturebox, die man mit der Maus hin und her bewegt.

@ jaensen: Ich muss trotzdem erst die Koordinaten ausrechnen, bevor ich sie setzen kann.
Desweiteren hatte Scale ein paar Macken. Ich setze zuerst Width und dann erst Left, damit das Auge die Bewegung nicht so sehr mitbekommt. Scale macht es genau umgekehrt. Es ist nur ein grafischer Unterschied, deswegen mach ich es manuell.

10.07.2007 - 15:24 Uhr

Nicht ganz Stu42. Das zoomen mit einer Picturebox funktioniert ein wenig anders:

Damit es überhaupt möglich ist muss bei der Picturebox die Eigenschaft Sizemode auf Zoom stellen. Nun kann man reinzoomen, indem man die Picturebox vergrößert, und rauszoomen indem die Picturebox verkleinert wird.

Damit man sich beim zoomen leichter tut, habe ich einen Zoomfaktor mit eingebaut. Standardmäßig beträgt er 1.0, Maximal 2.0 und Minimal 0.01.

So wie ich das am Anfang gedacht habe sind es zwei "Koordinatensysteme" geworden. Eins ohne Zoomfaktor und eines mit. Der Grund war der, das es bei hohem Zoom zu Rundungsfehlern kommen könnte, sobald ich selbst zeichne. Was böse negative Effekte für mich hätte. Deswegen wollte ich immer neu von den originalen Zahlen berechnen, und nicht über gerundete.

Ich check immer noch nicht wirklich was an dem falsch ist, was ich oben auskommentiert habe... 🤔

10.07.2007 - 14:46 Uhr

Da muss man sich nicht groß durchwühlen. Er ist gegliedert und logisch aufgebaut. Sind ja grad mal 400 Zeilen. Desweiteren ist es viel leichter nachvollziehbar, wenn man ein Beispiel hat, an dem man es direkt sehen kann 😉

Aber ich tu dir den Gefallen:

        private void ZoomPicture()
        {
            double Height = 0.0;
            double Width = 0.0;
            double Left = 0.0;
            double Top = 0.0;

            Width = (double)this.myPictureWidthWithoutZoom * myActualZoom;
            Height = (double)this.myPictureHeightWithoutZoom * myActualZoom;
            Top = (double)this.myPictureTopWithoutZoom * myActualZoom;
            Left = (double)this.myPictureLeftWithoutZoom * myActualZoom;

            /*Left = (double)this.pcbPicture.Left / myOldZoom * myActualZoom;
            Width = (double)this.pcbPicture.Width / myOldZoom * myActualZoom;
            Top = (double)this.pcbPicture.Top / myOldZoom * myActualZoom;
            Height = (double)this.pcbPicture.Height / myOldZoom * myActualZoom;*/

            // Left
            if (Left <= MAXLEFT)
            {
                if (Left >= this.myMinLeft)
                    this.pcbPicture.Left = (int)Left;
                else
                    this.pcbPicture.Left = (int)this.myMinLeft;
            }
            else
                this.pcbPicture.Left = MAXLEFT;

            // Width
            if (Width <= this.pnlPictureBox.Width)
                this.pcbPicture.Width = this.pnlPictureBox.Width - 4;
            else
                this.pcbPicture.Width = (int)Width;

            // Top
            if (Top <= MAXTOP)
            {
                if (Top >= this.myMinTop)
                    this.pcbPicture.Top = (int)Top;
                else
                    this.pcbPicture.Top = (int)this.myMinTop;
            }
            else
                this.pcbPicture.Top = MAXTOP;

            // Height
            if (Height <= this.pnlPictureBox.Height)
                this.pcbPicture.Height = this.pnlPictureBox.Height - 4;
            else
                this.pcbPicture.Height = (int)Height;

            // Tooltip setzen + alte Werte speichern
            this.ttpPicture.SetToolTip(this.pcbPicture, "Zoomstufe: " + ((myActualZoom * 100) - 100) + "%");

        }

Hier läufts falsch. Keine der beiden Lösungen funktioniert. Das der Zoom an der linken oberen Ecke (in dieser Version) ist, ist logisch, da ich keine Berechnung für den Mittelpunkt mit eingebaut habe.
Was mich aber stutzig macht ist, das wenn ich das auskommentierte benutze, das Bild hin und wieder solche "Sprünge" drin hat wie anfangs beschrieben. Leider weiß ich nicht warum, und das ist das Problem.

10.07.2007 - 14:04 Uhr

Ich hab ne Picturebox genommen, weil es für mich das logischte war. Ich muss das Bild später modifizieren (selbst zeichnen), die Picturebox kann indirekt einen Zoom und es gibt Beispiele dazu.

10.07.2007 - 13:40 Uhr

Servus zusammen,

bin gerade dabei ein eigenes Control zu schreiben. Dabei gehts um ein Bild in einer Picturebox, welche ich scrollen und zoomen können muss.

Mein Problem ist derzeit der Zoom, da er mir das Bild nicht so verschiebt wie ich es möchte. Erstens verschiebt er das Bild mit dem Mittelpunkt links oben in der Ecke (ich will aber mittig zoomen), und zweitens hat die Berechnung hin und wieder ein paar Macken, wo er das Bild um ein paar Pixel zu weit nach rechts bzw. oben schiebt.

Anscheinend stell ich mich gerade ein bischen doof an, aber ich bekomms ums verrecken nicht auf die Reihe. Scheiß niedere Mathematik. g

Falls jemand Zeit und Lust hat könnte er es sich doch bitte mal anschauen. Sind alle Fehler ausgebessert wird die Picturebox hier im Forum mit Beschreibung neu veröffentlicht, so das jeder was davon hat. Ist zumindest geplant, wenn ihr sie wollt 😉

mfg

Easy

P.S.: Ressourcen-Datei des Anhangs löschen und eigenes Bild einbauen, da meins zu groß ist.

11.04.2007 - 13:42 Uhr

Huhu,

ich bins mal wieder, dieses Mal mit einer etwas theoretischen Frage: Wie stelle ich am besten einen Proxyserver für eine Pluginfähige Software bereit? Und wie kann ich jede Kommunikation über meine Applikation laufen lassen?

Um das ganze zu verdeutlichen beschreibe ich kurz den Aufbau:

Software A: Hauptanwendung
Hier soll der Proxy eingestellt und (de)aktiviert werden können. Es werden alle Plugins von dieser Anwendung geladen und in der Anwendung selbst als Child geladen (Forms) bzw. als Childprozess (Schnittstellen, Funktionsdlls) gestartet.

Software B: Das Plugin
Mit diesem Plugin wird "irgendetwas" mit dem Netzwerk gemacht, z. B. Ping oder Dateidownload. Was genau gemacht wird kann ich entweder nicht sagen oder ich weiß es einfach noch nicht.

Für den konzeptionellen Aufbau habe ich mir folgende Optionen vorgestellt:

Erstens: Einen Proxy für die Plugins bereitstellen.
Um einen Proxy für ein Plugin bereit zu stellen fällt mir als Lösungsweg das Interface ein. Ich stelle in einem Interface Funktionen und Eigenschaften zur Verfügung, mit denen jedes Plugin selbst überprüft ob es über einen Proxy gehen soll. Beispiel:

public bool UseProxy;
public IPAdress ProxyAdress

Das Problem bei diesem Aufbau ist, das jedes Plugin die Überprüfung auf einen Proxy mit einbauen muss. Vergisst man das, bzw. lässt man es mit Absicht weg, kann man so eine geplante Sicherheitsvorkehrung umgehen. (Risikofaktor 1)

Gibt es noch andere Möglichkeiten einen Proxy bereitzustellen, so das er (evtl.) automatisch benutzt wird? Wenn nein, kommen wir zum nächsten Punkt.

Zweitens: Wie kann ich ein Plugin so absichern, das jedwege Netzwerkommunikation über meine Hauptanwendung läuft?

Könnte ich das so bewerkstelligen, würde die Sache mit dem Proxy wegfallen, da ich es dann selbst in meiner Hauptanwendung überprüfen würde.

Ist das auch nicht möglich, haben wir Risikofaktor 2.

Ich hoffe ich habe es einigermaßen erklären können, es ist schwer eine Skizze in Worte zu fassen. Für Nachfragen, Tips und konstruktive Kritik bin ich dankbar.

mfg

Easy

10.04.2007 - 12:14 Uhr

Hallo,

mach doch anstatt


...
object missing = Missing.Value; ;
object filename = "C:\temp\test.doc";
object template = Missing.Value;
object newTemplate = Missing.Value;
object documentType = Missing.Value;
object visible = true;
...

einfach nur


...
object missing = Missing.Value; ;
object filename = "C:\temp\test.doc";
object visible = true;
...

und übergib in der Funktion app.Documents.Add immer das object missing. So sparst du dir drei Variablen, und der Quellcode wird übersichtlicher.

23.03.2007 - 19:17 Uhr

Fuck bong Hirn anschmeiß

Ja, du hast recht. Hab wohl zuviel gearbeitet diese Woche. Im Grunde ganz leicht: Transparentes FillPolygon drüberlegen, Events registrieren, beim Klick zeichnen / löschen.

Auf die Idee, das beim verschieben zu suchen, bin ich leider nicht gekommen g

Danke dir Herbivore 👍

23.03.2007 - 18:44 Uhr

Servus,

habe da mal ein mittelschweres Konzeptproblem. Es geht darum einzelne Länder auf einer Weltkarte "auswählbar" zu machen, diese zu markieren und grafisch hervorzuheben.

Als Lösungsansatz habe ich mir sowas wie Hotspots in HTML vorgestellt. Bin aber trotz längerer Suche nicht fündig geworden. Evtl. habe ich auch nur nach den falschen Begriffen gesucht.

Hat jemand eine Idee wie sich das, ohne größeren Aufwand, in C# realisieren lassen könnte?

mfg

Easy

20.02.2007 - 14:44 Uhr

Hallo zusammen,

mir stellt sich gerade die Aufgabe Word aus meiner Anwendung zu starten. Der Haken daran ist das die Funktionen extrem eingeschränkt werden müssen.

Ich muss alles ausblenden / deaktivieren, bis auf drei oder vier Punkte. Diese Punkte habe ich mir in einer eigenen Menüleiste zusammengeklickt.

Desweiteren ist anzumerken das ich das Word nicht so manipulieren darf, das danach bei jedem Start alles ausgeblendet ist. Nur wenn mein Programm Word explizit startet soll alles weg, ansonsten muss Word so aussehen wie der Benutzer es das letzte Mal verlassen hat.

Derzeit mache ich es so:

        ApplicationClass app = null;

        private void cmdStarteWord_Click(object sender, EventArgs e)
        {

            object empty = null;

            try
            {
                app = new ApplicationClass();

                foreach (CommandBar bar in app.CommandBars)
                {

                    if (bar.Name != "MyProgramName")
                        bar.Visible = false;
                    else
                        bar.Visible = true;

                }

                app.Visible = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                app.Quit(ref empty, ref empty, ref empty);
            }

        }

Leider resultiert das ganze in folgendem Fehler:

Message: "Beim Aufruf einer COM-Komponente wurde ein HRESULT E_FAIL-Fehler zurückgegeben."
StackTrace: "   bei Microsoft.Office.Core.CommandBar.set_Visible(Boolean pvarfVisible)
bei WordTest.frmMain.cmdStarteWord_Click(Object sender, EventArgs e) in ...\\WordTest\\frmMain.cs:Zeile 63."

Der Fehler sagt mir leider nichts. Weiß jemand was er bedeutet?

Über ein paar Beispiele / Snippets / Tips würde ich mich auch sehr freuen. Google und andere Suchmaschinen werfen extrem viel Schrott aus, da "Word", "Symbolleiste" oder "Speichern" einfach häufig benutzte Wörter sind...

mfg

Easy

15.02.2007 - 15:57 Uhr

Erstmal danke für eure Antworten.

@ Reman: Leider funktioniert das nicht mit meinen Schnittstellen-DLLs, da diese nicht als gültige COM-Assemblys angesehen werden.

@ svenson: Ersetze ulong durch uint und es sollte klappen. Genau das wars, dankeschön. Das in C ein long 32bit lang ist habe ich nicht gewusst, wieder was neues gelernt 8)

@ DarKlajid: Bis jetzt habe ich noch keine CallingConventions benötigt. Arbeite bereits mit ein paar weiteren DLLs in dieser Richtung, aber noch keine Funktion hat mir solche Probleme gemacht.

Um die "alten Sachen" ansprechen zu können muss man halt auf alte Schnittstellen zugreifen, auch wenns schon seehr alt ist...

Danke Leute 👍

15.02.2007 - 14:28 Uhr

Servus,

ich bin anscheinend zu blöd einen DLL-Import richtig auf die Reihe zu bekommen. Folgende Funktion benötige ich:

unsigned int CWB_ENTRY cwbNL_CCSIDToCodePage(
                             unsigned long   CCSID,
                             unsigned long  *codePage,
                             cwbSV_ErrHandle errorHandle);

Hier ist die Doku dazu.

Hab es bereits ein paar mal probiert, aber ich bekomme immer diese "StackImbalance"-Fehler, ergo is meine Definition falsch.

Eines der Beispiele, mit denen ich es probiert habe:

[DllImport("cwbnl.dll", EntryPoint = "cwbNL_CCSIDToCodePage")]
private static extern uint myCCSIDToCodePage(
            ulong hostCCSID, ref ulong hostCodePage,
            IntPtr errorMessages);

Falls jemand weiß was ich falsch mache, klärt mich bitte auf. Ich habs nicht so sehr mit Pointern und Referenzen gg

mfg

Easy

12.02.2007 - 15:50 Uhr

Das große Problem ist das ich die Forms für alles mögliche benutze. Ich erklärs euch kurz:

Die Formulare leiten von einer Klasse ab, die in einer Schnittstelle deklariert ist. Diese Formulare sind (dank der DockPanel Suite) wie in der Visual-Studio-IDE bewegbar. Ohne ein Objekt des Formulars bringt mir das einfache Anzeigen nichts.

@DarKlajid: Ich habe ehrlich gesagt keine Ahnung was in den Formularen alles kommt. Unser Kunde hat eine uralte AS400 am laufen, auf der mehrere tausend einzelne Programme auf eine "richtige" grafische Oberfläche umgeschrieben werden müssen. Da aber das Produktivsystem nicht beeinträchtigt werden darf ist eine Plugin-Bauweise zwingend erforderlich.

Da die Anwendung auf einem MainFrame läuft, und die Benutzer nur mit Terminals arbeiten, wäre ein solcher Updater ohne Neustart der Software sehr bevorzugt gewesen.

Aber hilft wohl nix. Was nicht geht geht halt nicht. Danke für eure Ideen 👍

12.02.2007 - 12:37 Uhr

Na toll:

Einige Systemtypen erweitern zwar MarshalByRefObject, führen jedoch Sicherheitsüberprüfungen zur Laufzeit aus, um tatsächliche Remoteaufrufe eines Objekt des MarshalByRefObject-Typs von außerhalb der Anwendungsdomäne zu verhindern. AppDomain und System.Windows.Forms.Form sind zwei Beispiele für solche Systemtypen. Obwohl es scheinbar möglich sein sollte, MarshalByRefObject zu erweitern und einen entsprechenden Verweis remote abzurufen, ist dies bei diesen besonderen Typen nicht der Fall. Möglicherweise möchten Sie den prozessinternen Verweis in einem anderen remotefähigen Typ einschließen, jedoch wird dadurch unbeabsichtigt die Codezugriffssicherheit umgangen. Die sollte in jedem Fall vermieden werden.

Quelle:
>

Da wird man von .NET gezwungen eine Assembly in eine neue AppDomain zu laden, damit man sie später evtl. wieder entladen kann, gleichzeitig aber lässt man mich keine GUI´s von einer AppDomain in die andere übertragen, weil ich so die Sicherheit umgehen würde. Na vielen dank...

🙄 😜

11.02.2007 - 20:49 Uhr

Danke für deine Antwort talla 😁

Wie du bereits gesagt hast muss es mir egal sein ob das Objekt ein Formular ist, eine Klasse oder sonst irgendwas.

Zur Idee mit einer eigenen Klasse schreiben: Ansich wäre das ein optionaler Lösungsweg, der aber einen (meiner Spezifikation nach zu großen) Haken hat: Ich muss fest implementieren welche Eigenschaften das sind. Sobald nun aber ein Plugin-Entwickler eine eigene Eigenschaft einbaut, welche z. B. eine eigene Klasse aus dem Plugin implementiert würde es hier crashen. Mit so einer Klasse ist das Plugin einfach nicht "wirklich" dynamisch, sondern statisch. 🙁

Deine zweite Idee hört sich auch nicht schlecht an, aber das wäre mit einem enormen Aufwand verbunden. Ich müsste jede Methode und Eigenschaft aus der Schnittstelle, die Zugriff auf meine Hauptanwendung erlaubt, invoken, und umgekehrt. Der komplette Daten- und Eventverkehr zwischen den beiden AppDomains müsste neu geschrieben werden. Das würde Wochen, wenn nicht sogar Monate dauern X(

Hat sonst noch jemand eine Idee wie ich ein Objekt von AppDomain A nach AppDomain B bringe, das nicht serialisierbar ist?

11.02.2007 - 16:05 Uhr

Servus zusammen,

ich quäle mich jetzt schon das ganze Wochenende mit einem Problem herum und komme auch nach vielen Stunden des Denkens und Suchens nicht weiter. Bevor ich euch mein genaues Problem erkläre muss ich euch zeigen, wie das ganze zustande kommt. Folgende Aufgabenstellung:

Ich muss eine Plugin-Fähige Umgebung schaffen, in der einzelne Formulare bzw. Funktionen in DLLs ausgelagert werden. Da die Umgebung bei einem Update nicht neugestartet werden kann (Terminalumgebung) muss das ganze dynamisch gemacht werden. Dies geht in .NET nur über eine zweite AppDomain, wie hier im Forum bereits schön erklärt ist. Diese habe ich realisiert, auch das Laden der Assembly und das benutzen von Funktionen daraus ist ohne Probleme möglich.

Mein Problem ist jetzt das laden eines Formulars. Ich bekomme jedesmal folgende Ausnahme:


Der Typ System.Windows.Forms.Control+ControlCollection in Assembly System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=.... ist als nicht serialisierbar gekennzeichnet.

Ich bin bis jetzt schonmal so schlau:

Ich weiß das ein Formular nicht serialisierbar ist. Warum habe ich trotz Suche leider noch nicht gefunden. So wie es aussieht sind alle Controls und Forms ohne das Attribut "[Serializable]" gekennzeichnet, wahrscheinlich auch mit gutem Grund. Wenn jemand weiß warum und mich aufklären könnte, wäre das sehr nett.

?( Meine eigentliche Frage aber lautet: Wie kann ich Formulare für meine Rahmenanwendung in AppDomain A bereitstellen, wenn diese Formulare in einer DLL in der AppDomain B liegen?

Wenn das nicht möglich ist, kann ich dann mein internes Design irgendwie umstellen, um die Problemstellung zu realisieren?

Ich bin für jeden Tip und jede Hilfe dankbar. Erst recht mein Kopf, der raucht schon mehr als ich 👅

mfg

Easy

05.02.2007 - 14:07 Uhr

Hab grade ein wenig gesucht, aber ich finde leider nix wie ich die Handles bekomme, die auf eine bestimmte Datei zugreifen.

Hast du evtl. ein Beispiel? Oder kannst mir die richtigen Stichwörter für die Suche sagen? g

05.02.2007 - 12:56 Uhr

Theoretisch wäre das möglich, aber dann ist dieser Teil meiner Software fix auf OpenOffice gebunden. Ohne eine Unterstützung für andere Textverarbeitungsprogramme macht es (in diesem Projektteil) keinen Sinn.

Werd ich das ganze wohl anders lösen müssen.

Danke auf jedenfall mal für eure Hilfe bis jetzt. 🙂

05.02.2007 - 12:12 Uhr

Servus,

in den normalen Open-Office-Einstellungen gibts leider keine Möglichkeit pro Fenster einen eigenen Thread zu erstellen. Schauen wir mal ob wir sonst noch was finden.

@ Borg: Wie meinst du das, das man OpenOffice "scripten" kann?

Ich zieh mir jetzt erst mal eine gemütliche Line (DevelopersGuide für OpenOffice g).

05.02.2007 - 10:19 Uhr

So funktioniert das leider nicht.

Wie oben beschrieben ist jedes Writer-Fenster im gleichen Prozess. Mit Process.WaitForExit() müsste er alle Writer-Fenster schließen bis ich weitermachen könnte. Aber er soll nur ein einziges Fenster (das, das ich gestartet habe) schließen müssen.

05.02.2007 - 10:05 Uhr

Servus,

ich habe ein Problem, und zwar muss ich feststellen wann ein von mir gestarteter Prozess beendet worden ist. Folgendes Beispiel:

Über ein Event wird eine Instanz des swriters von Open-Office gestartet:


try
{
    ProcessStartInfo WriterProcessInfo = new ProcessStartInfo(this.myWriterPath, " -o \"" + this.myFileToOpen + "\"");
    Process WriterProcess = new Process();
    WriterProcess.StartInfo = WriterProcessInfo;
    WriterProcess.Start();
    this.myTimer.Stop();
    this.myWaitTimer.Start();
}
catch (Exception ex)
{
    this.myTimer.Stop();
    MessageBox.Show(ex.Message);
}

Im WaitTimer-Event möchte ich nun jede Sekunde überprüfen, ob der gestartete Prozess schon beendet ist. Das Problem ist, das OpenOffice anscheinend eine "Starter-Klasse" vor dem eigentlichen Programm eingebaut hat. Wenn ich nun mehrere Writer-Fenster mit unterschiedlichen Dateien geöffnet habe sind Process-ID und Thread-ID die selbe:

Fenster 1:
Process: soffice.bin
Process-ID: 986
Thread-ID: 1836

Fenster 2:
Process: soffice.bin
Process-ID: 986
Thread-ID: 1836

Fenster 3:
Process: soffice.bin
Process-ID: 986
Thread-ID: 1836

Die Daten habe ich mit Spy++ erhalten.

Die einzige Möglichkeit die mir noch einfällt, ist diejenige, die ich nicht gerne nehmen möchte: Über FindWindow. Ich weiß zwar wie der Text oben aufgebaut ist, und auch die Klasse, aber das kann doch auch nicht die beste Lösung sein.

Ich hoffe jemand hat eine Idee, bzw. hat sowas schonmal gemacht.

mfg

Easy

26.01.2007 - 13:33 Uhr

Servus zusammen,

wie es im Themanamen schon steht habe ich ein Problem mit unterschiedlichen Codierungen.

Meine Software läuft unter einem Windows Server 2003, ganz normal. Die Programme, die ich per Remote ausführen soll, liegen auf einer AS400 / iSeries (IBM Großrechner) beim Kunden.

Ich habe jetzt das Problem, das diese Programme Parameter zum starten benötigen. Es stellt für mich kein Problem dar eine Kommunikation aufzubauen, die entsprechenden Programme zu finden und auszuführen.

Das Problem bei mir ist, das die Zielmaschine eine andere Codierung benutzt, und zwar eine EBCDIC 273 Codierung. Wenn ich nun einen normalen String, so wie es in C# definiert ist, als Parameter an das Programm schicke, kommt nur kauderwelsch an.

Wie kann ich einen String in meinem Programm in das Format EBCDIC codieren?

mfg

Easy

09.01.2007 - 18:18 Uhr

*edit: Ok, hat sich erledigt. Anstatt WM_SETTEXT einfach WM_CHAR benutzen, dann funktionierts...

09.01.2007 - 14:36 Uhr

Sers zusammen,

ich versuche gerade einen automatischen Login in einer externen Anwendung auf die Reihe zu bekommen. Sobald die externe Anwendung gestartet wird geht ein zweites Fenster mit ShowDialog() auf. In dem sind dann zwei Textboxen, in denen der Benutzername und das Passwort eingegeben werden.

Folgender Lösungsversuch:





        private void ExecAutoLogin()
        {
            IntPtr loginHandle;
            IntPtr userHandle;
            IntPtr pwHandle;

            loginHandle = FindWindow("#32770", "Anmeldung an iSeries");
            if (loginHandle != IntPtr.Zero)
            {
                userHandle = GetDlgItem(loginHandle, 1321);
                if (userHandle != IntPtr.Zero)
                {
                    SetDlgItemText(loginHandle, 1321, this.myUsername);
                }

                pwHandle = GetDlgItem(loginHandle, 1323);
                if(pwHandle != IntPtr.Zero)
                {
                    SetDlgItemText(loginHandle, 1323, this.myPassword);
                }
            }

        }

Der Code läuft ohne meckern und murren durch. Die IDs der beiden Textboxen habe ich mir per Spy++ geholt. Trotzdem wird mir aber der Text nicht angezeigt. Die beiden Textboxen sind nach wie vor leer.

Wo liegt mein Fehler?

mfg

Easy

05.01.2007 - 10:45 Uhr

Ok, das hab ich verstanden, nur:

Wie zum Geier überschreib ich die Funktion in meinem Handle? Die Form, die ich mit SetParent(..) in meine Form "stehle", ist eigentlich eine externe Anwendung. Kann ich die Funktion dann irgendwie zur Laufzeit überschreiben?

edit: Ich hab bis jetzt versucht irgendwie eine Form oder ein NativeWindow aus der Applikation zu holen. Also so:

NativeWindow window = (NativeWindow)NativeWindow.FromHandle(myHandle);

Belohnung: Bei jedem Aufruf schmiert meine Kiste mit einem Bluescreen und der Fehlermeldung "0x0000008E" ab.

Das gleiche war mit Control und Form. So lässt sich das also auch nicht lösen 😕

04.01.2007 - 18:56 Uhr

Huhu zusammen,

meine Anwendung soll bei einer externen Anwendung die Controlboxen, den Titel, das Icon und den Rand, also einfach den ganzen Rahmen bzw. die Non-Client-Area um ein Formular herum entfernen.

Weiß jemand welche API-Funktionen da zur Verfügung stehen? Ich selbst habe leider keine gefunden.

mfg

Easy

03.01.2007 - 16:00 Uhr

Wie marsgk schon gesagt hat, schau dir mal das Color-Objekt an. Finden tust du es unter System.Drawing.Color. Ich glaube nicht das du dann noch mehr Farben brauchst, den wenn dir die nicht reichen wirds eh eng. 😉

mfg

Easy

03.01.2007 - 14:03 Uhr

Hallo zusammen,

hänge mal wieder bei einem "kleinen" Problemchen. Erstmal ne kleine Beschreibung dazu:

Meine Software startet eine externe Applikation. Beim Start soll diese Applikation direkt auf "Hide" gesetzt werden. Soweit mal kein Problem. Nun möchte ich die grafische Ausgabe dieser Applikation in meiner Software anzeigen lassen. Das ganze sollte nicht zu langsam und speicherintensiv werden.

Folgende Lösungswege habe ich mir mal ergoogelt bzw. ausgedacht:

1. Screen Capturing

Hier klicken, um den Beispielcode anzusehen.

Vorteile:*Einfache Implementierung *Kein Verständnisproblem 😛

Nachteile:*Langsam, somit nicht sinnvoll *Ressourcenfressend (CPU-Auslast sehr hoch, Speicherintensiv) *Wiedergabe "laggy"

Fazit: In meinem Fall kann man das vergessen... X(

2. Screen-Buffer auslesen
(theorie!)

Habe leider noch keinen Quellcode dazu gefunden. Unter Screen-Buffer auslesen verstehe ich, den Buffer der Grafikkarte für die Bildschirmausgabe mitzuschneiden, meinen Teil für die Anwendung dann zu extrahieren und diesen dann per "Paint()" in meine Form zu zeichen.

Vorteile:*Schneller als Bitmaps zu erstellen.

Nachteile:*Noch keine Ahnung wie man das implementieren könnte. *Denke mal das DirectX benötigt wird (Auslesen über OpenGL oder Direct3d) *Hoher Arbeitsaufwand, alles Neugebiet für mich

Fragen:*Hat das schon jemand mal gemacht und könnte mir bei den ersten Schritten helfen / mir ein Beispiel geben? *Geht sowas evtl. auch ohne DirectX? *Muss etwas spezielles beachtet werden (bei unterschiedlichen Grakas etc)?

Fazit: Möglicher Lösungsansatz Nr. 1, aber Fragen über Fragen

3. Handle überschreiben
(theorie!)

Dieser Lösungsansatz basiert auf reiner Spekulation. Folgende (kranke 😉 ) Denkweise in meinem Hirn: Jedes Handle ruft doch die Methode Paint() auf sobald es für ungültig erklärt wird. Dabei wird das Zeichnen auf dem gleichen Handle gemacht, die die Methode aufruft. Wenn ich nun der Applikation das Handle beim Aufruf von Paint() überschreibe (mit meinem eigenen), und nach Ablauf der Paint-Methode das Handle wieder auf das originale zurücksetze, müsste die Zeichnung auf meinem Handle sein.

Vorteile:*Hervorragende Performance

Nachteile:*Noch weniger Ahnung wie man das implementieren könnte.

Fragen:*Kann mir jemand sagen ob dies möglich ist?

Fazit: Möglicher Lösungsansatz Nr. 2

Was schlagt ihr vor? Wie sollte ich das Problem am besten angehen? Habe ich bei Google eine Lösung nicht finden können? Bzw. habt ihr eine gefunden? Wisst ihr noch einen Lösungsansatz? Bin für jeden Tip dankbar.

Danke an alle die bis hierher gelesen haben.

mfg

Easy

19.12.2006 - 12:11 Uhr

*edit: Ich frag mich aber immer noch warum er den ersten Parameter als Referenz haben will? Der Parameter gibt nur den Index der Funktion in der DLL an, mehr nicht. grübel...

P.S.: Sry 4 Doppelpost, Browser spinnt grad ein wenig...

19.12.2006 - 12:09 Uhr

Original von svenson
Na immerhin, das bringt schon ein bißchen mehr Licht ins Dunkel:

[DllImport("PCSHLL32.DLL")]  
public static extern void win_hllapi(ref int function, IntPtr functype, ref int length, ref int returncode);  

Bingo, das wars. Er will alle Parameter als Referenz, ausser dem functype! Den will er als In- Out- Parameter.

        [DllImport("PCSHLL32.DLL")]
        public static extern int win_hllapi(ref int function, [In, Out] char[] functype, ref int length, ref int returncode);

Dann funktionierts. Vielen Dank svenson, das war Spitze. 🙂

19.12.2006 - 11:38 Uhr

Nachfolgend ist das originale Beispiel, das ich in C# nachbilden soll. Das Beispiel wurde mit VB 6.0 programmiert:


Form, in der die Funktion aufgerufen wird:

Private Sub Execute_Click()
  HllFunctionNo = 3
  HllData = Keydata.Text
  HllLength = Val(Length.Text)
  HllReturnCode = 0
  dummy& = hllapi&(HllFunctionNo, HllData, HllLength, HllReturnCode)
  ReturnCode.Text = Str$(HllReturnCode)
...
End Sub


Globales Modul:

Type Func22Type
  SessionIDList As String * 1
  Reserved As String * 3
  LongName As String * 8
  SessionType As String * 1
  SesChr As Byte
  Rows As Integer
  Cols As Integer
  HCP As Integer
End Type

Declare Function hllapi22& Lib "PCSHLL32.DLL" Alias "hllapi" (Func&, Hll22Data As Func22Type, Length&, RetC&)       '@M1A

Wer sich das ganze Beispiel anschauen möchte, der findet eshier.

19.12.2006 - 10:33 Uhr

Ich hab jetzt mal eine kleine Theorie erstellt (reines Gedankenspiel!):

Mein data-Array, das als in- und out-Parameter (!) deklariert und initialisiert ist wird in einem .NET eigenen Speicher gespeichert. Rufe ich nun meine Funktion auf, wird der DLL das data-Array als Pointer übergeben. Somit ist die Variable noch immer im Bereich des Managed Code. Wenn aber nun die DLL versucht die Daten, für die ich ja die Funktion aufrufe, in das Array zu schreiben, verweigert .NET ihm den Zugriff. Aus meiner Sicht darum, weil es unmanaged Code ist.

Hier das ganze mal bildlich dargestellt:
http://img334.imageshack.us/img334/5449/accessviolentexceptionrn0.th.jpg

19.12.2006 - 10:28 Uhr

Original von svenson
Kannst du leicht selbst prüfen: Rufe mal Marshal.Sizeof() auf deiner Struktur auf.

Hab ich auch, im Catch-Block, wenn es kein String ist. Und da wird mir korrekterweise 20 ausgegeben. Leider interessiert das meine Funktion anscheinend nicht, sie will immer noch crashen ^^

19.12.2006 - 10:16 Uhr

Original von svenson

[DllImport("PCSHLL32.DLL")]  
public static extern int win_hllapi(int function, IntPtr functype, int length, int position);  

Nutzung sollte so gehen:

string fName = "X                "; // GENAU (!) 18 Zeichen lang, mit Leerzeichen aufgefüllt  
IntPtr inStr = Marshal.StringToHGlobalAnsi (fName );  
win_hllapi(22, inStr , 18, 1); // Längenparameter scheint mir spanisch....  
QuerySessionStatus status;  
Marshal.PtrToStructure(inStr, status);  
Marshal.FreeHGlobal(inStr);  
  

Deine QuerySessionStatus-Definition scheint mir falsch. Sie muss genau 18 Bytes lang sein, ist aber nur 11.

Hab ich probiert, selbes Ergebnis. grml

Die Definition müsste eigentlich so korrekt sein. Die DLL unterstützt auch noch 16-Bit Betriebssysteme. Bei 16-Bit muss der Parameter 18 Bytes lang sein, bei 32-Bit 20 Bytes. Deswegen der Parameter length. Nur in der Dokumentation, die ich oben per Link eingebunden habe, steht das nicht dabei. Das findet man nur in der Originaldoku von IBM 😉

19.12.2006 - 09:58 Uhr

Wie wäre es denn mit einem globalen Flag?


bool stopflag=false;

Methode1()
{

    call Methode2();

    while(!stopflag)
    {
        CurrentThread.Pause(50);
    }
}

Method2()
{
    ...
    if(allesokunderledigt)
        stopflag=true;
}

19.12.2006 - 09:43 Uhr
struct HLDQuerySessionStatus 
{
  unsigned char qsst_shortname;
  unsigned char qsst_longname[8];
  unsigned char qsst_sestype;
  unsigned char qsst_char;

  unsigned short int qsst_ps_rows;
 
  unsigned short int qsst_ps_cols;

  unsigned short int qsst_host_nls;
  unsigned char qsst_reserv18;
}

So sieht das Array aus, das ich der zweiten Funktion als Parameter übergeben muss. Der Quelltext oben ist aus der Originalen C-Headerdatei.

19.12.2006 - 09:31 Uhr

Original von marsgk
Versuch doch mal ein byte[] array zu übergeben.[/csharp]

Ich habe es gerade mal probiert wie du gesagt hast, leider immer noch dieselbe Fehlermeldung. Trotzdem danke für den Versuch.

Original von svenson
Da hier Strings im Spiel sind, muss ggf. auch das Encoding im DLLImport gesetzt werden. Ist der String null-terminiert? Nur dann funzt es mit dem StringBuilder.

Und wie setzt man das Encoding beim Import? Hab ich anscheinend noch nicht gesehen.Der DLL ist es anscheinend egal ob der String hinten terminiert ist oder nicht, da ich es schon mit strings, Stringbuilder, char-Arrays und nun auch schon mit einem Byte-Array probiert habe. Immer mit dem Ergebnis:

Fehler: 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.

Hat sonst noch jemand eine Idee dazu? Bin langsam am Verzweifeln 🙁

*edit: Sry, vergessen reinzuschreiben 😛

18.12.2006 - 18:38 Uhr

Huhu zusammen,

ich hab hier ein Problem, bei dem ich nun schon fast den ganzen Tag hänge. Folgende Gegebenheiten: Meine Anwendung soll über eine Schnittstelle bestimmte Informationen aus einem Fenster auslesen:

Per DLL-Import binde ich die Unmanaged-C-Dll in meinen Quellcode mit ein. Diese möchte ich dann zur Laufzeit aufrufen, was mir aber einen Fehler wirft. Weiter unten beschreibe ich ihn noch genau. Hier erst einmal der DLL-Import:

[DllImport("PCSHLL32.DLL")]
public static extern int win_hllapi(int function, out string functype, int length, int position);

function = Die ID der Funktion, da in der DLL die einzelnen Funktion über IDs angesprochen werden.
functype = Angabe des Fensters, von dem die Informationen abgerufen werden sollen + gleichzeitig string-Item, in dem die Werte zurück gegeben werden.
length = Länge des Strings (bzw. Char-Arrays).
position = uninteressant

Den functype(mypara) bastel ich mir über ein structure zusammen. Der Aufbau ist dabei wichtig, wie ich es mache ist egal. Wenn die Funktion aufgerufen wird muss im functype "A" (der Name des Fensters) und 19 Leerzeichen enthalten sein. Fix. Hier gibts mehr Informationen zur Funktion.

try
{
    myreturn = win_hllapi(22, out mypara, 20, returncode);
}

So sieht mein DLL-Aufruf aus. Mache ich das nun so, bekomme ich folgende Fehlermeldung:

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.

Die Frage ist jetzt warum? Versucht der unmanaged Code dann meinen String, welcher noch im Managed Code ist, zu überschreiben und schmiert deswegen ab? Oder mag er ganz einfach einen string nicht? Woran könnte es sonst noch liegen?

Folgende Möglichkeiten habe ich bereits ausprobiert:

  • anstatt out ein ref
  • kein String, sondern ein Char-Array benutzen
  • einen ganz anderen Datentyp benutzen
  • 5 Stunden Google 🙁

Bin für jeden Tip dankbar.

mfg

Easy