2009-04-18 14 views
9

Trên MSDN Tôi đã tìm thấy các mô tả sau đây cho hai thuộc tính:DllImport - PreserverSig và SetLastError thuộc tính

PreserveSig Đặt lĩnh vực PreserveSig true trực tiếp dịch chữ ký không được quản lý với HRESULT hoặc giá trị retval; đặt nó thành false để tự động chuyển đổi các giá trị HRESULT hoặc retval thành các ngoại lệ. Theo mặc định, trường PreserveSig là đúng.

SetLastError Cho phép người gọi sử dụng hàm Marshal.GetLastWin32Error để xác định xem có xảy ra lỗi khi thực hiện phương pháp hay không. Trong Visual Basic, mặc định là đúng (có thêm một số phí); trong C# và C++, mặc định là sai.

Câu hỏi của tôi là: Hai cách này liên quan lẫn nhau như thế nào? Giả sử tôi có PreserveSig được đặt thành 'false' - điều đó có nghĩa là tôi cần HRESULT được chuyển thành ngoại lệ - nếu hàm không được quản lý trả về số nguyên cho biết lỗi hoặc không xảy ra lỗi, cách dịch này có thể được dịch sang ngoại lệ?

Ngoài ra tại sao tôi cần phải gọi phương thức GetLastWin32Error nếu tôi bằng cách nào đó quản lý để trích xuất ngoại lệ bằng PreserveSig?

Kind coi PK

Trả lời

14

chức năng Win32 hầu như không bao giờ quay trở lại một HRESULT. Thay vào đó, họ trả về BOOL hoặc sử dụng các giá trị đặc biệt để biểu thị lỗi (ví dụ: CreateFile trả về INVALID_HANDLE_VALUE). Chúng lưu trữ mã lỗi trong một biến cho mỗi luồng, mà bạn có thể đọc với GetLastError(). SetLastError=true chỉ thị người sắp xếp thứ tự đọc biến này sau khi hàm gốc trả về và stash mã lỗi nơi bạn có thể đọc sau bằng Marshal.GetLastWin32Error(). Ý tưởng là thời gian chạy .NET có thể gọi các hàm Win32 khác đằng sau các cảnh làm rối tung mã lỗi từ cuộc gọi p/gọi của bạn trước khi bạn có cơ hội kiểm tra nó.

Các hàm trả về HRESULT (hoặc tương đương, ví dụ: NTSTATUS) thuộc về mức trừu tượng khác với hàm Win32. Nói chung các chức năng này có liên quan đến COM (trên Win32) hoặc từ ntdll (bên dưới Win32), vì vậy chúng không sử dụng mã lỗi cuối cùng của Win32 (chúng có thể gọi hàm Win32 bên trong).

PreserveSig=false yêu cầu người so sánh kiểm tra trả lại HRESULT và nếu đó không phải là mã thành công, để tạo và ném ngoại lệ có chứa HRESULT. Khai báo được quản lý của hàm DllImport ed của bạn sau đó có void làm loại trả về.

Hãy nhớ rằng trình biên dịch C# hoặc VB không thể kiểm tra chữ ký không được quản lý của hàm ed, do đó, nó phải tin tưởng bất cứ điều gì bạn nói. Nếu bạn đặt PreserveSig=false vào một hàm trả về một thứ khác không phải là HRESULT, bạn sẽ nhận được kết quả lạ (ví dụ: ngoại lệ ngẫu nhiên). Nếu bạn đặt SetLastError=true trên một hàm không đặt mã lỗi Win32 cuối cùng, bạn sẽ nhận được rác thay vì mã lỗi hữu ích.

+0

Tôi không có kinh nghiệm với các đối tượng COM vì vậy hãy để tôi hỏi thêm một câu hỏi về việc tạo chữ ký phương thức. Câu hỏi đặt ra là: khi tôi thấy hàm COM trả về HRESULT tôi có thể đánh dấu phương thức của tôi là trả về void và đặt PreserveSig = false (như bạn đã nói), hoặc đặt PreserveSig = true và đánh dấu phương thức của tôi là trả về IntPtr để kiểm tra mã trả về bằng tay? – pkolodziej

+0

Vâng, đó là chính xác, ngoại trừ HRESULTs là UInt32s, không phải IntPtrs. –

+0

Cảm ơn bạn - bạn đã rất hữu ích. – pkolodziej