一些在xp下设计的程序,转到vista\7下就不能运行了。尤其是那种写入注册表的,写入program file文件夹的程序。
在msdn上给出了解释。uac还有这样子的保护,相当于虚拟机了。
[来自MSDN]
很多应用程序都设计为把文件写入Program Files,Windows目录,或者系统根(一般是C盘)文件夹。一些应用程序被设计为更新Microsoft Windows 注册表的值,特别是HKLM/Software中的值。但是这样会有存在一个问题:文件或注册表的值并没有被创建或更新。您可能会问,“怎么回事?我的应用程序运行良好并没有报错啊。我的文件到底去哪儿了?”
您可能遇到过下面的一种或多种情况:
• 您的应用程序写入Program Files,Windows目录,或者系统根(一般是C盘)文件夹,但是您在这些地方并没有找到您的文件
• 您的应用程序写入Windows注册表,特别是HKLM/Software中,但是您没有看到注册表进行了更新
• 您切换到了另一个帐户,并且您的应用程序没有办法找到已写入Program Files,Windows目录,或者系统根(一般是C盘)文件夹的文件,或者找到了这些文件的老版本
• 在启用或禁用用户帐户控制(UAC)后,您的应用程序都没有办法找到Program Files或Windows目录中的文件
如果这些出现在了您的应用程序中,都是由于UAC虚拟化的原因。下面所提供的信息为您介绍了所有关于发现这个应用程序兼容性问题,解决方案,以及特殊兼容性问题的一些附加信息。
真正的问题:UAC 虚拟化
在Windows Vista中,一般由管理员来运行应用程序。这样,应用程序可以自由的读写系统文件和注册表的值。如果标准用户可以运行这些应用程序,那他们可能会由于没有足够的权限而导致失败。Windows Vista通过重定向写入(以及后续文件或者注册表操作)对应用户的配置文件(profile)位置,来对标准用户运行应用程序的能力进行了提升。
例如,如果一个应用程序试图写入C:\Program Files\Contoso\Settings.ini,并且用户没有权限来对该文件夹进行写入操作,写入操作将会被重定向到C:\Users\Username\AppData\Local\VirtualStore\Program Files\Contoso\settings.ini。如果应用程序试图在注册表中写入HKEY_LOCAL_MACHINE\Software\Contoso\,这将会被自动重定向到HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\Software\Contoso或HKEY_USERS\UserSID_Classes\VirtualStore\Machine\Software\Contoso。
下图显示了Windows 虚拟化进程的两个组件:文件虚拟化和注册表虚拟化
重要注意
当为Windows Vista开发应用程序时,请确定在对应的requestedExecutionLevel元素中嵌入应用程序清单文件。这将会关闭文件和注册表虚拟化,减少虚拟化的文件和注册表值的复杂性。
更多关于UAC虚拟化和新UAC技术,请参阅“Windows Vista中的新UAC技术”http://msdn.microsoft.com/en-us/library/bb756960.aspx .
解决方案
虚拟化是为了帮助现存的应用程序解决兼容性问题而出现的。为Windows 7而设计的新的应用程序不应该对敏感的系统区域进行写入操作,不应该依靠虚拟化来对不正确的应用程序行为进行修正。开发应用程序的时候,应该始终考虑使其运行在标准用户的权限下,而不是在管理员权限下运行。测试您的应用程序时,也要用标准用户权限而不是管理员权限。
如果您正在使用UAC虚拟化来为Windows 7开发应用程序,那么请将您的应用程序重新设计为将文件写入合适位置。当更新现有的代码以在Windows 7上运行的时候,您应该:
• 确定在运行时,应用程序存储数据只是在对应用户的位置或者在对访问控制列表(ACL)进行了设置的%alluserprofile%系统位置。更多关于ACLs的信息,请参阅访问控制列表.
• 使用已知的文件夹来写入数据文件。所有用户可以使用的一般数据应该被写入一个对所有人共享的公共位置。所有其他的数据都应该被写入对应用户的位置。
o 一般数据文件可以包含,但不限制,日志文件,配置文件(INI/XML),状态存储应用程序例如保存的游戏等等。
o 用户文件则不同;它们应该被保存到Documents文件夹(或者用户指定的位置)
• 确保您没有在代码中指定你觉得合适的路径。建议您使用下面的模型和APIs来获取特定已知的Windows的正确路径:
o C/C++ native 应用程序: 使用SHGetKnownFolderPath方法来获取已知文件夹的整个路径,它们可以用文件夹的KNOWNFOLDERID来识别。它是一个标识您想要获取的已知位置的GUID参数:
FOLDERID_ProgramData – 向所有人共享项目数据的目录
FOLDERID_LocalAppData – 对应用户项目数据的目录(不可移动的)
FOLDERID_RoamingAppData –对应用户项目数据的目录(可移动的)
o 托管代码: 使用System.Environment.GetFolderPath方法。GetFolderPath包含一个标识您想要获取的已知位置的参数:
Environment.SpecialFolder.CommonApplicationData –向所有人共享项目数据的目录
Environment.SpecialFolder.LocalApplicationData –对应用户项目数据的目录(不可移动的)
Environment.SpecialFolder.ApplicationData –对应用户项目数据的目录(可移动的)
• 如果上面提到的方法都不起作用,则请您使用环境变量:
o %ALLUSERSPROFILE% –向所有人共享项目数据的目录
o %LOCALAPPDATA% –对应用户项目数据的目录(不可移动的) - Windows Vista或更高版本
o %APPDATA% –对应用户项目数据的目录(可移动的) - Windows Vista或更高版本