tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルVB6.0で使用したDLLをVB.NETで使用したい
記事No5944
投稿日: 2007/07/30(Mon) 18:45
投稿者まいど
初めまして、「まいど」と申します。

VB.NETで質問があります。

VB6.0で使用した(動作は確認とれてます。)DLLを.NETで使用したいのですが、エラーが発行されます。
以下、内容

"AccessViolationException"
保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。

ソースは"declare"を使用しています。
何か必要な設定等があるのでしょうか?
ソース自体はほぼVB6.0からコピーする形でコーディングしました。

よろしくお願いします。

[ツリー表示へ]
タイトルRe: VB6.0で使用したDLLをVB.NETで使用したい
記事No5945
投稿日: 2007/07/30(Mon) 19:53
投稿者よねKEN
> ソースは"declare"を使用しています。
> 何か必要な設定等があるのでしょうか?
> ソース自体はほぼVB6.0からコピーする形でコーディングしました。

VB6とVB.NETでは結構変わっていますので、VB6のソースそのままでは問題があることがほとんどです。
Declareで宣言して使用している外部DLLの場合、
Declare文、および、それを使用している箇所のコードの見直しが必要です。

例えば、VB6のLong(32bit)はVB.NETのLong(64bit)と型のサイズが異なります。
こういった場合にVB.NETではInteger(32bit)を使う必要のある場合が多いです。
#より適切な型を利用するにはそのDLLのC言語などでの宣言をみないとわからない場合もあります。

> よろしくお願いします。

Declareを使う場合に関係する変更点はいくつかありますので、
Declareで宣言している箇所とその関数を利用している箇所付近の関連ソースを
みないとこれくらいしか言えないですね。

[ツリー表示へ]
タイトルRe^2: VB6.0で使用したDLLをVB.NETで使用したい
記事No5948
投稿日: 2007/07/31(Tue) 08:58
投稿者ファラダ
TEST

[ツリー表示へ]
タイトルRe^2: VB6.0で使用したDLLをVB.NETで使用したい
記事No5949
投稿日: 2007/07/31(Tue) 09:07
投稿者まいど
> > ソースは"declare"を使用しています。
> > 何か必要な設定等があるのでしょうか?
> > ソース自体はほぼVB6.0からコピーする形でコーディングしました。
>
> VB6とVB.NETでは結構変わっていますので、VB6のソースそのままでは問題があることがほとんどです。
> Declareで宣言して使用している外部DLLの場合、
> Declare文、および、それを使用している箇所のコードの見直しが必要です。
>
> 例えば、VB6のLong(32bit)はVB.NETのLong(64bit)と型のサイズが異なります。
> こういった場合にVB.NETではInteger(32bit)を使う必要のある場合が多いです。
> #より適切な型を利用するにはそのDLLのC言語などでの宣言をみないとわからない場合もあります。
>
> > よろしくお願いします。
>
> Declareを使う場合に関係する変更点はいくつかありますので、
> Declareで宣言している箇所とその関数を利用している箇所付近の関連ソースを
> みないとこれくらいしか言えないですね。

ありがとうございます。色々勉強になります。
ソースの方を掲載します。(DLLはオリジナルなので、名称等は記載できません。申し訳ない)。他の名称で何のソースか分かるかもしれませんが…
************************************************************Mojule@
    Structure SIDE_STATUS
        Dim mem0 As Long        
        Dim mem1 As Long              
        Dim mem2 As Long              
        Dim mem3 As Long              
        Dim mem4 As Long              
        Dim mem5 As Long              
    End Structure

    Structure CARD_STATUS
        Dim status As Long                
        Dim state() As Long                  
        Dim ScannerName() As Byte    
        Dim ScannerVer() As Byte      
        Dim SerialNumber() As Byte    
        Dim FirmVer() As Byte        
        Dim Ri10_1Ver() As Byte      
        Dim Ri10_2Ver() As Byte      
        Dim FPGA_Ver() As Byte        
        Dim side() As SIDE_STATUS      )
    End Structure

    Structure CARD_STATUS_OCR
        Dim CARDSTATUS As CARD_STATUS                        
        Dim fullname() As Byte
        Dim birthday() As Byte
        Dim domicile() As Byte
        Dim address() As Byte
        Dim grantday() As Byte
        Dim validity() As Byte
        Dim license() As Byte
        Dim acquisition1() As Byte
        Dim acquisition2() As Byte
        Dim acquisition3() As Byte
        Dim condition() As Byte
    End Structure

    Public Structure BITMAPFILEHEADER
        Dim bfType As Integer
        Dim bfSize As Long
        Dim bfReserved1 As Integer
        Dim bfReserved2 As Integer
        Dim bfOffBits As Long
    End Structure

    Public Structure BITMAPINFOHEADER
        Dim biSize As Long
        Dim biWidth As Long
        Dim biHeight As Long
        Dim biPlanes As Integer
        Dim biBitCount As Integer
        Dim biCompression As Long
        Dim biSizeImage As Long
        Dim biXPelsPerMeter As Long
        Dim biYPelsPerMeter As Long
        Dim biClrUsed As Long
        Dim biClrImportant As Long
    End Structure
    Public Structure RGBQUAD
        Dim rgbBlue As Byte
        Dim rgbGreen As Byte
        Dim rgbRed As Byte
        Dim rgbReserved As Byte
    End Structure
    Public Structure BITMAPINFO
        Dim bmiHeader As BITMAPINFOHEADER
        Dim bmiColors() As RGBQUAD
    End Structure

    Declare Function CardScanStart Lib "aaaaa" (ByVal crdSts As CARD_STATUS_OCR) As Long
************************************************************Form@
    Dim lngRst As Long
    Dim crdStsOcr As CARD_STATUS_OCR
    Private Sub RD_Timer_Tick(ByVal sender As System.Object,
        _ByVal e As System.EventArgs) Handles RD_Timer.Tick
        lngRst = CardScanStart(crdStsOcr) ←実行時のエラー発生箇所
    End Sub
************************************************************

こんな感じなのですが…VB6.0のコードをほぼそのままで、.NETに移行した感じです。よろしくお願いします。

[ツリー表示へ]
タイトルRe^3: VB6.0で使用したDLLをVB.NETで使用したい
記事No5952
投稿日: 2007/07/31(Tue) 09:47
投稿者魔界の仮面弁士
API に渡す構造体は、適切な StructLayout 属性を付加しておいた方が安全ですよ。

それと、VB.NET と VB6 では、整数型のサイズも異なります。
API の仕様にあわせて、適切なデータ型を選択する必要があります

 16bit 整数なら …… (VB6) Integer / (VB.NET) Short または UShort
 32bit 整数なら …… (VB6) Long / (VB.NET) Integer または UInteger
 64bit 整数なら …… (VB6) Currency または 2個のLong / (VB.NET) Long または ULong


>     Public Structure BITMAPFILEHEADER
>         Dim bfType As Integer
>         Dim bfSize As Long

ということで、宣言が間違っていますね。

[ツリー表示へ]
タイトルRe^4: VB6.0で使用したDLLをVB.NETで使用したい
記事No5955
投稿日: 2007/07/31(Tue) 10:02
投稿者まいど
> API に渡す構造体は、適切な StructLayout 属性を付加しておいた方が安全ですよ。
>
> それと、VB.NET と VB6 では、整数型のサイズも異なります。
> API の仕様にあわせて、適切なデータ型を選択する必要があります
>
>  16bit 整数なら …… (VB6) Integer / (VB.NET) Short または UShort
>  32bit 整数なら …… (VB6) Long / (VB.NET) Integer または UInteger
>  64bit 整数なら …… (VB6) Currency または 2個のLong / (VB.NET) Long または ULong
>
>
> >     Public Structure BITMAPFILEHEADER
> >         Dim bfType As Integer
> >         Dim bfSize As Long
>
> ということで、宣言が間違っていますね。

回答ありがとうございます。
【結果】
宣言はすべて修正後、再実行しましたが、同様のエラーでこけました。

もしかすると、配列構造(100)となっていたのを()にしたのが駄目だったのかもと思って今、修正しています。.NETでStructure内では配列は宣言できないみたいでしたので、削除後に実行していました。Redimは行っていません。

色々、助言いただきありがとうございます。

[ツリー表示へ]
タイトルRe^3: VB6.0で使用したDLLをVB.NETで使用したい
記事No5954
投稿日: 2007/07/31(Tue) 10:01
投稿者よねKEN
#先も書きましたが、DLLを作成した言語側でのオリジナルの各構造体定義を見ないと
#正確なことはわかりませんので、参考までに。

Integer → Short
Long → Integer
の変更を行えば、うまく行きそうな感じがします。

後、各構造体の定義前に
<StructLayout(LayoutKind.Sequential)> _
を付加しておいた方がよさそうです。

例)
<StructLayout(LayoutKind.Sequential)> _
Public Structure BITMAPINFOHEADER

<参考>
「VB 6.0 ユーザーのための VB .NET 移行ガイド - Short、Integer、Long」
http://www.microsoft.com/japan/msdn/net/vbtransitionguide/chapter4/chapter4_3.aspx
「KEN's .NET [特集6] GetPrivateProfileStringにみるAPIの使用方法 」
http://www5b.biglobe.ne.jp/~yone-ken/VBNET/special/sp06_GetPrivateProfileString.html
「値型に対する既定のマーシャリング」
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/cpguide/html/cpconDefaultMarshalingForValueTypes.asp

[ツリー表示へ]
タイトルRe^4: VB6.0で使用したDLLをVB.NETで使用したい
記事No5956
投稿日: 2007/07/31(Tue) 10:11
投稿者まいど
> #先も書きましたが、DLLを作成した言語側でのオリジナルの各構造体定義を見ないと
> #正確なことはわかりませんので、参考までに。
>
> Integer → Short
> Long → Integer
> の変更を行えば、うまく行きそうな感じがします。
>
> 後、各構造体の定義前に
> <StructLayout(LayoutKind.Sequential)> _
> を付加しておいた方がよさそうです。
>
> 例)
> <StructLayout(LayoutKind.Sequential)> _
> Public Structure BITMAPINFOHEADER
>
> <参考>
> 「VB 6.0 ユーザーのための VB .NET 移行ガイド - Short、Integer、Long」
> http://www.microsoft.com/japan/msdn/net/vbtransitionguide/chapter4/chapter4_3.aspx
> 「KEN's .NET [特集6] GetPrivateProfileStringにみるAPIの使用方法 」
> http://www5b.biglobe.ne.jp/~yone-ken/VBNET/special/sp06_GetPrivateProfileString.html
> 「値型に対する既定のマーシャリング」
> http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/cpguide/html/cpconDefaultMarshalingForValueTypes.asp

ありがとうございます。上記方法、試してみます。

[ツリー表示へ]
タイトルRe^5: VB6.0で使用したDLLをVB.NETで使用したい
記事No5957
投稿日: 2007/07/31(Tue) 10:47
投稿者まいど
> > #先も書きましたが、DLLを作成した言語側でのオリジナルの各構造体定義を見ないと
> > #正確なことはわかりませんので、参考までに。
> >
> > Integer → Short
> > Long → Integer
> > の変更を行えば、うまく行きそうな感じがします。
> >
> > 後、各構造体の定義前に
> > <StructLayout(LayoutKind.Sequential)> _
> > を付加しておいた方がよさそうです。
> >
> > 例)
> > <StructLayout(LayoutKind.Sequential)> _
> > Public Structure BITMAPINFOHEADER
> >
> > <参考>
> > 「VB 6.0 ユーザーのための VB .NET 移行ガイド - Short、Integer、Long」
> > http://www.microsoft.com/japan/msdn/net/vbtransitionguide/chapter4/chapter4_3.aspx
> > 「KEN's .NET [特集6] GetPrivateProfileStringにみるAPIの使用方法 」
> > http://www5b.biglobe.ne.jp/~yone-ken/VBNET/special/sp06_GetPrivateProfileString.html
> > 「値型に対する既定のマーシャリング」
> > http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/cpguide/html/cpconDefaultMarshalingForValueTypes.asp
>
> ありがとうございます。上記方法、試してみます。

→結果です。
    @<StructLayout(LayoutKind.Sequential)> _ の付加
  A宣言部の変更

してみましたが、やはり結果はNGでした。
これは根本的な問題で私のコーディングがおかしいとしか思えません。
お二方のアドバイスをヒントに再度、調査したいと思います。

とても勉強になりました。ありがとうございました。

[ツリー表示へ]
タイトルRe^6: VB6.0で使用したDLLをVB.NETで使用したい
記事No5962
投稿日: 2007/07/31(Tue) 12:38
投稿者魔界の仮面弁士
>     <StructLayout(LayoutKind.Sequential)> _ の付加
Pack 引数も指定しておいた方が良いでしょう。

VB6 でのアライメントは Pack:=4 固定なのですが、.NET の標準は Pack:=8 です。
また、API によっては、Pack:=1 を要求するものもあります。

それと、要素数が固定の配列メンバを含む場合には、それぞれのメンバに
MarshalAs 属性を付加して、固定長構造体配列メンバとして宣言してみてください。

[ツリー表示へ]
タイトルRe^7: VB6.0で使用したDLLをVB.NETで使用したい
記事No5967
投稿日: 2007/07/31(Tue) 14:12
投稿者まいど
どうもありがとうございます。まいどです。

> >     <StructLayout(LayoutKind.Sequential)> _ の付加
> Pack 引数も指定しておいた方が良いでしょう。
>
> VB6 でのアライメントは Pack:=4 固定なのですが、.NET の標準は Pack:=8 です。
> また、API によっては、Pack:=1 を要求するものもあります。
>
> それと、要素数が固定の配列メンバを含む場合には、それぞれのメンバに
> MarshalAs 属性を付加して、固定長構造体配列メンバとして宣言してみてください。

→うまくいかないというか、使えないみたいです。
System.Runtime.InteropServices.MarshalDirectiveException はハンドルされませんでした。
  Message="'return value' をマーシャリングできません: 無効なマネージ/アンマネージ型の組み合わせです。Int32/UInt32 は I4、U4、または Error と組で使用してください。"

これはInt属性の定義はできないということなのでしょうか?
もしくはpackが間違っている?一応、1、4、8、すべて試しました。
結果はNGです。

> >     <StructLayout(LayoutKind.Sequential)> _ の付加

ですが、上記を付加したことによって、パラメータが間違いというエラーに変わりました。

結果はまだ解決していないですが、少しずつ紐解きたいと思います。

[ツリー表示へ]