避免使用 Win API
如果您是一位 Microsoft Visual Basic® 开发人员您就无法避免调用 Win API开发人员有太多的任务需要完成而 Visual Basic 却不能提供任何实现方法例如在 Visual Basic 中您很难完成以下任务
确定文件版本信息
在注册表的任何位置进行读取和写入操作
确定用户的特定文件夹例如 Microsoft Windows® 收藏夹或个人文件夹
检索所有可用驱动器的列表
查找用户的登录名或计算机名
检索所有打开窗口的列表
如果仅使用 Visual Basic 中提供的工具您不可能解决上述任何问题对于每个问题开发人员都需要使用 Windows API许多开发人员使用 Windows API 已经找到了完成这些(以及许多其他)任务的方法
Windows API 存在什么问题?
为什么不继续在 NET 环境中使用 Windows API 呢?如果使用 NET 平台调用服务(称为P/Invoke)您当然可以这样做从 Visual Basic 开发人员的角度来说调用 Windows API 并不比使用他们所熟悉的 Declare 语句困难不过在 NET 环境中使用 Windows API 存在一些比较严重的缺陷您可能需要考虑采取任何可行的措施来避免这些问题例如
NET 公共语言运行时不会受平台影响当您使用 Windows API 调用时您将代码绑定到编写代码的特定平台上(即相对于其他操作系统的某个特定 Windows 版本或 Windows 本身)必要时您需要将代码转换到另一个平台上而这样做就需要修改使用 API 调用的每行代码
从 NET 中调用 Windows API(或 DLL 中的任何非托管代码)不像在 Visual Basic 中那样简单例如对结构的工作方式的限制使得很难将结构传递给 API 调用此外由于数据类型的更改以及更严格的类型转换Visual Basic 的 API 声明也需要进行更改
根据语言的不同使用 Windows API(以及通常情况下使用的外部代码)的技巧也不尽相同如果您打算在多 NET 语言环境中工作则需要掌握各种语言的不同技巧
调用 Windows API 的代码要求调用这些代码的用户具有执行此操作的权限这将影响应用程序的安全保护方案您需要对此要求提前做出安排
这个问题很简单尽管您可以在 Visual Basic NET 应用程序中继续使用 Windows API但通常情况下您应当尽可能寻找由 NET 框架提供的替代品虽然 NET 框架的目的并不是要阻止您直接使用 Windows 的功能但框架的确提供了大量的类可以帮助您放弃对 Windows API 调用的依赖
如果能够给出一个完整列表列出 Win API 调用以及在 NET 框架中完成相同任务的相应方法(如果有)可能会很方便不过本文不涉及此任务在本文中您将了解到一些由 NET 框架提供的特定且非常有用的类它们可以解决您的问题在每个示例中本文所讨论的类都可以用来替代一个或多个 Win API 调用而在 Microsoft Visual Basic 中您必须调用一个或多个 Win API 才能完成相同的任务
使用注册表
如果您与大多数 Visual Basic 开发人员一样您会发现 Microsoft Visual Basic for Applications (VBA) 中内置的 SaveSettingGetSettingGetAllSettings 和 DeleteSetting 方法有点儿用处但却很可能被它们的局限性弄得精疲力尽所有这些方法都只能在注册表的 HKEY_CURRENT_USER\Software\VB 和 VBA Program Settings 下的项中使用如果您要在注册表的其他地方读取或写入注册表项或注册表值则必须使用复杂的 API 调用或依靠别人的代码来处理此问题
NET 框架在 MicrosoftWin 名称空间中提供了一对功能强大的类(Registry 和 RegistryKey)从而简化了注册表的使用即不再需要 API 调用!
作为演示请在示例项目的主窗体上单击 Work with the Registry(使用注册表)按钮此窗体提供了 SOFTWARE\Microsoft\Windows\CurrentVersion\Run 项的 HKEY_LOCAL_MACHINE 配置单元中所有注册表值的列表您可以右键单击列表中的任何项然后选择插入新项或者编辑或删除选定项如图 所示
提示示例窗体也已经过设计在列表框中按下 Enter 键时可以编辑当前选定的项按下 Delete 键可以删除选定项按下 Insert 键可以添加一个新值这些项对应于列表框的上下文菜单中的项
图 使用 Registry 和 RegistryKey 类轻松检索和修改 Windows 注册表中的信息NET 框架提供了两个非常有用的类使您可以轻松使用 Windows 注册表第一个类是 Registry它提供的字段与标准 Registry 配置单元的各字段相对应
ClassesRoot (HKEY_CLASSES_ROOT)
CurrentConfig (HKEY_CURRENT_CONFIG)
CurrentUser (HKEY_CURRENT_USER)
DynData (HKEY_DYN_DATA)
LocalMachine (HKEY_LOCAL_MACHINE)
PerformanceData (HKEY_PERFORMANCE_DATA)
Users (HKEY_USERS)
要使用 Registry 类只需检索所需配置单元的引用示例窗体的 LoadList 过程中包含如下代码以便使用注册表中的 HKEY_LOCAL_MACHINE 配置单元
Imports MicrosoftWin
Dim reg As RegistryKey = RegistryLocalMachine
另一个类是 RegistryKey它可以完成所有工作它提供了一组使用 Registry 的方法表 列出了 RegistryKey 类的所有有用方法
RegistryKey 类还提供以下三个属性
Name检索项的名称
SubkeyCount检索与该项相关联的子项的数量
ValueCount检索与该项相关联的项值的数量
示例窗体的 ListLoad 过程将检索所请求项中的所有值并将检索到的值添加到窗体的列表框中
Private Const conRegKey As String = _
SOFTWARE\Microsoft\Windows\CurrentVersion\Run
Private Structure RegData
Public Value As String
Public Data As String
Public Overrides _
Function ToString() As String
Return MeValue
End Function
End Structure
Private Sub ListLoad()
Dim reg As RegistryKey = RegistryLocalMachine
Dim astrValues() As String
Dim strValue As String
Dim rd As RegData
清除列表框中的现有项
lstItemsBeginUpdate()
lstItemsItemsClear()
打开注册表项然后使用
该项的值加载列表框
reg = regOpenSubKey(conRegKey)
astrValues = regGetValueNames()
For Each strValue In astrValues
rdValue = strValueToString
rdData = regGetValue(strValue)
lstItemsItemsAdd(rd)
Next
lstItemsEndUpdate()
End Sub
要编辑示例窗体中的值或添加新值需要运行以下代码
Private Sub AddOrEdit( _
ByVal rd As RegData _
ByVal Mode As frmAddValueAccessMode)
Dim reg As RegistryKey = RegistryLocalMachine
Dim frm As New frmAddValue(Mode)
frmKeyName = rdValue
frmKeyData = rdData
If frmShowDialog() = DialogResultOK Then
If frmKeyName <> StringEmpty Then
reg = regOpenSubKey(conRegKey True)
regSetValue(frmKeyName frmKeyData)
ListLoad()
End If
End If
End Sub
此代码将再次打开注册表项这次将请求写入项值的权限(此请求由 OpenSubKey 的第二个参数发出)然后代码将调用 SetValue 方法传递图 所示的对话框窗体中的项名和项值为简化工作可以使用 SetValue 方法添加新值或修改现有值如果项值不存在SetValue 方法将添加一个项值
要删除项值示例窗体将调用以下代码
Private Sub DeleteKey(ByVal rd As RegData)
Dim strText As String
Dim reg As RegistryKey = RegistryLocalMachine
If lstItemsSelectedIndex = Then
Exit Sub
End If
删除选定的项
strText = StringFormat( _
Are you sure you want to delete {}? _
rdValue)
If MessageBoxShow(strText _
Delete Registry Value _
MessageBoxButtonsYesNo _
MessageBoxIconQuestion) = DialogResultYes Then
打开项允许写入
reg = regOpenSubKey(conRegKey True)
regDeleteValue(rdValue)
重新加载列表框
ListLoad()
End If
End Sub
此代码将打开项并请求对其执行写入操作然后将调用 DeleteValue 方法删除选定的值
有了示例窗体提供的信息和 NET 框架附带的文档便可以轻松地完成与注册表相关的任何任务而不必使用 Windows API这是一个简单的对象模型但它提供的功能比 Visual Basic 开发人员先前所拥有的功能更强大
提示如果具有必要的权限您还可以使用远程计算机上的注册表您可以调用