代码之家  ›  专栏  ›  技术社区  ›  Charles

为什么我不能让getprivateprofilestring通过pinvoke工作?

  •  4
  • Charles  · 技术社区  · 16 年前

    运行我在64位Vista上写的C控制台应用程序。代码如下:

    class Class1
    {
        static void Main(string[] args)
        {
            Debug.Assert(File.Exists(@"c:\test.ini"));
            StringBuilder sb = new StringBuilder(500);
            uint res = GetPrivateProfileString("AppName", "KeyName", "", sb, sb.Capacity, @"c:\test.ini");
            Console.WriteLine(sb.ToString());
        }
        [DllImport("kernel32.dll")]
        static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName);
    }
    

    我肯定我会得到一个大“该死!”但我不明白为什么这行不通。除了debug.assert,此代码是从位于 this page

    6 回复  |  直到 16 年前
        1
  •  5
  •   Lee    16 年前

    这一天我的排骨也坏了一整天。我想我找到了一个解决办法,我真的不想处理这个问题:在.in i文件的第一个节头前面插入一个空行。现在运行你的应用程序,看看你是否没有开始看到你期望的值。

    考虑到这个bug已经存在多年了,我很惊讶微软现在还没有修复它。但当时,.ini文件本应在几年前就已经消失了。这当然很有趣,因为微软有很多地方使用.ini文件(例如desktop.ini)。但我认为微软知道这个bug,因为我注意到我的desktop.ini文件中有一个前导空白行。六羟甲基三聚氰胺六甲醚。。。

        2
  •  1
  •   Reed Copsey    16 年前

    我看到的主要事情是你应该通过 无符号整型 对于nsize,以及返回值。这是因为返回和nsize参数 GetPrivateProfileString 是 DWORD 值,这些值是无符号32位整数。

    我个人在 PInvoke.net :

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

    此外,除非文件位于Windows目录中,否则需要将文件的完整路径放置到位。来自文档:

    如果此参数不包含文件的完整路径,系统将在Windows目录中搜索该文件。

        3
  •  1
  •   Chris R. Timmons    16 年前

    如果没有指定路径, GetPrivateProfileString 将在Windows目录中查找test.ini。

    像getprivateprofilestring这样的旧API不能很好地处理Unicode(即使有getprivateprofilestringw函数)。如果test.ini包含utf头或unicode字符,这可能足以阻止getprivateprofilestring正常工作。

    此外,Vista的UAC还可以使处理“特殊”位置的文件变得困难(C:\、C:\Windows、C:\Program Files等)。尝试将test.ini放在文件夹中而不是C:驱动器的根目录中,或者关闭UAC。有一个 thread on CodeProject 这将讨论在尝试从由UAC控制的文件夹中读取.ini时GetPrivateProfileString会自动失败。

        4
  •  0
  •   Brett Allen    16 年前

    根据pinvoke.net,nsize应该是一个uint。而且他们在示例中使用了绝对路径。

    除了这些差异,我什么都看不见。

    如果它引发了一个无效的格式异常,请尝试将目标平台设置为x86以解决此问题。

    pinvoke.net的用法示例是

    [DllImport("kernel32.dll", CharSet=CharSet.Unicode)]
        static extern uint GetPrivateProfileString(
        string lpAppName, 
        string lpKeyName,
        string lpDefault, 
        StringBuilder lpReturnedString, 
        uint nSize,
        string lpFileName);
    
    
     static void Main(string[] args)
     {
       StringBuilder sb = new StringBuilder(500);
       uint res = GetPrivateProfileString("AppName", "KeyName", "", sb, (uint)sb.Capacity, @"c:\test.ini");
       Console.WriteLine(sb.ToString());
     }
    
        5
  •  0
  •   t0mm13b    16 年前

    也许您应该研究一个开源解决方案,它可以在不担心P/Invoke的情况下做到这一点。 nini 我在一个我正在做的项目中使用它,并且我推荐它。

    希望这有帮助, 最好的问候, 汤姆。

        6
  •  0
  •   Emerick Rogul    16 年前

    你能核实一下 test.ini 文件?考虑到您尝试过的所有步骤,我开始怀疑您的数据文件格式不正确(拼写错误等),换句话说, GetPrivateProfileString 可能在“工作”,但找不到你的线。根据您发布的代码, 蒂尼 文件应如下所示:

    [名称]
    KeYNAME= FOO

    推荐文章