2017-10-03 18 views
3

VBA에서 일부 오래된 VB 함수를로드하고 대부분 VB.NET으로 업데이트되었지만 제대로 일치하지 않는 "wininet.dll"함수의 함수 선언이 있습니다.어떻게 관리되지 않는 dll에 대한 올바른 인수 구조를 알아낼 수 있습니까?

내가 갖는 오류 : 슬로우

예외 : 관리 디버깅 도우미 'PInvokeStackImbalance'...

길고 그 짧은은 그 길이 선언 된 인수는 명시 적이어야하며 dll의 실제 함수와 일치하지 않습니다.

나는 이것들을 보았고, 수표를 제거하는 것만으로 얻을 수 있었지만, "스택 불균형"이 생겨 결국이 콜이 만들어지면서 모든 스택을 먹었다. 또한 이러한 것을 "관리되지 않는"dll이라고하며 일부 선언은 PInvoke 함수 위키 http://pinvoke.net에 있습니다. 이 위키는 내가 사용하고있는 함수 호출 중 일부를 가지고 있지만 전부는 아닙니다. 그들 중 몇 명은 어떤 것을 추측해야만했고, 그것은 효과가 없었습니다. 이전 코드에서 사용되지 않았다 내가 이전 코드가 long에서 int32 또는 integer로 변경되었다에서 복사 한 것과 변경 및 IntPtr에 몇 가지 변경, 대부분의

. 나는 이것이 모든 정수 크기가 정확하다고 가정합니다 (예 : 16/32/64 비트). 아마도 대부분의 문제가 있었던 부분 일 것입니다. 하나의 경우지만, long에서 string()으로 바뀌 었습니다. 다소 이상하게 보였으므로 제대로 컴파일되지 않았습니다.

그렇다면 DLL에서 함수 길이를 실제로 찾아보고 API와 어떻게 일치합니까?

Visual Studio의 c : \ windows \ system32 \ wininet.dll에 대한 참조를 Visual Studio의 VB.NET 프로젝트에 추가하려고하면 추가 할 수 없다는 메시지가 나타납니다. Visual Studio에서 개체 또는 어셈블리 브라우저를 사용할 수 없게됩니다. COM 개체로 나타나지 않습니다. 도움이 필요 하신가요?

Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (_ 
    ByVal Agent As String, ByVal AccessType As Long, ByVal ProxyName As String, _ 
    ByVal ProxyBypass As String, ByVal Flags As Long) As Long 

Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" (_ 
    ByVal hInternetSession As Long, ByVal ServerName As String, ByVal ServerPort As Integer, ByVal UserName As String, _ 
    ByVal Password As String, ByVal Service As Long, ByVal Flags As Long, ByVal Context As Long) As Long 

Private Declare Function InternetCloseHandle Lib "wininet.dll" (_ 
    ByVal hInet As Long) As Boolean 

Private Declare Function InternetReadFile Lib "wininet.dll" (_ 
    ByVal hConnect As Long, ByVal Buffer As String, ByVal NumberOfBytesToRead As Long, _ 
    NumberOfBytesRead As Long) As Boolean 

Private Declare Function HttpOpenRequest Lib "wininet.dll" Alias "HttpOpenRequestA" (_ 
    ByVal hHttpSession As Long, ByVal Verb As String, ByVal ObjectName As String, ByVal Version As String, _ 
    ByVal Referer As String, ByVal AcceptTypes As Long, ByVal Flags As Long, Context As Long) As Long 

Private Declare Function HttpSendRequest Lib "wininet.dll" Alias "HttpSendRequestA" (_ 
    ByVal hHttpRequest As Long, ByVal Headers As String, ByVal HeadersLength As Long, _ 
    ByVal sOptional As String, ByVal OptionalLength As Long) As Boolean 
+1

이 기능에 대한 MSDN 선언과 비교. DWORD는 Integer이고 HINTERNET은 IntPtr입니다. 그리고 이것들을 철회하면 WebClient와 WebRequest를 사용해야합니다. –

+0

@HansPassant 더 새로운 프레임 워크에서 이들을 다시 구현할 계획이지만 먼저 오래된 코드가 작동하도록하고 싶습니다. 너무 가깝습니다. 다른 어떤 것도 아니라면이 같은 문제를 더 잘 이해하고 배우십시오. ** MSDN 신고와 관련하여 ** ** 어디에서 찾을 수 있습니까? – LightCC

+1

MSDN. 또는 Google의 첫 번째 히트 곡. –

답변

4

으로 이미 noted by Hans Passant 대신 관리 대안을 사용해야합니다

는 참고로, 여기에 실패 이전 코드입니다.

그러나 실제 질문에 대답하려면 : 기본적으로 MSDN 설명서 문서 Windows Data Types을 확인하고 형식 선언에 따라 해당 .NET 유형을 결정해야합니다.

예컨대

하는 DWORD :

DWORD
32 비트 부호없는 정수. 범위는 0부터 4294967295까지입니다.

이 유형은 IntSafe에 선언되어 있습니다.H는 다음과 같다 : 우리는 범위 (0-4294967295)로 갈 수 어느 이때

typedef unsigned long DWORD;

이것은 부호없는 32 비트 정수되어야하는지 결정하기 위해 또는 순서대로 정의 (unsigned long) (UInt32 또는 UInteger). C/C++에서 longint과 같은 것이므로 Long/ULong이 아닌 정수로 매핑됩니다.

다음은 가장 일반적인 유형의 요약이다 :

(큰 감사를 David Heffernan에 나 문자열 선언의 일부를 수정 돕는!)

+------------------+------------------------------------------------------+ 
| Windows Type |     .NET equivalent     | 
+------------------+------------------------------------------------------+ 
| BOOL    | <MarshalAs(UnmanagedType.Bool)> Boolean (vb.net) | 
| BOOL    | [MarshalAs(UnmanagedType.Bool)] bool  (c#)  | 
| BYTE    | Byte /Byte  (vb.net)/byte (c#)    | 
| CHAR    | Char /Char  (vb.net)/char (c#)    | 
| DWORD   | UInt32/UInteger (vb.net)/uint (c#)    | 
| DWORDLONG  | UInt64/ULong (vb.net)/ulong (c#)    | 
| DWORD_PTR  | UIntPtr            | 
| FLOAT   | Single/Single (vb.net)/float (c#)    | 
|     |              | 
| HANDLE   | IntPtr            | 
| HBITMAP   | IntPtr            | 
| HCURSOR   | IntPtr            | 
| HDESK   | IntPtr            | 
| HDC    | IntPtr            | 
| HICON   | IntPtr            | 
| HINSTANCE  | IntPtr            | 
| HRESULT   | Int32/Integer (vb.net)/int (c#)     | 
| HWND    | IntPtr            | 
|     |              | 
| INT    | Int32/Integer (vb.net)/int (c#)     | 
| INT_PTR   | IntPtr            | 
| INT8    | SByte            | 
| INT16   | Int16/Short (vb.net)/short (c#)    | 
| INT32   | Int32/Integer (vb.net)/int (c#)    | 
| INT64   | Int64/Long (vb.net)/long (c#)    | 
| LONG    | Int32/Integer (vb.net)/int (c#)    | 
| LONGLONG   | Int64/Long (vb.net)/long (c#)    | 
| LONG_PTR   | IntPtr            | 
| LPARAM   | IntPtr            | 
|     |              | 
| LPCSTR   | String (Specify CharSet.Ansi in DllImport)   | 
| LPCTSTR   | String            | 
| LPCWSTR   | String (Specify CharSet.Unicode in DllImport)  | 
| LPDWORD   | (= DWORD, declared as ByRef (vb.net)/ref (c#)) | 
| LPHANDLE   | (= HANDLE, declared as ByRef (vb.net)/ref (c#)) | 
| LPINT   | IntPtr            | 
| LPLONG   | IntPtr            | 
|     |              | 
| LPSTR   | StringBuilder (Specify CharSet.Ansi in DllImport) | 
| LPTSTR   | StringBuilder          | 
| LPVOID   | IntPtr            | 
| LPWORD   | (= WORD, declared as ByRef (vb.net)/ref (c#))  | 
| LPWSTR   | StringBuilder (Specify CharSet.Unicode in DllImport) | 
|     |              | 
| QWORD   | UInt64/ULong (vb.net)/ulong (c#)     | 
| SHORT   | Int16/Short (vb.net)/short (c#)     | 
| SIZE_T   | UIntPtr            | 
| UCHAR   | Byte/Byte (vb.net)/byte (c#)     | 
| UINT    | Int32/Integer (vb.net)/int (c#)     | 
| UINT_PTR   | IntPtr            | 
| UINT8   | Byte /Byte  (vb.net)/byte (c#)    | 
| UINT16   | UInt16/UShort (vb.net)/ushort (c#)    | 
| UINT32   | UInt32/UInteger (vb.net)/int (c#)    | 
| UINT64   | UInt64/ULong (vb.net)/long (c#)    | 
| ULONG   | UInt32/UInteger (vb.net)/int (c#)    | 
| ULONGLONG  | UInt64/ULong (vb.net)/long (c#)    | 
| ULONG_PTR  | UIntPtr            | 
| USHORT   | UInt16/UShort (vb.net)/ushort (c#)    | 
| WORD    | UInt16/UShort (vb.net)/ushort (c#)    | 
+------------------+------------------------------------------------------+ 
+0

감사합니다. 테이블이 필요한 마지막 부분입니다. – LightCC

+0

@LightCC : 기꺼이 도와 드리겠습니다! 프로젝트에 행운을 빌어 요! –

+0

'LPCSTR'과'LPCWSTR'는 인코딩이 다릅니다. 전자는'const char *'이고, 후자는'const wchar_t *'이다. 둘 다'string'에 매핑됩니다. 반면에'StringBuilder'는'char *'또는'wchar_t *'에 매핑되며, 그 별칭은'LPSTR'과'LPWSTR'입니다. –