• 締切済み

[C#] DeviceIoControlの変数の型

Visual C# 2008でDeviceIoControlを利用して USBを操作しようとしているのですが、 DLLImportの時に指定する変数の型がわからないのです。 BOOL DeviceIoControl( HANDLE hDevice, // デバイス、ファイル、ディレクトリいずれかのハンドル DWORD dwIoControlCode, // 実行する動作の制御コード LPVOID lpInBuffer, // 入力データを供給するバッファへのポインタ DWORD nInBufferSize, // 入力バッファのバイト単位のサイズ LPVOID lpOutBuffer, // 出力データを受け取るバッファへのポインタ DWORD nOutBufferSize, // 出力バッファのバイト単位のサイズ LPDWORD lpBytesReturned, // バイト数を受け取る変数へのポインタ LPOVERLAPPED lpOverlapped // 非同期動作を表す構造体へのポインタ ); と、MSDNに載っていて [DllImport("kernel32", SetLastError = true)] private static extern bool DeviceIoControl( IntPtr hDevice, // デバイス、ファイル、ディレクトリいずれかのハンドル uint dwIoControlCode, // 実行する動作の制御コード ref byte[] lpInBuffer, uint nInBufferSize, // 入力バッファのバイト単位のサイズ ref byte[] lpOutBuffer, uint nOutBufferSize, // 出力バッファのバイト単位のサイズ ref int lpBytesReturned, // バイト数を受け取る変数へのポインタ int Overlapped // overlapped buffer ); と、して Bool ret = DeviceIoControl(hDevice,123456,null,0,null,0,0); と、しても戻り値がfalseにしかなりません。 具体的には byte配列で{ 0x01, 0x23, 0x45, 0x67, 0,89}のような値を入力データにして byte bytes = new byte[10]; で、確保したbytesに出力データを受け取りたいのです。 どのようにすればよいでしょうか?

みんなの回答

回答No.1

APIのBOOL型をbool型にマーシャルする場合は,明示的に指定する必要があります。 つまり, [return: MarshalAs(UnmanagedType.Bool)] という属性がDeviceIoControlに必要です。 あとは,Marshal.GetLastWin32Errorでエラーコードを取得して調べていくしか……。

knoppixer
質問者

補足

ありがとうございます。 下のようにやってみたのですが、errorの値は 87(パラメータが正しくありません)となってしまいます。 入力データは全て0x00で4バイト分、 出力のバッファは10バイトでDeviceIoControlを呼び足したいのですが・・・ hDeviceの取得は失敗しておらず、 byte[] Buf = null int abc = 0; DeviceIoControl(hDevice, 2236465, ref Buf, 0, ref Buf, 0, ref abc, 0) とした時は、GetLastError()で取得した値が0で成功していました。 どこのパラメータが不正なのでしょうか? [DllImport("kernel32", SetLastError = true)] private static extern bool DeviceIoControl( IntPtr hDevice, // デバイス、ファイル、ディレクトリいずれかのハンドル uint dwIoControlCode, // 実行する動作の制御コード ref byte[] lpInBuffer, uint nInBufferSize, // 入力バッファのバイト単位のサイズ ref byte[] lpOutBuffer, uint nOutBufferSize, // 出力バッファのバイト単位のサイズ ref int lpBytesReturned, // バイト数を受け取る変数へのポインタ int Overlapped // overlapped buffer ); RetData = new byte[10]; SendData = new byte[4]; int test = 0; DeviceIoControl(hDevice, 2236497, ref SendData, 4, ref RetData, 10, ref test, 0); int error = Marshal.GetLastWin32Error();

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 未割り当てのローカル変数

    未割り当てのローカル変数 '' が使用されました。と出てコンパイルできません・・。 以下ソースです。 [DllImport("kernel32.dll")] public static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe); public struct PROCESSENTRY32 { public uint dwSize; public uint cntUsage; public uint th32ProcessID; public uint th32DefaultHeapID; public uint th32ModuleID; public uint cntThreads; public uint th32ParentProcessID; public int pcPriClassBase; public uint dwFlags; public string szExeFile; } PROCESSENTRY32 pe; pe.dwSize = 0; pe.cntThreads = 0; pe.th32ProcessID = 0; pe.th32DefaultHeapID = 0; pe.th32ModuleID = 0; pe.cntThreads = 0; pe.th32ParentProcessID = 0; pe.pcPriClassBase = 0; pe.dwFlags = 0; pe.szExeFile = "aa"; bool bResult = Process32First(hSnap, ref pe); ~~~ こんな風に全部0で代入して初期化?してもエラーが出ます。 回答よろしくお願いします・・。

  • OVERLAPPED構造体が分かりません・・。

    シリアルポートで非同期データ通信するプログラム作成初歩段階です。 ReadFileの第5引数にはOVERLAPPED構造体へのポインタを指定することは分かったのですが。この構造体の各メンバにどんな値を入れたらいいのか分りません・・・。 よろしくお願いします。 typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; DWORD Offset; DWORD OffsetHigh; HANDLE hEvent; } OVERLAPPED;

  • C#からVC++DLLの呼び出しに失敗する

    VS.NET2005のC#からVC++6.0で作成したDLLを呼び出しています。 VCのデバッガでデバッグしてみると呼び出した関数は正常に動作しているようなのですが、最後のreturnを実行しC#に戻るところでエラーが出てしまいます。 C#側では「'System.ExecutionEngineException' のハンドルされていない例外が ConsoleApplication1.exe で発生しました。」となります。 C#での宣言は、 [DllImport("test.dll")] public static extern uint TestFunc(ref byte[] moji, ref uint nagasa); です。 VC++の宣言は、 __declspec(dllexport) unsigned long __stdcall TestFunc(unsigned char* moji, unsigned long* nagasa) です。 C#へ値を返さない関数は問題ないのですが、値を返そうとすると起きるようです。不備などあればご指摘いただけないでしょうか。 ちなみにVB6からは問題なく動作できました。

  • FormatMessageでのバッファサイズの指定

    FormatMessageでのバッファサイズの指定 DWORD FormatMessage( DWORD dwFlags, // 入力元と処理方法のオプション LPCVOID lpSource, // メッセージの入力元 DWORD dwMessageId, // メッセージ識別子 DWORD dwLanguageId, // 言語識別子 LPTSTR lpBuffer, // メッセージバッファ DWORD nSize, // メッセージバッファの最大サイズ va_list *Arguments // 複数のメッセージ挿入シーケンスからなる配列 ); 上記関数にて、「DWORD nSize, // メッセージバッファの最大サイズ」のところで バッファサイズの最大値を指定したいのですが、仕様を見ると 「0以外の値は、出力行の最大の文字数を表します。」となっています。 しかし、バイト数で指定したいのです。(2048バイト) 何か解決策、良い方法はありますでしょうか? よろしかったらご教授よろしくお願いいたします。

  • WTSEumerateSessionsでのデータの取得

    以下のプログラムで、&SessionInfoに戻ってきた データを表示させたいのですがうまくいきません。 教えていただきたいです。 #include<stdio.h> #include<windows.h> #include<wtsapi32.h> int main(){ char* name; //NetBIOS名の入れ物 char*型 HANDLE handle; //HANDLEの戻り値を取得する入れ物 BOOL bWts; //BOOLの戻り値を取得する入れ物 LPVOID lpMsgBuf; //WTSOpenでバファの格納するための入れ物 DWORD BytesReturned; //WTSOpenでバイト数を格納するための入れ物 WTS_INFO_CLASS WTSInfoClass; //WTSOpenで使う 接続情報を調べたい PWTS_SESSION_INFOA SessionInfo=NULL; DWORD Count=0; DWORD Reserved=0; DWORD Version=1; name=NULL; handle =WTSOpenServer(name); bWts = WTSEnumerateSessions( handle, Reserved, Version, &SessionInfo, &Count ); printf("セッション数は %d です\n",Count); WTSFreeMemory(SessionInfo); return 0; }

  • 基本的な質問です。

    SetDIBitsToDevice ( HDC hdc, int XDest, int YDest, DWORD dwWidth, DWORD dwHeight, int XSrc, int YSrc, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits, CONST BITMAPINFO *lpbmi, UINT fuColorUse=DIB_PAL_COLORS ) において lpvBitsには画像のデータ位置のポインタを指定し lpbmiには画像のBITMAPINFO値を指定するとして パレットはどこに指定するのでしょうか? lpbmiのサイズは40+4バイトであり パレットデータ用には1個(4バイト)しか用意されていません。 パレットデータが256個ある場合には他の255個入れる場所がありません。 これで絵が描けるのでしょうか?

  • C言語 ダブルポインタを引数にもつAPI

    GetBuf ( char ** address, size_t *dataSize ); 第1引数: バッファの先頭アドレスをかえす 第2引数: バッファサイズをByte単位で返す 戻り値 1:成功      -1 取得失敗 typedef struct Test_t{ char* tempAddr; /* 先頭アドレスを格納 */ int bufSize; /* サイズを格納 */ } test_t 上記のAPIから情報を取得し、以下の構造体にデータを保持しようとしていますが GetBuffのダブルポインタの情報を構造体のメンバtempAddrに格納するにはどうしたらよいでしょうか このAPIのように引数でダブルポインタを使用するケースは一般的なのでしょうか? 教えていただけるとうれしいです。 よろしくお願い致します。

  • C#で構造体の配列を持った構造体を使いたいのですが

    C#で構造体の配列を持った構造体を使いたいのですが Cならば struct xyz { struct abc _abc[32]; int index; }; struct abc { int a; int b; int c; }; struct xyz _xyz[8]; xyz[0]._abc[3].b = 1; のような使い方で という感じで やっていた事を C#で 同じような事をやろうとしても うまくいきません うまくやる方法をどなたかご存知ないでしょうか Visual Studio 2005行った場合 コンパイルで 構文エラーです。不適切な配列の宣言子です。マネージ配列を宣言するには、次元指定子を変数の識別子の前に指定します。固定サイズ バッファ フィールドを宣言するには、フィールド型の前に fixed キーワードを使用します となり fixed をつけると 固定サイズ バッファの型は次のうちの 1 つでなければなりません: bool、byte、short、int、long、char、sbyte、ushort、uint、ulong、float または double となってしまいます

  • 構造体の初期化の時にポインタを入れるにはどうしたらいいですか?

    構造体の初期化の時にポインタを入れるにはどうしたらいいですか? 例えば、このような構造体で↓ struct PACKET { uint16_t size; // データの長さ uint16_t *data; // データバイト列 }; 初期化の時にsizeとdataを入れるにはどうしたらいいのでしょうか? dataがuint16_t*じゃなくてchar*なら struct PACKET { uint16_t size; // データの長さ char *data; // データバイト列 }; struct PACKET p = { 5, "12345" }; というようにできるのですが・・・

  • PICとPCでのシリアル通信

    PICとPC間でのシリアル通信を行ってるんですけどうまくいきません。ハイパーターミナル使えばうまくいくんでPIC側のソース(C)はうまくいってると思います。ハイパーターミナルを使わずにシリアルの送受信のプログラム(C++)を組んでるんですけどうまくいかなくて。。。 アドバイスなどお願いします!!どこが違うんでしょうか。。。 ●PC側のソース(C++) #include "stdafx.h" #include <stdlib.h> #include <windows.h> #include<iostream> using namespace std; #define COM_PORT_NAME "COM1" #define BAUD_RATE 9600 #define BYTE_SIZE 8 #define PARITY EVENPARITY #define STOP_BIT TRUE #define F_PARITY ONESTOPBIT HANDLE hComm; // シリアルポートとの通信ハンドル bool ComInit() { // シリアルポートを開ける hComm = CreateFile( COM_PORT_NAME, /* シリアルポートの文字列 */ GENERIC_READ | GENERIC_WRITE, /* アクセスモード:読み書き */ 0, /* 共有モード:他からはアクセス不可 */ NULL, /* セキュリティ属性:ハンドル継承せず */ OPEN_EXISTING, /* 作成フラグ: */ FILE_ATTRIBUTE_NORMAL, /* 属性: */ NULL /* テンプレートのハンドル: */ ); if (hComm == INVALID_HANDLE_VALUE) { printf("シリアルポートを開くことが出来ませんでした。\n"); return false; } // 通信属性を設定する DCB dcb; GetCommState(hComm, &dcb); /* DCB を取得 */ dcb.BaudRate = BAUD_RATE; dcb.ByteSize = BYTE_SIZE; dcb.Parity = PARITY; dcb.fParity = STOP_BIT; dcb.StopBits = F_PARITY; SetCommState(hComm, &dcb); /* DCB を設定 */ return true; } void ComEnd() { // ハンドルを閉じる CloseHandle(hComm); } bool WriteData(char *buff, unsigned int data_size) { DWORD dwWritten; /* ポートへ書き込んだバイト数 */ WriteFile(hComm, buff, data_size, &dwWritten, NULL); if (dwWritten!=data_size) { printf("データの送信に失敗しました。\n"); return false; } return true; } bool ReadData(char *buff, unsigned int max_size) { DWORD dwErrors; /* エラー情報 */ COMSTAT ComStat; /* デバイスの状態 */ DWORD dwCount; /* 受信データのバイト数 */ DWORD dwRead; /* ポートから読み出したバイト数 */ ClearCommError(hComm, &dwErrors, &ComStat); dwCount = ComStat.cbInQue; if (dwCount > max_size) { printf("バッファサイズが足りません。\n"); return false; } ReadFile(hComm, buff, dwCount, &dwRead, NULL); if (dwCount != dwRead) { printf("データの受け取りに失敗しました。\n"); return false; } return true; } int main(int argc, char* argv[]) { char ch; while(1){ cin >> ch; printf("入力 %c\n", ch); ComInit(); WriteData(&ch, strlen(&ch)); ReadData(&ch, strlen(&ch)); ComEnd(); } return 0; }