2012-03-09 3 views
1

SetupDiGetDeviceInterfaceDetail() here을 호출 중이며 SP_DEVICE_INTERFACE_DETAIL_DATA 구조가 올바르게 마샬링되지 않습니다. 구조체 정의는 here입니다. 나는이 구조에 대한 정의를 PInvoke.net here에서 사용하려고 시도했지만 아무 소용이 없다.32 비트 및 64 비트 런타임에서 동적 구조를 마샬링

지금까지 함수 호출이 성공하면 (즉, 마샬 러가 오류를 throw하지 않음) 반환 값은 1784 (INVALID_USER_BUFFER)입니다. 이 코드가 제 박스의 32 비트 프로세스에서 실행되면 모든 것이 올바르게 작동합니다. 64 비트 프로세스에서 실행될 때이 문제가 발생합니다.

나의 현재 SetupDiGetInterfaceDetailData() 서명은 다음과 같습니다

[DllImport(@"c:\Windows\System32\SetupApi.dll", SetLastError = true, CharSet = CharSet.Auto)] 
[return : MarshalAs(UnmanagedType.Bool)] 
public static extern bool SetupDiGetDeviceInterfaceDetail(
    SafeHandleZeroOrMinusOneIsInvalid deviceInfoSet, 
    ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData, 
    IntPtr deviceInterfaceDetailData, 
    uint deviceInterfaceDetailDataSize, 
    IntPtr requiredSize, 
    IntPtr deviceInfoData); 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
public struct SP_DEVICE_INTERFACE_DETAIL_DATA 
{ 
    public UInt32 cbSize; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] 
    public string DevicePath; 
} 

을 현재 내가 원수를 사용하여 해당 버퍼에서 데이터를 읽기/Marshal.AllocHGlobal()와 쓰기에 메모리를 할당하고 * 함수의 가족.. 내가 언급 한 바와 같이 SP_DEVICE_INTERFACE_DETAIL_DATA (위의 링크 참조) PInvoke.net에 의해 설명 된 새로운했다으로

public string GetPathToDevice(SafeHandleZeroOrMinusOneIsInvalid hDevList, 
           SP_DEVICE_INTERFACE_DATA devIntfData) 
{ 
    uint sizeNeeded = 0; 
    // get's the size needed 
    SetupApi.SetupDiGetDeviceInterfaceDetailData(hDevList, 
               ref devIntfData, 
               IntPtr.Zero, 
               0, 
               ref sizeNeeded, 
               IntPtr.Zero); 

    IntPtr pBuffer = Marshal.AllocHGlobal((int)(sizeNeeded + 4)); // +4 for cbSize 
    SetupApi.SetupDiGetDeviceInterfaceDetailData(hDevList, 
               ref devIntfData, 
               pBuffer, 
               sizeNeeded, 
               IntPtr.Zero, 
               IntPtr.Zero); 

    // copy bytes from unmanaged space in pBuffer to a manged byte array 
    // free unmanaged memory 

    return theStringParsedFromByteArray; 
} 

, 나는 구조를 정의하는 시도했다 :

참고로

이 내가 뭘하는지입니다 그것을 처리하는 PInvoke 메서드 서명. 64 비트 시스템에서 실행하면 동일한 문제가 발생합니다. 즉, 함수는 1784를 반환합니다. 이유는 C#의 참조가 64 비트 런타임에서 실행될 때 8 바이트 정렬 (다른 StackOverflow 문서). 레이아웃 (명시 적 및 필드 오프셋을 사용하여) 4 바이트 정렬 구조체 강제로 시도하는 해당 구조에 다양한 레이아웃을 시도했다 그러나 그 중 하나 나를 위해 작동하지 않았다. 나는 시간 문제를 컴파일했다.

나는 PInvoke 메서드의 sigature 매개 변수에 다양한 장식을 사용해 보았습니다. 예를 들어 MarshalAs (UnmanagedType.LPStruct)와 같이 부적절하게 계속 페어링하고 있습니다. 나는 지금 내가이 일에 도움이 필요하다는 점에 이르렀다.

내가 정말로 이해하지 못하는 이유는 그것이 전혀 일어나지 않는 이유입니다. 32 비트 런타임에서 실행될 때 내 상자에서 작동하더라도 64 비트 런타임이 올바른 64 비트 버전의 설치 API에 연결되지 않습니까? 뭐가 문제 야? 어떤 도움

감사합니다,

문제가 좋은 점은, 지금 해결 될되고, 자극적 일이 내가 한 두 시간의 내 일을 고정 싫어입니다

를 해결 앤디 여기에 게시. 그래서 문제는 64 비트 문제였습니다. Marshal.GetLastWin32Error()의 오류 코드가 문제를 말해주었습니다. cbSize 값이 잘못되었습니다. 나는 그것을 8로 바꿨고 모든 것이 지금 작동한다.

누군가 64 비트에서 8 비트가 된 이유를 설명해주십시오. 이제 구조가 위에 있습니다 (의견 작성자가 포함하도록 요청했습니다). 이 구조는 하나의 DWORD와 TCHAR [ANYSIZE_ARRAY]의 두 멤버로 구성됩니다. ANYSIZE_ARRAY는 1로 평가되고, TCHAR은 유니 코드이면 항상 WCHAR이고 그렇지 않으면 char입니다. DWORD는 항상 32 비트 (4 바이트)이며 유니 코드의 단일 TCHAR은 2 바이트입니다. 그래서 4 + 2 = 6입니다. 왜 8입니까? 64 비트의 구조체에 대한 바이트 정렬 때문입니까? 나는 이것을 정말로 알고 싶다.

어쨌든 64 비트의 경우 8, 32 비트의 경우 6으로 cbSize 멤버를 설정하고 위에 할당 된 메모리 할당/할당 해제 및 마샬링 대신 위에 정의 된 구조를 사용할 수 있습니다.

+0

C#에서 정의한 구조 게시하기 구조체의 크기를 명확하게 정의해야합니다. –

+0

@Ramhound 현재 구조는 내가 개별적으로 쓰는 원시 메모리입니다. PInvoke에서 정의한 구조는 내가 게시 한 링크에 있습니다. 나는 거기에 그것을 보여주기 위해 편집 할 것이다. –

+0

'c : \ Windows \ System32 \ SetupApi.dll'을 DLL 이름으로 사용하는 것은 좋지 않습니다. 경로를 하드 코딩하면 위험합니다. 그냥'setupapi.dll'을 사용하십시오. –

답변

0

이 대답에서 코드를 복사했기 때문에이 구조체에 넘어갔습니다. https://stackoverflow.com/a/2937588/1070906 구조체 정의에 오류가 있습니다. 아마 같은 실수를했을 수도 있습니다.

http://msdn.microsoft.com/en-us/library/windows/hardware/ff552344(v=vs.85).aspx에서 SP_DEVINFO_DATA의 정의를 보면 마지막 매개 변수는 포인터이며 다른 게시물과 동일한 것이 아닙니다.

[StructLayout(LayoutKind.Sequential)] 
private struct SP_DEVINFO_DATA 
{ 
    /// <summary>Size of the structure, in bytes.</summary> 
    public uint cbSize; 
    /// <summary>GUID of the device interface class.</summary> 
    public Guid ClassGuid; 
    /// <summary>Handle to this device instance.</summary> 
    public uint DevInst; 
    /// <summary>Reserved; do not use.</summary> 
    public IntPtr Reserved; 
} 
작동

: 난에 구조체 정의를 변경 때문에

!

Marshall.SizeOf (new SP_DEVINFO_DATA())는 28 대신 현재 32를 반환하고 직렬 포트가 표시됩니다.

+0

내 문제는 SP_DEVINFO_DATA의 정의가 아니라 SP_DEVICE_INTERFACE_DETAIL_DATA입니다. 솔루션은 David Heffernan의 제안을 사용하고 단순히 AllocHGlobal을 사용하여 필요한 메모리를 할당하고 손으로 노력해야한다고 생각합니다. –

관련 문제