Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Winapi 使用不同的Visual Studio版本编译时GetPrivateProfileString行为不一致 我们有一个C++程序,编译很久以前使用的。lpFileNamearg只是ini文件的名称,因此根据文档,预期的行为是它应该在Windows目录中查找该文件:_Winapi - Fatal编程技术网

Winapi 使用不同的Visual Studio版本编译时GetPrivateProfileString行为不一致 我们有一个C++程序,编译很久以前使用的。lpFileNamearg只是ini文件的名称,因此根据文档,预期的行为是它应该在Windows目录中查找该文件:

Winapi 使用不同的Visual Studio版本编译时GetPrivateProfileString行为不一致 我们有一个C++程序,编译很久以前使用的。lpFileNamearg只是ini文件的名称,因此根据文档,预期的行为是它应该在Windows目录中查找该文件:,winapi,Winapi,lpFileName[in] 初始化文件的名称。如果此参数 不包含文件的完整路径,系统将搜索 Windows目录中的文件 最近,程序被重新编译(没有代码更改)并重新部署,这导致程序无法再读取ini文件 两个程序与Process Monitor的比较表明,旧程序试图在%HOMEPATH%\Windows而不是C:\Windows中查找文件 作为测试,我使用Visual Studio 2012编译了以下代码,并在2003服务器上运行,在命令行上传入一些随机文件名: void wmain(int ar

lpFileName[in] 初始化文件的名称。如果此参数 不包含文件的完整路径,系统将搜索 Windows目录中的文件

最近,程序被重新编译(没有代码更改)并重新部署,这导致程序无法再读取ini文件

两个程序与Process Monitor的比较表明,旧程序试图在%HOMEPATH%\Windows而不是C:\Windows中查找文件

作为测试,我使用Visual Studio 2012编译了以下代码,并在2003服务器上运行,在命令行上传入一些随机文件名:

void wmain(int argc, wchar_t* argv[])
{
    wchar_t *appName = L"xxx";
    wchar_t *keyName = L"yyy";
    wchar_t *defValue = L"default value";
    wchar_t buffer[1024];
    DWORD bufferSize = sizeof(buffer);
    wchar_t *fileName = argv[1];

    DWORD result = GetPrivateProfileString(
        appName,
        keyName,
        defValue,
        buffer,
        bufferSize,
        fileName
        );

    wprintf(L"result: %d\n", result);
}
使用Process Monitor监视该文件名,我可以看到它在C:\Windows中查找该文件,这与预期的一样。但是,当在VS 2003中编译完全相同的代码并在2003 server上运行时,它会在%HOMEPATH%\Windows中查找该文件

返回原始的、未重新编译的程序。我注意到,在Windows 2008服务器上,只要双击exe,它就会在%HOMEPATH%\Windows中查找文件。但是,如果我右键单击exe并以管理员身份运行,它将在C:\Windows中查找该文件!但在Windows Server 2003上,它总是在%HOMEPATH%\Windows中查找


这与文档不一致

这种行为几乎肯定与终端服务器有关。当您安装了终端服务器(后来在Server 2003和更高版本的SKU中重命名为远程桌面服务)时,任何访问系统(Windows)目录的尝试都会被重定向到用户本地Windows目录(
%HOMEPATH%\Windows

这在的文档的“备注”部分中进行了说明,这可能是GetPrivateProfileString()在未指定完整路径的情况下在引擎盖下使用的,并且它会返回到其在系统目录中查找的16位Windows行为

如果您正在使用
图像\u DLLCHARACTERISTICS\u终端\u服务器\u AWARE
标志(在链接器下的项目属性页中设置)链接二进制文件→ 系统→ 终端服务器→ ), 然后,它假设您知道这种行为,并且理解终端服务器不同于普通客户机。因此,它为您提供实际的Windows目录,而不是专用的Windows目录

否则,如果您正在链接
/TSAWARE:NO
,则会获得向后兼容行为,该行为会将对系统Windows目录的请求重定向到私有用户本地Windows目录

这个标志的默认设置可能在VS 2003和VS 2012之间的某段时间发生了变化。我不知道确切的时间,但Visual Studio的现代版本确实假设您具有终端服务器意识

陈雷蒙曾在博客中写道:


无论如何,这都只是学术上的好奇。你的程序有缺陷,很久以前你就发现了这种好奇。应用程序不应该将数据写入Windows目录,无论是系统Windows目录还是伪用户本地Windows目录。有两种方法可以解决这一问题:

  • 完全停止调用GetPrivateProfileString(),并按照David Heffernan的建议,使用第三方INI文件解析器。Google将显示多个结果。看起来是个不错的选择

  • 如果您还没有准备好进行更改,您至少应该指定INI文件的完整路径。这将避免16位Windows在系统目录中转储文件的行为,但您仍将受制于这个古老API的其他缺点


  • 是的,这个长期被弃用的函数充满了奇怪的兼容性垫片和未记录的奇怪之处。添加,然后你决定将ini文件放在系统的Windows目录中。真的吗?!!现在是2016年。是时候停止使用此API了,是时候停止污染系统目录了。好吧,是时候在20多年前完成所有这些了。获取本机C或C++ini文件解析器,并将自己从这个API的暴政中解脱出来。如果你打算继续使用这个过时的API,至少要指定一个完整的路径。不要将你的垃圾存储在Windows目录中。这在你注意到它之前就被破坏了。@CodyGray的确,我忘了提到错误的行为是被依赖的行为n-无论出于何种原因,我们将ini文件存储在%HOMEPATH%\Windows中。现在它工作正常,它破坏了程序!这篇文章更多地是关于“为什么”我的猜测是,它与虚拟化和UAC有关。如果您尝试写入Windows目录,UAC将失败。但如果您的进程是虚拟化的,则会重定向到预期的虚拟存储。如果该文件存在于虚拟存储中,则会从那里读取,如果进程它是虚拟化的。但所有这些都是猜测。担心它是毫无意义的。你需要修复严重损坏的程序。@david UAC是我的第一个想法,但那不可能。Server 2003没有UAC,但它仍在进行虚拟化。这可能与终端服务器意识有关。Eurotrash似乎坚持要对其进行解释这种行为,所以我写了一个答案,他可以接受,这样他就可以忙于修复他的程序。事实上是TSAWARE开关。