-
Gesamte Inhalte
1167 -
Benutzer seit
-
Letzter Besuch
Inhaltstyp
Profile
Forum
Downloads
Kalender
Blogs
Shop
Alle Inhalte von Gateway_man
-
[Cpp] Speicherüberlauf (Vermutlich irgendwelche leaks)
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Jup wird geändert. Das ist ne Leiche aus einer hier nicht aufgeführt Funktion. Hab ich jetzt mal rauskommentiert. Irgendwie hatte ich das Gefühl das der Desktruktor nicht aufgerufen wurde. Also hab ich Release() geschrieben und für den Fall das er doch in den Desktruktor gehen sollte, sollte er nicht versuchen doppelt das delete auszuführen deswegen der boolean. Weil das teilweise enorm großen Bitmaps sein können und ich eigentlich immer der Meinung war das große Objekte nichts auf dem Stack zu suchen haben. Danke ich dachte ich versuchs mal und da der Debugger das nicht als Syntaxfehler angekreidet hat, dachte ich er hats gefressen. @all: Seid ihr euch sicher das hier: Der Leak stattfindet? Ihr dürft die Zusammenhänge nicht vergessen. In der Resize Funktion wird ein neues Bitmap auf dem Heap generiert (newBitmap). Dann hol ich mir den Pointer der auf die Bitmapdaten zeigt newBitmap->GetHBITMAP(NULL,&result); Ich kann innerhalb dieser Funktion unmöglich das Bitmap löschen da sonst C# die Bitmapdaten nicht abgreifen kann. Jetzt sieht es ja so aus das C# die Bitmapdaten mithilfe des Pointers in ein neues Image Objekt kopiert. Image ImgCache = Image.FromHbitmap(ptr); Dannach wird mit hilfe der Funktion ReleaseHBitmap der Pointer an meine Cpp Funktion "ReleaseHBitmap" übergeben um dort das Bitmap zu löschen. ScreenCaptureExt.ReleaseHBitmap(ptr) Dort wird dann das Bitmap zerstört: _extern bool ReleaseHBitmap(HBITMAP hbitmap){ return DeleteObject(hbitmap ); } -
[Cpp] Speicherüberlauf (Vermutlich irgendwelche leaks)
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Hi, ich muss das Thema leider noch mal in den Fokus rücken. Das Problem mit den obigen Funktionen ist behoben. Zwar schauckelt er sich teilweise recht hoch mit der Speichernutzung, jedoch gibt er es brav wieder frei. Jetzt habe ich ein paar Testläufe Ãn Cpp gestartet unter Verwendung von GDI. Hier besteht leider wieder das Problem und es ist nicht mit der vorherigen Lösung behoben. Ich erhalte wieder in C# eine Out of Memory Exception und ich vermute stark das es an der Cpp Implementierung liegt. GdiCore.h #include <Windows.h> #include <GdiPlus.h> #pragma once using namespace Gdiplus; using namespace std; class GdiCore { private: Bitmap* bmp; GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; HPALETTE* palette; bool hDeleted; public: ~GdiCore(void); GdiCore(HBITMAP input); //diverse andere Grafikfunktionen //... //diverse andere Grafikfunktionen HBITMAP Resize(int width, int height); void Release(); }; GdiCore.cpp: #include "StdAfx.h" #include "GdiCore.h" GdiCore::GdiCore(HBITMAP input) { GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); palette = new HPALETTE(); bmp = new Bitmap(input,*palette); } GdiCore::~GdiCore(void) { if (!hDeleted ) Release(); } HBITMAP GdiCore::Resize(int width, int height){ HBITMAP result = NULL; UINT o_height = bmp->GetHeight(); UINT o_width = bmp->GetWidth(); int n_width = width; int n_height = height; double ratio = ((double)o_width) / ((double)o_height); if (o_width > o_height) { n_height = static_cast<int>(((double)n_width) / ratio); } else { n_width = static_cast<int>(n_height * ratio); } Bitmap* newBitmap = new Bitmap(n_width, n_height, bmp->GetPixelFormat()); Graphics graphics(newBitmap); graphics.DrawImage(bmp, 0, 0, n_width, n_height); newBitmap->GetHBITMAP(NULL,&result); return result; } void GdiCore::Release(){ if (!hDeleted ){ //DeleteObject(bmp); delete palette,bmp; GdiplusShutdown(gdiplusToken); hDeleted = true; } } Die Funktion die ich aus C# Aufrufe ist wie folgt definiert: _extern HBITMAP ResizeImageExt(HBITMAP bmp, int width, int height){ HBITMAP result = NULL; GdiCore* core = new GdiCore(bmp); result = core->Resize(width,height); core->Release(); delete core; return result; } Hier ist der C# Sharp Aufruf: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Drawing; namespace Utility.Interop.dGDI { public sealed class ImageUtilExt { #region pInvoke [DllImport("dGDI.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ResizeImageExt(IntPtr bmp, int width, int height); #endregion #region Static Functions public static Image ResizeImage(Bitmap input, int width, int height) { Image result = null; if (input == null) return null; IntPtr src = IntPtr.Zero; try { src = input.GetHbitmap(); } catch { return (Image)input; } IntPtr ptr = ResizeImageExt(src, width, height); if (ptr != IntPtr.Zero) { Image ImgCache = Image.FromHbitmap(ptr); result = (Image)(ImgCache.Clone()); bool bRelease = ScreenCaptureExt.ReleaseHBitmap(ptr); System.Diagnostics.Trace.WriteLine(bRelease.ToString()); ImgCache.Dispose(); ImgCache = null; } return result; } #endregion } } Hat jemand von euch eine Vermutung woran es liegen könnte? lg Gateway -
[Cpp] GdiPlus Erfahrungen
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Ja da hast du recht . Ich hatte die clr im neuen Projekt. Nachdem ich jetzt den clr support wieder rausgenommen habe hab ich wieder die 204 Fehler bekommen. Kurz bevor ich aufgeben wollte, hab ich gemerkt das die ATL Header nicht mit im Projekt einbezogen wurden. Nachdem ich das geändert hatte lies es sich kompilieren . lg Gateway -
[Cpp] GdiPlus Erfahrungen
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Das liegt daran das ich es bereits probiert habe. Selbige Fehleranzahl und auch Fehler. Was ich jetzt aber zusätzlich probiert habe ist folgendes. Ich hatte ja die Vermutung das es bezüglich dem Win7 Sdk Probleme gibt. Also hab ich einen neuen Versuch auf ner VM von mir gestartet. Auf der VM sind die Bedingung bis auf das Win7 Sdk identisch. Dort erhalte ich nur folgende fünf Fehler: Es hat sich nichts am Code geändert außer dem Klassennamen. Wenn ich jetzt nochmal die Funktionen in die Klasse reinpacke verändern sich die Fehler. So sieht das Headerfile (in der VM) jetzt aus: #include <Windows.h> #include <GdiPlus.h> #include <string> #pragma once ref class gditest { public: gditest(void); ULONG_PTR(m_gdiplusToken); GdiplusStartupInput gdiplusstartupinput; GdiplusStartup(&m_gdiplusToken, &gdiplusstartupinput, NULL); }; Die Fehler sehen jetzt wie folgt aus: Kann es sein das die GDI header ursprünglich für C ausgelegt wurden und manche C Typen nicht mit Cpp kompatibel sind? lg Gateway -
[Cpp] GdiPlus Erfahrungen
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Nein nicht in meinem Projekt. Ich hab ein neues Testprojekt erstellt. Das ist die DevGDI.h Datei: #include<Windows.h> #include <GdiPlus.h> #include <string> #pragma once class DevGDI { public: DevGDI(void); ~DevGDI(void); }; Das ist die DevGDI.cpp Datei: #include "StdAfx.h" #include "DevGDI.h" DevGDI::DevGDI(void) { } DevGDI::~DevGDI(void) { } Das ist alles was bisher definiert wurde. hm bisher tappe ich immer noch im dunkeln . lg Gateway -
[Cpp] GdiPlus Erfahrungen
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Hi, sry :upps. Wie sollt ihr mir helfen können wenn ich die Fehler nicht poste. Wobei das mit der Kristallkugel wäre bestimmt auch interessant geworden . Ich kopiere mal die Liste. Bei nähere Betrachtung habe ich selbst schon ein paar Theorien aufgestellt. Beispielsweise: Kann es sein das das installierte Win7 Sdk über eigene Gdi Header verfügt er jetzt zwei mal die Gdi header eingebunden werden?! lg Gateway -
[Cpp] GdiPlus Erfahrungen
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Hi, Beispiel das ich meinte. Zum anderen hab ich das bereits probiert. Es ändert sich nichts. Es sind immernoch 204 Fehler. #include<Windows.h> #include <GdiPlus.h> lg Gateway -
Hallo leute, ich wollte mich mal etwas vertrauter machen mit den Gdi Klassen die Systemseitig schon bereitgestellt werden. Aus diesem Grunde hab ich mir mal ein paar beispiele reingezogen. Überall wird für den Einstieg lediglich der Header GdiPlus importiert. Aber immer wenn ich das File Include kassiere ich 200 Fehler wegen falschen Klammer und sonstigen Syntaktischen schmarn. Ich versteh das jetzt nicht wirklich. Ich hab noch nichtmal was anderes getippt. #include <GdiPlus.h> #pragma once class GdiTest { public: GdiTest(void); ~GdiTest(void); }; Schon hagelt es 204 Fehler. Zu den Projekteinstellungen. Ich verwende weder Atl noch MFC und auch nicht die Clr. Weiß jemand warum das so ist. Fehlen vielleicht noch ein paar Includes vor GdiPlus? Aber wenn ja warum soll es dann in den Tutorials angeblich funktionieren. lg Gateway
-
[Cpp] Speicherüberlauf (Vermutlich irgendwelche leaks)
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Genau das mach ich momentan Deswegen funktionierts jetzt ja auch . So sieht ein beispielaufruf in C# aus. Image result = null; IntPtr ptr = GetDesktopImageExt(biPlanes, biBitCount, (int)compression, biSizeImage, biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant); if (ptr != IntPtr.Zero) { result = (Image)Image.FromHbitmap(ptr).Clone(); ReleaseHBitmap(ptr); if (includeCursor) result = Utility.ImageUtil.CaptureScreen.IncludeCurrentCursor(result); } return result; Lg und Danke Gateway -
[Cpp] Speicherüberlauf (Vermutlich irgendwelche leaks)
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Sry ich meinte den Stack Frame der Funktion die ich aufrufe . Die Bitmap daten befinden sich auf dem Heap das ist schon klar. Bist du dir da sicher? Ich hab nämlich doch einen AccessViolation Exception erhalten. Nur wird die in System.Drawing gehandelt. Steht also lediglich im Output fenster. Das habe ich bereits versucht. Jedoch habe ich dann eine Null Reference Exception seitens .NET bekommen. Ist ja auch irgendwo klar. Wenn ich innerhalb der Cpp Funktion das Bitmap erstelle um es am Ende der Funktion wieder freizugeben und das .NET dann versuch mit dem Pointer die Bitmap daten abzugreifen muss es ja unweigerlich krachen. lg Gateway -
[Cpp] Speicherüberlauf (Vermutlich irgendwelche leaks)
Gateway_man antwortete auf Gateway_man's Thema in C++: Compiler, IDEs, APIs
Hi, hat sich erledigt. Es verhält sich so wie ich es mir dachte. Ich hätte es doch testen sollen bevor ich den Thread verfasste. Aber trotzdem sehr lehrreich. Es sieht wie folgt aus: Das Bitmap wird innerhalb des Stack Frames der Cpp Funktion erstellt. Dieser Stack Frame befindet sich natürlich innerhalb des Stack Frames der Cpp Library. Das .NET greift den Pointer ab. Mit der .NET Funktion Image.FromHBitmap wird die Struktur Image gefüllt mit den referenzierten Daten die immernoch innerhalb des Stack Frames der Cpp Funktion liegen. Wenn ich ein nun im .NET ein Dispose() auf das Image Objekt absetzte passiert nichts, da das Framework keine Zugriffsberechtigung auf den Speicherbereich meiner Cpp Library hat. Jetzt habe ich der Cpp Library noch eine Funktion spendiert die ein HBITMAP als parameter verlangt. Innerhalb dieser Funktion mach ich nun ein DeleteObject(BitmapPointer). Diese Funktion pInvoke ich im .Net nachdem ich das Image geklont habe. Und siehe da keine Problem mehr ...... lg Gateway -
Hi leute, da mir der Winapi Wrapper im .NET an sich zu langsam war beziehungsweise ich an die performance grenzen vom .NET gestoßen bin, habe ich mich entschieden das ganze innerhalb einer Cpp dll abzuwickeln und im .NET mit dem Result zu arbeiten. Das heißt der "Screenshot" sowie diverse algorithmen zum verkleinern und konvertieren wurden in die Cpp dll ausgelagert. Die C# dll ruft dann die entsprechende Funktion auf und bekommt einen Pointer (HBITMAP) zurück der auf das Bild zeigt. Den erhaltenen Performanceschub will ich nichtmehr missen (pure .NET 20 fps / Cpp 30 fps). Allerdings bringt mir das kein Stück wenn ich nach 10 Sekunden im .NET ne Out of Memory Fehlermeldung erhalte. Jetzt bin ich mir aber nicht so ganz sicher woran das liegt. Da das Image innerhalb des StackFrames meiner cpp dll generiert wird, vermute ich das das .NET dieses Objekt nicht freigeben kann. Aber wenn das stimmen würde, hätte ich ja längt eine MemoryViolation Exception erhalten. Was denkt ihr woran das liegen kann? Hier mal eine simple Funktion zum generieren eines normalen Bitmaps (auch hier tritt der fehler auf) in der cpp dll. _extern HBITMAP GetDesktopImageExt(){ HWND capture = GetDesktopWindow(); if(!IsWindow(capture)) return NULL; RECT rect; GetWindowRect(capture, &rect); size_t dx = rect.right - rect.left; size_t dy = rect.bottom - rect.top; BITMAPINFO info; info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); info.bmiHeader.biWidth = dx; info.bmiHeader.biHeight = dy; info.bmiHeader.biPlanes = 1; info.bmiHeader.biBitCount = 24; info.bmiHeader.biCompression = BI_RGB; info.bmiHeader.biSizeImage = 0; info.bmiHeader.biXPelsPerMeter = 0; info.bmiHeader.biYPelsPerMeter = 0; info.bmiHeader.biClrUsed = 0; info.bmiHeader.biClrImportant = 0; HBITMAP bitmap = 0; BYTE* memory = 0; HDC device = GetDC(capture); bitmap = CreateDIBSection(device, &info, DIB_RGB_COLORS, (void**)&memory, 0, 0); ReleaseDC(capture, device); if(!bitmap || !memory) return NULL; HDC winDC = GetWindowDC(capture); HDC memDC = CreateCompatibleDC(winDC); SelectObject(memDC, bitmap); //HGDIOBJ obj = SelectObject(memDC, bitmap); BitBlt(memDC, 0, 0, dx, dy, winDC, 0, 0, SRCCOPY); //DeleteObject(obj); DeleteDC(memDC); ReleaseDC(capture, winDC); return bitmap ; } Möglicherweise hab ich auch einfach ein Release/Delete vergessen... Ich steh grad ein wenig auf dem Schlauch. Ich hatte mir kurzeitig üblegt ob ich eine externe Funktion definiere, welcher ich den Pointer übergebe und das HBITMAP wieder innerhalb der Cpp dll release. Ach keine Ahnung irgendwie ist grad alles leer im oberstübchen... lg Gateway
-
[C#] Probleme mit Pinvoke (Stabel ist gstört..)
Gateway_man antwortete auf Gateway_man's Thema in .NET
Hi, super danke dir. Der Aufruf liefert keinen Fehler mehr zurück. Jetzt hab ich nurnoch das Problem das das HBITMAP falsch ist. Aber gut das ist vermutlich ein Fehler in der cpp lib. lg Gateway -
Hi, ich verzweifle grade an einem Pinvoke und hab schon diverse Dinge ausprobiert. Aktuell sieht das so aus. Funktion aus der dll die Invoked werden soll: extern "C" __declspec(dllexport) HBITMAP GetSubRect(int x, int y, int witdh, int height) { //ein paar Dinge... } Das ist der letzte stand der C# Signatur. Die auch Fehlschlägt... private static extern IntPtr GetSubRect([MarshalAs(UnmanagedType.I4)] int x, [MarshalAs(UnmanagedType.I4)] int y, [MarshalAs(UnmanagedType.I4)] int witdh, [MarshalAs(UnmanagedType.I4)] int height); Der Fehler der beim Aufruf auftritt sieht wie folgt aus: Leider mach ich das verhältnismäßig selten und kenne mich daher nicht so gut aus. Sieht einer von euch den Fehler? lg Gateway
-
[C#] Starten einer Benutzersession unter Windows Server 2K8
Gateway_man antwortete auf Gateway_man's Thema in .NET
Ich will da jetzt nicht zu sehr ins Detail gehen da es zu lange dauern würde. Es ist Verwaltungsprogramm. Nein weil das Programm zusätzlich über Serverfunktionalitäten verfügt. Das heißt Client XY verbindet sich mit der Anwendung und holt/sendet Informationen. Letztendlich könnte man jetzt sagen, warum hast du das ganze nicht strikter getrennt und die Server Funktionen in ein eigenes Projekt ausgelagert. Ich kann nur eines sagen.Im Nachhinein ist man immer schlauer . Zumal ist diese Komponente extrem klein und ich hatte ehrlich gesagt keine Lust extra für die zwei Klassen noch ein ein neues Projekt anzulegen das ich dann immer weiter mitpflegen muss. Ich wusste jetzt nicht wie ich es nennen sollte. Ich meine vergleichbare Funktionalitäten wie rdp. Das heißt ein Modul des Programm ermöglicht mir Remote Eingaben und überträgt mir den Bildschirm. Ich wollte eigentlich das gleiche Verhalten wie bei Remote Desktop. Das heißt: Du gibts die Daten ein und verbindest dich. Dann öffnet sich ein Dialog in dem der User den Windows Benutzer sowie das Passwort einträgt. Dann wird auf der Remote Maschine eine Session gestartet und du siehst/steuerst dann die Session. Ich weiß. Remote Desktop läuft als Service. Jedoch ist diese Funktionalität nur ein bruchteil des Programmes und wie schon gesagt. Das umschreiben würde mich mind. zwei Wochen kosten. Diese Zeit habe ich nicht. Deswegen habe ich gefragt ob jemand eine Funktion im .NET Framework kennt die mir das ermöglicht. Letztendlich ist es doch eine Win32 Funktion gewesen und das Problem ist so gelöst wie es mir am besten gefällt . Jetzt wird geprüft ob der Rechner gesperrt oder abgemeldet ist. Ist das der Fall, sendet das Servermodul dem Clientmodul eine Authentifizierungsanfrage. Der User tippt das brav ein, überträgt das dem Servermodul und das Servermodul setzt ein Logonuser ab und prüft das handle das es bekommt. Wenn es gültig ist, war die Anmeldung erfolgreich und schon kanns weitergehn. Um die Sicherheit muss ich mir kein Kopf machen da die komplette Kommunikation mit einer Symmetrischen 128 bit Verschlüsselung gesichert wurde. lg Gateway -
[C#] Starten einer Benutzersession unter Windows Server 2K8
Gateway_man antwortete auf Gateway_man's Thema in .NET
So ich hab gefunden wonach ich gesucht habe. advapi32.logonuser Die WinApi ist in der Tat ein Geschenk des Himmels . lg Gateway -
[C#] Starten einer Benutzersession unter Windows Server 2K8
Gateway_man antwortete auf Gateway_man's Thema in .NET
Dann geh ich mal genauer drauf ein. Ich habe eine Anwendung. Diese Anwendung wird immer unter dem selben Benutzer ausgeführt. Nehmen wir mal an es läuft auf meinem Rechner. Es kommt hin und wieder vor das ich unterwegs bin und den Rechner aus diesen gründen Sperre. Nun möchte ich von unterwegs kurz mit der Instanz des Programmes auf meinem Rechner arbeiten. Aus diesem Grund verfügt das Programm über Rdp Funktionalitäten. Was ich machen will ist folgendes. Ich verbinde mich per Client mit meiner Anwendung die auf meinem Rechner läuft. Diese soll prüfen ob der Rechner gesperrt ist. Wenn das der Fall ist soll diese den Rechner entsperren bevor die rdp session initialisiert wird. Ich weigere mich zu glauben das nur ein Service in der Lage ist einen Userlogin zu starten. Irgendwo in den untiefen der Windows Api gibt es sicherlich eine Funktion die ich dazu invoken kann. Ich könnte mich sogar vorstellen das das .Net Framework schon Funktionen dafür bereitstellt. Es soll natürlich auch funktionieren wenn der User abgemeldet ist. Ich hab das schon getestet. Wenn ich abgemeldet bin läuft die Anwendung im Hintergrund weiter. (Sie ist über Netzwerk erreichbar). Lg Gateway -
[C#] Starten einer Benutzersession unter Windows Server 2K8
Gateway_man antwortete auf Gateway_man's Thema in .NET
Ich habe nicht gesagt, das das Programm ohne Interaktion auskommt. Es soll per direkter Interaktion sowie Remote Steuerbar sein. Aus diesem Grunde verfügt das Programm über Remote Desktop funktionalitäten. Nun muss ich jetzt nurnoch das obige Problem lösen. lg Gateway -
[C#] Starten einer Benutzersession unter Windows Server 2K8
Gateway_man antwortete auf Gateway_man's Thema in .NET
Meinst du Windows Service? Wenn ja, das ist kein Service Projekt. Und es umzuschreiben ist keine Option, da es schon sehr umfangreich ist. Zumal ist die GUI unabdinglich und soweit ich weiß haben Windows Services keine Oberfläche. Es zu ändern würde mich zwei Wochen kosten die ich nicht investieren kann und auch nicht möchte. lg Gateway -
Hi leute, weiß einer von euch wie man einer Benutzer Session über code startet. Das programm bekommt quasi die Windows benutzerdaten während kein Windows user angemeldet ist. Jetzt soll das Programm den erhaltenen Benutzer anmelden. Ich hab schonmal gesucht und fand nur "skurile" Registry Lösungen. Gibts da keine native WinApi Funktion oder möglicherweise sogar eine managed .NET Funktion? Lg Gateway
-
[C#] Handles aller verfügbaren Screens ermitteln
Gateway_man antwortete auf Gateway_man's Thema in .NET
hat sich erledigt danke. -
[C#] Handles aller verfügbaren Screens ermitteln
Gateway_man antwortete auf Gateway_man's Thema in .NET
Ah okay. Kennst du zufällig eine ApiFunktion mit der ich den kompletten Bildschirmbereich für das bild erfassen kann? Ich kann ja dannach mit BitBlt den entsprechend relevanten Bereich herauskopieren. Alternativvorschläge sind auch erwünsch . Wichtig für mich ist, das das ganze über pInvoke geschieht. lg Gateway -
Hi leute, gleich noch ein zweites Problem. Ich möchte Screenshots über die WinApi machen. Beim dem Primary Screen ist das kein Problem. Für diesen hol ich mir das Handle über GetDesktopWindow aus der User32.dll. Das klappt auch wunderbar. Allerdings möchte ich auch weitere Screens supporten. Ich bin dann auf EnumDisplayMonitors gestoßen. Die Funktion liefert mir im Grunde schon alle Screens zurück, jedoch ist das Handle Invalid. Ich hab das Handle meines Hauptbildschirmes das ich mit EnumDisplayMonitors mit dem Handle verglichen, das ich mit GetDesktopWindow bekomme. Sie sind unterschiedlich (aber kein Zero). Und wenn ich dann natürlich ein Screenshot machen möchte sagt mir GetLastError das das Handle Invalid ist. Das ist die Klasse die mir die Informationen über alle MonitorDevices geben soll: public sealed class MonitorIdentifier { #region Fields private int counter = 0; private int maxDevices = System.Windows.Forms.Screen.AllScreens.Count(); private CloneableList<ScreenDevice> availableScreens = null; private AsyncStateChanged asyncResult = null; USER32.MonitorEnumDelegate med; #endregion public MonitorIdentifier() { med = new USER32.MonitorEnumDelegate(EnumDisplayMonitorsCallBack); } public MonitorIdentifier(AsyncStateChanged result) { med = new USER32.MonitorEnumDelegate(EnumDisplayMonitorsCallBack); asyncResult = result; if (asyncResult == null) throw new InvalidOperationException("AsyncResult can't be null!"); } #region Public Functions public bool BeginEnumMonitors() { if (AsyncResult == null) throw new InvalidOperationException("AsyncResult can't be null!"); else return USER32.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, med, IntPtr.Zero); } #endregion #region Properties public AsyncStateChanged AsyncResult { get { return asyncResult; } set { asyncResult = value; } } #endregion #region Private Functions private bool EnumDisplayMonitorsCallBack(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeStructures.RECT lprcMonitor, IntPtr dwData){ counter++; IntPtr ptr = Utillity.WinApi.USER32.GetDesktopWindow(); NativeStructures.MonitorInfo mi = new NativeStructures.MonitorInfo(); mi.size = (uint)Marshal.SizeOf(mi); bool success = USER32.GetMonitorInfo(hMonitor, ref mi); if (availableScreens == null) { availableScreens = new CloneableList<ScreenDevice>(); } if (success) { ScreenDevice dev = new ScreenDevice(); dev.mInfo = mi; dev.hMonitor = hMonitor; dev.dwData = dwData; dev.hdcMonitor = hdcMonitor; availableScreens.Add(dev); } if (counter == maxDevices) { asyncResult.Invoke(this, new object[] { availableScreens.Clone() }); counter = 0; availableScreens.Clear(); availableScreens = null; } return success; } #endregion } Das ist die ScreenDevice Structure: public struct ScreenDevice { #region Fields public Utillity.NativeStructures.MonitorInfo mInfo; public IntPtr hMonitor; public IntPtr hdcMonitor; public NativeStructures.RECT Rect; public IntPtr dwData; #endregion }; Das ist die MonitorInfo Structure: [StructLayout(LayoutKind.Sequential)] public struct MonitorInfo { public uint size; public RECT monitor; public RECT work; public uint flags; }; Die User32 Signaturen sehen bei mir so aus: [DllImport("user32.dll")] public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData); [DllImport("user32.dll")] public static extern bool GetMonitorInfo(IntPtr hmon, ref NativeStructures.MonitorInfo mi); Definition des MonitorEnumDelegate: public delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeStructures.RECT lprcMonitor, IntPtr dwData); Das AsyncStateChanged Delegate ist eigentlich nicht relevant aber falls es jemand wissen möchte wie es definiert wurde: public delegate void AsyncStateChanged(object sender, object[] data); Ein Beispielaufruf sieht so aus: public partial class Form1 : Form { private ScreenDevice dev = new ScreenDevice(); private Utillity.Templates.CloneableList<Utillity.Devices.ScreenDevice> screens = null; private Utillity.Devices.MonitorIdentifier monitoridentifier = null; public Form1() { InitializeComponent(); monitoridentifier = new Utillity.Devices.MonitorIdentifier(new Utillity.AsyncStateChanged(AsyncFinished)); monitoridentifier.BeginEnumMonitors(); } private void AsyncFinished(object sender, object[] data) { if (data != null) { screens = (Utillity.Templates.CloneableList<Utillity.Devices.ScreenDevice>)data[0]; //dev = screens.Where(P => P.mInfo.monitor.Left > 0).ToList()[0]; dev = screens[1]; } private void CaptureScreen() { Bitmap bmp; if (dev.hMonitor != IntPtr.Zero) bmp = (Bitmap)Utillity.ImageUtil.CaptureScreen.CaptureWindow(dev.hMonitor); else bmp = Utillity.ImageUtil.CaptureScreen.GetDesktopImage(); if (bmp != null) { pictureBox1.Image = bmp; } } } Um das Wertetechnisch hier mal zu erfassen. Laut GetDesktopWindow hat mein Primärer Desktop das handle 65552. Laut EnumDisplayMonitors hat mein Primärer Desktop das handle 65537. Das handle das ich über GetDesktopWindow() ist gültig, hingegen EnumDisplayMonitors ein ungültiges Handle zurückgibt. Hat jemand eine Idee? lg Gateway
-
[C#] Image.Save u. Bitmap.Save werfen jedes mal ExternalExceptions
Gateway_man antwortete auf Gateway_man's Thema in .NET
Vielen Dank, aber ich werd mir was saueres Überlegen . -
Hi, Syntax highlighting wäre eine cooles Future . Da Ihr das Forum aber nicht selbst geschrieben habt, weiß ich nicht ob das ein schnell umzusetztendes Ziel wäre. Beziehungsweise ob Ihr da überhaupt selbst Hand anlegen dürft... Ich glaube mich daran erinnern zu können, das hier mal jemand was von kostenpflichtiger Forensoftware gesagt hat. Wenn die Lizenz Änderungen zulässt bin ich mir eigentlich auch fast sicher, das Ihr Hilfe von einigen Usern erhalten würdet . lg Gateway