服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

使用.net框架类替代api调用的问题


  避免使用 win32 api
  如果您是一位 microsoft visual basic® 6.0 开发人员,您就无法避免调用 win32 api。开发人员有太多的任务需要完成,而 visual basic 却不能提供任何实现方法。例如,在 visual basic 6.0 中,您很难完成以下任务:
  
  确定文件版本信息
  在注册表的任何位置进行读取和写入操作。
  确定用户的特定文件夹,例如 microsoft windows® 收藏夹或个人文件夹。
  检索所有可用驱动器的列表。
  查找用户的登录名或计算机名。
  检索所有打开窗口的列表。
  如果仅使用 visual basic 6.0 中提供的工具,您不可能解决上述任何问题。对于每个问题,开发人员都需要使用 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 6.0 中那样简单。例如,对结构的工作方式的限制使得很难将结构传递给 api 调用。此外,由于数据类型的更改以及更严格的类型转换,visual basic 6.0 的 api 声明也需要进行更改。
  根据语言的不同,使用 windows api(以及通常情况下使用的外部代码)的技巧也不尽相同。如果您打算在多 .net 语言环境中工作,则需要掌握各种语言的不同技巧。
  调用 windows api 的代码要求调用这些代码的用户具有执行此操作的权限。这将影响应用程序的安全保护方案,您需要对此要求提前做出安排。
  这个问题很简单:尽管您可以在 visual basic .net 应用程序中继续使用 windows api,但通常情况下,您应当尽可能寻找由 .net 框架提供的替代品。虽然 .net 框架的目的并不是要阻止您直接使用 windows 的功能,但框架的确提供了大量的类,可以帮助您放弃对 windows api 调用的依赖。
  
  如果能够给出一个完整列表,列出 win32 api 调用以及在 .net 框架中完成相同任务的相应方法(如果有),可能会很方便,不过本文不涉及此任务。在本文中,您将了解到一些由 .net 框架提供的特定且非常有用的类,它们可以解决您的问题。在每个示例中,本文所讨论的类都可以用来替代一个或多个 win32 api 调用,而在 microsoft visual basic 6.0 中,您必须调用一个或多个 win32 api 才能完成相同的任务。
  
  使用注册表
  如果您与大多数 visual basic 6.0 开发人员一样,您会发现 microsoft visual basic for applications (vba) 中内置的 savesetting、getsetting、getallsettings 和 deletesetting 方法有点儿用处,但却很可能被它们的局限性弄得精疲力尽。所有这些方法都只能在注册表的 hkey_current_user/software/vb 和 vba program settings 下的项中使用。如果您要在注册表的其他地方读取或写入注册表项或注册表值,则必须使用复杂的 api 调用,或依靠别人的代码来处理此问题。
  
  .net 框架在 microsoft.win32 名称空间中提供了一对功能强大的类(registry 和 registrykey),从而简化了注册表的使用,即不再需要 api 调用!
  
  作为演示,请在示例项目的主窗体上单击 work with the registry(使用注册表)按钮。此窗体提供了 software/microsoft/windows/currentversion/run 项的 hkey_local_machine 配置单元中所有注册表值的列表。您可以右键单击列表中的任何项,然后选择插入新项,或者编辑或删除选定项,如图 1 所示。
  
  提示:示例窗体也已经过设计,在列表框中按下 enter 键时,可以编辑当前选定的项。按下 delete 键可以删除选定项,按下 insert 键可以添加一个新值。这些项对应于列表框的上下文菜单中的项。
  
 使用.net框架类替代api调用的问题(图一)

  
图 1:使用 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 microsoft.win32
  
  dim reg as registrykey = registry.localmachine
  
  另一个类是 registrykey,它可以完成所有工作。它提供了一组使用 registry 的方法。表 1 列出了 registrykey 类的所有有用方法。
  
  
 使用.net框架类替代api调用的问题(图二)

  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 me.value
  end function
  end structure
  
  private sub listload()
  dim reg as registrykey = registry.localmachine
  dim astrvalues() as string
  dim strvalue as string
  dim rd as regdata
  
  ' 清除列表框中的现有项。
  lstitems.beginupdate()
  lstitems.items.clear()
  
  ' 打开注册表项,然后使用
  ' 该项的值加载列表框。
  reg = reg.opensubkey(conregkey)
  astrvalues = reg.getvaluenames()
  for each strvalue in astrvalues
  rd.value = strvalue.tostring
  rd.data = reg.getvalue(strvalue)
  lstitems.items.add(rd)
  next
  lstitems.endupdate()
  end sub
  
  要编辑示例窗体中的值或添加新值,需要运行以下代码:
  
  private sub addoredit( _
  byval rd as regdata, _
  byval mode as frmaddvalue.accessmode)
  dim reg as registrykey = registry.localmachine
  dim frm as new frmaddvalue(mode)
  
  frm.keyname = rd.value
  frm.keydata = rd.data
  
  if frm.showdialog() = dialogresult.ok then
  if frm.keyname <> string.empty then
  reg = reg.opensubkey(conregkey, true)
  reg.setvalue(frm.keyname, frm.keydata)
  listload()
  end if
  end if
  end sub
  
  此代码将再次打开注册表项,这次将请求写入项值的权限(此请求由 opensubkey 的第二个参数发出)。然后,代码将调用 setvalue 方法,传递图 1 所示的对话框窗体中的项名和项值。为简化工作,可以使用 setvalue 方法添加新值或修改现有值。如果项值不存在,setvalue 方法将添加一个项值。
  
  要删除项值,示例窗体将调用以下代码:
  private sub deletekey(byval rd as regdata)
  dim strtext as string
  dim reg as registrykey = registry.localmachine
  
  if lstitems.selectedindex = -1 then
  exit sub
  end if
  
  ' 删除选定的项。
  strtext = string.format( _
  "are you sure you want to delete ""{0}""?", _
  rd.value)
  
  if messagebox.show(strtext, _
  "delete registry value", _
  messageboxbuttons.yesno, _
  messageboxicon.question) = dialogresult.yes then
  ' 打开项,允许写入。
  reg = reg.opensubkey(conregkey, true)
  reg.deletevalue(rd.value)
  ' 重新加载列表框。
  listload()
  end if
  end sub
  
  此代码将打开项并请求对其执行写入操作,然后将调用 deletevalue 方法删除选定的值。
  
  有了示例窗体提供的信息和 .net 框架附带的文档,便可以轻松地完成与注册表相关的任何任务,而不必使用 windows api。这是一个简单的对象模型,但它提供的功能比 visual basic 6.0 开发人员先前所拥有的功能更强大。
  
  提示:如果具有必要的权限,您还可以使用远程计算机上的注册表。您可以调用

扫描关注微信公众号