Everybody who used P/Invoke of Windows API knows a long list of declarations of static functions with attributes like
[DllImport ("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
The declaration of structures copied from Windows headers like WinNT.h or from web sites like www.pinvoke.net take also a lot of place in our programs.
Why we all have to spend our time for this? Why Microsoft not give us a simple way to include a line like in old unmanaged programs
#include <windows.h>
and we would be have access to a static class Native
with all or the most Windows functions and structures inside?
UPDATED based on some answers:
It you will be honest with yourself, which part of your .NET programs are running not under Windows? 5%? 1%? If you use WMI, Process, Registry or ServiceProcess.ServiceBase classes etc. in .NET is your program so “platform independent” and more “compatible” if you not use native API? Has Thread.ApartmentState
everywhere sense out of Windows?
Usage of SafeHandle
or try {…} finally
is of cause required. I would be happy to have a standard definition of Native API in any of these forms.
I know that some structures in windows.h
have different versions 32/64 or XP/Vista etc. I think it would be enough to have also different version of Native structures like MIB_IPADDRROW_XP
and MIB_IPADDRROW_W2K
or IMAGE_NT_HEADERS32
and IMAGE_NT_HEADERS64
(see the same names in windows headers).
One should of cause use managed .NET classes and methods if there are exist. It’s a pity, but the implementation of some the most powerful features of Windows come in managed .NET too开发者_StackOverflow社区 late and a lot of there are accessed till now only in unmanaged world. 10 year ago at one of the first Microsoft conference about .NET I asked about my favor Memory Mapped Files. Only .NET 4 has now MemoryMappedFile
class implemented (see http://blogs.msdn.com/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files-in-net-4.aspx). The same problems exist permanently if one writes utilities for administrative purpose. For example, opening file with CreateFile
and Flag FILE_FLAG_BACKUP_SEMANTICS
or RegCreateKeyEx
with REG_OPTION_BACKUP_RESTORE
or REG_OPTION_CREATE_LINK
. Hard Links and Junctions (see http://msdn.microsoft.com/en-us/library/aa365006(v=VS.85).aspx) are next examples. One more example: working with Job Objects instead of Process (see http://msdn.microsoft.com/en-us/library/ms684161(VS.85).aspx and http://www.microsoft.com/msj/0399/jobkernelobj/jobkernelobj.aspx). If you want to start a process and wait not till this process, but also untill all it’s child processes be ended, job is very useful. One can use CreateJobObject
and AssignProcessToJobObject
and then use TerminateJobObject
or WaitHandle
like .NET version of (WaitForSingleObject
).
Only in .NET 4.0 System.IntPtr
und System.UIntPtr
classes supports Add
and Subtract
methods.
I can continue the examples, but I hope you understand what I mean. So I want to write a program in .NET because of a lot of advantages but I can do this not always without usage of native API. Moreover, there are sometimes customer's requirement to the language of software implementation and I choose the required way.
UPDATED 2: Microsoft improved the interoperability with COM in .NET 4.0, but not with C-like Windows API. I see some ways to makes working with P/Invoke easier. What way to do this you see? I suggest three directions which I see:
- One makes an assembly with declaration of all (or the most important) not yet fully implemented in .NET Windows API. This assemble can has only (or almost only) metadata of static Native class with static functions and corresponding classes / structures. This assembly can be placed in GAC and everybody could use it. (This way I tested. It works very well.)
- One implements a collection of snippets with declaration and samples of using of different native Windows API.
- One start an open source project on www.codeplex.com where one create .NET classes and extension methods to some most important native Windows API which are not yet implemented in .NET.
I am sure that exist more ways to make easier for developer the usage of native Windows API. Other suggestions are welcome.
I don't know why MSFT made that decision, but here are a few reasons why I think the decision was the correct one:
The Windows SDK header files (
windows.h
et al) make extensive use of conditional compilation based on things like the target Windows version and architecture to determine what functions get declared and how data structures are laid out. None of this would be possible in any of the .NET languages, as one does not target Windows versions but rather framework versions, with the resulting binaries able to run natively on 32- and 64-bit architectures across many versions and editions of WindowsMany Windows API calls and data structures cannot be fully expressed via P/Invoke. One that comes immediately to mind is
DeviceIoControl
. Another are the many so-called 'variable length' structures, containing arrays with an unknown (at compile time) number of elements in themP/Invoke has evolved over time, particularly in the way handles are exposed (
IntPtr
in early versions of the framework;SafeHandle
classes later); if MSFT maintained a single static class with most or all Win32 API functions, they would also be obligated to maintain compatibility with previous versions of this class, locking themselves in to however P/Invoke was implemented originallyEven MSFT themselves do not maintain a single
Native
class in the framework internals. Now that the .NET Framework 3.5 source code is available, you can see for yourself how ad-hoc use of P/Invoke is, even within the very framework we are supposed to use in lieu of P/Invoke. For example, System.Net and System.IO have their own separate P/Invoke declarations.The .NET Framework and managed code were designed from the beginning as a new way of building software for Windows. How stupid would it be to provide this new way while at the same time requiring use of the old way for many tasks?
I say this as someone who makes extensive use of P/Invoke for things like IOCTLs and volume-level I/O operations. The more I use P/Invoke, the more I hate it. It's hard to work with, error prone, and slow. Every time I use P/Invoke, it's because I've exhausted all other options. If you find yourself with a problem whose solution requires a lot of direct Windows API calls, you probably:
a) Are missing some feature within the Framework that will do what you want
b) Are taking the wrong approach to solving the problem, particularly if you are used to the native Windows API and still think in those terms
c) Should write your low-level code in C++/CLI, and expose chunky higher-level interfaces for your .NET code to consume
I'm sure the thought crossed your minds but I think there should be an open source project that did this. Rather than waiting on Microsoft to do this, we can collect all of the knowledge that people who've actually used P/Invoke day in day out so that others don't have to reinvent the wheel.
Keep collecting the API as people use them, need them.
Any volunteers? :)
pinvoke.net doesn't count - it's not readily pluggable to your solution.
One view is that PInvoke is a compatibility crutch. You should be using 100% .Net libraries and functions, not "legacy" Win32 calls.
精彩评论