【问题标题】:reading local acount ini file读取本地帐户ini文件
【发布时间】:2014-02-17 05:48:41
【问题描述】:

我有一个旧的 VB6 应用程序,它将其数据保存到一个 ini 文件中,它希望该文件位于 windows 文件夹中。在 VB6 代码中,我只引用文件名(不带路径),它由 Windows 自动定位在 Windows 文件夹中。然而,在 Windows 8 和企业网络上,Windows 将文件移动到用户帐户,因此它出现在 \Users\username\AppData 文件夹结构下。

VB6 不在乎,它总是读取“ipmdata.ini”并从 AppData 文件夹中获取由 Windows 交给它的用户特定的一个。

但是,我现在需要从 C# 应用程序中读取相同的 ini 文件。所以我添加了 GetPrivateProfileString 的定义,并用我给 VB6 的相同参数提供给它。 C#代码总是从windows文件夹中的文件读取,与VB6正在读写的不是同一个文件。

有什么想法可以让 C# 调用与 VB6 调用相同的 API 一样吗?

我尝试将 .Net 应用程序针对 Framework 2.0,编译为 x86 并运行 editbin 以在最终可执行文件上设置 /TSAWARE:NO(虽然我不知道如何检查它是否有效 - 它只是没有“失败” ')。

VB6 代码由声明和读取组成:

Public Declare Function GetPrivateProfileString Lib "kernel32" _
     Alias "GetPrivateProfileStringA" ( _
     ByVal lpApplicationName As String, _
     ByVal lpKeyName As Any, _
     ByVal lpDefault As String, _
     ByVal lpReturnedString As String, _
     ByVal nSize As Long, _
     ByVal lpFileName As String) As Long

   nRetcode = GetPrivateProfileString("PCD", "TemplateFolder", "", sTemp, 512, "mystuff.ini")

c#应用程序中的等效代码包括:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    static extern uint GetPrivateProfileString(
       string lpAppName,
       string lpKeyName,
       string lpDefault,
       StringBuilder lpReturnedString,
       uint nSize,
       string lpFileName);

        StringBuilder sb = new StringBuilder(2048);
        GetPrivateProfileString("PCD", "TemplateFolder", "", sb, 2048, "mystuff.ini");

测试程序中没有其他内容,只有这段代码用于读取 ini 文件。 C# 代码读取当前在我的 \Windows 文件夹中的 ini,VB6 代码从 \users\user\appdata\virtualstore\windows 文件夹中读取。

【问题讨论】:

  • 如果您在当前使用的 VB 和 C# 中显示用于读取 ini 文件的相关代码,将会有所帮助。如果您只使用 VB 中的 Private Declare Function GetPrivateProfileString Lib "kernel32" 和 C# 中的 [DllImport("kernel32.dll"] static extern uint GetPrivateProfileString(),我怀疑 API 调用会导致这种行为,因为它们是相同的。可能有其他代码干扰了路径,或者 API 调用在当前目录中查找,对于不同的应用程序可能会有所不同。
  • 另外,当移植依赖于此类ancient WinAPI calls 的应用程序时,您可能需要考虑用using a library 替换它们。
  • 既然要将应用程序移植到 .NET,为什么不也移植 .ini 呢?您可以将设置添加到 app.config 文件。配置文件与应用程序存储在同一文件夹中。这是一篇 MSDN 文章,其中有更详细的解释。 msdn.microsoft.com/en-us/library/a65txexh.aspx
  • 对不起,我没有收到任何关于 cmets 的通知。我将使用代码更新帖子。但是,作为测试,我将其剥离到绝对最低限度。所以有一个测试 VB6 程序,它由一个声明和一个具有相同有限代码的 C# 程序组成。我没有移植应用程序。我有一个需要在 .Net 中完成的新要求。旧的 vB6 应用程序将保持原样。
  • 仅供参考,我现在已将清单嵌入到应用程序中,并明确更改了安全选项以启用虚拟化。在尝试读取它之前,我还更改了程序以写入 ini 文件。可悲的是,没有区别; VB6 读取虚拟的,.Net 读取真实的。我想我会写代码先去寻找虚拟化的ini文件,如果我找不到虚拟化的文件,就只读取windows一个。这是一个垃圾解决方案,但可能是我拥有的最好的解决方案。

标签: c# .net vb6 ini


【解决方案1】:

这里有很多误解。

UAC 早在 2006 年就开始使用 Windows Vista,而不是 Windows 8。

文件系统虚拟化不是应用程序功能,而是一个错误。微软已明确警告程序员不要依赖它。

您的 .Net 程序可能有一个将其标记为 Vista Aware 的清单,在这种情况下,虚拟化永远不会适用。

这似乎也是Force an existing application to always run with UAC virtualization on的副本

基本上,真正的答案是修复您的程序,使其不需要虚拟化。

【讨论】:

  • 我同意,这对我来说就像一个错误。可悲的是,这是我需要忍受的错误。我将我的 .net 应用程序修改为 32 位,并添加了一个应该启用虚拟化的清单。没用。我的感觉是,当编译启用虚拟化的程序时,后台正在发生其他事情。我在虚拟机上有一个旧的 VS2008 副本,我会尝试在那里构建应用程序,看看它是否有什么不同。虚拟化不是我想要使用的东西,也不是我要求的东西。这是强加给我的。
  • 那么只需复制文件虚拟化进程的行为,而不是尝试使用虚拟化。查找虚拟化 INI,如果不存在,则通过从 Windows 文件夹中复制一个来创建它。
  • 这有它自己的问题,因为 api 无法找出虚拟化文件夹的名称,而且我无法硬编码名称,因为它可以本地化。出于此应用程序的目的,我想我从包含 AppData 的任何文件夹开始并执行递归搜索,直到找到 ini 文件或用完可以查看的地方。对于这个特定的应用程序,我可以摆脱它。使用已发布的界面会很好。
【解决方案2】:

您是否尝试过指定完整路径?

GetPrivateProfileString("PCD", "TemplateFolder", "", sb, 2048, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\mystuff.ini");

【讨论】:

  • 是的,我指定完整路径还是不指定路径都没有关系。
  • @sab 我不明白,因为我在发布之前对其进行了测试,它是从预期的文件夹中抓取的。
  • 你所做的不一样。您专门去了 AppData 文件夹。 VB6 代码写入它认为是 Windows 文件夹,Windows 重定向到虚拟化文件夹。 C# 中的相同代码不会被重定向。我需要实现的是让 Windows 以与 VB6 相同的方式处理我的 .net 代码并将其重定向到虚拟化的 windows 文件夹。
猜你喜欢
  • 2013-04-18
  • 2015-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
  • 2012-06-29
  • 2016-02-23
相关资源
最近更新 更多