5

最初に、ばかげたことを言っても許してください。私は IT 担当者ではなく、電子工学エンジニアですが、より多くのスキルを必要とする仕事に割り当てられています。

SD カードの物理セクターを読み書きする必要があります。私は C++ でそれを達成しましたが、メインのアプリケーションは C# で書かれているので、最初の dll を書くのに良い瞬間だと思いました。

これは、セクターを書き込むために c++ で動作するコードです。

private: System::Void button4_Click(System::Object^  sender, System::EventArgs^  e) {
HANDLE hFile   = INVALID_HANDLE_VALUE;
    BOOL fSuccess  = FALSE;


    DWORD dwBytesWritten = 0; 

    unsigned char  chBuffer[SIZE]; 

    long SectorActual = 39;
    long PosicionInicio = SectorActual * 512;

        for (int i=0; i<SIZE; i++) // Garbage values to be written
        {
            chBuffer[i]= i % 16;
            if((i/16)%2==0)
            {
                chBuffer[i]= 15 - chBuffer[i];
            }
        }
        hFile = CreateFileA("\\\\.\\PhysicalDrive5",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

        if (hFile == INVALID_HANDLE_VALUE) 
        { 
            textBox1->Text += "Could not open file (error " + GetLastError() + ") \r\n";
            return; 
        }

        DWORD dwPtr = SetFilePointer( hFile, 
                                PosicionInicio, 
                                NULL, 
                                FILE_BEGIN ); 

        if (dwPtr == INVALID_SET_FILE_POINTER) // Test for failure
        { 
            textBox1->Text += "Error moving pointer (error " + GetLastError() + ") \r\n";
            return;     // Deal with failure 
        } // End of error handler 

        fSuccess = WriteFile(hFile, chBuffer, TAMANYO_SECTOR, &dwBytesWritten, NULL); 
        if (!fSuccess) 
        {
            textBox1->Text += "WriteFile failed\r\n";
        }
        else
        {
            textBox1->Text += "WriteFile wrote " + dwBytesWritten.ToString() + " bytes\r\n";
        }

        CloseHandle(hFile);
    }

次に、DLL を作成しました。機能は次のとおりです。

 int AccesoBajoNivel::EscribeBloqueFisico(char numeroDisco, unsigned char * buffer, long      BytesQueEscribir, long posicion_inicio)
{
    HANDLE hFile   = INVALID_HANDLE_VALUE;
            BOOL fSuccess  = FALSE;
    DWORD dwBytesWritten = 0; 

    char ArrayDeChars[] = "\\\\.\\PhysicalDrive5";
            ArrayDeChars[17] = numeroDisco;
    LPCSTR pathAlDisco = ArrayDeChars;

    hFile = CreateFileA(pathAlDisco,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

    if (hFile == INVALID_HANDLE_VALUE) 
    { 
        //printf("Could not open file (error %d)\n", GetLastError());
        CloseHandle(hFile);
        return -1; 
    }

    DWORD dwPtr = SetFilePointer( hFile, 
                            posicion_inicio, 
                            NULL, 
                            FILE_BEGIN ); 

    if (dwPtr == INVALID_SET_FILE_POINTER) // Test for failure
    { 
        CloseHandle(hFile);
        return -2;     // Deal with failure 
    } // End of error handler 

    fSuccess = WriteFile(hFile, buffer, BytesQueEscribir, &dwBytesWritten, NULL); 
    if (!fSuccess) 
    {
        CloseHandle(hFile);
        return -3;
    }
    else
    {
        CloseHandle(hFile);
        //return dwBytesWritten;
        return dwPtr;
    }

    CloseHandle(hFile);
}

次に、C# プロジェクトにインポートしました。

[DllImport("AccesoBajoNivel.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int EscribeBloqueFisico(char numeroDisco, byte[] buffer, long BytesQueEscribir, long posicion_inicio);

次に、関数を呼び出します。

int ResultEscribir = EscribeBloqueFisico(numeroDiscoFisico, BufferEscritura, 512, SectorEscribir * 512);

「posicion_inicio」の値に関係なく、常に最初のセクターに書き込みます (開始オフセットです。スペイン語のタグについては申し訳ありません) . これは常にゼロのように見えますが、これは明らかに私が望んでいるものではありません。しかし、最初の関数が機能し、dll 呼び出しが機能しない理由がわかりません。

一見するとわかるかもしれませんが、私が言ったように、私はこの種のプログラミングに慣れていない電子工学の男です...

他の機能 (DISK_GEOMETRY または VOLUME_DISK_EXTENTS の読み取りとして) が機能し、これを使用して、どの物理ドライブが特定の論理ユニットであるかを判断します。また、私が言うように、書き込みと読み取りはうまく機能しますが、常にセクター 0 を指しているだけです...

前もって感謝します。また、こちらに投稿するのは初めてです。何度も読みました(それが私がここで質問することを選んだ理由です)が、質問を投稿するときに間違いを犯した場合は、それを指摘してください.

4

1 に答える 1

3

C++のlongは32ビットです。これにより、C#ではintになります。pinvoke宣言でlongをintに置き換えます。

あなたはそれについてのPInvokeStackImbalance警告を受け取っているはずです。警告をオフにした場合は、必ずその警告を再度有効にしてください。また、デバッガーで*position_inicio*の値が間違っていることは簡単にわかります。アンマネージデバッグ、[プロジェクト+プロパティ]、[デバッグ]タブを必ず有効にしてください。これで、C++コードにブレークポイントを設定できます。

于 2012-10-18T08:35:38.983 に答える