4.1 The VBMigrationPartner_Support module/VB Migration Partnerサポートモジュール
4.2 Code analysis features/コード解析機能
4.3 Refactoring features/リファクタリング機能
4.4 Extenders/機能拡張
4.5 Support for 3rd-party ActiveX controls/サードパーティActiveXコントロール対応
4.6 Using the VBMP command-line tool/VBMPのコマンドラインツールを利用する
4.7 The VB Project Dumper add-in/VBプロジェクトのダンパーアドイン
4.8 Support for Dynamic Data Exchange (DDE)/動的データ交換(DDE)対応
4. Advanced Topics/アドバンストトピックス
4.1 The VBMigrationPartner_Support module/VB Migration Partnerサポートモジュール
While VB Migration Partner can often automatically translate most VB6 constructs, in some cases it is necessary for you to either modify the VB6 code before the conversion or modify the VB.NET code after the conversion process.
VB Migration Partnerは多くの場合自動的にVB6の構造物を変換することができますが、いくつかのケースにおいて変換前にVB6のコードを修正するか、または変換プロセスの後で、VB.NETのコードを修正する必要があります。
In general, we recommend that you don’t alter the original VB6 code in a significant way if the VB6 application is still in production, because relevant edits should be thoroughly tested and validated. If you edit the original VB6 application you should be guaranteed that your edits don’t change the application’s behavior.
一般的に、VB6のアプリケーションがまだ稼動中であれば、大きな観点でオリジナルのVB6コードを修正しないことをお勧めします。なぜなら適切な修正がなされたかどうか徹底的にテストされ、正しい動作が確認されるべきであるからです。もしオリジナルのVB6アプリケーションを修正したのであれば、修正した箇所がアプリケーションの動作を変えないことを保証されるべきです。
Ideally, you should modify the VB6 code only by means of pragmas. Pragmas are just remarks, therefore they can’t affect the original application in any way. For example, you can use the InsertStatement pragma to insert VB.NET statements in the middle of the code to be migrated:
理想的には、PragmaによってのみVB6コードを修正すべきです。Pragmaはただのコメントです。したがって、それらはどのような方法でもオリジナルのVB6アプリケーションに影響を及ぼすことはできません。例えば、変換しようとするコードの真ん中にVB.NETのステートメントを挿入するようにInsertStatement Pragmaを使うことができます。
'## InsertStatement If x < 0 Then Return x
The main limitation of the InsertStatement pragma is that it can only insert entire VB.NET statements; it can’t, for example, add function calls in the middle of an expression.
InsertStatement Pragmaの主要な制限は完全なVB.NETのステートメントのみ挿入することができるということです。例えば、式の真ん中にファンクションコールを追加することはできません。
VB Migration Partner comes with a special VB6 module – stored in the VBMigrationPartner_Support.bas file – that contains many special methods that you can use in your VB6 applications to prepare them for a smooth translation to VB.NET. You need to include this module in the VB6 project being converted, so that you can use these methods; VB Migration Partner never translates this module nor includes it in the migrated VB.NET.
VB Migration Partnerは特別なVB6モジュールを搭載しており、そのモジュールはVBMigrationPartner_Support.basファイルに格納されています。VB6モジュールにはたくさんの特別なメソッドが含まれており、VB.NETへのスムーズな変換を準備できるようにVB6アプリケーションの中で使用することができます。これらのメソッド使用することができるように、変換されるVB6プロジェクトにこのモジュールを含める必要があります。VB Migration Partnerはこのモジュールを変換しませんし、変換されたVB.NETにもそれを含めません。
All the methods in this support module have names with a trailing “6” character, therefore chances of name clashing with other methods or variables in the original VB6 application are negligible. All these methods are just “do-nothing” or “pass-through” methods and don’t alter VB6 behavior. To see how these methods can be useful, consider the following VB6 code fragment:
このサポートモジュールの全てのメソッドは末尾に“6”という文字を付加した名前を持っています。よって、VB6アプリケーションの中で他のメソッドや変数に名前が衝突することはめったに起こらないことになります。全てのこれらのメソッドはただの“do-nothing”または“pass-through”メソッドで、VB6の動作を変えることはありません。これらのメソッドがどのように有益なものとなるかを見るために、次のVB6コード断片を御覧ください。
' change fore and back color properties of an object, if possible
可能であれば、オブジェクトのForeColorとBackColorプロパティをチェンジします
Sub ChangeColor(ByVal obj As Object, ByVal foreColor As Long, ByVal backColor As Long)
On Error Resume Next
obj.ForeColor = foreColor
obj.BackColor = backColor
End Sub
The problem with this code is that the target object is accessed through late binding, therefore VB Migration Partner has no way to determine that the ForeColor and BackColor properties take a System.Drawing.Color object and that a conversion from the 32-bit integer is needed.
このコードの問題は遅延バインディングでターゲットのオブジェクトがアクセスされるということです。したがって、VB Migration Partnerには、ForeColorとBackColorのプロパティがSystem.Drawing.Colorオブジェクトを使うことや、32ビットの整数からの変換が必要であることを決定する方法がありません。
One way to solve this problem is by means of the FromOleColor6 method defined in the VBMigrationPartner_Support module. After adding the module to current VB6 project, change the original code as follows:
この問題を解決するひとつの方法としては、VBMigrationPartner_Supportモジュールに定義されているFromOleColor6によって解決することができます。当該VB6プロジェクトにそのモジュールを追加した後で、次のようにオリジナルコードを変更してください。
' change fore and back color properties of an object, if possible
可能であれば、オブジェクトのForeColorとBackColorプロパティをチェンジします
Sub ChangeColor(ByVal obj As Object, ByVal foreColor As Long, ByVal backColor As Long)
On Error Resume Next
obj.ForeColor = FromOleColor6(foreColor)
obj.BackColor = FromOleColor6(backColor)
End Sub
The FromOleColor6 method is a “pass-through” method: it takes a 32-bit integer and returns it to the caller, without modifying it in any way. This ensures that the VB6 code continues to work as before the edit. However, when the code is translated to VB.NET, the VBMigrationPartner_Support module is discarded and the converted VB.NET code now references the FromOleColor6 method defined in the language support library, which converts a 32-bit value to the corresponding System.Drawing.Color object. The bottom line: the converted VB.NET code works like the original application and no manual fix after the migration is needed.
FromOleColor6メソッドは“Pass – Through”メソッドです。32ビットの整数を取り、全く修正せずにCallerに戻します。これはコードを編集する前と同様にVB6コードが動作を継続するということを保証します。しかし、コードがVB.NETに変換された際に、VBMigrationPartner_Supportモジュールは捨てられます。そして変換されたVB.NETコードは、次にLanguageサポートライブラリ内に定義されたFromOleColor6メソッドを参照し、32ビットの値を対応したSystem.Drawing.Colorオブジェクトに変換します。結論:移行が必要であった後に、手動で修正することなく、変換されたVB.NETコードはオリジナルアプリケーションのように動作します。
The VBMigrationPartner_Support module contains several conversion methods. You can use them when VB Migration Partner isn’t able to detect the type used in an expression or in an assignment, for example when the value is held in a Variant variable:
VBMigrationPartner_Supportモジュールは様々な変換メソッドを含みます。VB Migration Partnerが式や代入で使用されている型を検出できない場合にそれらを使用することができます。例えば、値がバリアント変数に保持されている場合です。
FromOleColor6, ToOleColor6:
FromOleColor6 convert a 32-bit integer into a .NET Color value, whereas ToOleColor6 converts a .NET Color value into the corresponding 32-bit integer.
FromOleColor6は32ビットの整数を.NET Color値に変換する一方で、ToOleColor6は.NET Color値を対応する32ビットの整数に変換します。
RGB6, QBColor6:
Similar to RGB and QBColor methods, except they return a .NET Color object.
.NET Color オブジェクトを戻す以外は、RGBとQBColorメソッドと同様です。
DateToDouble6, DoubleToDate6:
Explicitly convert a Date value to a Double value, and vice versa.
明確にDate値をDouble値に変換します、そして、逆もまた同様です。
ByteArrayToString6, StringToByteArray6:
Explicit convert a Byte array to a String value, and vice versa.
明確にバイト配列をString値に変換します、そして、逆もまた同様です。
Another group of methods force VB Migration Partner to generate the correct code when you access a Font object in late-bound mode. For example, consider this method:
メソッドの別のグループが、Late – BoundモードでFontオブジェクトにアクセスする際、VB Migration Partnerは正しいコードを生成します。次のメソッドの例を参照下さい。
Sub SetControlFont(ByVal frm As Form) Dim ctrl As Control For ctrl In frm.Controls ctrl.Font.Name = "Arial" ctrl.Font.Size = 12 ctrl.Font.Bold = True Next End Sub
Once again, the problem is that ctrl is an IDispatch variable: the Font property is accessed in late-bound mode, therefore VB Migration Partner can’t determine that it references a System.Drawing.Font object and can’t take the appropriate steps to account for the fact that .NET font objects are immutable.
もう一度、問題は、ctrlがIDispatch変数であるということです。FontプロパティがLate Boundモードでアクセスされており、したがって、VB Migration Partnerは、System.Drawing.Fontオブジェクトを参照することを決定できず、.NETフォントオブジェクトが不変である事実を明確にするために正しい措置をとることができません。
The VBMigrationPartner_Support module includes the FontChangeName6, FontChangeSize6, FontChangeBold6, FontChangeItalic6, FontChangeStrikeout6, and FontChangeUnderline6 methods which, as their name suggest, allow you to work around the read-only nature of the corresponding property of the .NET Font object. Here’s how you can use these methods to prepare previous code snippet for a smooth translation:
VBMigrationPartner_SupportモジュールはFontChangeName6、FontChangeSize6、FontChangeBold6、FontChangeItalic6、FontChangeStrikeout6、FontChangeUnderline6メソッドを含みます。これらの名前が示唆しているように、.NET Fontオブジェクトに対応するプロパティでReadOnlyという性質で動作します。ここに、スムーズな変換をするために前述のコード断片を用意して、これらのメソッドの使用方法を記します。
Sub SetControlFont(ByVal frm As Form) Dim ctrl As Control For ctrl In frm.Controls ChangeFontName6(ctrl.Font, "Arial") ChangeFontSize6(ctrl.Font, 12) ChangeFontBold6(ctrl.Font, True) Next End Sub
(This is exactly the code that VB Migration Partner would generate if the control variable was accessed in early-bound mode.)
(もしコントロール変数がEarly – Boundモードでアクセスされたならば、VB Migration Partnerは正しいコードを生成します。)
Read the remarks in the VBMigrationPartner_Support module for a complete list of supported methods, their purpose, and example usages.
VBMigrationPartner_Supportモジュールの備考をご覧下さい。そこには、サポートされるメソッドの一覧、それらの目的、およびサンプルの用法などがあります。
4.2 Code analysis features/コード解析機能
VB Migration Partner employs several code analysis techniques to deliver high-quality VB.NET code.
VB Migration Partnerは、高品質なVB.NETコードを提供するのにいくつかのコード分析技術を用います。
Implicitly declared local variables/暗黙的に宣言されたローカル変数
VB Migration Partner emits an UPGRADE INFO remark for each local variable that wasn’t declared explicitly in the original project. For example, the following VB6 code:
VB Migration Partnerはオリジナルプロジェクトで明確に宣言されなかった各ローカル変数のためにUPGRADE INFOとして所見を出力します。次のVB6コード例をご覧下さい。
Public Sub Test() x = 123 End Sub
generates the following VB.NET code
次のようなVB.NETコードを生成します。
Public Sub Test()
' UPGRADE_INFO (#05B1): The 'x' variable wasn't declared explicitly.
x = 123
End Sub
You can force VB Migration Partner to generate an explicit declaration for such local variables by means of the DeclareImplicitVariables pragma, therefore this VB6 code:
DeclareImplicitVariables Pragmaによってそのようなローカル変数を明確に宣言するようにVB Migration Partnerに指示することができます。このVB6コードに適用すると次のようになります。
Public Sub Test()
'## DeclareImplicitVariables
x = 123
End Sub
generates the following VB.NET code
次のようなVB.NETコードを生成します。
Public Sub Test()
' UPGRADE_INFO (#05B1): The 'x' variable wasn't declared explicitly.
Dim x As Object = Nothing
x = 123
End Sub
Notice that the upgrade remark is emitted even if the variable declaration is now present in the generated code, but you can get rid of this comment by means of a DisableMessage pragma.
変数宣言が現在生成されたコードで存在していてもアップグレードされた備考が出力されていることに注意してください。しかし、DisableMessage Pragmaによってこのコメントを取り除くことができます。
Also, notice that all implicitly-declared variables are Object variable. However, users of VB Migration Partner can use an InferType pragma to generate a less-generic data type. For example, the following VB6 code:
また、すべての暗黙的に宣言された変数がObject変数である場合にも注意してください。しかし、VB Migration Partner Enterprise Editionを使用しているユーザーは、Less – Genericデータ型を生成するのにInferType Pragmaを使用できます。次のコードをご覧下さい。
Public Sub Test()
'## DeclareImplicitVariables
'## InferType
'## DisableMessage 05B1
x = 123
End Sub
Is converted to VB.NET as follows:
次のようなVB.NETコードに変換されます。
Public Sub Test() Dim x As Integer x = 123 End Sub
Unused members/未使用のメンバ
Unused classes, fields, and methods are tagged with a special UPGRADE_INFO comment, which encourages the developer to whether the member is actually unnecessary and possibly delete it from the original VB6 application.
未使用のクラス、フィールド、メソッドについて、UPGRADE_INFOが出力されます。本当に使用していないメンバは、オリジナルのVB6アプリケーションから削除することを推奨します。
Public Sub Test()
' UPGRADE_INFO (#0501): 'Test' member isn't used anywhere in current application.
' ...
End Sub
The code analyzer is smart enough to mark as unused those methods that invoke each other but don’t belong to any possible execution path. For example, suppose that method Test references Test2. In this case, VB Migration Partner emits a slightly different message:
コードアナライザーは参照あるいは実行されることのない、未使用のメソッドを、高精度で検出します。例えば、メソッドTestはTest2を参照すると仮定してください。この場合、VB Migration Partnerは異なった表現のメッセージを出力します。
Public Sub Test2()
' UPGRADE_INFO (#0511): The 'Test' member is referenced only by members that
' haven't found to be used in the current project/solution.
' ...
End Sub
Bear in mind that code analysis can account only for members that are referenced by means of a strongly-typed variable. If the member is referenced exclusively via a Variant, Object, or Control variable, the member is mistakenly considered to be “unused”. A similar problem occurs if the member is referenced only though a CallByName method. In such cases you can tell VB Migration Partner not to include the field, property, or method in the list of referenced members by means of the MarkAsReference pragma:
コードアナライザーは、厳密に型が指定された変数によって参照されているメンバのみを認識できることを覚えておいてください。もし、メンバがバリアント、オブジェクト、コントロール変数だけに参照されているとしたら、メンバは“未使用”と判断されます。同様の問題は、メンバがCallByName関数だけに参照されている場合にも起きます。そのような場合、MarkAsReference Pragmaを使うことにより、参照されるメンバリストの中にフィールド、プロパティ、メソッドを含めないようにVB Migration Partnerに設定することが可能です。
'## Test.MarkAsReferenced Public Sub Test() ' ... End Sub
Another case when VB Migration Partner can mistakenly find “unused” members is when migrating an ActiveX DLL or ActiveX EXE project. If you are migrating such a project individually, most of the public properties and methods of its public classes and controls are never referenced elsewhere. Even if you migrate the project as part of a group that contains a client project, chances are that the client project doesn’t reference each and every public member of all public classes of the ActiveX DLL or EXE project.
その他のケースとして、VB Migration Partnerは、ActiveX DLLやActiveX EXEプロジェクトをマイグレーションする時に、誤って“未使用の”メンバを検出してしまいます。それらのプロジェクトを個別にマイグレーションする場合、PublicクラスとコントロールのほとんどのPublicプロパティとメソッドは、どこからも参照されていません。クライアントプロジェクトを含むグループの一部のプロジェクトをマイグレーションしていたとしても、クライアントプロジェクトは、ActiveX DLLやEXEプロジェクトの全てのPublicクラスに存在するPublicメンバのどこも参照していない可能性があります。
To cope with this situation, VB Migration Partner supports the MarkPublicAsReferenced pragma, which automatically marks as referenced all the public members in current class. You can apply this pragma at the project level, too, in which case all public members of all public classes in the project are marked as referenced:
この状況に対処するために、VB Migration PartnerはMarkPublicAsReferenced Pragmaをサポートします。このPragmaは、今のクラスに存在する全てのPublicメンバが参照されているものとして、自動的に示します。このPragmaをプロジェクトレベルに当てはめると、プロジェクトの中の全てのPublicクラスの全てのPublicメンバが参照されているものとして示されます。
'## project:AddPublicAsReferenced
Because of late-bound references and accesses from external processes, VB Migration Partner doesn’t automatically delete unused members. However, we provide an extender that deletes unused Declare and Const statements, which are never accessed in late-bound mode or from external projects. You can enable this feature in the Extenders tab of the Tools-Options dialog box.
外部プロセスからのLate Bound参照とアクセスにより、VB Migration Partnerは自動で未使用のメンバを消去することはありません。しかし、我々はLate – Boundモードや外部プロジェクトからアクセスされることのない、未使用のDeclareステートメントやConstステートメントを消すExtenderを提供します。ツール−オプションをクリックすると現れるダイアログボックスのタブで、このExtenderの使用が可能です。
Parameters unnecessarily marked as ByRef/ByRefとして不必要とみなされたパラメータ
By default, VB6’s default passing mechanism is by-reference, and many developers mistakenly omitted the ByVal keyword for parameters that were meant to be passed by value. VB Migration Partner emits an UPGRADE_INFO remark for all parameters that are passed byreference but aren’t assigned in the method itself, nor are passed by-reference to methods that modify them. Let’s consider the following VB6 code:
VB6でのパラメータ指定は、デフォルトで参照渡しでした。そして多くの開発者は、値渡しとして定義されるべきパラメータに対しても、誤ってByValキーワードを省略しました。VB Migration PartnerはByRefで渡され、メソッドの中で割り当てられていない全てのパラメータに対してUPGRADE_INFOを出力しますが、メソッドの中で変更されるby-reference引数は除きます。次のようなVB6コードについて考えてみましょう。
Public Sub Test(n1 As Integer, ByRef n2 As Integer, n3 As Integer) Test2 n1, n2, n3 End Sub Public Sub Test2(ByVal n1 As Integer, ByRef n2 As Integer, n3 As Integer) Debug.Print n1 Debug.Print n2 Get #1, , n3 End Sub
Parameter n1 is never assigned in method Test and can’t be modified by Test2 because it is passed into a ByVal parameter. Parameter n2 is passed to a ByRef parameter of Test2 method, yet Test2 never modifies it. Finally, parameter n3 is not flagged is passed to Test2 method in a ByRef parameter and it is indeed modified inside that method. Here’s is the code that VB Migration Partner emits:
まず、パラメータn1はメソッドTest2の引数指定としてByValで定義されているため、値を変更することが出来ません。パラメータn2はメソッドTest2でByRefとして渡されますが、メソッド内での値の変更は行われません。最後に、ByRefもByValも付いていない(引数指定が省略されている)パラメータn3はByRefとして渡され、メソッドTest2の中で値が変更されます。上記のコードを、VB Migration Partnerで変換した場合以下のようなコードになります。
Public Sub Test(ByRef n1 As Short, ByRef n2 As Short, ByRef n3 As Short) ' UPGRADE_INFO (#0551): The 'n1' parameter is neither assigned in current method nor ' is passed to methods that modify it. Consider changing its declaration using the ' ByVal keyword. ' UPGRADE_INFO (#0551): The 'n2' parameter is neither assigned in current method nor ' is passed to methods that modify it. Consider changing its declaration using the ' ByVal keyword. Test2(n1, n2, n3) End Sub Public Sub Test2(ByVal n1 As Short, ByRef n2 As Short, ByRef n3 As Short) ' UPGRADE_INFO (#0551): The 'n2' parameter is neither assigned in current method nor ' is passed to methods that modify it. Consider changing its declaration using the ' ByVal keyword. Debug.WriteLine(n1) Debug.WriteLine(n2) FileGet6(1, n3) End Sub
In general, you should consider changing the passing semantics of parameters flagged with the special UPGRADE_INFO remark, because ByVal parameters are often faster than ByRef parameters. The only exception to this rule is structures, and for this reason VB Migration Partner never applies this remark to Structures.
パラメータの意味合いによりUPGRADE INFOが出力されていることを考えてください。例えば、ByValパラメータはByRefパラメータより処理されるスピードは早いですが、このルールは構造体の引数には当てはまりません。このため、VB Migration Partnerはこのルールを構造体に当てはめません。
Even more important, replacing ByRef parameters with ByVal parameters often avoids hard-to-find bugs in the VB.NET code. 更に重要なことですが、ByRefパラメータをByValパラメータに取り替えることで、VB.NETコード上での、見つけることが難しいバグを避けられることがあります。
To help you in applying the ByVal keyword where needed, VB Migration Partner supports the UseByVal pragma, which can be applied at the project, file, or method level. This pragma takes one argument, chosen among the following values:
VB Migration Partnerは、必要に応じてByValキーワードを当てはめられるように、UseByVal Pragmaをサポートします。このPragmaはプロジェクト、ファイル、メソッドレベルで適用でき、下記に示す値から選んだ1つの引数を持ちます。
Yes:
VB Migration Partner applies the ByVal keyword with unassigned parameters that implicitly use by-reference semantics (i.e. have no explicit ByRef or ByVal keyword).
VB Migration Partnerは、無条件にby-referenceとして使用されている割り当てられていないパラメータをByValキーワードとして使います。(例えば、ByRefやByValキーワードが指定されていない場合)
Force:
VB Migration Partner applies the ByVal keyword with all unassigned parameters that use by-reference semantics, even if an explicit ByRef keyword is found.
VB Migration Partnerは、明示的なByRefキーワードが見つかったとしても、by-referenceとして使用されている全ての割り当てられていないパラメータをByValキーワードとして使います。
No:
VB Migration Partner never applies the ByVal keyword. (This is the default behavior, yet this option can be useful to override another pragma at a broader scope.)
VB Migration Partnerは、決してByValキーワードを適用しません。(これはデフォルトの動作で、このオプションはより広いスコープで他のPragmaを無視するのに役立ちます。)
Let’s see how this pragma can affect the Test and Test2 methods seen in previous example:
このPragmaが上記で検証したTestとTest2メソッドにどのような影響を与えるかについて見てみましょう。
Public Sub Test(n1 As Integer, ByRef n2 As Integer, n3 As Integer) '## UseByVal Yes Test2 n1, n2, n3 End Sub Public Sub Test2(ByVal n1 As Integer, ByRef n2 As Integer, n3 As Integer) '## UseByVal Force Debug.Print n1 Debug.Print n2 Get #1, , n3 End Sub
Here’s the result from VB Migration Partner:
こちらはVB Migration Partnerの結果です。
Public Sub Test(ByVal n1 As Short, ByRef n2 As Short, ByVal n3 As Short)
' UPGRADE_INFO (#0551): The 'n2' parameter is neither assigned in current method nor
' is passed to methods that modify it. Consider changing its declaration using the
' ByVal keyword.
Test2(n1, n2, n3)
End Sub
Public Sub Test2(ByVal n1 As Short, ByVal n2 As Short, ByRef n3 As Short)
Debug.WriteLine(n1)
Debug.WriteLine(n2)
FileGet6(1, n3)
End Sub
All parameters that were flagged by the special remark in previous example are now defined with the ByVal keyword (and therefore have no remark associated with them), except the n2 parameter of Test method, because it was defined with an explicit ByRef keyword and we didn’t use the “Force” option in that method.
前述の変換例で定義が省略されていた全てのパラメータは、今度はByValキーワードを付けて定義されています。(メソッドTest1は、引数に関連した記述はありませんので、このメソッドでは“Force”オプションを使いませんでした。)
Unreachable code/Unreachable code(どこからも呼ばれないコード)
Sections of unreachable code inside methods are tagged with a special UPGRADE_INFO comment; examples of such sections are those that immediately follow Exit Sub, Exit Function, and Exit Property statements:
メソッドの中でどこからも呼ばれないコードのセクションに対し、特別なUPGRADE INFOコメントが出力されます。そのようなセクションは、Exit Sub、Exit Function、Exit Property ステートメントの後ろに記述されます。
Public Sub Test() ' ... Exit Sub ' UPGRADE_INFO (#0521): Unreachable code detected Test2() End Sub
VB Migration Partner correctly recognizes as unreachable code the region that follows a label that isn’t referenced by any GoTo, GoSub, On GoTo, On GoSub, On Error Goto, or Resume statement.
VB Migration Partnerは、GoTo、GoSub、On GoTo、On GoSub、On Error GoTo、On Resume Statementによって参照されないUnreachable codeの範囲を正確に認識しています。
Unreachable code detection in current version of VB Migration Partner accounts neither for conditional structures (e.g. If blocks) nor for unhandled errors caused by an Error or Err.Raise statement. For example, in both these examples the code analyzer fails to detect that the call to Test3 is unreachable:
VB Migration Partnerの現バージョンでは、条件文(例えば、If文)とエラーやErr.Raiseステートメントによって起きるハンドルされていないエラーの両方共に、Unreachable codeを検出できません。例えば、これら2つの例で、コードアナライザーはTest3が呼ばれないことを検出できません。
Public Sub Test(ByVal x As Integer) If x < 0 Then ' ... Exit Sub Else ' ... Exit Sub End If Test3 End Sub Public Sub Test2(ByVal x As Integer) ' ... Err.Raise 5 Test3 End Sub
The reason why VB Migration Partner doesn’t recognize as unreachable code the regions that are preceded by an Error or Err.Raise statement is that such error-related statements are ignored if an On Error Resume Next statement is active. You can have VB Migration Partner recognize those regions as unreachable by simply appending an Exit Sub (or Exit Function or Exit Property) immediately after the Error or Err.Raise statement.
VB Migration PartnerがエラーやErr.Riseステートメントが存在することによってどこからも呼ばれないコード範囲が分かるのに認識しない理由は、On Error Resume Next Statementがアクティブな場合、error-relatedステートメントが無視されるためです。エラーやErr.Eraseステートメントの後ろにExit Sub(あるいはExit FunctionやExit Property)を追加するだけで、VB Migration Partnerにこれらの範囲をUnreachableとして認識させることが可能です。
Unneeded Class_Initialize events/必要でないClass_Initializeイベント
The only way to initialize class fields under VB6 is to assign them in the Class_Initialize event handlers. (This method is named Form_Initialize inside forms, UserControl_Initialize inside user controls.)
VB6において、クラスの中で定義される変数を初期化する唯一の方法は、それらをClass_Initializeイベントハンドラー割り当てることです。(この方法は、FormではForm_Initialize、ユーザ・コントロールではUserControl_Initializeと呼ばれています。)
Public StartTime As Date Public NumberOfDays As Integer Private Sub Class_Initialize() StartTime = Now NumberOfDays = 10 End Sub
VB Migration Partner attempts to move assignments from the Initialize event handler to the field declaration, thus the above VB6 code is translated to VB.NET as follows:
VB Migration Partnerは、変数の初期化をInitializeイベントハンドラからフィールド宣言へ割り当てを動かそうと試みますので、結果として、VB6のコードは以下のようにVB.NETに変換されます。
' UPGRADE_INFO (#0721): The 'Class_Initialize' method is empty because all
' its statements were rendered as class field initializers.
Private Sub Class_Initialize_VB6()
End Sub
You can tell VB Migration Partner not to generate empty Initialize methods by adding a project- or file-level RemoveUnusedMembers pragma in the original VB6 source code.
オリジナルのVB6ソースコードでプロジェクト或いはファイルレベルにRemoveUnusedMembers Pragmaを追加して、空のInitialize method を発生させないようにVB Migration Partnerに指定することができます。
Unneeded Class_Terminate events/必要でないClass_Terminateイベント
Many VB6 developers define a Class_Terminate event handler just to set class-level variables to Nothing. Such assignments are superfluous – because the object is released anyway when the “Me” object is destroyed, but this coding style doesn’t harm in VB6.
多くのVB6開発者が、ただクラスレベル変数をNothingに設定するためにClass_Terminateイベントハンドラを定義します。しかし、この定義は本来必要がありません。なぜなら”Me”オブジェクトが破棄されるとき、オブジェクトは必ず開放されるためです。ただし、このコーディングスタイルはVB6においては害にはなりません。
When you convert this code to VB.NET, however, the Class_Terminate handler is translated into a Finalize method. As you may know, finalizable VB.NET classes are less efficient than standard classes, therefore you should avoid to declare the Finalize method unless it is strictly necessary. To help you follow .NET Framework coding best practices, VB Migration Partner emits an UPDATE_INFO remark when a Class_Terminate event handler can be safely removed, as in this case:
このコードをVB.NETに変換する際に、Class_TerminateハンドラはFinalizeメソッドに変換されます。ご存知の方もいらっしゃるかもしれませんが、VB.NETのファイナライズクラスは一般的なクラスより効率的ではありません。したがって、それが厳密に必要でない場合、あなたがFinalizeメソッドを宣言するのを避けるべきです。VB Migration Partnerは最適な.NET Frameworkコーディングの手助けとなるように、下記のようにClass_Terminateイベントハンドラが安全に取り除ける場合は、UPGRADE_INFOコメントを出力します。
Private col As New Collection
' UPGRADE_INFO (#0541): This 'Class_Terminate' method appears to be useless. Please
' delete it in the original project and restart migration.
Private Sub Class_Terminate_VB6()
col = Nothing
End Sub
Unneeded On Error Goto 0 statements/必要でないOn Error Goto 0 ステートメント
Many VB6 developers like to reset error handling on exiting a method, as in this code:
多くのVB6開発者は、次のコードのように、存在するメソッド上でエラー処理をリセットする処理を好みます。
Public Sub Test(n1 As Integer, ByRef n2 As Integer, n3 As Integer)
On Error GoTo ErrorHandler
Debug.Print n1, n2, 3
ErrorHandler:
' ...
' reset error handling before exiting
On Error GoTo 0
End Sub
It turns out that the On Error GoTo 0 statement is useless in this case, because the VB error handling is always reset on exiting a method. For this reason, VB Migration Partner remarks out the statement:
この場合、On Error Goto 0ステートメントは意味のないことが明らかです。なぜなら、VBのエラー処理が、メソッドを抜けるときに常にリセットを行うからです。このために、VB Migration Partnerはステートメントをコメントアウトします。
Public Sub Test(ByRef n1 As Short, ByRef n2 As Short, ByRef n3 As Short)
On Error GoTo ErrorHandler
DebugPrintLine6(n1, TAB(), n2, TAB(), 3)
ErrorHandler:
' ...
' IGNORED: On Error GoTo 0
End Sub
Members without “As” clause/「As」を省略したメンバ
Some VB6 developers – especially those who have written code in other languages, such as C or Pascal – incorrectly assume that the following statement defines three 32-bit variables:
以前CやPascalのような他の言語でコードを書いていたVB6開発者の中には、下記の記述が3つの32ビット変数を定義していると思い込んでいる人たちがいます。
Dim x, y, z As Long
Instead, the statement defines two Variant variables and one Long variable. (More precisely, the type of x and y variables depends on the active DefXxx directive and is Variant only if no such a directive exist in current file.) VB Migration Partner translates the variable declarations correctly, but adds a warning so that you can spot the probable mistake:
そうではなく、この記述は2つのバリアント型変数と1つのLong型の変数を定義します。(より正確に言うと、xとyの変数の型はDefXxxディレクティブに依存し、そのようなディレクティブが存在しないVariant型のみ現在のファイルに依存しています。)VB Migration Partnerは変数の宣言を正しく変換しますが、警告を発します。その結果、存在する可能性のある間違いに気付くことが出来ます。
' UPGRADE_INFO (#0561): The 'x' symbol was defined without an explicit "As" clause. Dim x As Object = Nothing ' UPGRADE_INFO (#0561): The 'y' symbol was defined without an explicit "As" clause. Dim y As Object = Nothing Dim z As Integer
A similar warning is emitted for functions, properties, and parameters that lack an explicit “As” clause.
同様な警告が関数、プロパティ、そして明確に「As」が付いていないパラメータに対して発行されます。
String concatenation inside loops/Loopの中におけるStringの連結
In general, VB.NET is slower than VB6 at concatenating strings. As a matter of fact, you should avoid string concatenations inside a time-critical loop, as in this case:
一般的に、VB.NETはStringの連結がVB6より遅いです。実際、この場合のように、時間がかかるLoopの中ではStringの連結を避けるべきです。
Dim s As String Dim n As Integer For n = 1 To 10000 s = s & Str(n) & "," Next
VB Migration Partner helps you optimize your code by marking string concatenations inside a For, While, or Do loop with a special migration warning. This is how the previous code is converted to VB.NET:
VB Migration Partnerは、For、While、あるいはDo Loopの中で行われているStringの連結に、特別なマイグレーション警告を伴った目印を付けることにより、コードを最適化する手助けをします。下記のコードは、上記のコードがVB.NETにどのように変換されたかを示すものです。
Dim s As String = ""
Dim n As Short
For n = 1 To 10000
' UPGRADE_INFO (#0571): String concatenation inside a loop.
' Consider declaring the 's' variable as a StringBuilder6 object.
s = s & Str6(n) & ","
Next
You should scrutinize all upgrade infos #0571 and decide whether you should change the type of the string variable into System.Text.StringBuilder or the special StringBuilder6 type exposed by VB Migration Partner’s support library. The latter type is usually preferable because it minimizes the code edits that are necessary to deliver working code:
全ての#0571アップグレードインフォメーションを吟味して、System.Text.StringBuilderクラス あるいは VB Migration Partnerのサポートライブラリで公表されている特別なStringBuilder6タイプを使って、String変数の型を変えるべきか判断してください。 後者を使う方が望ましいです。なぜなら、後者は動いているコードに対して加えるコードの編集量を最小限にするからです。
Dim s As StringBuilder6 = ""
' (remainder of code as before)
You can also use a SetType pragma to replace the data type from inside the VB6 code:
また、VB6コードの中からデータ型を置き換えるのにSetType Pragmaを使用できます。
'## s.SetType StringBuilder6
Dim s As String
Unused type libraries/未使用のタイプライブラリ
VB6 projects often contain references to type libraries that aren’t directly used by the current project. For example, if you create a new VB6 project by selecting the “Data Project” or the “VB Enterprise Edition Controls” template, Visual Basic 6 creates a project that references a number of type libraries that you don’t actually use. VB Migration Partner detects all unreferenced type libraries and lists them at the top of one of the VB.NET source files:
VB6プロジェクトは、現在のプロジェクトでは直接使われていないタイプライブラリの参照をよく含みます。例えば、“Data Project”や“VB Enterprice Edition コントロール”テンプレートを選択することによって、新しいVB6プロジェクトを生成した場合、Visual Basic 6は実際には使用しない、いくつかのタイプライブラリを参照するプロジェクトを生成します。VB Migration Partnerは全ての参照していないタイプライブラリを検知し、VB.NETソースファイルの一つとして、一番上にリストアップします。
' UPGRADE_INFO (#0571): The 'DDSLibrary' type library is never used in current project. ' Consider deleting it from VB6 project references.
Notice that the unused reference is not removed automatically from the converted VB.NET project. It’s up to the developer to decide whether the type library is truly unnecessary and remove it manually from the original VB6 project. This manual fix ensures that the VB.NET project contains only the references that are strictly necessary and speeds up the conversion process.
変換したVB.NETプロジェクトから、使われていない参照が自動的に除かれていないことに注目してください。タイプライブラリが本当に必要でないか、そしてオリジナルのVB6プロジェクトから手動で取り除くかを決めるのは開発者です。このマニュアルの対処通りにすると、VB.NETプロジェクトは厳密に必要な参照だけを含み、変換プロセスのスピードを上げることを保証します。
4.3 Refactoring features/リファクタリング機能
VB Migration Partner leverages code analysis techniques to refactor the VB.NET to make faster and more readable.
VB Migration Partnerは、コード分析技術を用いて、VB.NET上でより早く、より読みやすいコードにリファクタリングします。
Return values/戻り値
VB6’s Function and Property Get procedures return a value to their caller by assigning the value to a local variable named after the procedure itself, as in this code:
VB6の関数とプロパティを取得するプロシージャは、プロシージャの名前をとって付けられたローカル変数に値を割り当てることによって、呼び出し元に値を戻します。
Function GetData() As Integer … If x > 0 Then GetData = x Exit Function End If … End Function
VB Migration Partner is able to collapse the assignment and the Exit statement into a VB.NET Return statement if it’s safe to do so:
VB Migration Partnerは上記のように変数に値を割り当てないこともできます。VB.NETの中では、VB6のExitステートメントは下記のように安全なReturnステートメントに変わります。
Function GetData() As Short … If x > 0 Then Return x End If … End Function
This feature is quite sophisticated and works as expected even in more intricate cases, as in the following example:
この特徴はとても洗練されていて、下記のように、より複雑な場合でも期待された通りに動きます。
Function GetData() As Integer … If x > 0 Then If y > 0 Then GetData = y Else GetData = x End If Exit Function End If … GetData = 0 End Function
which translates to:
これを移行すると、
Function GetData() As Short … If x > 0 Then If y > 0 Then Return y Else Return x End If Exit Function End If … Return 0 End Function
Notice that the Exit Function keyword is left in code and must be removed manually.
Exit Functionキーワードがコードの中に残されていて、手で取り除かねばいけないことに注意してください。
Variable initialization/変数の初期化
VB Migration Partner attempts to merge a local variable’s declaration with its initialization. For example, the following VB6 code:
VB Migration Partnerはローカル変数の宣言時に初期化を一緒に行おうとします。次のVB6コードをご覧ください。
Dim d As Double, i As Integer, v As Long, o As Object d = 1.8 i = 11 … If d = 0 Then v = 111
is translated to VB.NET as
このコードをVB.NETに移行すると、
Dim d As Double = 1.8 Dim i As Integer = 11 Dim v As Long Dim o As Object = Nothing … If d = 0 Then v = 111
In this example, the d and i variables can be safely declared and initialized in a single statement, whereas the v variable can’t. This feature is enabled only for strings and scalar variables; Object and other reference type variables are always explicitly initialized to Nothing to prevent the VB.NET compiler from complaining about uninitialized variables that might throw a NullReference exception.
この例では、変数dと変数iが1行で安全に宣言・初期化されているのに、変数vはそうではありません。これはストリングスやスカラー変数で見られる特徴です。オブジェクトや他の参照型変数の規定値は常にNothingに設定され、VB.NETコンパイラーがNullReference Exceptionを投げる可能性のある、初期化されていない変数によるエラーが出るのを避けています。
VB Migration Partner takes a conservative approach and doesn’t merge a variable declaration with the first assignment to that variable if the code block between these two statements includes keywords that change execution flow, for example method calls or Select Case blocks, or if the value being assigned isn’t constant.
VB Migration Partnerは時には変数の初期化と値の代入を同時に行わないことがあります。それは、これら2つのステートメントの間のコードブロックに、関数の呼び出しやSelect Caseブロック、一定でない値の代入のようなchange実行フローキーワードを含む場合です。
You can force variable initialization by adding a MergeInitialization pragma for that specific variable. Consider this code fragment:
特別な変数にMergeInitialization Pragmaを用いることにより、変数の初期化を強力に行うことができます。このコードの断片を考えてみてください。
'## n1.MergeInitialization Force
Dim n1 As Integer, n2 As Integer
n1 = 10 + GetValue()
n2 = 11 + n1
In this case the MergeInitialization Force pragma informs VB Migration Partner that the call to the GetValue method can be safely included in the variable initialization. The code generator merges the declaration and initialization of n1 variable, because of the MergeInitialization pragma, but not of n2 variable:
この場合、VB Migration PartnerはMergeInitialization Force Pragmaを使うことで、GetValueメソッドが変数の初期化で安全に使用されていることを認識します。コード生成プログラムは、MergeInitialization Pragma によってn1変数の宣言と初期化を同時に行いますが、n2変数に対しては行いません。
Dim n1 As Short = 10 + GetValue() Dim n2 As Short n2 = 11 + n1
You can disable this optimization at the project, file, method, or variable level by means of the following pragma:
次に記すPramgaを使うことによって、プロジェクト、ファイル、メソッド、変数レベルの最適化を無効にすることができます。
'## MergeInitialization No
VB Migration Partner is also able to merge class field declarations and assignments found in the Class_Initialize (or Form_Initialize) methods. However, the MergeInitialization pragma has no effect on class fields.
VB Migration Partnerはクラスフィールド宣言とクラスの初期化(あるいはForm_Initialize)メソッドを一緒に行うこともできます。けれども、MergeInitialization Pragmaはクラスフィールドに対して効果がありません。
Note:
in a method that contains one or more Gosub statements that are converted to separate methods, because of a ConvertGosubs pragma, the variable initialization feature is disabled.
別のメソッドに変換される1つかそれ以上のGoSubステートメントを含むメソッドにおいて、ConvertGosubs Pragmaを用いると、変数初期化の特徴は無効になります。
Compound assignment operators/複合代入演算子
VB Migration Partner is able to replace plain assignment symbols with compound assignment operators, such as += or /=. For example, the following code:
VB Migration Partnerは簡単な代入記号を複合代入演算子(例えば、+= や /=)に変換することができます。
sum = sum + 1.8 value = value \ 2 text = text & "abc" Label1.Caption = Label1.Caption & "." Label2 = Label2 + "< end > "
is translated to VB.NET as follows:
VB.NETに変換すると、
sum += 1.8
value \= 2
text & = "abc"
Label1.Caption & = "."
Label2.Caption & = " < end > "
' notice that default property has been resolved
デフォルトプロパティが解決されていることに注目してください。
Wrapping fields in properties/プロパティのラッピングフィールド
VB Migration Partner can automatically wrap a specific public field in a class (or all public fields in the current class or project) in an equivalent Property. This feature is enabled by means of the AutoProperty pragma. For example, the following VB6 code:
VB Migration Partner Enterprise Editionは、クラスの中の特定のPublicフィールド(或いは、今のクラスやプロジェクトの中の全てのPublicフィールド)を、同等なプロパティとして、自動的にラップすることが出来ます。 この特徴はAutoProperty Pragmaによって実現されます。下記のVB6コードをご覧ください。
'## AutoProperty
Public Name As String
Public Widget As New Widget
is rendered as follows:
は下のように変換されます。
Public Property Name() as String Get Return Name_InnerField End Get Set(ByVal value As String) Name_InnerField = value End Set End Property Private Name_InnerField As String = "" Public Property Widget() As Widget Get If Widget_InnerField Is Nothing Then Widget_InnerField = New Widget() Return Widget_InnerField End Get Set(ByVal value As Widget) Widget_InnerField = value End Set End Property Private Widget_InnerField As Widget
Notice that the AutoProperty pragma automatically enforces the auto-instancing (As New) semantics if possible, regardless of whether the variable is under the scope of an AutoNew pragma.
変数がAutoNew Pragmaのスコープの影響を受けているかどうかに関係なく、AutoProperty Pragmaは自動でインスタンスの生成(As New)を行うことに注意してください。
Appending to the Text property/テキストプロパティへの追加
When the original VB6 code appends a string to the Text property of a TextBox, MaskEdBox, RichTextBox, or WLText control, VB Migration Partner can translate this operation into a more efficient call to the AppendText method. This is a special case of the pattern described at previous point:
オリジナルのVB6コードは、テキストボックス、MaskEdBox、リッチテキストボックス、WLTextコントロールのテキストプロパティにstringを付け加えるのに対し、VB Migration Partnerはこの機能をより有効なAppendTextメソッドに変換します。このことは以前のポイントで記した場合の特別なケースです。
Me.Text1.Text = Me.Text1.Text & "< end > " Text2 = Text2 + "< end > "
becomes
は、下記のように変換されます。
Me.Text1.AppendText("< end > ") Text2.AppendText("< end > ")
If … Else simplification/If … Elseの簡略化
VB Migration partner is able to drop If blocks if the Then and the Else blocks contain the same code. Such blocks can be produced, for example, by a conversion of a VB6 property. A VB6 Variant propery can have both the Property Let and Property Set blocks, if the property can be assigned either a scalar or an object value, as in this example:
VB Migration Partnerは、ThenやElseステートメントに同じコードを含む場合、If節を削除します。そのような例は、VB6プロパティを変換した時に起こります。VB6バリアントプロパティにはProperty LetとProperty Setの両方が存在します。プロパティがスカラー値かオブジェクト値のどちらかなら、プロパティは次のように割り当てられます。
Private m_Tag As Variant Property Get Tag() As Variant If IsObject(m_Tag) Then Set Tag = m_Tag Else Tag = m_Tag End If End Property Property Let Tag(ByVal newValue As Variant) m_Tag = newValue End Property Property Set Tag(ByVal newValue As Variant) Set m_Tag = newValue End Property
Converting this property literally delivers the following VB.NET code:
このプロパティをありのままに変換すると、下記のようなVB.NETコードになります。
Private m_Tag As Object Public Property Tag() As Object Get If IsObject6(m_Tag) Then Return m_Tag Else Return m_Tag End If End Get Set(ByVal newValue As Object) If IsObject6(newValue) Then m_Tag = newValue Else m_Tag = newValue End If End Set End Property
VB Migration Partner detects that the Then and the Else portions of the If blocks contain the same executable statements and can simplify them as follows:
VB Migration Partnerは、IfブロックのThenとElseに同じ実行文が含まれていて、下記のように簡略化できることを検知します。
Private m_Tag As Object Public Property Tag() As Object Get Return m_Tag End Get Set(ByVal newValue As Object) m_Tag = newValue End Set End Property
The IsNot operator/IsNot演算子
VB Migration Partner can automatically to adopt the IsNot operator in all expressions that test whether two objects are equal or if an object is equal to Nothing. For example, the following VB6 code:
VB Migration Partnerは2つのオブジェクトが等しいか、それともオブジェクトがNothingかどうか調べる全ての式の中で、自動的にIsNot演算子を選んで使います。下記のVB6コードをご覧ください。
If Not obj Is Nothing And Not obj Is obj2 Then
Is translated as follows:
これは下のように変換されます。
If obj IsNot Nothing And obj IsNot obj2 Then
Nested If merging/If文の入れ子
VB Migration Partner can detect whether the original VB6 code contains two or more nested If blocks and automatically merge them into a single If condition that contains the AndAlso operator. The key to this refactoring feature is the MergeIfs pragma, which can have project-, file-, or method-scope. For example, consider the following VB6 code:
VB Migration Partner Enterprise Editionは、オリジナルのVB6コードに、2つ以上の入れ子にされたIfブロックを含んでいるかを調べ、自動的にAndAlso演算子を含んだ状態の一つのIf文に統合します。このリファクタリングの機能の鍵はMergeIfs Pragmaです。(プロジェクト、ファイル、メソッドで範囲指定が出来ます)例えば、下記のVB6コードについて考えてみてください。
Sub Test(ByVal obj As Object, ByVal obj2 As Object)
'## MergeIfs True
If Not obj Is Nothing Then
If obj.Text = "" Then Debug.Print "Empty Text"
End If
If Not obj Is Nothing Then
If Not obj2 Is Nothing Then
If obj.Text = obj2.Text Then Debug.Print "Same text"
End If
End If
End Sub
This is how VB Migration Partner translates it to VB.NET
VB Migration PartnerはVB.NETに次のように変換します。
Sub Test(ByVal obj As Object, ByVal obj2 As Object) ' UPGRADE_INFO (#0581): Two nested If...End If blocks have been merged. If (obj IsNot Nothing) AndAlso (obj.Text = "") Then Debug.WriteLine("Empty Text") End If ' UPGRADE_INFO (#0581): Three nested If...End If blocks have been merged. If (obj IsNot Nothing) AndAlso (obj2 IsNot Nothing) AndAlso (obj.Text = obj2.Text) Then Debug.WriteLine("Same text") End If End Sub
You can further simplify the expression by dropping the parenthesis around each subexpressions, by using the following pragma:
各部分式の周りの()を削除すると、より式を簡単にできます。それを実現するために、下記に記すPragmaを使ってください。
'## MergeIfs True, False
Structured Exception Handling/構造化例外処理
VB Migration Partner can replace old-styled On Error Goto statements into structured exception handling (SEH) based on the Try-Catch block. You can activate this feature by means of the UseTryCatch pragma, which can have project-, file-, and method-level scope. For example, the following VB6 code:
VB Migration Partner Enterprise editionは古い形式のOn Error GotoステートメントをTry-Catchブロックに基づいた構造化例外処理(SEH)へ替えます。UseTryCatch pragmaを使うことによって、この特色を実現することができます。UseTryCatch Pragmaはプロジェクト、ファイル、メソッドレベルで範囲指定が出来ます。下記のVB6コードをご覧ください。
Sub Test() '## UseTryCatch On Error Goto ErrorHandler ' method body ErrorHandler: ' error handler End Sub
is translated to the following VB.NET code:
上で挙げた例は、次のようなVB.NETコードに変換されます。
Sub Test() Try ' IGNORED: On Error Goto ErrorHandler ' method body Catch _ex As Exception ' IGNORED: ErrorHandler: ' error handler End Try End Sub
The Try…Catch block can be inserted only if the following conditions are all true:
Try. . .Catchブロックは下記に挙げる状態がtrueの場合に挿入されます。
- The method contains only a single On Error GoTo <label> method.
メソッドの中にOn Error GoTo<ラベル>メソッドが一つ存在する。
- The On Error GoTo <label> statement doesn’t appear inside a conditional block such as If, For, Select Case, and isn’t preceded by a GoTo statement.
- If、For、Select Caseのような条件節の中でOn Error GoTo<ラベル>ステートメントが現れず、GoToステートメントの前にも現れない場合
- The method doesn’t contain GoSub, Resume, or Resume Next statements. (Resume <label> statements are acceptable, though)
- GoSub、Resume、Resume Nextステートメントがメソッドに存在しない場合
- There is no Goto statement in the method body that points to a label that is defined in the error handler. (Notice that it is ok if a GoTo in the error handler points to a label defined in the method body.)
- エラーハンドラーが定義されているラベルへジャンプするGotoステートメントがメソッド本体に存在しない場合(エラーハンドラーの中に存在するGoToが、メソッドに定義されたラベルへジャンプすることは大丈夫なことに注意してください。)
- If the method contains one or more On Error Goto 0 statements, such statements must immediately precede a statement that causes exiting from the current method, e.g. Exit Sub or End Function.
- メソッドに1つ以上のOn Error GoTo 0ステートメントを含む場合は、Exit SubやExit Functionのような、現在のメソッドをすぐに終了させるコードの手前になくてはならない。
- If the current method is a Property Let procedure, there must not be a Property Set procedure for the same property. Likewise, If the current method is a Property Set procedure, there must not be a Property Let procedure for the same property.
- メソッドにProperty Letプロシージャが存在するときに、Property Setプロシージャは絶対に存在しません。同じように、メソッドにProperty Setプロシージャが存在するときに、Property Letプロシージャは存在しません。
For example, the following VB6 code:
例えば、次のVB6コードは、
Sub Test() '## UseTryCatch On Error Goto ErrorHandler ' method body If x > 0 Then GoTo ErrorHandler2 ErrorHandler: ' error handler ErrorHandler2: ' do something here End Sub
can’t be converted to VB.NET using a Try-Catch block because a GoTo statement in the method body points to a label that is defined in the error handler.
Try-Catchブロックを使ってVB.NETには変換されません。理由は、メソッドに存在しているGoToステートメントが、エラーハンドラとして定義されている行にジャンプするからです。
By default, VB Migration Partner inserts a Try-Catch also if the method contains the On Error Resume Next statement plus another executable statement. For example, the following VB6 code:
デフォルトで、メソッドがOn Error Resume Nextステートメントと別の実行文を含んでいるなら、VB Migration PartnerはTry- Catchを挿入します。 例えば、以下のVB6コードを御覧下さい。
Function Reciprocal(ByVal x As Double) As Double '## UseTryCatch True On Error Resume Next Reciprocal = 1 / x ' returns zero if an error occurs (e.g. X is zero) End Function
contains only two executable statements (including On Error Resume Next) and is converted to:
上に挙げた例では、On Error Resume Next を含むと2つの実行可能なステートメントを含みます。そして、次のように変換されます。
Function Reciprocal(ByVal x As Double) As Double Try Return 1 / x ' returns zero if an error occurs (e.g. X is zero) Catch ' Do nothing if an error occurs End Try End Function
Methods with three or more executable statements can be converted using Try Catch if you specify a value higher than 2 in the second argument for the UseTryCatch pragma. For example, all methods with up to 5 executable statements under the scope of the following pragma:
3つ以上の実行可能なステートメントを持つメソッドは、UseTryCatch Pragmaの2つ目の引数に2より大きい値を指定することによってTry Catchを使って変換できます。例えば、下に記すようなPragmaを用いると、5つまで実行可能なステートメントを持つメソッドが、
'## UseTryCatch True, 5
are converted using a Try-Catch block.
Try-Catchブロックを使って変換されます。
Notice that the UseTryCatch pragma can be used together with the AutoDispose Force pragma, in which case VB Migration Partner generates a complete Try-Catch-Finally block.
UseTryCatch pragmaはAutoDispose Force Pragmaと一緒に使われることに注目してください。この2つのPragmaを一緒に使うことで、VB Migration PartnerはTry-catch-Finallyブロックを生成します。
GoSub refactoring/GoSubリファクタリング
VB Migration Partner is able, in many circumstances, to automatically refactor old-styled Gosub keywords into calls to a separate method. This feature can be applied at the project-, file-, or method-level by means of the ConvertGosubs pragma. For example, consider the following VB6 code:
VB Migration Partner Enterpriseは多くの場合、古い形式のGoSubキーワードを別のメソッドを呼び出すように自動的にリファクタリングしています。ConvertGosubs Pragmaを使うことによって、この特徴をプロジェクト、ファイル、メソッドレベルで適用可能です。下のようなVB6のコードについて考えてみましょう。
Function GetValue(x As Integer) As Integer
'## ConvertGosubs True
On Error Resume Next
Dim s As String, name As String
s = "ABC"
name = "Code Architects"
GoSub BuildResult
Exit Function
BuildResult:
GetValue = x + Len(s) + Len(name)
Return
End Function
VB Migration Partner detects that the code that begins at the BuildResult label (a.k.a. the target label) can be safely refactored to a separate method, that receives four arguments. The result of the conversion is therefore:
VB Migration PartnerはBuildResultラベル(ターゲットラベル)で始まるコードは安全に別のメソッドへリファクタリングされ、4つの引数を取ることを見つけます。変換すると、次のようになります。
Public Function GetValue(ByRef x As Short) As Short Dim s As String Dim name As String On Error Resume Next s = "ABC" name = "Code Architects" Gosub_GetValue_BuildResult(x, GetValue, s, name) Exit Function End Function Private Sub Gosub_GetValue_BuildResult(ByRef x As Short, ByRef GetValue As Short, _ ByRef s As String, ByRef name As String) On Error Resume Next GetValue = x + Len6(s) + Len6(name) End Sub
Notice that the external method contains an On Error Resume Next statement, because the original GetValue method also contains this statement.
形式上、メソッドはOn Error Resume Nextステートメントを含むことに注目してください。それは、オリジナルのGetValueメソッドがOn Error Resume Nextステートメントを含むからです。
All arguments to the new Gosub_GetValue_BuildResult method are passed by reference, so that the caller can receive any value that has been modified inside the method (as is the case with the GetValue parameter in previous example.) You can have VB Migration Partner optimize this passing mechanism and use ByVal if possible by passing True as the second argument to the ConvertGosubs pragma:
新しいGosub_GetValue_BuildResultメソッドの全ての引数は参照渡しなので、呼び元はメソッドの中でどんな値に変更されたとしても値を受け取ることができます。(以前例に挙げたGetValueパラメータと同じケースです。) VB Migration Partnerでこの引数渡しのメカニズムを最大限に利用することが可能であり、ConvertGosubs Pragmaの2番目の引数にTrueを設定することによってByValを使うことも可能となります。
'## ConvertGosubs True, True
If this optimization is used in the above code, the separate method is rendered as follows:
上記のコードにこのPragmaを使うと、分割されるメソッドは下記のように変わります。
Private Sub Gosub_GetValue_BuildResult(ByVal x As Short, ByRef GetValue As Short, _ ByVal s As String, ByVal name As String) On Error Resume Next GetValue = x + Len6(s) + Len6(name) End Sub
If you don’t like the name that VB Migration Partner assigns to the automatically-generated method, you can easily change it by means of a PostProcess pragma:
VB Migration Partnerが自動的に生成するメソッド名が好みでないならば、PostProcess Pragmaを使うことによって間単に名前を変えることができます。
'## PostProcess "Gosub_GetValue_BuildResult", "AssignValueResult"
It is important to keep in mind that the conversion of a Gosub block of code into a separate method isn’t always possible. More precisely, VB Migration Partner can perform this conversions only if all the following conditions are met:
GoSubブロックコードを別のメソッドに変換することがいつも可能でないことを覚えておくことは、とても重要です。もっと詳しく言うと、VB Migration Partnerは下に記すような条件が満たされた場合にのみ、この変換を行います。
- The method doesn’t contain any Resume statement. (On Error Resume Next is OK, though).
- メソッドにResumeステートメントを含んでいない。(On Error Resume NextはOKです。)
- The target label isn’t located inside a If, Select, For, Do, or Loop block.
- ターゲットラベルがIf、Select、For、Do、Loopブロックの中に存在しない。
- The target label isn’t referenced by a Goto, On Goto/Gosub, or On Error statement.
- ターゲットラベルがGoto、On Goto/GoSub、On Error Statementに参照されない。
- The target label must be preceded by a Goto, Return, End, Or Exit Sub/Function/Property statement.
- ターゲットラベルがGoto、Return、End、Exit Sub/Function/Propertyステートメントの前に存在している。
- The code block must terminate with an unconditional Return, or an End Sub/Function/Property statement. (Blocks that terminate with Exit Sub/Function/Property statements aren’t converted.)
- コードブロックがReturn、End Sub/Function/Propertyステートメントで終わる。(Exit Sub/Function/Propertyステートメントで終わるブロックは変換されません。)
- The block of code between the target label and the closing Return/End statement doesn’t contain another label.
- ターゲットラベルと「終了」を示すReturn/Endステートメント間のコードブロックに別のラベルを含まない。
If a method contains one or more labels that can’t be converted to a separate method, VB Migration Partner still manages to convert the remaining labels. In general, a label can be converted to a separate method if it neither references nor is referenced by a label that can’t be converted (for example, a label that is defined inside an If block or a label that doesn’t end with an unconditional Return statement.)
VB Migration Partnerは、変換出来なかったラベルの他に、1つ以上のラベルがメソッドの中に含まれている場合、引き続き残りのラベルをなんとか変換しようと試みます。それらは、変換できなかったラベルとの参照関係がなければ、一般的に、別のメソッドに変換されます。(例えば、If文の中で定義されたラベルや、Returnステートメントで終わらなかったラベルなどです。)
Note:
in a method that contains one or more Gosub statements that are converted to separate methods, the variable initialization merging feature is disabled.
別のメソッドに変換された1つ以上のGoSubステートメントを含んだメソッドにおいて、変数の初期化と宣言は同時には起こりません。
Type inference/型の推測
VB Migration Partner is capable, in most cases, to correctly deduce a less generic data type for Variant local variables, parameters, class fields, functions and properties. This applies both to members that were explicitly declared as Variant and to members that lacked an explicit As clause. To see how this feature works, consider the following VB6 code:
VB Migration Partner Enterprise editionは、たくさんのバリアント型のローカル変数、パラメータ、クラスフィールド、関数とプロパティのデータ型を正しく推測できます。これは、バリアント型として明確に定義されたメンバと明確に定義されていないメンバの両方にあてはまります。この特徴の動作を確認するために、以下のVB6コードを考察してください。
'## DeclareImplicitVariables True
Private m_Width As Single
Property Get Width ()
Width = m_Width
End Property
Property Let Width (value)
m_Width = value
End Property
Sub Test(x As Integer, frm)
Dim v1 As Variant, v2
v1 = x * 10
v2 = Width + x
Set frm = New frmMain
res = frm.Caption
End Sub
By default this code is converted to VB.NET as follows:
デフォルトで、このコードは下記のようなVB.NETに変換されます。
Private m_Width As Single Public Property Width() As Object Get ' UPGRADE_WARNING (#0364): Unable to assign default member of symbol 'Width'. ' Consider using the SetDefaultMember6 helper method. Return m_Width End Get Set(ByVal value As Object) ' UPGRADE_WARNING (#0354): Unable to read default member of symbol 'value'. ' Consider using the GetDefaultMember6 helper method. m_Width = value End Set End Property Public Sub Test(ByRef x As Short, ByRef frm As Object) ' UPGRADE_INFO (#05B1): The 'res' variable wasn't declared explicitly. Dim res As Object = Nothing ' UPGRADE_INFO (#0561): The 'frm' symbol was defined without an explicit "As" clause. Dim v1 As Object = Nothing ' UPGRADE_INFO (#0561): The 'v2' symbol was defined without an explicit "As" clause. Dim v2 As Object = Nothing ' UPGRADE_WARNING (#0364): Unable to assign default member of symbol 'v1'. ' Consider using the SetDefaultMember6 helper method. v1 = x * 10 ' UPGRADE_WARNING (#0364): Unable to assign default member of symbol 'v2'. ' Consider using the SetDefaultMember6 helper method. v2 = Width + x frm = New Form1() ' UPGRADE_WARNING (#0354): Unable to read default member of symbol 'frm.Caption'. ' Consider using the GetDefaultMember6 helper method. ' UPGRADE_WARNING (#0364): Unable to assign default member of symbol 'res'. ' Consider using the SetDefaultMember6 helper method. res = frm.Caption End Sub
Variant variables – either implicitly declared or not – are translated into Object variables, which causes several warning to be emitted and, more important, adds an overhead at runtime. This overhead can be often avoided by declaring the variable of a more defined scalar type. You can have VB Migration Partner change the data type for a given member by means of the SetType pragma, but this operation requires a careful analysis of which values are assigned to the variable.
バリアント型の変数(暗黙の宣言を含む)はオブジェクト型に変換されますが、それが原因でいくつかの警告が出され、より重要なこととして、処理に時間がかかってしまうようになります。このオーバーヘッドは、より厳密に定義されたスカラー型の変数で宣言することで避けることができます。SetType Pragmaを使うことによって、メンバ変数のデータ型が変わったことをVB Migration Partnerに知らせることができます。けれども、この機能は変数に割り当てられた値に対して慎重な分析を必要とします。
Users of VB Migration Partner can have this analysis performed automatically, by inserting an InferType pragma at the project-, file-, method- or variable-level. For example, let’s assume that the previous VB6 code contains the following pragma at the file level:
VB Migration Partner Enterprise editionの利用者は、プロジェクト、ファイル、メソッド、変数レベルでInferType Pragmaを挿入することで、この分析を自動で行わせることができます。ファイルレベルにこのコードを使ったVB6コードの例を見てみることにしましょう。
'## InferType Yes
The Yes argument in this pragma makes VB Migration Partner attempt to infer the type of al the implicitly-declared local variables and of all the local variables, class fields, functions and properties that lack an explicit As clause:
このPragmaに引数Yesを指定することで、VB Migration Partnerは全ての厳密に宣言されたローカル変数と、厳密に定義されていない全てのローカル変数、クラスフィールド、関数、プロパティの型の推測を試みることができます。
Private m_Width As Single Public Property Width() As Single Get Return m_Width End Get Set(ByVal value As Single) m_Width = value End Set End Property Public Sub Test(ByRef x As Short, ByRef frm As Object) ' UPGRADE_INFO (#0561): The 'frm' symbol was defined without an explicit "As" clause. ' UPGRADE_INFO (#05B1): The 'res' variable wasn't declared explicitly. Dim res As Object = Nothing Dim v1 As Object = Nothing ' UPGRADE_INFO (#0561): The 'v2' symbol was defined without an explicit "As" clause. Dim v2 As Single ' UPGRADE_WARNING (#0364): Unable to assign default member of symbol 'v1'. ' Consider using the SetDefaultMember6 helper method. v1 = x * 10 v2 = Height + x frm = New Form1() ' UPGRADE_WARNING (#0354): Unable to read default member of symbol 'frm.Caption'. ' Consider using the GetDefaultMember6 helper method. ' UPGRADE_WARNING (#0364): Unable to assign default member of symbol 'res'. ' Consider using the SetDefaultMember6 helper method. res = frm.Caption End Sub
In this new version, VB Migration Partner can infer the type of the Width property from the type of the m_Width variable, which in turn permits to infer the type of the v2 local variable. VB Migration Partner attempts to infer neither the type of the v1 local variable (because it is explicitly declared As Variant) nor the type of the frm parameter (because by default method parameters aren’t under the scope of the InferType pragma).
今度の新しいバージョンでは、VB Migration Partnerはm_Width変数の型からWidthプロパティの型を推測することができ、同様にv2ローカル変数の型を推測します。VB Migration Partnerは、v1ローカル変数の型(v1ははっきりとバリアント型で宣言されています。)とfrmパラメータ(デフォルトで、メソッドのパラメータはInferType pragmaのスコープ範囲にありません。)の両方ともに推測しようとしません。
You can extend type inference to members that were declared with an explicit As Variant by using the Force argument in the pragma. In addition, passing True in the second (optional) argument extends the scope to method parameters:
InferType Pragmaに引数Forceを指定することで、明示的にバリアント型で宣言されたメンバに対しても型の推理が可能となります。さらに2つ目の任意の引数にTrueを指定することで、メソッドパラメータにスコープを広げられます。
'## InferType Force, True
The result of the conversion is now the following:
変換した結果は以下のようになります。
Private m_Width As Single Public Property Width() As Single Get Return m_Width End Get Set(ByVal value As Single) m_Width = value End Set End Property Public Sub Test(ByRef x As Short, ByRef frm As Form1) ' UPGRADE_INFO (#0561): The 'frm' symbol was defined without an explicit "As" clause. ' UPGRADE_INFO (#05B1): The 'res' variable wasn't declared explicitly. Dim res As String = Nothing Dim v1 As Integer ' UPGRADE_INFO (#0561): The 'v2' symbol was defined without an explicit "As" clause. Dim v2 As Single v1 = x * 10 v2 = Width + x frm = New Form1() res = frm.Caption End Sub
Notice that in this new version the type of frm parameter is inferred correctly, which in turn permits to infer the type of the res local variable.
今度のバージョンでは、frmパラメータの型が正しく推測され、同様にresローカル変数の型を推測することに注目してください。型の推測はスカラ型とオブジェクト型の両方で行われます。次のようなVB6コードについて考えてみましょう。
Type inference works both with scalar types and object types. For example, consider the following VB6 code:
VB Migration Partnerは、変数tbがTextBox型であることを推測でき、デフォルトプロパティを正しく拡張できます。
'## InferType
Public Sub SetAddress(ByVal address As String)
Dim tb
Set tb = Me.txtAddress ' where txtAddress is a TextBox
tb = address
End Sub
VB Migration Partner can infer that the tb variable is of type TextBox and, consequently, it can correctly expand its default property:
メソッドパラメータへPragmaスコープを広げていくことは、常に良策であるとは限りません。それは、VB Migration Partnerの現バージョンでは、メソッドの中での割り当てを見ることによりパラメータの型を推測しており、メソッドの呼び出しによって生じる暗黙の割り当てについては評価しないからです。このため、マイグレーションで推測される型は、ときには正しくないかもしれません。
Public Sub SetAddress(ByVal address As String) Dim tb As VB6TextBox = Me.txtAddress tb.Text = address End Sub
Extending the pragma scope to method parameters isn’t always a good idea, because the current version of VB Migration Partner infers the type of parameters by looking at assignments inside the method and doesn’t account for implicit assignments that result from method calls. For this reason, the type inferred during the migration process might not be correct in some cases.
重要事項:型の推測は正確な技術ではないので、VB Migration Partnerによって推測されたデータ型が正しいかどうかを、いつもダブルチェックすべきです。よりよい方法としては、マイグレーションの早い段階だけにInferType Pragmaを使い、その後は元のVB6コードを編集するか、もしくはSetType Pragmaを使うことによってメンバに特別な型を割り当てることです。
Important note:
Type inference isn’t an exact science and you should always double-check that the data type inferred by VB Migration Partner is correct. Even better, we recommend that you use the InferType pragma only during early migration attempts and then you later assign a specific type to members by editing the original VB6 code or by means of the SetType pragma.
タイプの推定は科学的に正確ではないので、VBMPによって推定されたデータタイプが正しいことを常に2重チェックするべきです。さらに良い方法として、私たちはマイグレーションの初期にInferTypeプラグマを使い、後で、元のVB6ソースコードを編集するかSetTypeを使用してメンバーに特定のタイプを割り当てることを推奨します。
Unreachable code removal/Unreachable code(どこからも呼ばれないコード)の撤去
All versions of VB Migration Partner insert an upgrade comment at the beginning of an unreachable code region. Unreachable code is, for example, the code that follows a Return or Exit Sub statement:
VB Migration Partnerの全てのバージョンは、Unreachable code(どこからも呼ばれないコード)範囲の前にアップグレードコメントを入れます。Unreachable codeとは、例えばReturnやExit Subステートメントの後ろにあるコードのことです。
Public Sub Test(ByRef x As Integer, ByRef y As Integer)
x = 123
Exit Sub
' UPGRADE INFO (#0521): Unreachable code detected
x = 456
y = 789
End Sub
Users of VB Migration Partner can use the RemoveUnrechableCode pragma to either remove or comment out all the statements in the unreachable code block. This pragma takes one argument which can be equal to Off (do nothing, the default behavior), On (remove all statements in the unreachable block), or Remarks (comment out all statements in the unreachable block). For example, assuming that the previous code snippet is under the scope of the following pragma:
VB Migration Partner Enterprise editionの利用者は、RemoveUnrechableCode Pragmaを使ってUnreachable codeブロックの中にある全てのステートメントを撤去するか、コメントアウトするかのどちらかができます。このPragmaは下のような1つの引数を取ります。OFF(デフォルト値で何もしません。)ON(Unreachableブロックの中の全てのステートメントを取り去ります。)Remarks(Unreachableブロックの中の全てのステートメントをコメントアウトします。)先ほど挙げたコードの断片が次のPragmaのスコープ範囲にあると仮定してください。
'## RemoveUnreachableCode Remarks
then the code generated by VB Migration Partner would be as follows:
VB Migration Partnerによって生成されたコードは次のようになります。
Public Sub Test(ByRef x As Integer)
x = 123
Exit Sub
' UPGRADE INFO (#06F1): Unreachable code removed ' EXCLUDED: x = 456
' EXCLUDED: y = 789
End Sub
Unused members removal/未使用のメンバの撤去
All versions of VB Migration Partner insert an upgrade comment just before unused fields, constants, variables, properties, and methods. The actual message depends on whether the member is never used in the application or it is referenced by a method that, in turn, appears to be unused. The following piece of generated VB.NET code shows both kinds of messages:
VB Migration Partnerの全てのバージョンは、未使用のフィールド、定数、変数、プロパティ、メソッドの直前にアップグレードコメントを入れます。実際のメッセージは、メンバがアプリケーションの中で使われていないかどうか、未使用と思われるメソッドに参照されているかどうかによって決まります。VB.NETが生成した下記のコードの断片は、上で述べた両方のメッセージの例を示しています。
' UPGRADE_INFO (#0501): the 'UnusedField' member isn’t used anywhere in current application Public UnusedField As String ' UPGRADE_INFO (#0511): the 'UnusedConst' member is referenced only by members that ' haven’t found to be used in current application Public Const UnusedConst As String = "Foobar"
VB Migration Partner comes with an extender that automatically removes unused constants and Declare statements.
VB Migration Partnerは自動で未使用の定数とDeclareステートメントを取り去ります。
In addition, users of VB Migration Partner can use a RemoveUnusedMembers pragma to automatically remove (or remark out) all sorts of unused members. For example, if the previous code snippet were under the scope of the following pragma:
VB Migration Partner Enterprise editionの利用者は、RemoveUnusedMembers Pragmaを使って全ての未使用のメンバを取り去ります。(または、コメントアウトします。) 先ほど挙げたコードの断片が次のPragmaのスコープ範囲にあると仮定すると、
'## RemoveUnusedMembers Remarks
then the result would be as follows:
変換結果は次のようになります。
' UPGRADE_INFO (#0701): the 'UnusedField' member has been removed because ' it isn’t used anywhere in current application Public UnusedField As String ' UPGRADE_INFO (#0711): the 'UnusedConst' member has been removed because ' it is referenced only by members that haven’t found to be used in current application Public Const UnusedConst As String = "Foobar"
Please notice that the RemoveUnusedMembers pragma used with the Remarks disables a few other refactoring features, for example the ConvertGosubs pragma. In other words, if the following pragmas are active:
RemoveUnusedMembers PragmaにRemarksを引数として使用した場合、他のいくつかのリファクタリング機能(例えば、ConvertGosubsPragma)が無効になることに注意してください。言い換えると、下記のPragmaがアクティブで有った場合、
'## RemoveUnusedMembers Remarks '## ConvertGosubs '## UseTryCatch
then VB Migration Partner generates (remarked out) nonoptimized VB.NET code, where Gosub keywords are not rendered as separate methods and On Error statements are not converted into Try-Catch blocks.
VB Migration Partnerは最適化されていないVB.NETコードを生成します。生成されたコードは、GoSubキーワードが別のメソッドに変換されませんし、On Error StatementsはTry-Catchブロックに変換されません。
Important note:
the RemoveUnusedMembers pragma deletes or remarks all members that haven’t found to be referenced by any other member in the current project or other projects in the current solution. However, this mechanism can lead to unwanted removal if the member is part of a public class that is accessed by another project (not in the solution) or if the member is accessed via late-binding. You can use the MarkAsReferenced or MarkPublicAsReferenced pragmas to account for the first case.
RemoveUnusedMembers Pragmaを使うと、現ソリューションの現プロジェクトや他のプロジェクトの中でどのメンバにも参照されていないように見える全てのメンバを消したりメンバの存在に気付くことができます。けれども、この手法を用いることで、メンバが(ソリューションではなく)他のプロジェクトからアクセスされているPublicクラスに属している場合や、遅延バインディングでアクセスされているときに、望まない撤去が行われる可能性があるということです。一番目のケースを解明するのにMarkAsReferencedや MarkPublicAsReferenced Pragmaを使うことができます。
However, there is no simple way to detect whether a member is accessed via late-binding. For this reason the RemoveUnusedMembers pragma supports a second safeMode parameter. If this parameter is True then the pragma affects only members that can’t be reached via late-binding, e.g. constants, Declare statements, and members with a scope other than public.
メンバが遅延バインディングでアクセスされているかどうか検出する簡単な方法はありません。このため、RemoveUnusedMembers Pragmaが2番目のセーフモードパラメータをサポートします。このパラメータがTrueならば、Pragmaは遅延バインディングで呼ばれていないメンバ(例えば、定数、Declareステートメント、パブリック以外のスコープを持つメンバ)だけに影響します。
Renaming program members/プログラムのメンバの名前を変更する
VB Migration Partner supports enforcement of renaming guidelines by means of declarative rules that can be specified in an XML file. Thanks to this feature you can – for example – rename all push button controls so that their name begins with “btn” and possibly delete the “cmd” prefix that appeared in their VB6 name.
VB Migration Partner Enterprise editionは、XMLファイルの中で記載されている宣言の規則に基づいてリネームの指針が実行されるのをサポートします。これにより、“btn”で始まる全てのプッシュボタンコントロールのリネームが可能となり、VB6で見られた“cmd”の接頭辞を消すことができます。
You enable the XML-based renaming engine by means of the ApplyRenameRules pragma. This pragma takes an optional argument that, if specified, must be equal to the path of the XML file that contains the renaming rules. If the argument is omitted, VB Migration Partner uses the RenameRules.xml file in its install folder. (It is recommended that you make a copy of this file and have the pragma point to the copy rather than the original file created by the setup procedure.) Here’s an example of this pragma:
ApplyRenameRules PragmaによってXMLベースのリネームエンジンを動かせます。このPragmaはオプションで1つの引数を持ち、リネーム規則を含むXMLファイルと同じパスに具体的に明記されています。引数をうっかり忘れると、VB Migration Partnerはインストールフォルダに置かれたRenameRules.xmlファイルを使います。(このファイルをコピーして、setupプロシージャによって生成されたオリジナルファイルではなく、コピーしたファイルをPragmaに使わせることをお勧めします。) Pragmaの例をご覧ください。
'## ApplyRenameRules c:\apps\myrules.xml
An important note: this pragma has an implicit project scope and affects all the projects in the project group being migrated. (This behavior is an exception to the usual scoping rules for pragmas.)
重要な注記:このPragmaは暗黙のプロジェクトスコープを持っていて、プロジェクトグループでマイグレーションされた全てのプロジェクトに影響を与えます。(この振る舞いは、Pragmaの普通のスコープ規則に対する例外です。)
The RenameRules.xml file provided with VB Migration Partner includes all the common naming rules for controls and forms. Here’s an excerpt of the file:
VB Migration Partner が提供したRenameRules.xmlファイルには、コントロールとフォームに関する共通の全命名規則が書かれています。ファイルから抜粋したものを示します。
< ?xml version="1.0" encoding="utf-8" ?>
<NamingRules>
< Symbol kind="Form">
< Rule pattern="^frm" replace="" />
< Rule pattern="(Form)?(? < num > \d*)$" replace="Form${num}" />
< /Symbol>
< Symbol kind="Component" type="VB.CommandButton" >
< Rule pattern="^(cmd)?" replace="btn" />
< Rule pattern="Button$" replace="" changeCase="pascal" isFinal="true" />
< /Symbol>
< !-- more controls are dealt with here -->
</NamingRules>
The kind attribute is used first to determine the kind of symbol the rule applies to. Valid names are Form, Class, Module, Type, UserControl, Enum, Component, Method (includes subs and functions), Field, Property, Event, EnumItem (the members of an Enum declaration), Constant, and Variable (includes, local variables and parameters.)
Kind属性は、最初に、規則を当てはまるシンボルの種類を決定するのに使用されます。有効な名前としては、Form、Class、Module、Type、ユーザーコントロール、Enum、コンポーネント、メソッド(SubsとFunctionsを含みます。)、フィールド、プロパティ、イベント、EnumItem(Enum宣言のメンバ)、定数と変数(ローカル変数とパラメータを含む)があります。
If kind is equal to Component or Variable, you can optionally include a type attribute, that specifies the VB6 type of the member to which the rule applies. For example, the following rule renames all Integer variables named “i” into “index”
もしkindがコンポーネントや変数なら、任意でType属性を含めることができ、ルールを適用したいVB6型のメンバの指定ができます。下記の例では、“i”として定義されたInteger型の変数を“index”にリネームしています。
< Symbol kind="Variable" type="Integer" > < Rule pattern="^i$" replace="index" ignoreCase="false" /> </Symbol>
Renaming rules are based on regular expressions. The pattern attribute is used to decide whether the rule applies to a given member, and the replace attribute specifies how the member should be renamed. The ignoreCase optional attribute should be false if you want the pattern to be applied in case-sensitive mode (by default comparisons are case-insensitive). The changeCase optional attribute allows you to change the case of the result and can be equal to “lower”, “upper”, “pascal” (first char is uppercase), or “camel” (first char is lowercase).
リネーム規則は正規表現に基づいています。pattern属性は規則が特定のメンバに適用されるかどうか決めるのに使用され、replace属性はメンバがどう改名されるべきであるかを指定します。大文字と小文字を区別してパターンを適用したい場合は、ignoreCase オプション属性をfalseに設定してください。(デフォルトでは、大文字と小文字を区別しません) changeCaseオプション属性は、結果の活字ケースを“lower”, “upper”, “pascal”, “camel”と同等に変更することが可能です。
Being Visual Basic a case-insensitive language, in most cases the default behavior is fine. However, consider the following renaming requirement: many VB6 developers preferred to use “C” as a prefix for all class names, but this guideline has been deprecated in VB.NET. Here’s a rule that drops the leading “C”, but only if it is followed by another uppercase character:
Visual Basicは大文字と小文字を区別しない言語なので、たいていはデフォルトの振る舞いで問題ありません。しかしながら、次のようなリネームが必要なものについて考えてみてください。多くのVB6開発者が、すべてのクラス名に接頭語として「C」を使用するのを好みましが、この方針はVB.NETでは推奨されません。ここに、それが別の大文字キャラクタが後に続いている場合にだけ、先頭の「C」を削除するルールがあります。
< Symbol kind="Class"> < Rule pattern="^C(?=[A-Z])" replace="" ignoreCase="false" /> </Symbol>
The changeCase attribute is useful to enforce naming rules that involve the case of identifiers. For example, a few developers like all-uppercase constant names; there a rule that enforce this guideline:
changeCase属性は識別子を含んだときのネーミング規則を強化するのに役立ちます。例えば、定数の名前を全て大文字にする開発者が中にはいますが、この方針を強化するのに次のような規則があります。
< Symbol kind="Constant" > < Rule pattern="^.+$" replace="${0}" changeCase="upper" /> </Symbol>
You can restrict a rule to one or more project items by means of the projectItem optional attribute. This attribute is considered as a regular expression applied to the name of the parent project item where the symbol is defined. (The project item name is in the form “projectname.itemname”. For example, let’s say that you want to drop any “str” prefix that appears in string variables defined inside the frmMain form and in Helpers module of the TestApp project:
projectItemオプション属性によって、変換ルールを複数のプロジェクトに制限することが出来ます。この属性はシンボルが定義された親プロジェクトに適用された正規表現としてみなされます。フォームの中に“projectname.itemname”というプロジェクトアイテム名があります。例えば、TestAppプロジェクトのfrmMainとHelpersモジュール内で定義された、文字変数のstr接頭語を削除したい場合、
< Symbol kind="Variable" type="String" projectItem="^TestApp\.(frmForm|Helpers)$" > < Rule pattern="^str" replace="" /> < /Symbol>
It is essential that the projectItem regular expression accounts for the project name; if you want to apply the rename rule to any project – as it’s often the case – you must specify the .+ regular expression for the project name part. For example, the following rule changes the name of the ChangeID method in the Helpers module in all converted projects
プロジェクト名を表す、projectItem正規表現は不可欠です。よくあるケースですが、リネーム規則を全てのプロジェクトに当てはめたい場合、正規表現のプロジェクト名パートに” .+”を指定する必要があります。例えば以下のルールでは、全ての変換されたプロジェクトの中の、Helpersモジュールの中のChangeIDメソッドの名前を変更します。
< Symbol kind="Method" projectItem="^.+\.Helpers$" > < Rule pattern="^ChangeID" replace="ChangeIdentifier" /> </Symbol>
The projectItem attribute is especially useful if your VB6 adopted the naming convention according to which all form names begin with “frm”, all classes with “cls” and so forth. In such a case, in fact, you can easily restrict a rule by relying on these prefixes:
projectItem属性は、全てのフォーム名が“frm”で始まったり、全てのクラス名が“cls”で始まったりなど、VB6のネーミング変換の際に特に役立ちます。このような場合、これらの接頭語を使うことによって、簡単に規則を制限することができます。
<!-- convert x,y into xPoint and yPoint, but only inside classes -->
<Symbol kind="Variable" type="Double" projectItem="^cls" >
< Rule pattern="^(x|y)$" replace="${0}Point" />
</Symbol>
By default, <Symbol> tags that have a non-empty projectItem attribute are evaluated before rules where this attribute is omitted. All the <Rule> tags inside each block are evaluated in order, from the first one to the last one. However, if a rule has the isFinal attribute set to “true” then all the rules that follow are ignored.
デフォルトでは、空でないprojectItem属性を持っている <Symbol> タグは、この属性が省略されたルールの前に判断されます。各々のブロックの中にある全ての <Rule> タグは、最初から最後まで順番に判断されます。ただし、isFinal属性が“true”に設定された変換ルールでは、全てのルールは以後無効となります。
Important note:
VB Migration Partner renaming engine doesn’t check whether the new name assigned to symbols is a valid VB.NET identifier and doesn’t check whether the new name is unique. It’s up to the developer ensuring that the generated VB.NET code doesn’t include invalid or duplicated identifier names. In practice you’ll notice this kind of errors as soon as you compile the generated VB.NET, therefore we don’t consider it a serious issue.
VB Migration Partnerリネーミングエンジンは、シンボルに割り当てられた新しい名前がVB.NETのものと比べて妥当であるかどうかをチェックしませんし、新しい名前が唯一の名前かどうかもチェックしません。生成されたVB.NETコードが無効でまったく同じ名前を含んでいないかどうかを確認するのは開発者の役目です。実際は、生成されたVB.NETコードをコンパイルした際にすぐにこの種のエラーに気付きます。なので、それほど深刻に考えなくても大丈夫です。
When applying this pragma, however, you should be aware that there is margin for other issues that do not cause a compilation error and that may go unnoticed if you don’t perform accurate tests on the generated VB.NET application. Consider the following VB6 code:
しかし、このPragmaを適用する際に、ご承知のとおり、生成されたVB.NETアプリケーションに対し緻密なテストを実行しないなら、コンパイルエラーではない別の問題が潜んでいる余地があることに十分に配慮してください。以下のVB6コードを参照下さい。
Const Name As String = "Code Architects"
Public Sub Test()
Const strName As String = "NAME"
Debug.Print strName & " = " & Name ' displays "NAME = Code Architects"「NAME = Code Architects」と示されます。
End Sub
Next, let’s assume that you apply a rename rule that prefixes all string constants with the “str” prefix, if the prefix is missing. This causes the first constant to be assigned the same name of the local constant. The neat effect is that the local constant shadows the first constant and that the method displays a different string:
次に接頭語がない文字定数の前に、”str”を接頭語として置くようなリネームルールを適用したと仮定してください。それは、最初の定数に、ローカル変数と同じ名前を割り当てることを引き起こします。適切な対処をするには、ローカル変数が最初の変数を示し、メソッドが別のstringを示すようにすることです。
Const strName As String = "Code Architects"
Public Sub Test()
Const strName As String = "NAME"
Debug.Print strName & " = " & strName ' displays "NAME = NAME""NAME = NAME"と示されます。
End Sub
This sort of issues are quite subtle because they don’t cause any compilation error. The current version of VB Migration Partner when a rename rule causes this problem, therefore it’s your responsibility ensuring that functional equivalence isn’t compromised by rename rules.
この種類の問題は、コンパイルエラーの原因とはならないため、かなりとらえにくい問題です。現在のVB Migration Partnerのバージョンで、リネームルールがこの問題を引き起こした時、機能等価がリネームルールにより悪い結果にならないように保証するのは、お客様側の責任になります。
4.4 Extenders/機能拡張
Developers can write extenders to receive notifications from VB Migration Partner during the parse and code generation process. An extender class can access VB Migration Partner’s object model, read pragmas (and dynamically add new ones), edit the VB6 code before it is being parsed, modify the VB.NET code after it has been generated, and so forth.
開発者は構文解析プログラムやコード生成プロセスが動いている間、VB Migration Partnerから通知を受け取ってExtenderを書くことができます。ExtenderクラスはVB Migration PartnerのオブジェクトモデルにアクセスしてPragmaを読んだり、新しいPragmaを追加します。そして、構文解析プログラムが動き出す前にVB6コードを編集し、生成されたVB.NETコードを修正します。
The following extender class inserts a remark at the top of all VB.NET code files produced during the migration process:
次のExtenderクラスはマイグレーションプロセスで生成されたVB.NETコードファイルの先頭に注記として挿入されます。
' this attribute marks the current DLL as an extender この属性は現在のDLLを拡張としてマークします <Assembly: CodeArchitects.VB6Library.VB6SupportLibrary(True)> <VBMigrationExtender("My first extender", _ "A demo extender for CodeArchitect's VB Migration Partner")> _ Public Class DemoExtender Implements IVBMigrationExtender Public Sub Connect(ByVal data As ExtenderData) _ Implements IVBMigrationExtender.Connect ' do nothing at connect time 接続時間で何もしません。 End Sub Sub Notify(ByVal data As ExtenderData, ByVal info As _ OperationInfo) Implements IVBMigrationExtender.Notify If info.Operation = OperationType.ProjectItemConverted Then Dim remark As String = "Generated by VB Migration Partner" & vbCrLf info.ProjectItem.NetCodeText = _ remark & info.ProjectItem.NetCodeText End If End Sub End Class
All pragmas are visible to extenders. Even better, an extender can programmatically create new instances of pragmas and associate them with code entities, as if they were embedded in the VB6 code being migrated. This feature enables developers to overcome that static nature of pragmas hard-coded in VB6 code. For example, the decision to treat a variable as an auto-instancing variable might be taken after checking how the variable is used, as in this code:
全てのPragmaはExtenderに見えます。さらによいことは、まるでVB6のコードがマイグレーションされたかのように、ExtenderはPragmaの新しいインスタンスを生成でき、それらをコードの実体と関連づけます。この特性は、開発者にとって、Pragmaの静的な性質がVB6で難しかったコーディングに勝ることを可能にします。例えば、自動インスタンス変数として変数を扱う決定は、次に示すコードのように、変数がどのように使われているかをチェックした後でなされます。
' (this code runs inside an extender DLL) If someCondition Then ' treat the "cn" field as a true auto-instancing variable Dim cnSymb As VBSymbol = info.ProjectItem.Symbol.Symbols("cn") Dim pragma As New VBPragma("AutoNew True", Nothing) cnSymb.Pragmas.Add(pragma) End If
For VB Migration Partner to recognize an extender DLL, developers need to deploy the DLL in VB Migration Partner’s main directory. The interactive user can then enable and disable extensions from the Extensions tab of the Tools-Options dialog box.
VB Migration Partnerがextender DLLを認識するためには、開発者はVB Migration PartnerのメインディレクトリにDLLを置く必要があります。Tools → Optionsの順番にクリックすると現れるダイアログの中にあるExtensionsタブで、Extensionを有効にしたり、無効にしたりすることができます。
The sample extenders that are provided with VB Migration Partner perform quite generic task, for example removing unused Const and Declare statements or polishing the code of a VB6 user control class after the conversion to VB.NET.
VB Migration Partnerから提供されたExtenderのサンプルは、かなり包括的な仕事をします。例えば、未使用の定数や宣言のステートメントを削除したり、VB.NETに変換された後のユーザコントロールクラスのVB6コードを洗練します。
However, the main purpose of extenders is to customize VB Migration Partner’s behavior and output for specific projects and coding styles. For example, a software company might decide to create a base class for all their forms and therefore all the forms in the VB.NET application should derive from this base class rather than CodeArchitects.VB6Library.VB6Form. Implementing an extender that changes the base class for all forms is quite simple:
けれども、Extenderの主な目的は、VB Migration Partnerの振る舞いをカスタマイズして、一定のプロジェクトやコーディング形式を出力することです。ソフトウェア会社は全てのFormの基になるクラスを生成しようと試み、そのような訳でVB.NETアプリケーションの全てのFormはCodeArchitects.VB6Library.VB6Formよりこの基になるクラスから派生すべきです。全フォームがかなり単純となるように、基になるクラスを変更するExtenderを実行すると下記のようになります。
Sub Notify(ByVal data As ExtenderData, ByVal info As OperationInfo) _
Implements IVBMigrationExtender.Notify
If info.Operation = OperationType.ProjectItemConverted AndAlso
info.ProjectItem.Symbol.Kind = SymbolKind.Form Then
' VB Migration Partner has completed the conversion of a form
info.ProjectItem.NetDesignerText = info.ProjectItem.NetDesignerText.Replace( _
"Inherits System.Windows.Forms.Form", "Inherits CompanyName.CompanyFormBase")
End If
End Sub
(Notice that the CompanyName.CompanyFormBase class must inherit from CodeArchitects.VB6Library.VB6Form for the converted application to work correctly.)
(CompanyName.CompanyFormBaseクラスは変換されたアプリケーションが正しく動くためにCodeArchitects.VB6Library.VB6Formを継承しなければなりません。) 4.5 3rdパーティActiveXコントロールのサポートについて
4.5 Support for 3rd-party ActiveX controls/サードパーティActiveXコントロール対応
VB Migration Partner supports all the controls included in the Visual Basic 6 package, with the only exception of the OLE and Repeater controls. When migrating a form that contains unrecognized controls, such controls are transformed into “placeholder” controls that stand out on the form because of their red background.
VB Migration PartnerはVisual Basic 6のパッケージに含まれる全てのコントロールをサポートします。ただし、OLEとRepeater コントロールは除きます。認識されないコントロールを含むFormをマイグレーションすると、そのようなコントロールは赤い背景色をしているためにFormの上で目立つ“プレースホルダー”コントロールに変換されます。
Once you have a .NET control that mimics or wraps the original ActiveX control, you just need to copy the .NET DLL inside VB Migration Partner’s main directory; no registration is required. The next time you run VB Migration Partner, the new control is recognized as if it were one of the VB6 built-in controls.
Alternatively, you can copy it to a folder and then use an AddLibraryPath pragma to have VB Migration Partner recognize all the DLLs in that folder:
独自のActiveXコントロールに似ているか、またはラップした.NETコントロールが存在した場合、それらはVB Migration Partnerのメインディレクトリの中で.NET DLLにコピーされます。レジストリ登録は必要ありません。VB Migration Partnerを次回起動すると、新しいコントロールがまるでVB6で組み込まれているコントロールであるかのように認識されます。あるいは、それをフォルダにコピーし、AddLibraryPathPragmaを使うことで、VB Migration Partnerがフォルダの中の全てのDLLを認識できるようにすることができます。
'## AddLibraryPath "c:\mydlls"
VB Migration Partner can handle additional ActiveX controls, in addition to those that are supported out of the box. The exact sequence of actions that is necessary to implement such support depends on the type of the control you want to support. Three options are available, listed here in order of increased difficulty:
VB Migration PartnerはもともとサポートされているActiveXに加えて、追加したActiveXコントロールにも対応可能です。そのようなサポートを実行するのに必要な正しい順序は、サポートしたいコントロールのタイプに依存します。3つのオプションを使うことができますが、後に記されているほど実現困難となります。
- Use VB Migration Partner to migrate it to VB.NET. (This option requires that the control is authored in VB6 and you have its source code.)
- マイグレーションするためにVB Migration Partnerを使用して、VB.NETに変換します。(このオプションではコントロールがVB6で作成され、そのソースコードが存在する必要があります。)
- Create a managed wrapper around the original ActiveX control. VB Migration Partner’s package includes the AxWrapperGen utility that automates this process.
- 独自のActiveXコントロールから管理されたラッパーを生成します。VB Migration Partnerのパッケージにはこのプロセスを自動で行うAxWrapperGenユーティリティが含まれています。
- Create a fully managed control that behaves like the original control.
- オリジナルのコントロールと同じように動作する、完全に管理されたコントロールを作成する。
For completeness’s sake, when comparing all the available solutions you should also consider a fourth solution strategy:
また、万全を期するのであれば、利用可能な全ての解決策を比べたうえで、さらに4番目の解決方法を考慮するべきです。
- Migrate the application as usual, then manually replace the “placeholder” control with a .NET control and then manually fix all the references to the control’s properties and methods.
- アプリケーションを通常変換して下さい。それから、手動で“プレースホルダー”コントロールを.NETコントロールに置き換え、さらに手動でコントロールのプロパティとメソッドの参照を調整します。
If you have the VB6 source code of the ActiveX control it is recommended that you follow the a) strategy. If source code isn’t available, the choice between remaining strategies depends on a number of considerations:
ActiveXコントロールのVB6ソースコードがあるなら、上記a)を行うことをおすすめします。ソースコードが利用できないのであれば、いくつかのことを考慮する必要があります。
- A VB.NET that uses wrappers for ActiveX controls can’t benefit from some advantages of the .NET Framework platform, for example XCOPY deployment and side-by-side execution of different versions of the same component.
- ActiveXコントロールにラッパーを使うVB.NETは、.NET Frameworkから恩恵を受けられません。例えば、XCOPYデプロイメント、同じコンポーネントの異なるVerisonのside-by-side実行など。
- The COM Interop mechanism isn’t perfect and we have noticed that a few complex controls – most notably, the DataGrid control – occasionally crashes when placed on a .NET form. You should carefully test all forms that host one or more ActiveX controls, either directly or wrapped by a .NET class.
- COM Interopメカニズムは完全ではないので、特にDataGridコントロールなどのいくつかの複雑なコントロールは、.NETのFormに配置されたときに壊れることがあります。.NETクラスによるラップあるいは直接配置された1つ以上のActiveXコントロールをもったすべてのFormについて、注意深く動作確認すべきです。
- If the ActiveX control is used massively by the project being migrated – or in other projects that you plan to migrate in the near future – the time required to create a fully managed control that behaves like the original control can pay off nicely.
- ActiveXコントロールがマイグレーションされたプロジェクト、または近い将来マイグレーションしようとしている他のプロジェクトでたくさん使われている場合、オリジナルのコントロールのように動作する完全に管理されたコントロールを作成する時間が要求されます。
- If the application being migrated sparingly uses the control – for example it appears only in one or two forms – running VB Migration Partner and then manually fixing all references is possibly the most cost effective strategy
- マイグレーションされたアプリケーションが1つか2つのFormの中でだけに貼られているコントロールを使う場合、VB Migration Partnerを活用し、全ての参照を手動で修正していくことが、一番費用対効果の高いやりかたです。
The remainder of this section explains how to implement strategy a) and b).
このセクションの残りでは、方針a) と b) の実行方法を説明します。
Note:
Details about strategy c) will be made available when the release version is launched.
方針c) についての詳細はりリースバージョンが起動されたときに利用できるようになります。
Migrating ActiveX Controls authored in VB6/VB6で署名されたActiveXコントロールの移行
If the control or component is authored with VB6 and you have its source code, in most cases adding support for that control or component is a simple process: just run VB Migration Partner to migrate the ActiveX DLL or ActiveX Control project that contains the user control, going through the usual convert-test-fix cycle. When the migrated project finally works correctly, you might want to polish the VB.NET code.
コントロールやコンポーネントがVB6で作られていて、かつそのソースコードがあるとしたら、多くの場合そのコントロールやコンポーネントに対するサポートを追加することは簡単な工程となります。ユーザコントロールを含むActiveX DLLかActiveX Controlプロジェクトを移行のためにVB Migration Partnerをただ利用し、通常の「convert-test-fix」サイクルを通して変換するシンプルな工程です。プロジェクトのマイグレーションが終わったときには、VB.NETのコードは洗練され、正確に動作していることでしょう。
For example, most VB6 user controls have been created by means of the ActiveX Control Interface Wizard, which generates tons of VB6 code whose only purpose is remedying the lack of inheritance in VB6. For example, assume that you are migrating a VB6 user control that works like an enhanced TextBox control. Such a control surely includes a Text property that does nothing but wrapping the property with same name of the inner TextBox control:
例えば、ほとんどのVB6ユーザコントロールはActiveX Control Interface Wizardによって生成され、VB6において欠如された継承を改善することのみを目的としたたくさんのVB6コードを生成しています。例えば、テキストボックスの機能を拡張した、VB6のユーザコントロールをマイグレーションしていると仮定してください。そのようなコントロールは、TextBoxコントロール内にもつ同じ名前のプロパティをラッビングしただけのTextプロパティが含まれます。
Public Property Get Text() As String Text = Text1.Text End Property Public Property Let Text(ByVal New_Text As String) Text1.Text() = New_Text PropertyChanged "Text" End Property
This property is translated correctly to VB.NET, however it is unnecessary and could be dropped without any negative impact on the migrated project. The simplest way to fix this code is by means of a couple of OutputMode pragmas:
このプロパティは正確にVB.NETに変換されましたが、マイグレーションされたプロジェクトには必要でなく、どんな悪い影響もありません。このコードを修正する最も簡単な方法は、二つの対になるOutputMode Pragmaを使うことです。
'## OutputMode Off Public Property Get Text() As String Text = Text1.Text End Property Public Property Let Text(ByVal New_Text As String) Text1.Text() = New_Text PropertyChanged "Text" End Property '## OutputMode On
Also, you can use PostProcess pragmas to delete special remarks added by the ActiveX Control Interface Wizard, as well as calls to the PropertyChanged method (which are useless under VB.NET).
(VB.NETでは使い物にならない)PropertyChangedメソッドの呼び出しと同じように、ActiveX Control Interface Wizardによって付け加えられた特別な備考を消すPostProcess Pragmaを使うことができます。
Running the AxWrapperGen tool/AxWrapperGenツールを実行する
AxWrapperGen is a tool that is part of the VB Migration Partner package. (You can find it in the main installation directory, which by default is C:\Program Files\Code Architects\VB Migration Partner.) It is a command-line utility, therefore you must open a command window and run AxWrapperGen from there.
AxWrapperGenはVB Migration Partnerパッケージに含まれているツールです。(AxWrapperGenはVB Migration Partnerのメインインストールディレクトリに存在しており、デフォルトのフォルダは、C:\Program Files\Code Architects\VB Migration Partnerです。)このツールはコマンドラインユーティリティーなので、コマンドプロンプト上で動かします。
AxWrapperGen’s main purpose is allowing VB Migration Partner to support compiled 3rd-party ActiveX controls. AxWrapperGen takes one mandatory argument, that is, the path of the .ocx file that contains the ActiveX control to be wrapped. For example, the following command creates the wrapper class for the Microsoft Calendar control (and of course assumes that such control is installed in the c:\windows\system32 folder):
AxWrapperGenの主な目的は、VB Migration Partnerに3rdパーティActiveXコントロールのサポートをさせることです。AxWrapperGenは1つの必須の引数をとり、その引数とはラップされたActiveXコントロールを含むocxファイルのパスです。下記のコマンドはMicrosoft カレンダーコントロール(このコントロールはご存知の通りc:\windows\system32フォルダにインストールされています。)のラッパークラスを生成します。
AxWrapperGen c:\windows\system32\mscal.ocx
(Notice that we are using the MSCAL.OCX control only for illustration purposes, because VB Migration Partner already supports this control.) If the file name contains spaces, you must enclose the name inside double quotes. AxWrapperGen is able to convert multiple ActiveX controls in one shot
(MSCAL.OCXコントロールを実例として挙げたのは、VB Migration Partnerが既にこのコントロールをサポートしていることを覚えておいてください。)ファイル名にスペースを含んでいるならば、ダブルコーテーションでファイル名を囲まなければなりません。AxWrapperGenは多様なActiveXコントロールを1発で変換することができます。
AxWrapperGen c:\windows\system32\mscal.ocx "c:\windows\system32\threed32.ocx"
By default, AxWrapperGen generates a new project and solution named AxWrapper in current directory. You can change these default by means of the /out switch (to indicate an alternative output directory) and /project switch (to set the name of the new project and solution):
デフォルトで、AxWrapperGenは現在のディレクトリにAxWrapperと名付けられた新しいプロジェクトとソリューションを生成します。オプションに/out(他の出力ディレクトリを指定します。)や/project(新しいプロジェクト名やソリューション名を設定します。)を指定することによってデフォルトの設定を変えることが可能です。
AxWrapperGen c:\windows\system32\mscal.ocx /out:c:\myapp /project:NetCalendar
By default, AxWrapperGen generates VS2008 projects. You can generate VS2010 projects by adding a /version option:
デフォルトで、AxWrapperGenはVS2008プロジェクトを生成します。/versionオプションを指定すると、VS2005プロジェクトを生成することができます。
AxWrapperGen c:\windows\system32\mscal.ocx /version:2010or you can generate VS2010 projects that target .NET Framework 4.0 with this command:
AxWrapperGen c:\windows\system32\mscal.ocx /version:2010_40
AxWrapperGen runs the AxImp tool – which is part of the .NET Framework SDK – behind the scenes, to generate two DLLs that work as the RCW (Runtime Component Wrapper) for the selected control. For example, the mscal.ocx control generates the following two files: msacal.dll and axmsacal.dll. You can specify the following five options, which AxWrapperGen passes to AxImp: /keyfile, /keycontainer, /publickey, /delaysign, and /source. For more information, read .NET Framework SDK documentation.
AxWrapperGenはAxImpツール上で動きます。AxImpツールは.NET Framework SDKに含まれており、背後で、選択されたコントロールにRCW(Runtime Component Wrapper)として働く2つのDLLを生成します。例えば、mscal.ocxコントロールはmsacal.dll と axmsacal.dll.という2つのファイルを生成します。また、/keyfile、/keycontainer、/publickey、/delaysign、/sourceというAxWrapperGenがAxImpに渡す5つのオプションがあります。もっと情報が必要であれば、.NET Framework SDKドキュメントをお読みください。
At the end of generation process, AxWrapperGen runs Microsoft Visual Studio and loads a solution that contains one VB.NET class library (DLL) project, containing a pair of classes for each ActiveX control:
生成プロセスの最後で、AxWrapperGenはMicrosoft Visual Studioを起動し、1つのVB.NETクラスライブラリ(DLL)プロジェクトを含むソリューションをロードします。また、それぞれのActiveXコントロールに対して1組のクラスを含んでいます。
- The first class of each pair works as a wrapper for the original ActiveX control.
1組のクラスのうち最初のクラスは、オリジナルのActiveXコントロールのラッパーとして働きます。 - The second class of each pair provides support during the migration process.
1組のクラスの2番目のクラスは、マイグレーション中にサポートします。
In our example, the MSCAL.OCX file contains only one ActiveX control, therefore only two classes will be created: the class named VB6Calendar inherits from AxMSACAL.AxCalendar and wraps the ActiveX control; the second class is named VB6Calendar_Support And inherits from VB6ControlSupportBase. This class will be instantiated and used by VB Migration Partner during the migration process, but not at runtime during execution.
挙げた例では、MSCAL.OCXファイルはたった1つのActiveXコントロールを含みます、その場合2つのクラスが生成されます。VB6Calendarと名付けられたクラスはAxMSACAL.AxCalendarから継承し、ActiveXコントロールをラップします。2番目のクラスはVB6Calendar_Supportと命名され、VB6ControlSupportBaseから継承します。このクラスはインスタンス化されマイグレーションプロセス中はVB Migration Partnerによって使用されますが、実行中は使用されません。
Before compiling the solution, check the “Instructions” region at the top of each class. In most cases, the project that AxWrapperGen utility creates compiles correctly at the first attempt. The compilation process creates a DLL that you must manually copy into the VB Migration Partner’s main directory.
ソリューションをコンパイルする前に、それぞれのクラスの一番上にある「Instructions」領域をチェックしてください。多くの場合、AxWrapperGenユーティリティが生成したプロジェクトは、初めてのコンパイル時は正確にコンパイルします。コンパイルプロセスは手動でVB Migration PartnerのメインディレクトリにコピーしなければならないDLLを生成します。
In some cases, however, you need to tweak the code that has been created. More precisely, if any property or method has to do with graphic units – in other words, it represents a width or height and is therefore affected by the container’s ScaleMode property – you need to shadow the original member and create your own. For example, the DataGrid control exposes a property named RowHeight, which requires this treatment. This is the code that implements the required fix:
いくつかのケースでは、生成されたコードを手直しする必要があります。もっと正確に言うと、プロパティやメソッドがグラフィックユニットに対してすべきことがある場合、他の言葉で言うと、widthやheightがコンテナのScaleModeプロパティに影響されている場合、オリジナルのメンバを遮断し新しいメンバを生成する必要があります。例えば、RowHeightという名前のプロパティを持つDataGridコントロールは、この処理が必要です。下記は必要な修正を実装するコードです。
<Localizable(True)> _ <Category("Appearance")> _ Public Shadows Property RowHeight() As Single Get Return VB6Utils.FromPixelY(Me, CInt(MyBase.RowHeight), False, True) End Get Set(ByVal value As Single) MyBase.RowHeight = VB6Utils.ToPixelY(Me, value, False, True) End Set End Property
The bulk of the work is done inside the FromPixelY and ToPixelY methods of the VB6Utils class, contained in the CodeArchitects.VBLibrary.dll. These methods check the current ScaleMode value and perform all the required conversions. (Of course, the class exposes also the FromPixelX and ToPixelX methods, for measures along the X axis.)
この処理の大部分はCodeArchitects.VBLibrary.dllに含まれるVB6UtilsクラスのFromPixelY および ToPixelYメソッドで行われます。これらのメソッドは、現在のScaleMode値をチェックし、全ての必要とされる変換を行います。(もちろん、クラスにもX軸を測るFromPixelXとToPixelXメソッドが存在します。)
4.6 Using the VBMP command-line tool/VBMPのコマンドラインツールを利用する
VB Migration Partner supports automated conversions by means of the VBMP.EXE command-line too. You can use this tool inside batch files and in MSBuild projects. Its syntax is quite simple:
VB Migration PartnerはVBMP.EXEコマンドラインによる自動変換をサポートします。このツールはバッチファイルやMSBuildプロジェクトで使用することができます。その構文は非常に簡単です。
VBMP projectfile options
Where projectfile is the complete path of the VB6 project (or project group) file, and options is zero or more of the following:
projectfileがVB6プロジェクト(あるいはプロジェクトグループ)の絶対パスの場合は、optionsは0もしくは下記のようになります。
/out:pathspecifies the parent directory of the folder that will be created for the VB.NET solution. This option corresponds to the path you can enter in the Save tab of the Tools-Options dialog box.)
VB.NETソリューションの為に作成されるフォルダの、親ディレクトリを指定します。(このオプションは、[Tools] −[Options]ダイアログボックスの[Save]タブで入力したパスに一致します。)
/version:VVVV
specifies the Visual Basic version of the code to be output. VVVV can be either 2005, 2008, 2010 or 2010_40. (The default is 2008). The 2010_40 settings generates projects that target .NET Framework 4.0, all other settings generate projects that target .NET Framework 2.0/3.5.
出力するVisual Basicのコードのバージョンを指定します。VVVVは2005もしくは2008のどちらかです。(デフォルトは2005)
/maxissues:NN
specifies the max number of conversions issues. If the conversion process generates more issues than this value, the VBMP utility exits with a non-zero errorlevel and doesn’t proceed with the compilation step even if the /compile option is defined. (If omitted, this value is equal to 10.)
変換で出た問題の最大数を指定します。変換プロセスがこの値以上の問題を生成した場合、VBMPユーティリティは非ゼロのエラーレベルで終了し、/compileオプションが定義されていたとしても変換は続行されません。 (入力を省略した場合、値は10です。)
/compile
causes the converted VB.NET to be compiled.
変換したVB.NETをコンパイルします。
/clearcache
clears the typelib cache.
タイプライブラリのキャッシュをクリアします。
/quiet
suppresses most messages.
メッセージを制限します。
/help or /h
displays a brief explanation of each option.
各々のオプションの簡単な説明を示します。
For example, the following command compiles the c:\vb6\widgets.vbg project and creates a VB2010 solution in the c:\vbnet\widgets folder, then compiles the result unless the conversion process generated more than 30 migration issues:
例えば、次のコマンドはc:\vb6に存在するwidgets.vbgプロジェクトをコンパイルして、c:\vbnet\widgetsフォルダにVB2008ソリューションを生成し、30以上のマイグレーションに関する問題が出力されなければ、ソリューションをコンパイルします。
VBMP c:\vb6\widgets.vbg /out:c:\vbnet /compile /maxissues:30 /version:2010
If the specified VB6 project can’t be converted, or the conversion was aborted because of a fatal error, or the conversion produced more issues than allowed, or if the compilation step produced one or more errors, then VBMP returns a nonzero errorlevel to the operating system.
指定されたVB6プロジェクトが変換されなかったり、致命的なエラーによって変換が失敗したり、変換によってより問題が増えたり、変換中1つ以上の解決困難な問題が発生した場合、VBMPはオペレーティングシステムに非ゼロの値を返します。
4.7 The VB Project Dumper add-in/VBプロジェクトのダンパーアドイン
VB Migration Partner converts all the properties assigned at design-time and whose value is stored in the hidden portion of .frm forms. However, in very few cases, the information stored in these .frm is encoded in a format that we didn’t manage to decode.
VB Migration Partnerはデザイン時に割り付けられた全てのプロパティを変換し、それらの値は拡張子が.frmであるFormの隠れた部分の中に格納されます。これらの.frmに格納された情報は、デコードできない形式でエンコードされることはまれです。
For example, we haven’t found a way to decode how properties of the MSChart control are stored in the .frm form. To correctly migrate this control you should load the original project in the VB6 IDE and run the VBMP Project Dumper add-in.
例えば我々は、拡張子が.frmのFormに格納されたMSChartコントロールのプロパティをデコードする方法を知りません。このコントロールを正しくマイグレーションするためには、VB6 IDEの独自のプロジェクトをロードし、VBMPプロジェクトのダンパーアドインとして動かすべきです。
The VBMP Project Dumper is a VB6 add-in that adds a new command to the Add-ins menu, which – when invoked – creates an XML file containing all the properties of all the controls in the project. You need to invoke the command just once, before attempting the migration process. (You need to invoke it again only if you modify one or more properties of an MSChart control in the VB6 project or if accidentally delete the XML file.)
VBMPプロジェクトのダンパーは、アドインメニューに新しいコマンドを加えるVB6のアドインで、起動時にはプロジェクトの中に含まれる全てのコントロールの全プロパティを含むXMLファイルを生成します。マイグレーションプロセスを試みる前に、一度だけ起動すればよいです。(VB6プロジェクトの中のMSChartコントロールのプロパティを一度以上修正したり、間違ってXMLファイルを消してしまった時は、再度起動する必要があります。)
If you migrate a form containing an MSChart control or another control that may require decoding – for example the DataTimePicker control – VB Migration Partner searches for this XML file and issues a migration note asking to run the add-in if the file can’t be found.
MSChartコントロールやデコードを必要とするその他のコントロール(例えば、DataTimePicker コントロール)を含むFormをマイグレーションする場合、VB Migration PartnerはこのXMLファイルを探して、もしファイルが見つからなければ稼動しているアドインに問い合わせ警告を発します。
You install the VBMP Project Dumper by registering the ProjectDumperAddin.dll using the RegSvr32 utility:
RegSvr32ユーティリティを使ってProjectDumperAddin.dllをレジストリ登録することで、VBMPプロジェクトのダンパーをインストールできます。
RegSvr32 ProjectDumperAddin.dll
4.8 Support for Dynamic Data Exchange (DDE)/動的データ交換(DDE)対応
Starting with release 1.20, VB Migration Partner supports DDE-related properties (LinkItem, LinkTopic, LinkMode, LinkTimeout), methods (LinkExecute, LinkPoke, LinkSend, LinkRequest) and events (LinkOpen, LinkClose, LinkExecute, LinkError, LinkNotify).
バージョン1.20のリリース開始と共に、VB Migration PartnerはDDE関連のプロパティ(LinkItem, LinkTopic, LinkMode, LinkTimeout)、メソッド(LinkExecute, LinkPoke, LinkSend, LinkRequest)、イベント(LinkOpen, LinkClose, LinkExecute, LinkError, LinkNotify)をサポートしてきました。
It’s essential to bear in mind that DDE support is implemented by simulating the VB6 behavior, but without actually using any native DDE feature offered by Windows. This detail has an important consequence: DDE communications only work between VB.NET applications that has been converted by VB Migration Partner and that use VB Migration Partner’s support library. If your original VB6 code uses DDE to communicate with Microsoft Excel or any other compiled DDE server application, it won’t be impossible to establish the communication.
DDEサポートがVB6の動作をシミュレートすることによって実装されますが、実際にどんなネイティブなDDEの特徴も使用せずにWindowsによって提供されることを覚えておくのは重要です。この詳細は重要な結果を持っています。DDEとの通信はVB Migration Partnerによって変換されたVB.NETアプリケーションとだけなされ、VB Migration Partnerのサポートライブラリを使用します。もしオリジナルのVB6コードがMicrosoft Excelやその他のコンパイルされたDDEサーバーアプリケーションとコミュニケートするのにDDEを使う場合は、コミュニケーションを確立するのは不可能ではありません。
Internally, VB Migration Partner implements DDE-related features by means of inter-process Windows messages. In current release all DDE members are supported except the LinkTimeout property and the LinkError event. More precisely, DDE communications in converted VB.NET apps never time out and never raise a LinkError event. These features are likely to be implemented in a future release.
内部で、VB Migration PartnerはインタープロセスWindowsメッセージによってDDE関連の機能を実装します。現在リリースされているものは、LinkTimeoutプロパティとLinkErrorイベントを除いた全てのDDEメンバがサポートされます。より正確に言うと、変換されたVB.NETにおけるDDEコミュニケートは決してタイムアウトしませんし、リンクエラーイベントも起きません。これらの機能は将来リリースされるバージョンでも実装されます。
When you migrate a VB6 form that works as a DDE server, the corresponding VB.NET form will react to all DDE requests in the form
DDEサーバーとして動くVB6のFormをマイグレーションする場合、対応するVB.NETのFormはフォームの中の全てのDDEリクエストに反応することでしょう。
appname|formlinktopic
where appname is the App.Title property of the original VB6 project and formlinktopic is the value of the form’s LinkTopic property. You can change the former value by means of the VB6Config.DDEAppTitle.
appnameは元のVB6プロジェクトのApp.Titleプロパティで、formlinktopicはフォームのLinkTopicプロパティの値です。VB6Config.DDEAppTitleによって、以前の値を変更することができます。