VB6 升级到 VB.NET
本文讨论了将 VB6 应用程序升级到 VB.NET 时需要考虑的各种事项。
引言
我目前在一家公司工作,需要将 50 多个 VB6 程序升级到 VB.NET 2008。到目前为止,我已完成一半,并学到了一些能显著提高 VB.NET 应用程序性能的技巧。
由于有许多程序员将进行此迁移,因此我想分享这些信息。我确信这些信息对面临此任务的人来说非常有价值。
首先要考虑的是,您希望将 VB6 程序升级到 VB.NET 2008 Windows Forms 应用程序还是 VB.NET 2008 Windows Presentation Foundation (WPF) 应用程序。如果您升级到 VB.NET 2005,则没有 WPF 选项,但如果您升级到 VB.NET 2008,则可以选择使用它。
为什么要将 VB6 Windows Forms 应用程序升级到 WPF?因为这是 Windows 编程的未来。Windows Forms 已经使用了 15 年以上相同的技术,现在正处于其生命周期的开始阶段。Windows Forms 应用程序使用 User32 (User before 32-bit) 和 GDI/GDI+ 进行 GUI 渲染,而 WPF 应用程序使用 DirectX 进行 GUI 渲染,这更加强大。此外,WPF 使用可扩展应用程序标记语言 (XAML) 来定义界面的布局,并实例化 .NET 对象。
迄今为止,最简单的选择是将 VB6 Windows Forms 应用程序升级到 VB.NET 2008 Windows Forms 应用程序。由于 Windows Forms 将在相当长一段时间内存在,我们将重点关注这一点。
以下是将 VB6 Windows Forms 应用程序升级到 VB.NET 2008 Windows Forms 应用程序的一些步骤和技巧:
1. 使用 VS 2008 的升级向导
2. 更改目标框架
3. 删除升级报告
4. 修正所有错误
5. 更新代码
6. 添加 API 以提高 DoEvents 性能。
执行升级
- 1 使用 Visual Studio 2008 升级向导
打开 Visual Studio 2008
从“文件”菜单中,选择“打开”|“项目/解决方案”
- 导航到要升级的 VB6 项目,然后选择它。
- 升级向导将自动启动。
- 在向导的每个窗口中单击“下一步”,直到向导开始转换。
** 升级错误
我遇到了一些 VB6 项目未能完成升级向导,并且无法升级。我收到的一些错误是:
“升级失败:访问文件‘C’时发生一般性错误”
“无法读取项目文件……”
如果您在升级 VB6 应用程序到 VB.NET 时遇到问题,则有 3 个选项:
1. 安装 Visual Studio 2008 Service Pack 1 (SP1) 并重试。
2. 使用升级向导的命令行版本。
这是 VS IDE 升级向导使用的相同升级引擎,但不知何故,它每次 VB6 程序在升级过程中崩溃时都有效。方法如下:
- 在 C:\ 创建一个名称较短的文件夹(例如“Upgrade”)
- 将 VB6 项目文件复制并粘贴到此文件夹中。
- 打开 Visual Studio 命令提示符
(Windows XP: 开始按钮 > 所有程序 > Microsoft Visual Studio 2008 >
Visual Studio Tools > Visual Studio 2008 Command Prompt)
- 确保您在 VB 目录中(我的打开到 VC)
- 输入“cd..”,按 Enter 向上移动 1 个目录。
- 输入“cd VB”,按 Enter 更改目录。
- 进入 VBUpgrade 目录
- 输入“cd VBUpgrade”,按 Enter。
- 运行升级向导的命令行版本
- 包括“VBUpgrade.exe”
- 包括输入项目路径 <文件名>
- 包括将创建 VB.NET 项目的新文件夹(输出目录)
结构
VBUpgrade.exe <文件名> /Out <目录>
示例
VBUpgrade.exe "C:\Upgrade\Project1.vbp" /Out "C:\Upgrade\VB Upgrade"
- 输入上述命令后按 Enter 键,升级应开始。
3. 如果升级向导的命令行版本对您不起作用,请尝试
联系 Microsoft 的 John Hart (John.Hart@microsoft.com),他也许能提供帮助。
- 2 更改目标框架
默认情况下,目标框架将设置为“.Net Framework 2.0”。您可以选择使用它。我将其更改为“.Net Framework 3.5”。如果您想这样做,方法如下:
- 单击“项目”菜单 |“属性”
- 单击“编译”选项卡
- 单击选项卡页面底部的“高级编译选项…”按钮
- 将“目标框架”更改为“.Net Framework 3.5”
- 单击“确定”,然后单击“是”
- 3 删除升级报告
使用升级向导执行升级时,会自动生成升级报告。如果您想查看报告,请打开 Visual Studio 中的“解决方案资源管理器”(“视图”菜单 |“解决方案资源管理器”),然后双击“_UpgradeReport.htm”。我个人没有使用过此报告,因此我将其删除(在解决方案资源管理器中右键单击,然后选择“删除”)。
- 如果您决定删除报告,还需要打开 Windows 资源管理器,导航到您的项目文件夹,然后删除“_UpgradeReport_Files”文件夹。
示例:删除“C:\Upgrade\VB Upgrade\_UpgradeReport_Files”
- 4 错误修正
一旦您将 VB6 Windows Forms 应用程序升级到 .NET,就会出现大量错误!要查看错误列表,请打开“错误列表”(“视图”菜单 |“错误列表”)。
要转到某个错误,请从错误列表中双击一个错误。Visual Studio 将自动将您带到发生错误的行代码。
在发生错误的行代码上方,您会注意到一个“升级警告”。此警告描述了错误,并提供了一个非常有用的链接,可以帮助您获取有关错误的更多信息,以及可以采取的修复错误步骤。要使用此链接,请按住 Control 键,然后用鼠标左键单击它。
例如,如果您在 VB6 窗体上有一个 CommonDialog 控件,那么您将收到一个错误,告知 CommonDialog 未升级。该有用链接将提供指向替换 CommonDialog 的新控件的链接,例如“OpenFileDialog”、“SaveFileDialog”等。
在继续之前,请修正项目中的所有错误。
- 5 更新代码
VB.Net 2008 继续支持许多 VB6 方法。然而,它们的性能实际上比其 VB.NET 对应项慢,因此,逐行检查项目中的代码,并将每个 VB6 方法替换为其 .NET 对应项非常重要。
VB6 代码在 VB6 中运行良好,但 VB6 代码在 VB.NET 中运行糟糕(非常糟糕)。VB.NET 代码在 VB.NET 中运行良好(非常好),比 VB6 代码在 VB6 中运行的速度快得多(如果您能理解的话)。
以下是一些用 VB.NET 对应项替换 VB6 方法的示例:
'提示:VB.Net 字符串是零基索引的,换句话说,字符串的第一个位置是 0。在 VB6 中,第一个位置是 1。这极大地影响了字符串的解析方式。Dim myString As String = "Go ahead and search for this string"
- **Instr** - 不要使用 Instr() 方法来搜索字符串,而应使用 IndexOf() 方法。
-
Instr(myString, "search for this string") 'Old way myString.IndexOf("search for this string") 'New way
- **Mid** - 不要使用 Mid() 方法来获取字符串的一部分,而应使用 SubString() 方法。
Mid(myString, 14) 'Old way myString.SubString(13) 'New way
- **Trim** - 不要使用 Trim()、LTrim() 和 RTrim(),而应使用 .Trim()、.TrimStart()、.TrimEnd()
Trim(myString), LTrim(myString), RTrim(myString) 'Old way myString.Trim(), myString.TrimStart(), mystring.TrimEnd() 'New way
- **Len** - 不要使用 Len() 方法,而应使用 .Length() 来获取字符串的长度。
Len(myString) 'Old way myString.Length() 'New way
- 将“**And**”运算符替换为“AndAlso”。 (在任何非位运算比较中执行此操作)。
If 1 = 1 And 2 = 2 And 3 = 3 Then 'And Old way If 1 = 1 AndAlso 2 = 2 AndAlso 3 = 3 Then 'And New way
- 将“**Or**”运算符替换为“OrElse”。 (在任何非位运算比较中执行此操作)。
If 1 = 1 Or 2 = 2 Or 3 = 3 Then 'Or old way If 1 = 1 OrElse 2 = 2 OrElse 3 = 3 Then 'Or new way
- 将所有 VB6 **文件 I/O 类**替换为新的 .NET 文件 I/O 类。它们比 VB6 的快,所以一定要使用它们!
Dim myFile As String = "C:\Temp\myfile.txt" Dim instring As String = String.Empty '** VB6 File I/O: FileOpen(1, myFile, OpenMode.Input) Do Until EOF(1) instring = LineInput(1) 'Read 1 line from a file Loop FileClose(1) '** VB.Net File I/O: Dim reader As New System.IO.StreamReader(myF
ile) Do Until reader.EndOfStream = True instring = reader.ReadLine() 'Read 1 line from a file Loop reader.Close() reader.Dispose()
- 6 DoEvents
在我将处理器密集型的 VB6 应用程序升级到 VB.NET 后,我注意到性能非常糟糕!虽然代码升级是促成因素,但 DoEvents 是最大的罪魁祸首之一!VB6 应用程序升级到 VB.NET 后,(在某些情况下)速度会慢大约 10 倍。通过一些调整,VB.NET 应用程序的性能可以大大提高,使其运行速度比 VB6 快 40%-50%……
1. 向您的项目添加一个模块,并将其命名为“Do_Events”之类的名称。
2. 将以下代码插入您添加的模块中。Module Do_Events Friend Declare Function SetThreadPriority Lib "kernel32" (ByVal hThread As Integer, _ ByVal nPriority As Integer) As Integer Friend Declare Function SetPriorityClass Lib "kernel32" (ByVal hProcess As Integer, _ ByVal dwPriorityClass As Integer) As Integer Friend Declare Function GetCurrentThread Lib "kernel32" () As Integer Friend Declare Function GetCurrentProcess Lib "kernel32" () As Integer Friend Const THREAD_PRIORITY_HIGHEST As Short = 2 Friend Const HIGH_PRIORITY_CLASS As Integer = &H80 End Module
3. 在开始密集处理之前添加两行代码来设置线程优先级。
SetThreadPriority(GetCurre
4. 谨慎使用 DoEvents()!调用 DoEvents() 会对性能产生很大的影响,因此请谨慎使用。ntThread, THREAD_PRIORITY_HIGHEST) SetPriorityClass(GetCurren tProcess, HIGH_PRIORITY_CLASS)
Dim iLoops As Integer = 0 Do Until iLoops = 10000 'Calling DoEvents() every 500 loops will greatly increase application performance If iLoops Mod 500 = 0 Then DoEvents() iLoops += 1 'Add 1 to iLoops Loop
5. 创建一个特定的子例程来更新窗体上的控件,并在您想要更新窗体时调用该子例程。
在上例中,您可以将 DoEvents() 替换为您更新方法的名称。
示例
Private Sub UpdateForm() 'Update all controls here: progressBar1.Value += 1 'Update ProgressBar label1.Text = "Processing..." 'Update Labels, TextBoxes, etc... Application.DoEvents() 'Call DoEvents() so the form can refresh the changes to the controls End Sub
如果您遵循本文中的步骤和技巧,那么您的升级应该会相当顺利,并且您的应用程序在 VB.NET 中的性能应该会比在 VB6 中快很多。
祝您好运!
VBRocks