SetupDiGetDeviceInterfaceDetail()hereを呼び出していて、SP_DEVICE_INTERFACE_DETAIL_DATA構造体が正しくマーシャリングしていません。構造体の定義はhereです。私はPInvoke.net、hereからこの構造の定義を使用しようとしましたが、役に立たないです。32ビットおよび64ビットランタイムの動的構造を整理する
これまでは、関数の呼び出しが成功したとき(つまり、マーシャラがエラーをスローしない)、戻り値は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でメモリを割り当てる)と元帥を使用して、そのバッファからの書き込み/読み出しデータ午前関数の*家族。
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;
}
を私が述べたように、私はSP_DEVICE_INTERFACE_DETAIL_DATAためPInvoke.netによって概説されているような構造を定義しようとした(リンク上記参照)と新しいを作りました:参考までに、これは私がやっている
ですそれを処理するPInvokeメソッドのシグネチャ。 64ビットシステムから実行すると、同じ問題が発生します。つまり、関数は1784を返します。その理由は、C#での参照が64ビットのランタイムで実行されている場合、8バイトで整列されているStackOverflow記事)。私はその構造体にレイアウトを(明示的とフィールドオフセットを使用して)強制的に4バイト整列構造体にしようと試みましたが、それも私のためには機能しませんでした。コンパイル時に問題がありました。
私はPInvokeメソッドのシグネチャパラメータにさまざまなデコレーションを使用しようとしました。 MarshalAs(UnmanagedType.LPStruct)のように、私は不当に続けてペアリングを続けています。私は今、私がこの点で助けが必要であるという点までいます。
私が実際に理解していないことは、なぜそれが全く起こっているのかということです。 32ビットのランタイムで動作するときに私のボックスで動作しても、64ビットのランタイムはセットアップAPIの正しい64ビットバージョンに接続するだけではありませんか?どうしたの?任意の助け
おかげで、
問題は、良いことは、それが今解かれますされ、刺激性のものは、私は1時間か2時間の範囲内のものを固定好きではないです
を解決している アンディここに投稿してください。だから問題は確かに64ビット問題だった。 Marshal.GetLastWin32Error()のエラーコードが問題を伝えていました。 cbSize値が正しくありませんでした。私はそれを8に変更しました。
64ビットのサイズが8になった理由を教えてください。構造は今以上です(投稿者は私にそれを含めるように頼んだ)。構造体は、1つのDWORDとTCHAR [ANYSIZE_ARRAY]という2つのメンバで構成されています。 ANYSIZE_ARRAYは1と評価され、TCHARはUnicodeの場合は常にWCHAR、それ以外の場合はcharです。 DWORDは常に32ビット(4バイト)で、ユニコード用のTCHARは2バイトです。したがって、4 + 2 = 6.なぜ8ですか?これは、64ビットでその構造のバイトアライメントのためですか?私は本当にこれを理解したいと思います。
いずれにしても、cbSizeメンバーを64ビットで8、そして32ビットで6に設定すると、私は割り当てられていないメモリの割り当て/割り当て解除とマーシャリングの代わりに上記で定義した構造体を使用できます。
C#で定義した構造体を投稿する構造体のサイズを明確に定義する必要があります。 –
@Ramhound現在のところ、この構造は、私が個別に書いている生のメモリです。私がPInvokeから定義した構造は、私が投稿したリンクです。私はそこにそれを示すために編集する。 –
'c:\ Windows \ System32 \ SetupApi.dll'をあなたのDLL名にするのは悪い考えです。そのパスをハードコーディングするのは危険です。ちょうど 'setupapi.dll'を使用してください。 –