我已阅读所有相关主题,但未找到问题的完整答案。
我想授予SYSTEM和Read& amp ;;对Users组执行权限到Program Files下的文件夹。没什么,没什么。
我知道有三种方法可以使用WIX授予文件夹权限,但这些方法对我来说都不是很好,我会解释原因:
1)常规权限元素:
<CreateFolder Directory="Test">
<Permission User="SYSTEM" GenericAll="yes"/>
<Permission User="Users" Domain="[LOCAL_MACHINE_NAME]"
GenericRead="yes" Read="yes" GenericExecute="yes" ChangePermission="yes"/>
</CreateFolder>
问题:在外国操作系统上失败,因为它不知道“Users”关键字。我也尝试过SID。除此之外,我需要将Permission元素放在Test目录中的每个文件下(但如果这是唯一的情况,我会管理)
2) WixUtilsExtension PermissionEx元素:
<CreateFolder Directory="Test">
<util:PermissionEx User="SYSTEM" GenericAll="yes"/>
<util:PermissionEx User="Users" Domain="[LOCAL_MACHINE_NAME]"
GenericRead="yes" Read="yes" GenericExecute="yes" ChangePermission="yes"/>
</CreateFolder>
问题:该文件夹还保留Program Files文件夹的默认权限。我不能允许这样做。
3)使用Sddl的PermissionEx:
问题:此元素仅在使用MSI 5.0安装时可用。我正在使用安装程序3.01。
我很乐意获得任何解决方案,包括采用自定义操作的解决方案......
答案 0 :(得分:8)
我有同样的问题,并与Rob M讨论过这个问题。我打算做Christian G的答案(https://stackoverflow.com/a/5296967/18475),但Rob建议使用WixQueryOsWellKnownSID(http://wix.sourceforge.net/manual-wix3/osinfo.htm)来绕过非en-US语言环境。
在.wxs
文件中添加以下内容:
<PropertyRef Id="WIX_ACCOUNT_LOCALSYSTEM" />
<PropertyRef Id="WIX_ACCOUNT_USERS" />
在.wxs
文件中你想要应用权限的下一步就是这样:
<Permission GenericAll="yes" User="[WIX_ACCOUNT_LOCALSYSTEM]" />
<Permission GenericRead="yes" GenericExecute="yes" User="[WIX_ACCOUNT_USERS]" />
现在当你跑步时,你只需要链接WixUtilExtension
。
light -ext WiXUtilExtension ...
注意:根据您的WiX版本,可能不完全支持此功能。如果它不适合您,可以使用其他选项translate SIDs。
答案 1 :(得分:7)
使用以下代码无需自定义操作即可完成此操作。我已经验证了这个工作(也在子文件夹上)。此外,User Everyone映射在本地化的Windows操作系统上。
<CreateFolder>
<Permission User="Everyone" GenericAll="yes" ChangePermission="yes"/>
</CreateFolder>
答案 2 :(得分:2)
另一种选择是拥有一个简单的CA,它只是将包含SID的msi属性转换为本地化操作系统中组的实际名称。 CA不必延迟,也不是在设置权限的实际工作。
以下是CA的示例,它读取PROPERTY_TO_BE_TRANSLATED msi属性的值并转换由其指示的msi属性。通过这种方式,您可以运行CA来转换不同的msi属性。
[CustomAction]
public static ActionResult TranslateSidToName(Session session)
{
var property = session["PROPERTY_TO_BE_TRANSLATED"];
if (String.IsNullOrEmpty(property))
{
session.Log("The {0} property that should say what property to translate is empty", translateSidProperty);
return ActionResult.Failure;
}
var sid = session[property];
if (String.IsNullOrEmpty(sid))
{
session.Log("The {0} property that should contain the SID to translate is empty", property);
return ActionResult.Failure;
}
try
{
// convert the user sid to a domain\name
var account = new SecurityIdentifier(sid).Translate(typeof(NTAccount)).ToString();
session[property] = account;
session.Log("The {0} property translated from {1} SID to {2}", property, sid, account);
}
catch (Exception e)
{
session.Log("Exception getting the name for the {0} sid. Message: {1}", sid, e.Message);
return ActionResult.Failure;
}
return ActionResult.Success;
}
在WiX中,您可以使用SID for the accounts:
定义要翻译的属性 <Property Id="AdminAccount" Value="S-1-5-32-544" />
<Property Id="EveryoneAccount" Value="S-1-1-0" />
创建将设置PROPERTY_TO_BE_TRANSLATED属性的CA,然后调用CA进行翻译:
<CustomAction Id="TranslateAdmin_SetProperty" Property="PROPERTY_TO_BE_TRANSLATED" Value="AdminAccount"/>
<CustomAction Id="TranslateAdmin" BinaryKey="CommonCustomActions" DllEntry="TranslateSidToName" Impersonate="no" />
<CustomAction Id="TranslateEveryone_SetProperty" Property="PROPERTY_TO_BE_TRANSLATED" Value="EveryoneAccount" />
<CustomAction Id="TranslateEveryone" BinaryKey="CommonCustomActions" DllEntry="TranslateSidToName" Impersonate="no" />
设置权限时不要忘记使用msi属性:
<CreateFolder>
<Permission GenericAll="yes" User="[AdminAccount]" />
<Permission GenericRead="yes" GenericExecute="yes" User="[EveryoneAccount]" />
</CreateFolder>
最后,在CreateFolder之前安排CA
<InstallExecuteSequence>
<Custom Action='TranslateAdmin_SetProperty' Before='TranslateAdmin' />
<Custom Action='TranslateAdmin' Before='CreateFolders' />
<Custom Action='TranslateEveryone_SetProperty' Before='TranslateEveryone' />
<Custom Action='TranslateEveryone' Before='CreateFolders' />
</InstallExecuteSequence>
通过这种方式,CA只执行一些简单的工作,将权限设置保留给WiX元素。
答案 3 :(得分:1)
您需要实施延迟自定义操作以更改权限。 c#自定义操作示例:
[CustomAction]
public static ActionResult SetFolderPermission(Session session)
{
string folder = session.CustomActionData["Folder"].Trim('\"');
string sid = session.CustomActionData["SID"].Trim('\"');
System.Security.Principal.SecurityIdentifier sidID = new System.Security.Principal.SecurityIdentifier(sid);
System.Security.AccessControl.DirectorySecurity ds = System.IO.Directory.GetAccessControl(folder);
ds.AddAccessRule(new System.Security.AccessControl.FileSystemAccessRule(sidID
, System.Security.AccessControl.FileSystemRights.Write
, System.Security.AccessControl.InheritanceFlags.ObjectInherit
, System.Security.AccessControl.PropagationFlags.NoPropagateInherit
, System.Security.AccessControl.AccessControlType.Allow));
System.IO.Directory.SetAccessControl(folder , ds);
return ActionResult.Success;
}
您可以在C ++上移植它,必须延迟自定义操作 - 而不是必须通过CustomActionData访问您的会话属性
答案 4 :(得分:1)
作为&lt;权限&gt; element清除父文件夹的权限继承,您可以尝试使用单个&lt; Permission&gt;用户“Everyone”或“Administrators”后跟&lt; util:PermissionEx&gt;的元素用于设置&lt; Permission&gt;不支持的用户名权限的元素元素,例如:
<Permission User="Everyone" GenericRead="no" />
<util:PermissionEx User="Users" Domain="[LOCAL_MACHINE_NAME]" GenericRead="yes" Read="yes" GenericExecute="yes" ChangePermission="yes" />
不需要显式设置SYSTEM权限,因为安装程序会自动添加这些权限。