强制现有应用程序始终在启用UAC虚拟化的情况下运行

时间:2012-01-13 15:30:55

标签: uac

我见过几个与此相反的问题; “我如何禁用虚拟化?”那不是我的问题。我想强制应用程序在虚拟化启用的情况下运行。

我有一个在Windows XP下运行得很好的应用程序,但是,因为它将其配置写入其工作目录(“C:\ Program Files(x86)”的子文件夹),它在Windows 7下无法正常运行如果我使用任务管理器打开UAC虚拟化,它会保存其配置就好了,但当然它无法加载该配置。

我不想将其设置为以管理员身份运行,因为它不需要这些权限。我想将其设置为在启用UAC虚拟化的情况下运行。

found a suggestion我在HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags的注册表中添加了一些魔法。为了完整起见,我也把它放在Wow6432Node中,但都没有任何效果。

5 个答案:

答案 0 :(得分:5)

在某些情况下,文件系统是虚拟化的,那么当您的应用程序不符合条件时,您的问题是如何仍然打开它?这不太可能,MSDN

  

在以下情况下,虚拟化不可用:

     
      
  • 虚拟化不适用于已升级并使用完整管理访问令牌运行的应用程序。

  •   
  • 虚拟化仅支持32位应用程序。非提升的64位应用程序只会在它们收到拒绝访问的消息时收到   尝试获取Windows对象的句柄(唯一标识符)。   本机Windows 64位应用程序需要兼容   UAC并将数据写入正确的位置。

  •   
  • 如果应用程序包含具有请求的执行级别的应用程序清单,则会禁用应用程序的虚拟化   属性。

  •   

答案 1 :(得分:4)

这可能为时已晚,但我是您发现激活UAC虚拟化的建议的作者,我的帖子中有一个错误。要修改的注册表项如下:

HKLM\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\ 
HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\

(注意"图层" 附加)

所以一个完整的例子是:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
"C:\\Program Files (x86)\\Some Company\\someprogram.exe"="RUNASINVOKER"

请注意,必须使用空格字符分隔多个参数。

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
"C:\\Program Files (x86)\\Some Company\\someprogram.exe"="WINXPSP3 RUNASINVOKER"

-

我真诚地感到遗憾,因为我的错误,你失去了相当多的时间。

顺便说一句,让我表达我对Ian Boyd的帖子的不同意见。有些地方不应该向所有人授予写权限,例如这一权限,因为它违反了&#34的基本安全规则;系统范围的写入应仅授权给特权主体"。 Program Files是一个系统范围的地方,而不是每个用户。

当然,所有规则都有例外,但在目前的情况下,可以想象一个恶意制作的配置文件,使程序在运行它时执行任意命令。在较轻的一面,人们可以想象一个"错误删除"由另一个用户,这将使应用程序失败。回到更重要的一面,程序文件中的应用程序可执行文件通常由管理员运行,迟早。即使您不想,卸载程序也经常运行程序文件中的卸载可执行文件。也许卸载程序将使用该配置文件,如果它被恶意制作可能会产生后果。

当然你可能会说,这听起来有些偏执,同意了。在Win XP时我确实修改了程序文件中的一些NTFS ACL,之后能够睡觉,但为什么工具可用时会有最轻微的风险?

答案 2 :(得分:2)

我找到了一个不太引用的条件,其中UAC虚拟化不起作用:Program Files中的文件被设为只读

也就是说,假设文件C:\Program Files\<whatever>\config.ini被标记为只读。当应用程序尝试更改它时,UAC虚拟化将返回拒绝访问权限错误,而不是将其重新分析为%LOCALAPPDATA%\VirtualStore\<whatever>\config.ini

虽然我没有发现这个记录,但这种行为可能是由设计完成的,因为它有一定意义。

解决方案很简单:确保应用程序应该修改的所有文件都不是只读的(或者只是取消标记所有文件,因为用户无论如何都无法更改它们。)

答案 3 :(得分:0)

您有一个应用程序,并且想要用户能够修改默认 的位置中的注册表项或文件,只有管理员可以修改。

如果您运行的是Windows 2000,Windows XP,Windows Vista,Windows 7或Windows 8,则解决方案是相同的:

  • 向这些位置授予适当的权限

例如,如果您的程序需要修改以下文件:

C:\Program Files\Blizzard\World of Warcraft

然后更正操作 以更改World of Warcraft文件夹的权限。事实上,这是微软应用于魔兽世界的垫片。 (在下一次运行时,它将Everyone完全控制权授予该文件夹 - 无论用户登录什么,WoW如何自行更新。)

如果您希望用户能够修改某个位置的文件:您必须授予他们权限。如果您是标准用户试图在 Windows XP 上运行WoW,您将遇到同样的问题 - 并且需要应用相同的解决方案。


您的应用程序正在将其配置写入:

C:\Program Files (x86)\Hyperion Pro\preferences.ini

然后您实际上执行想要将用户 完全控制授予该文件:

enter image description here

所以你的:

  • 应用程序未设置为以管理员身份运行
  • 用户无法修改可执行文件
  • 用户可以修改Configuration.ini

授予权限并不是件坏事;这就是你管理服务器的方式。


有两种解决方案:

  • 安装到C:\ProgramData\Contoso\Preferences.ini并在安装时对其进行ACL
  • 安装到C:\Program Files\Contoso\Preferences.ini并在安装时对其进行ACL

如果你看看微软的AppCompat人员的指导:

  

Where Should I Write Program Data Instead of Program Files?

     

常见的应用程序代码更新是:“我的应用程序用于将文件写入程序文件。感觉就像把它放在任何其他地方一样好。它已经有我的应用程序名称,因为我的用户是管理员,它工作正常。但是现在我发现这可能不像我曾经想过的那样强大,因为UAC甚至管理员大多数时候都使用标准的类似用户的权限。那么,我应该在哪里放置我的文件呢?“

     

<强> FOLDERID_ProgramData

     

用户永远不想在资源管理器中浏览此处,此处更改的设置应该影响计算机上的每个用户。默认位置是%systemdrive%ProgramData,它是Windows Vista安装中的隐藏文件夹。 您需要创建目录并在安装时设置所需的ACL。

所以你有两个解决方案:

  • 在安装时创建您的文件,并对其进行ACL以便所有用户都可以在运行时修改它
  • 在安装时创建您的文件,并对其进行ACL以便所有用户都可以在运行时修改它

唯一的区别是语义。 程序文件文件夹是程序文件的意思。您不想在此处存储数据。

  • 并且因为Diego Queiroz对安全性有任何见解。
  • 这是因为它只是程序的去处。

有时机器会反复使用相同的程序文件进行成像。您不希望图像中的每台机器数据。该数据属于 ProgramData

这不是安全问题。

有些人必须了解安全边界的位置。

答案 4 :(得分:0)

在其他答案中有很多优点。
其实我都赞成。
因此,让我们将所有 combine 组合在一起,并 add 还有更多方面...

OP提到了一些“过去的遗留应用程序”。
因此我们可以假设它是x86(32位),并且也没有包含任何清单(尤其是未指定任何“ requestedExecutionLevel”)。

-

Roman R.对于x64manifest文件有很好的回答:
https://stackoverflow.com/a/8853363/1468842
但所有这些条件似乎都不适用于这种情况。

NovHak在他的答案中概述了一些AppCompatFlagsRUNASIVOKER
https://stackoverflow.com/a/25903006/1468842

迭戈·奎罗斯(Diego Queiroz)在他的回答中添加了有关read-only标志的有趣方面:
https://stackoverflow.com/a/42934048/1468842

伊恩·博伊德(Ian Boyd)指出,您甚至不应该进行这种“虚拟化”,而应根据ACL在那些感兴趣的文件(例如“ config.ini”)上进行设置:
https://stackoverflow.com/a/12940213/1468842

这是附加/新方面:
可以将policy设置为禁用所有虚拟化-系统范围内:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
"EnableVirtualization"=dword:00000000

实际上,我在我拥有的每个系统上都执行此策略。
因为否则会导致在multi-user环境中产生混乱的行为。
UserA在其中进行了一些更改,一切正常。
但随后UnserB不会获取UserA完成的更改。

万一某些老套的软件失败了,那就应该“失败”!
而不是说一切都很好。
恕我直言,“虚拟化”是微软有史以来最糟糕的设计决定。

那么也许系统启用了此策略,这就是为什么虚拟化对您不起作用的原因?

-

,所以最终的检查清单可能是:

  • 应用程序是 x86 还是 x64
  • exe是否有清单(包括requestedExecutionLevel)?
  • 您是否已选中只读属性(例如那些INI文件)?
  • 是否有政策EnableVirtualization强制设为0
  • 您是否使用RUNASIVOKER尝试了 AppCompatFlags
  • 或直接使用 ACL 代替虚拟化

-

最后,我们将讨论如何运行旧的旧版应用程序。
通过使用我们可以想到的任何变通方法和技巧。
可能应该在superuserserverfault上对此进行更好的讨论。

stackoverflow(针对programmers的目标)中我们都知道:现在是时候让我们自己的所有程序都与UAC概念兼容,以及如何以“正确”的方式实现事物了- “方式:)