2010-05-08 14 views
5

Tất cả mọi người sử dụng P/Invoke của Windows API biết một danh sách dài các tờ khai của các chức năng tĩnh với các thuộc tính nhưTại sao Microsoft không cung cấp cho C# một lớp Win32 tĩnh với các hàm và cấu trúc nguyên bản nhất bên trong như windows.h?

Việc kê khai các công trình sao chép từ tiêu đề Windows như WinNT.h hoặc từ các trang web như www.pinvoke .net cũng mất rất nhiều vị trí trong các chương trình của chúng tôi.

Tại sao tất cả chúng ta phải dành thời gian cho việc này? Tại sao Microsoft không cung cấp cho chúng ta một cách đơn giản để bao gồm một dòng như trong các chương trình không được quản lý cũ

#include <windows.h> 

và chúng tôi sẽ có quyền truy cập vào một lớp tĩnh Native với tất cả hoặc các chức năng của Windows nhất và cấu trúc bên trong?

CẬP NHẬT dựa trên số câu trả lời:

Nó bạn sẽ thành thật với chính mình, đó là một phần của chương trình .NET của bạn đang chạy không dưới Windows? 5%? 1%? Nếu bạn sử dụng WMI, Process, Registry hoặc ServiceProcess.ServiceBase lớp vv trong .NET là chương trình của bạn như vậy “nền tảng độc lập” và nhiều hơn nữa “tương thích” nếu bạn không sử dụng API bản địa? Có Thread.ApartmentState ở mọi nơi có ý nghĩa trong Windows không?

Việc sử dụng SafeHandle hoặc try {…} finally là nguyên nhân bắt buộc. Tôi rất vui khi có định nghĩa chuẩn về API gốc trong bất kỳ biểu mẫu nào trong số này.

Tôi biết rằng một số cấu trúc trong windows.h có các phiên bản khác nhau 32/64 hoặc XP/Vista vv Tôi nghĩ rằng nó sẽ là đủ để có phiên bản cũng khác nhau về cấu trúc Native như MIB_IPADDRROW_XPMIB_IPADDRROW_W2K hoặc IMAGE_NT_HEADERS32IMAGE_NT_HEADERS64 (xem cùng tên trong tiêu đề cửa sổ).

Một trong những nguyên nhân nên sử dụng các lớp và phương thức .NET được quản lý nếu có. Thật đáng tiếc, nhưng việc thực hiện một số tính năng mạnh mẽ nhất của Windows có trong .NET được quản lý quá muộn và rất nhiều trong số đó được truy cập cho đến bây giờ chỉ trong thế giới không được quản lý. 10 năm trước tại một trong những hội nghị đầu tiên của Microsoft về .NET Tôi hỏi về sự ủng hộ của tôi Các tập tin được ánh xạ bộ nhớ. Chỉ .NET 4 hiện đã thực hiện MemoryMappedFile lớp học (xem http://blogs.msdn.com/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files-in-net-4.aspx). Các vấn đề tương tự tồn tại vĩnh viễn nếu một người viết các tiện ích cho mục đích quản trị. Ví dụ: mở tệp bằng CreateFile và Gắn cờ FILE_FLAG_BACKUP_SEMANTICS hoặc RegCreateKeyEx với REG_OPTION_BACKUP_RESTORE hoặc REG_OPTION_CREATE_LINK. Các liên kết cứngCác mối nối (xem http://msdn.microsoft.com/en-us/library/aa365006(v=VS.85).aspx) là các ví dụ tiếp theo. Một ví dụ khác: làm việc với Đối tượng công việc thay vì Quy trình (xem http://msdn.microsoft.com/en-us/library/ms684161(VS.85).aspxhttp://www.microsoft.com/msj/0399/jobkernelobj/jobkernelobj.aspx). Nếu bạn muốn bắt đầu một quá trình và chờ đợi cho đến khi quá trình này, nhưng cũng cho đến khi tất cả các quy trình con của nó được kết thúc, công việc là rất hữu ích. Người ta có thể sử dụng CreateJobObjectAssignProcessToJobObject và sau đó sử dụng TerminateJobObject hoặc WaitHandle như phiên bản .NET của (WaitForSingleObject).

Chỉ trong .NET 4.0 System.IntPtr und System.UIntPtr các lớp hỗ trợ các phương thức AddSubtract.

Tôi có thể tiếp tục các ví dụ, nhưng tôi hy vọng bạn hiểu ý tôi. Vì vậy, Tôi muốn viết một chương trình .NET vì rất nhiều ưu điểm nhưng tôi có thể làm điều này không phải lúc nào cũng không cần sử dụng API gốc. Hơn nữa, đôi khi có yêu cầu của khách hàng đối với ngôn ngữ của việc triển khai phần mềm và tôi chọn cách thức cần thiết.

CẬP NHẬT 2: Microsoft đã cải thiện khả năng tương tác với COM trong .NET 4.0, nhưng không phải với API Windows giống như C. Tôi thấy một số cách để làm việc với P/Gọi dễ dàng hơn. Cách nào để làm điều này bạn thấy? Tôi đề xuất ba hướng mà tôi thấy:

  1. Một trong những công cụ lắp ráp có tuyên bố tất cả (hoặc quan trọng nhất) chưa được triển khai đầy đủ trong .NET Windows API. Sự tập hợp này có thể chỉ có siêu dữ liệu (hoặc gần như duy nhất) của lớp Native tĩnh với các hàm tĩnh và các lớp/cấu trúc tương ứng. Hội đồng này có thể được đặt trong GAC và mọi người đều có thể sử dụng nó. (Bằng cách này tôi đã thử nghiệm. Nó hoạt động rất tốt.)
  2. Thực hiện một tập hợp các đoạn mã với khai báo và các mẫu sử dụng API Windows gốc khác nhau.
  3. Bắt đầu một dự án mã nguồn mở trên www.codeplex.com, nơi tạo một lớp .NET và các phương thức mở rộng cho một số API Windows quan trọng nhất mà chưa được triển khai trong .NET.

Tôi chắc chắn rằng tồn tại nhiều cách hơn để giúp nhà phát triển dễ dàng sử dụng API Windows gốc hơn. Các đề xuất khác được hoan nghênh.

Trả lời

2

Một chế độ xem là PInvoke là một cái nạng tương thích. Bạn nên sử dụng 100%. Net thư viện và chức năng, không phải "di sản" Win32 cuộc gọi.

+1

Vì lý do nào đó bất cứ khi nào tôi cần một cái gì đó đặc biệt được thực hiện, điều này xảy ra khá thường xuyên, tôi sẽ sử dụng các cuộc gọi Win32 "kế thừa" để thực hiện phép thuật. Trong khi tôi đang viết này tôi đang tìm ra cách để làm cho cửa sổ WPF của tôi dính như winamp ... muốn thư viện .net đã làm điều đó cho tôi. – m0s

10

Tôi không biết tại sao MSFT đưa ra quyết định đó, nhưng đây là một vài lý do tại sao tôi nghĩ rằng quyết định này là đúng nhất:

  • Các tập tin tiêu đề của Windows SDK (windows.h et al) làm rộng sử dụng trình biên dịch có điều kiện dựa trên những thứ như phiên bản và kiến ​​trúc Windows đích để xác định những hàm nào được khai báo và cấu trúc dữ liệu được đặt ra như thế nào. Không có ngôn ngữ nào trong số các ngôn ngữ .NET này, vì không phải là phiên bản Windows mà là phiên bản khung, với các tệp nhị phân có thể chạy tự nhiên trên các kiến ​​trúc 32 và 64 bit trên nhiều phiên bản và phiên bản Windows

  • Nhiều cuộc gọi API Windows và cấu trúc dữ liệu không thể được biểu thị đầy đủ thông qua P/Invoke. Một ý nghĩ xuất hiện ngay lập tức trong đầu là DeviceIoControl. Một cấu trúc khác được gọi là cấu trúc 'độ dài biến đổi', chứa các mảng có số nguyên tố không xác định (tại thời gian biên dịch) của chúng

  • P/Invoke đã phát triển theo thời gian, đặc biệt trong cách xử lý (IntPtr trong các phiên bản ban đầu của khung; SafeHandle các lớp sau); nếu MSFT duy trì một lớp tĩnh với hầu hết hoặc tất cả các hàm API của Win32, chúng cũng có nghĩa vụ duy trì khả năng tương thích với các phiên bản trước của lớp này, tự khóa trong P/Invoke được thực hiện ban đầu. không duy trì một lớp Native duy nhất trong nội bộ khung. Bây giờ là .NET Framework 3.5 mã nguồn có sẵn, bạn có thể xem cho chính mình cách sử dụng đặc biệt của P/Invoke, ngay cả trong khuôn khổ mà chúng ta được cho là sử dụng thay cho P/Invoke. Ví dụ, System.Net và System.IO có các khai báo P/Invoke riêng của chúng.

  • Khuôn khổ .NET và mã được quản lý được thiết kế ngay từ đầu như là một cách xây dựng phần mềm mới cho Windows. Làm thế nào ngu ngốc nó sẽ được cung cấp theo cách mới này trong khi đồng thời đòi hỏi phải sử dụng cách cũ cho nhiều nhiệm vụ?

Tôi nói điều này là người sử dụng rộng rãi P/Gọi cho những thứ như IOCTL và các hoạt động I/O mức âm lượng. Tôi càng sử dụng P/Invoke, tôi càng ghét nó. Thật khó để làm việc với, dễ bị lỗi và chậm. Mỗi lần tôi sử dụng P/Invoke, đó là vì tôi đã hết tất cả các tùy chọn khác. Nếu bạn thấy mình có một vấn đề mà giải pháp đòi hỏi rất nhiều cuộc gọi API trực tiếp Windows, bạn có thể:

a) đang thiếu một số tính năng trong khung đó sẽ làm những gì bạn muốn

b) Có phải lấy sai cách tiếp cận để giải quyết vấn đề, đặc biệt nếu bạn quen với API Windows gốc và vẫn nghĩ theo các điều khoản đó

c) Nên viết mã cấp thấp của bạn bằng C++/CLI và hiển thị giao diện cấp cao hơn cho bạn. Mã số để tiêu thụ

+0

Tôi không nghĩ mình đã từng viết một chương trình .Net không có P/Invoke. – Gabe

+0

Bạn có cảm tình của tôi sau đó;) – anelson

+1

Xin lỗi, nhưng bạn đã sai với 'DeviceIoControl'. Bạn có thể sử dụng chức năng 'DeviceIoControl' để giao tiếp trực tiếp với trình điều khiển thiết bị. Nếu bạn muốn tôi có thể gửi cho bạn một ví dụ làm việc và bạn có thể thấy điều này cho mình. Nhưng có sự hiểu lầm trong những gì tôi muốn với câu hỏi của tôi. Vui lòng đọc "CẬP NHẬT 2" của câu hỏi. – Oleg

3

Tôi chắc chắn suy nghĩ đã vượt qua suy nghĩ của bạn nhưng tôi nghĩ rằng nên là một dự án nguồn mở đã làm điều này. Thay vì chờ đợi Microsoft thực hiện việc này, chúng tôi có thể thu thập tất cả kiến ​​thức mà những người đã thực sự sử dụng P/Gọi ngày trong ngày để những người khác không phải phát minh lại bánh xe.

Tiếp tục thu thập API khi mọi người sử dụng chúng, cần chúng.

Bất kỳ tình nguyện viên nào? :)

pinvoke.net không tính - không dễ dàng cắm vào giải pháp của bạn.

Các vấn đề liên quan