Frage Warum stellt Microsoft für C # keine statische Win32-Klasse mit den meisten nativen Funktionen und Strukturen innerhalb von windows.h bereit?


Jeder, der P / Invoke von Windows API verwendet, kennt eine lange Liste von Deklarationen von statischen Funktionen mit Attributen wie

 [DllImport ("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]

Die Deklaration von Strukturen, die von Windows-Headern wie WinNT.h oder von Webseiten wie www.pinvoke.net kopiert werden, nehmen auch in unseren Programmen eine große Rolle ein.

Warum müssen wir alle unsere Zeit dafür aufwenden? Warum Microsoft uns keine einfache Möglichkeit gibt, eine Zeile wie in alten nicht verwalteten Programmen einzubinden

#include <windows.h>

und wir hätten Zugang zu einer statischen Klasse Native mit allen oder den meisten Windows-Funktionen und -Strukturen?

AKTUALISIERT basierend auf einigen Antworten:

Sie werden ehrlich zu sich selbst sein, welcher Teil Ihrer .NET-Programme läuft nicht unter Windows? 5%? 1%? Wenn du benutzt WMI, Verarbeiten, Registrierung oder ServiceProcess.ServiceBase Klassen usw. in .NET ist Ihr Programm so "Plattformunabhängig" und mehr "kompatibel"Wenn Sie nicht die native API verwenden? Hat Thread.ApartmentState überall Sinn aus Windows?

Benutzung von SafeHandle oder try {…} finally ist natürlich erforderlich. Ich würde mich freuen, eine Standarddefinition von Native API in einer dieser Formen zu haben.

Ich weiß, dass einige Strukturen in windows.h habe verschiedene Versionen 32/64 oder XP / Vista etc. Ich denke es wäre genug, auch andere Versionen von Native-Strukturen zu haben MIB_IPADDRROW_XP und MIB_IPADDRROW_W2K oder IMAGE_NT_HEADERS32 und IMAGE_NT_HEADERS64 (Siehe die gleichen Namen in Windows-Kopfzeilen).

Man sollte verwaltete .NET-Klassen und -Methoden verwenden, wenn solche vorhanden sind. Es ist schade, aber die Implementierung einiger der leistungsfähigsten Funktionen von Windows kommt zu spät in Managed .NET und viele davon sind bisher nur in der nicht verwalteten Welt verfügbar. Vor 10 Jahren bei einer der ersten Microsoft-Konferenzen über .NET habe ich mich nach meinem Gefallen erkundigt Speicher zugeordnete Dateien. Nur .NET 4 hat jetzt MemoryMappedFile Klasse implementiert (siehe http://blogs.msdn.com/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files-in-net-4.aspx). Die gleichen Probleme bestehen permanent, wenn man Dienstprogramme für administrative Zwecke schreibt. Zum Beispiel, Datei mit öffnen CreateFile und Flagge FILE_FLAG_BACKUP_SEMANTICS oder RegCreateKeyEx mit REG_OPTION_BACKUP_RESTORE oder REG_OPTION_CREATE_LINK. Harte Verbindungen und Übergänge (sehen http://msdn.microsoft.com/en-us/library/aa365006(v=VS.85).aspx) sind die nächsten Beispiele. Ein weiteres Beispiel: Arbeiten mit Jobobjekte statt Prozess (siehe http://msdn.microsoft.com/en-us/library/ms684161(VS.85).aspx und http://www.microsoft.com/msj/0399/jobkernenlobj/jobkernelobj.aspx). Wenn Sie einen Prozess starten und nicht bis zu diesem Prozess warten möchten, aber bis alle seine untergeordneten Prozesse beendet sind, ist der Job sehr nützlich. Man kann verwenden CreateJobObject und AssignProcessToJobObject und dann benutzen TerminateJobObject oder WaitHandle wie .NET Version vonWaitForSingleObject).

Nur in .NET 4.0 System.IntPtr und System.UIntPtr Klassen unterstützt Add und Subtract Methoden.

Ich kann die Beispiele fortsetzen, aber ich hoffe, Sie verstehen, was ich meine. Damit Ich möchte ein Programm in .NET schreiben wegen einer Menge von Vorteilen, aber ich kann dies nicht immer ohne Verwendung der nativen API tun. Darüber hinaus gibt es manchmal Kundenanforderungen an die Sprache der Software-Implementierung und ich wähle den erforderlichen Weg.

AKTUALISIERT 2: Microsoft verbesserte die Interoperabilität mit COM in .NET 4.0, aber nicht mit C-ähnlicher Windows-API. Ich sehe einige Möglichkeiten, die Arbeit mit P / Invoke einfacher zu machen. Welchen Weg, um dies zu tun, siehst du? Ich schlage drei Richtungen vor, die ich sehe:

  1. Man erstellt eine Assembly mit der Deklaration aller (oder der wichtigsten), die in der .NET Windows API noch nicht vollständig implementiert sind. Diese Assembly-Klasse kann nur (oder fast nur) Metadaten der statischen nativen Klasse mit statischen Funktionen und entsprechenden Klassen / Strukturen enthalten. Diese Baugruppe kann in GAC platziert werden und jeder kann sie verwenden. (So ​​habe ich getestet. Es funktioniert sehr gut.)
  2. Man implementiert eine Sammlung von Snippets mit Deklaration und Beispielen für die Verwendung verschiedener nativer Windows API.
  3. Man startet ein Open-Source-Projekt auf www.codeplex.com, wo man .NET-Klassen und Erweiterungsmethoden für einige der wichtigsten nativen Windows-API erstellt, die in .NET noch nicht implementiert sind.

Ich bin mir sicher, dass es mehrere Möglichkeiten gibt, um Entwicklern die Verwendung der nativen Windows-API zu erleichtern. Andere Vorschläge sind willkommen.


5
2018-05-08 00:52


Ursprung


Antworten:


Ich weiß nicht, warum MSFT diese Entscheidung getroffen hat, aber hier sind einige Gründe, warum ich die Entscheidung für richtig hielt:

  • Die Windows SDK-Headerdateien (windows.h et al.) verwenden bedingte Kompilierung auf der Grundlage der Windows-Zielversion und -Architektur, um festzustellen, welche Funktionen deklariert werden und wie Datenstrukturen angelegt werden. Dies ist in keiner der .NET-Sprachen möglich, da nicht Windows-Versionen, sondern Framework-Versionen zum Einsatz kommen und die resultierenden Binaries nativ auf 32- und 64-Bit-Architekturen in vielen Versionen und Editionen von Windows ausgeführt werden können

  • Viele Windows API-Aufrufe und Datenstrukturen können nicht vollständig über P / Invoke ausgedrückt werden. Eine, die mir sofort in den Sinn kommt DeviceIoControl. Ein anderes sind die vielen sogenannten "variable length" Strukturen, die Arrays mit einer unbekannten (zur Kompilierungszeit) Anzahl von Elementen enthalten

  • P / Invoke hat sich im Laufe der Zeit entwickelt, insbesondere in der Art, wie Griffe behandelt werden (IntPtr in frühen Versionen des Frameworks; SafeHandle Klassen später); Wenn MSFT eine einzelne statische Klasse mit den meisten oder allen Win32-API-Funktionen verwaltet, wären sie auch verpflichtet, die Kompatibilität mit früheren Versionen dieser Klasse beizubehalten, indem sie sich jedoch daran binden, dass P / Invoke ursprünglich implementiert wurde

  • Selbst MSFT selbst verwalten keine einzige Native Klasse im Framework Internals. Jetzt, da der .NET Framework 3.5-Quellcode verfügbar ist, können Sie selbst sehen, wie Ad-hoc-Verwendung von P / Invoke ist, sogar innerhalb des Rahmens, den wir anstelle von P / Invoke verwenden sollten. Zum Beispiel haben System.Net und System.IO ihre eigenen separaten P / Invoke-Deklarationen.

  • Das .NET Framework und der verwaltete Code wurden von Anfang an als neue Möglichkeit entwickelt, Software für Windows zu erstellen. Wie dumm wäre es, diesen neuen Weg zu bieten und gleichzeitig den alten Weg für viele Aufgaben zu nutzen?

Ich sage dies als jemand, der P / Invoke umfangreich für Dinge wie IOCTLs und I / O-Operationen auf Datenträgerebene verwendet. Je mehr ich P / Invoke verwende, desto mehr hasse ich es. Es ist schwer zu arbeiten, fehleranfällig und langsam. Jedes Mal, wenn ich P / Invoke verwende, liegt das daran, dass ich alle anderen Optionen ausgeschöpft habe. Wenn Sie sich mit einem Problem konfrontiert sehen, dessen Lösung viele direkte Windows-API-Aufrufe erfordert, haben Sie wahrscheinlich Folgendes:

a) Fehlen einige Funktionen innerhalb des Frameworks, die das tun, was Sie wollen

b) Gehen Sie den Fehler falsch an, vor allem, wenn Sie mit der nativen Windows-API vertraut sind und immer noch so denken

c) Schreiben Sie Ihren Low-Level-Code in C ++ / CLI, und legen Sie Chunky-Interfaces höherer Ebenen offen, damit Ihr .NET-Code konsumiert werden kann


10
2018-05-08 04:44



Ich bin sicher, der Gedanke ist dir durch den Kopf gegangen, aber ich denke, dass es ein Open-Source-Projekt geben sollte, das das getan hat. Anstatt auf Microsoft zu warten, können wir all das Wissen sammeln, das P / Invoke Tag für Tag genutzt hat, damit andere das Rad nicht neu erfinden müssen.

Sammeln Sie die API weiterhin, wenn Nutzer sie verwenden, brauchen Sie sie.

Irgendwelche Freiwilligen? :)

pinvoke.net zählt nicht - es lässt sich nicht ohne weiteres in Ihre Lösung einbinden.


3
2018-05-27 18:31



Eine Ansicht ist, dass PInvoke eine Kompatibilitätskrücke ist. Sie sollten 100% .Net-Bibliotheken und -Funktionen verwenden, keine "alten" Win32-Aufrufe.


2
2018-05-08 00:54