Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von Spook
Thema: [erledigt] StructLayout.Explicit - welche Größe muss angegeben werden
Am im Forum: Rund um die Programmierung

Hallo Regenwurm,

du musst die Größe nur angeben, wenn du die Struct größer machen willst als die von dir deklarierten Member.

spooky

Thema: Byte-Array direkt in ein struct "kopieren"
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

dieses Snippet sollte funktionieren (kleiner fix incl):

public static object ByteArrayToStruct(byte[] array, int offset, Type structType)
{
    if (array == null)
        throw new ArgumentNullException("array");

    if (structType == null)
        throw new ArgumentNullException("structType");

    if (!structType.IsValueType)
        throw new ArgumentException("structType");

    int size = Marshal.SizeOf(structType);

    if (array.Length < size)
        throw new ArgumentException("array");

    if ((offset < 0) || (offset + size > array.Length))
        throw new ArgumentOutOfRangeException("offset");

    object structure;
    GCHandle arrayHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
    try
    {
        IntPtr ptr = arrayHandle.AddrOfPinnedObject();
        ptr += offset;
        structure = Marshal.PtrToStructure(arrayHandle.AddrOfPinnedObject(), structType);
    }
    finally
    {
        arrayHandle.Free();
    }
    return structure;
}

public static byte[] StructToByteArray(object structure)
{
    if (structure == null)
        throw new ArgumentNullException("structure");

    Type structType = structure.GetType();

    if (!structType.IsValueType)
        throw new ArgumentException("structure");

    int size = Marshal.SizeOf(structType);

    byte[] array = new byte[size];
    GCHandle arrayHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
    try
    {
        IntPtr ptr = arrayHandle.AddrOfPinnedObject();
        Marshal.StructureToPtr(structure, ptr, false);
    }
    finally
    {
        arrayHandle.Free();
    }
    return array;
}

Grüße

spooky

Thema: Byte-Array direkt in ein struct "kopieren"
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo Regenwurm,

diese Version sollte funktionieren:


static object ByteArrayToStruct(byte[] array, int offset, Type structType)
{
    if (array == null)
        throw new ArgumentNullException("array");

    if (!structType.IsValueType)
        throw new ArgumentException("structType");

    int size = Marshal.SizeOf(structType);

    if ((offset < 0) || (offset + size > array.Length))
        throw new ArgumentOutOfRangeException("offset");

    object structure;
    GCHandle structHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
    try
    {
        IntPtr ptr = structHandle.AddrOfPinnedObject();
        ptr += offset;
        structure = Marshal.PtrToStructure(structHandle.AddrOfPinnedObject(), structType);
    }
    finally
    {
        structHandle.Free();
    }
    return structure;
}

spooky

Thema: Applikation findet mitgelieferte Assembly nicht
Am im Forum: Entwicklungs- und Laufzeitumgebung (Infrastruktur)

Hallo,

da die Assembly selbst vorhanden ist, wird es wohl an einer ihrer Abhängigkeiten liegen. Versuche die InnerException Property der geworfenen Exception abzufragen um genauere Informationen zu erhalten.

spooky

Thema: Abzählalgorithmus
Am im Forum: Rund um die Programmierung

Hallo,

am leichtesten sollte es sein, wenn du alle Nummern in eine Liste (List<int>) packst.
Danach schmeisst du solange einen Eintrag raus bis nurnoch einer vorhanden ist. Um den Richtigen zu ermitteln sollte index = liste.Count % Silben reichen.

Grüße

Thema: Grundsatzfrage: new-keyword und Objekterzeugung
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo Fresh0razoR,

der Unterschied liegt darin, dass du in C++ Klassen wie Structs verwenden kannst:

Car mycar = Car();           // Variante 2

oder du kannst sie auf dem Heap erzeugen und so Polymorpie nutzen:
Car* mycar = new Car(); // Variante 1

Dies ist in C# nicht möglich. Structs werden immer auf dem Stack und Klassen immer auf dem Heap erzeugt (dabei verwenden beide Initialisierungen das new Schlüsselwort!).

spooky

Thema: Datenstrom von Graustufen-Pixelwerten (ushorts) in .bmp umwandeln
Am im Forum: Grafik und Sound

Hallo h0ppel,

als erstes solltest du wissen, welchen Wertebereich das zu konvertierende Bild hat. Dann musst du dir überlegen, wie du die Werte von 16 bit, nach vermutlich 8bit, konvertieren willst. Hierzu würde ich eine Histogramm- oder eine Min/Max-Skalierung verwenden.

Diese spuckt dir dann zwei Werte aus:
zb. min=32000 max=35000.

Damit kannst du dann jeden Pixel auf 8bit skalieren:
c = 255/(max-min)
y = (x - min) * c

Damm brauchst du ein Bitmap mit passender Palette (256 Farben vermutlich graustufen).
Einfach gleiche Größe erzeugen und jeden Pixel konvertieren.

spooky

Thema: Problem beim Aufruf eines Callback im unmanaged c++
Am im Forum: Rund um die Programmierung

Hallo,

auf den ersten Blick würde ich folgendes anmerken:

  • Ein C++ long ist in C# ein int.
  • Verwende für den Typen void** IntPtr und nicht IntPtr[]. Verwende diesen Zeiger dann wie er in C++ gedacht war.

spooky

Thema: externes Programm mit Timeout starten
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

du kannst auch die WaitForExit-Überladung verwenden, die einen TimeOut annimmt (hast du vermutlich übersehen):

public static int StartProgram(string fileName, string arguments, int timeout)
{
    Process process = Process.Start(fileName, arguments);
    process.WaitForExit(timeout);
    process.Refresh();
    if (!process.HasExited)
    {
        process.Kill();
        return -1;
    }
    return process.ExitCode;
}

spooky

Thema: [gelöst] Tastenabfrage mit GetKeyboardState
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

im Beispiel-Code wurde eine importierte Win32 Funktion verwendet (diese steht oben auf der verlinkten Seite).

Erstelle folgende Klasse in deinem Projekt:

internal static class NativeMethods
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetKeyboardState(byte [] lpKeyState);
}

Ggf musst du noch auf Namespaces aufpassen.
Zu beachten ist, dass das zu übergebende Array 256 bytes groß sein muss; kannst du ggf nach durch eine Wrapperfunktion in der statischen Klasse sicherstellen.

spooky

Thema: Win7: Englische vs. deutsche Pfade für die Special Folders
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

um einen Ordner in C:\Users erstellen zu können brauchst der Prozess Administratorenrechte. Ohne diese bekommst du eine UnauthorizedAccessException.

spooky

Thema: Problem mit PerformanceCounter beim CPU-Last auslesen
Am im Forum: Rund um die Programmierung

Hi,

du kannst die CPU-Zeit nur berechnen indem du diese innerhalb einer Zeitspanne betrachtest, alle 1000ms über ein Event zB. Dabei brauchst du "PercentProcessorTime" und "TimeStamp_Sys100NS", wobei die Formel
(cpu2-cpu1)/(time2-time1) ist.

In dem Beispiel wird das noch mit 100 multipliziert. Das Ganze muss man, so vermute ich, noch durch die Anzahl der CPU-Kerne dividieren (Environment.ProcessorCount); zumindest waren die Werte dann plausibel.

spooky

Thema: Problem mit PerformanceCounter beim CPU-Last auslesen
Am im Forum: Rund um die Programmierung

Hallo ddr2,

ich habe für ein Projekt zum Messen von CPU Zeit die Win32-Klasse Win32_PerfFormattedData_PerfProc_Process verwendet.
Dort kannst du die Process-IDs und auch den Parent-Prozess auslesen, jedoch musst du die CPU-Zeiten wohl manuell berechnen.

Für die Verwendung musst du einen Verweis auf System.Management hinzufügen.

            ManagementObjectSearcher searcher = new ManagementObjectSearcher(
                @"Select Name, PercentProcessorTime, IDProcess, CreatingProcessID from Win32_PerfRawData_PerfProc_Process");

            foreach (var obj in searcher.Get())
            {
                Console.WriteLine("{0} {1} {2} {3}", obj["Name"], obj["PercentProcessorTime"], obj["IDProcess"], obj["CreatingProcessID"]);
            }   


Vielleicht hilft dir das weiter.

Grüße,
spooky

Thema: Problem beim DllImport einer unmanaged DLL: Attempted to read or write protected memory
Am im Forum: Rund um die Programmierung

Hallo,

des Weiteren string verwenden anstatt StringBuilder und CharSet von Auto auf Ansi.

spooky

Thema: DLLImport und in einem Struct ein CharArray definieren und auslesen
Am im Forum: Rund um die Programmierung

Hallo,

ich würde die Struct so deklarieren:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct SenderType
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
        string name;
        short SenderId;
    }

Der Marshaller übernimmt das umwandeln in das inline Array und die Konvertierung von Unicode nach Ansi und du kannst trotzdem wie gewohnt einen string verwenden.

Nach der Änderung sollte es auch mit der Verwendung von ref klappen.

spooky

Thema: Speicher in struct kopieren mit unsafe code - wie gehts ?
Am im Forum: Rund um die Programmierung

Hi,

ab .Net 4 (glaube ich) verfügt der Typ IntPtr auch über den IntPtr +(IntPtr,int) Operator. Damit würde die Verwendung von .ToInt64() wegfallen.

spooky

Thema: Delphi 7 dll importieren: Aufruf von Methode aus DLL lässt Anwendung ohne Exception festhängen
Am im Forum: Rund um die Programmierung

Zitat von N1ls
Ich weiss auf jeden Fall, dass Du einmal den Stringbuilder für den Rückgabewert nutzen musst, einen einfachen String für den Übergabeparameter.

Das ist Unsinn. StringBuilder dient bei Plattformaufrufen als beschreibbarer Puffer. Diesen Methoden übergibt man den StringBuilder + dessen Kapazität.
Wenn du eine konstante Zeichenkette als Parameter übergibst oder als Rückgabewert bekommst kann dieser als string deklariert werden.

Beispiel:
int WINAPI GetWindowText(__in HWND hWnd, __out LPTSTR lpString, __in int MaxCount);
wird zu:

int GetWindowText(IntPtr hWnd, StringBuilder lpString, int MaxCount);

wohingegen
BOOL WINAPI SetWindowText(__in HWND hWnd, __in_opt LPCTSTR lpString);
zu

bool SetWindowText(IntPtr hWnd, string lpString);
wird.

Es kommt auf die Verwendung des Parameters an, welche man der Dokumentation entnehmen muss.

Der Artikel Marshalling zwischen verwaltetem und nicht verwaltetem Code geht auf das ganze Thema etwas detaillierter ein.

Thema: AForge MJPEGStream - Anwendung frisst mehr und mehr Speicher
Am im Forum: Grafik und Sound

Hallo,

ich habe den von dir verwendeten Code zur Konvertierung von Bitmap nach BitmapSource angeschaut. Dabei verwendest du den Zwischenschritt über ein hBitmap. Dieses hBitmap ist jedoch ein Handle, das nicht vom GC freigeben wird, siehe MSDN.

Dieses kleine Programm sollte das Problem und dessen Lösung erläutern:

using System;
using System.Drawing;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Bitmap bitmap = new Bitmap(@"c:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg");
            int i = 0;
            while (true)
            {
                IntPtr hBitmap = bitmap.GetHbitmap();
                var options = System.Windows.Media.Imaging.BitmapSizeOptions.FromWidthAndHeight(bitmap.Width, bitmap.Height);
                BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, new Int32Rect(0, 0, bitmap.Width, bitmap.Height), options);
                //DeleteObject(hBitmap);
                if (++i == 10)
                {
                    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
                    GC.WaitForPendingFinalizers();
                    Console.WriteLine("Memory used: {0}", Environment.WorkingSet);
                    i = 0;
                }
            }
        }

        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);
    }
}

Durch das Freigeben des Handles wird das Memoryleak geschlossen.

spooky

Thema: TAPI DLL in Projekt einbinden geht nicht
Am im Forum: Rund um die Programmierung

Hallo,

nachdem du den Verweis auf die COM dll hinzugefügt hast, musst du die Eigenschaften dieses öffnen und dort das Einbetten deaktivieren.

spooky

Thema: kopieren bzw initialisieren von Bitmaps ändert Bittiefe
Am im Forum: Grafik und Sound

Hallo,

ich habe mal die Methode Clone wie von MrSparkle genannt versucht, und diese funktionierte bei mir ohne Probleme (8bppindexed).


public static Bitmap Clone(Bitmap bitmap)
{
    if (bitmap == null)
        throw new ArgumentNullException("bitmap");
    Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    return bitmap.Clone(rect, bitmap.PixelFormat);
}

Sollte diese trotzdem nicht funktionieren, kannst du die Daten auch manuell klonen:


public static Bitmap Clone2(Bitmap bitmap)
{
    if (bitmap == null)
        throw new ArgumentNullException("bitmap");

    Bitmap clone;
    Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);
    try
    {
        clone = new Bitmap(bmpData.Width, bmpData.Height, bmpData.Stride, bmpData.PixelFormat, bmpData.Scan0);
    }
    finally
    {
        bitmap.UnlockBits(bmpData);
    }
    clone.Palette = bitmap.Palette;
    return clone;
}

Ich hoffe das hilft dir weiter zum Thema klonen.

Warum das manuelle Kopieren von dir nicht funktioniert liegt am Layout der Farbstruct. Diese ist nicht ARGB sondern BGRA (siehe RGBQUAD):

typedef struct tagRGBQUAD { 
  BYTE rgbBlue;
  BYTE rgbGreen;
  BYTE rgbRed;
  BYTE rgbReserved;
} RGBQUAD;

Grüße

spooky

Thema: Lockfreie threadsichere Queue
Am im Forum: .NET-Komponenten und C#-Snippets

Hallo,

man sollte Dequeue noch so erweitern, dass vor dem Verlassen der Methode das zurückgegebene Element aus der Datenstruktur entfernt wird:


    ...
    item = current.next.item;
    current.next.item = default(T);
    return true;
}

Bei Dequeue wird die Verkettete Liste um eine Element verschoben (effektiv: last wird zu last.next). Dabei wird diese Node zum neuen "Anker" der Liste und wird NICHT vom GC abgeräumt - auch nicht das darin enthaltene Element.

Grüße

spooky

Thema: Kombination von optionalen Parametern und params ...[] unmöglich?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

der optionale Parameter ist nur dann optional, wenn du weder ihn, noch Parameter rechts von ihm angibst. Da du den Paramter "Zusaetzliches" angibst, musst du auch "JaNein" angeben (in vb kann man glaube ich, auch optionale Parameter in der Mitte weglassen).
Was funktionieren würde, wäre gar keinen Parameter anzugeben.

spooky

Thema: Compiler bevorzugt generische Methodenvariante --> Compilerfehler
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

etwas zu deiner Klasse selbst ...

public static class EqualsExtensions
{
	public static bool EqualsOneOf(this object first, params object[] others)
	{
		return others.Any(o => Object.Equals(first, o));
	}

	public static bool EqualsOneOf<T>(this IEquatable<T> first, params T[] others)
	{
		if (Object.ReferenceEquals(first, null))
			return others.Any(o => Object.ReferenceEquals(o, null));

		return others.Any(o => first.Equals(o));
	}
}

Wäre diese Implementierung nicht "korrekter"? Die Methode soll schauen ob "first" zu einem der folgenden Objekte equivalent ist. Dies bedeut aber streng genommen nicht, dass diese auch IEquatable<T> implementieren, sondern nur vom Typen T sein müssen.

Spooky

Thema: C++ DLL für C# erstellen (DllImport)
Am im Forum: Rund um die Programmierung

Hallo,

ich hab das Projekt mal umgebaut. Die .dll muss nurnoch ins Ausgabe-Verzeichnis des .NET Projektes kopiert werden.

Spooky

PS: StringBuilder braucht man wenn man einen Buffer _übergibt_ in den geschrieben werden soll. Diese Funktionen haben dann meistens noch einen Parameter, der die Bufferlänge angibt zb:
void FillMe(char * buffer, int length, ...);
->
void FillMe(StringBuilder b, int length, ...);

Wenn es um fixe Strings geht braucht man keinen StringBuilder anlegen.

edit:
Der .NET Typ DateTime und der C++ Typ time_t sind wohl doch nicht kompatibel, daher musst du wohl einen kompatiblen Typen suchen oder Hilfsmethoden implementieren.

Thema: C++ DLL für C# erstellen (DllImport)
Am im Forum: Rund um die Programmierung

DateTime ist intern ein .NET long. Der C++ Typ time_t (time.h), der intern ebenfalls ein 64bit Integer ist könnte dafür ggf verwerdendet werden. Time Beispiel

Wie zommi schon gesagt hat, ist char * der Typ den du verwenden solltest. Ggf kannst du auch wchar_t * (Unicode) nehmen:


#include <time.h>
LPCWSTR __stdcall Generate(LPCWSTR s1, LPCWSTR s2, LPCWSTR s3, int number, time_t time);

Thema: C++ DLL für C# erstellen (DllImport)
Am im Forum: Rund um die Programmierung

Hallo JunkyXL,

am besten gehst du so vor:

Neues Projekt anlegen (Visual C++ -> Win32-Projekt) mit Anwendungstyp "Dll". Andere Optionen lassen, wie sie sind.

In der erzeugten .cpp Datei kannst du nun zB eine Funktion so deklarieren:


// Gehört eigentlich in die .h Datei
extern "C"
{
	BOOL __declspec(dllexport) __stdcall CheckKey(const unsigned char *key);
}

BOOL __stdcall InternalHelper(const unsigned char *key);
// Ende .h Datei

// Kann von aussen aufgerufen
BOOL __stdcall CheckKey(const unsigned char *key) {
	return InternalHelper(key);
}

// Nur intern verwendbar
BOOL __stdcall InternalHelper(const unsigned char *key) {
	return FALSE;
}

Dabei ist zu beachten, dass Funktionen die mit __declspec(dllexport) deklariert sind, nach aussen exportiert werden (d.h. Hilfsmethoden ohne dieses Tag können auch von aussen nicht aufgerufen werden).

Spooky

Thema: Struct von C++ nach C#
Am im Forum: Rund um die Programmierung

IntPtr strData = new IntPtr(plstr.ToInt32() + 4);

sollte noch in

IntPtr strData = new IntPtr(unchecked(plstr.ToInt64() + 4));

geändert werden um auch unter 64bit zu funktionieren. Ggf könnte man die Offset Operation noch in eine sperate Methode mit Over-/Underflow Check auslagern.

Spooky

Thema: Gibts es vorgefertigte Reference-Wrapperklassen für Wertetypen ?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Ein etwas aufgemotzerer Ansatz ...

public class Reference<T> where T : struct
{
	[DebuggerBrowsable(DebuggerBrowsableState.Never)]
	protected T value;

	public Reference()
	{

	}

	public Reference(T value)
	{
		this.value = value;
	}

	public static implicit operator T(Reference<T> value)
	{
		return value.value;
	}

	public static implicit operator Reference<T>(T value)
	{
		return new Reference<T>(value);
	}

	public T Value
	{
		get { return value; }
		set { this.value = value; }
	}

	public override string ToString()
	{
		return value.ToString();
	}

	public override int GetHashCode()
	{
		return value.GetHashCode();
	}

	public override bool Equals(object obj)
	{
		return (obj is Reference<T>) && value.Equals(((Reference<T>)obj).value);
	}
}

Thema: Gibts es vorgefertigte Reference-Wrapperklassen für Wertetypen ?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

deine Wrapper-Klasse ist genau richtig um aus einem Werttypen einen Referenztypen zu machen.
Nullable<T> macht aus einem Werttypen einen null-baren Typen, aber keinen Referenztyp.

Spooky

Thema: Struct von C++ nach C#
Am im Forum: Rund um die Programmierung

Hallo,

auch den Datentyp long solltest du genauer anschauen, da dieser normalerweile 4 byte groß ist, welches ein int in .NET wäre.

Spooky