为什么我无法通过 pinvoke 让 GetPrivateProfileString 工作?
运行我在 64 位 Vista 上编写的 ac# 控制台应用程序。代码如下:
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);
}
我确信我会得到一个大大的“DUH!”寻求答案,但我不明白为什么这不起作用。除了 Debug.Assert 之外,此代码是从 此页面
Running a c# console app I wrote on 64 bit Vista. Here's the code:
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);
}
I'm sure I'll get a big "DUH!" for an answer, but I'm not seeing why this fails to work. Other than the Debug.Assert, this code was cut from the c# sample at this page
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这个也让我一整天都筋疲力尽。我想我找到了一个解决方法,我真的不想处理它:在 .ini 文件中的第一个节标题之前插入一个空行。现在运行您的应用程序,看看您是否没有开始看到您期望的值。
考虑到这个错误显然已经存在多年,我很惊讶微软到现在还没有修复它。但是,.ini 文件应该在几年前就消失了。这当然很有趣,因为 MS 有很多地方使用 .ini 文件(例如,desktop.ini)。但我认为微软已经意识到了这个错误,因为我注意到我的desktop.ini 文件包含一个前导空行。嗯...
This one has been busting my chops all day, too. I think I found a work-around, which I really don't want to have to deal with: insert a blank line before the first section header in your .ini file. Now run your app and see if you don't start seeing the values you were expecting.
Considering this bug has apparently been around for years, I'm surprised MS hasn't fixed it by now. But then, .ini files were supposed to have gone away years ago. Which of course is funny, because there are a lot of places MS uses .ini file (e.g, desktop.ini). But I think MS is aware of the bug, because I notice my desktop.ini files include a leading blank line. Hmmm...
我看到的主要内容是,您应该为 nSize 传递一个 uint 以及返回值。这是因为 GetPrivateProfileString 是
DWORD
值,它们是无符号 32 位整数。我个人在 PInvoke.net 上使用过语法:
此外,您需要放置该文件的完整路径,除非该文件位于 Windows 目录中。来自文档:
The main thing I see is that you should be passing in an uint for nSize, as well as the return value. This is because the return and nSize parameters of GetPrivateProfileString are
DWORD
values, which are unsigned 32bit integers.I personally have used the syntax on PInvoke.net:
In addition, you'll need to put the full path to the file in place, unless the file is located in the Windows directory. From the docs:
根据 pinvoke.net,nSize 应该是 UINT。他们还在示例中使用绝对路径。
除了这些差异之外,我看不到其他任何东西。
如果抛出无效格式异常,请尝试将目标平台设置为 x86 来解决问题。
pinvoke.net 的用法示例是
According to pinvoke.net, nSize should be a UINT. Also they are using an absolute path in their example.
Other than those differences, I can't see anything else.
Providing it's throwing a invalid format exception, try setting target platform to x86 to solve the problem.
Usage example from pinvoke.net is
如果未指定路径,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。 CodeProject 上有一个 线程讨论了尝试从 UAC 控制的文件夹中读取 .ini 时 GetPrivateProfileString 默默失败。
If no path is specified, GetPrivateProfileString will look for Test.ini in the Windows directory.
Old APIs like GetPrivateProfileString don't handle Unicode well (even though there's a GetPrivateProfileStringW function). If Test.ini contains a UTF header or Unicode characters, that might be enough to prevent GetPrivateProfileString from working correctly.
Also, Vista's UAC can make handling files that are in "special" places tricky (C:\, C:\Windows, C:\Program Files, etc.). Try putting Test.ini in a folder rather than in the root of the C: drive, or turn off UAC. There's a thread on CodeProject that discusses GetPrivateProfileString failing silently when trying to read an .ini from a folder controlled by UAC.
也许您应该考虑寻找一个开源解决方案,它可以完全做到这一点,而无需担心 p/Invoke。针对 .NET 的项目称为 nini 我正在我正在开发的项目中使用它,我推荐它。
希望这有帮助,
此致,
汤姆.
Maybe you should look into looking at an open source solution that will do exactly that without you worrying about p/Invoke's. The project targetted for .NET is called nini I am using this in a project I am working on and I recommend it.
Hope this helps,
Best regards,
Tom.
您可以验证
test.ini
文件的内容吗?鉴于您尝试过的所有步骤,我开始怀疑您的数据文件格式不正确(拼写错误等)。换句话说,GetPrivateProfileString
可能正在“工作”,但是只是找不到你的字符串。根据您发布的代码,您的test.ini
文件应如下所示:Can you verify the contents of your
test.ini
file? Given all of the steps that you've tried, I'm beginning to suspect that your data file is not formatted correctly (misspelling, etc.) In other words,GetPrivateProfileString
may be "working", but just not finding your string. Based on the code that you posted, yourtest.ini
file should look something like this: