WIX: предоставление разрешений в папку
Я прочитал все связанные темы и не нашел полного ответа на мою проблему.
Я хотел бы предоставить полные разрешения для системных и Read и Execute разрешений для группы пользователей в папку в Program Files. Ничего больше, не меньше.
Я знаю, что есть 3 способа предоставить разрешения для папки с помощью 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>
Проблема: Он не работает на внешней ОС, так как он не знает ключевое слово "Пользователи". Я попробовал это с SID. Кроме того, мне нужно разместить элемент Permission под каждым файлом в тестовом каталоге (но если это был единственный случай, я бы справился)
2) Элемент VixUtilsExtension 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) PermissionEx с Sddl:
Проблема: Этот элемент доступен только при установке с MSI 5.0. Я использую installer 3.01.
Я буду рад получить любое решение, включая решения с пользовательскими действиями...
Ответы
Ответ 1
Используйте следующий код, чтобы выполнить это без специального действия. Я проверил это (также в дочерних папках). Также Пользователь всех отображается в локализованных операционных системах Windows.
<CreateFolder>
<Permission User="Everyone" GenericAll="yes" ChangePermission="yes"/>
</CreateFolder>
Ответ 2
У меня была такая же проблема и поговорил с Робом М об этом. Я собирался сделать ответ Christian G (fooobar.com/questions/317428/...), но Роб предложил использовать WixQueryOsWellKnownSID (http://wix.sourceforge.net/manual-wix3/osinfo.htm), чтобы обойти не-американские локали.
В файле .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 это может быть не полностью поддержано. Если это не сработает для вас, могут быть другие варианты, которые вы можете использовать для переводить SID.
Ответ 3
Другой вариант - иметь простой CA, который просто переводит свойство msi, которое содержит SID, в фактическое имя группы из локализованной ОС. CA не нужно откладывать, и он не выполняет фактическую работу по настройке разрешений.
Ниже приведен пример CA, который считывает значение свойства PROIty_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 для учетных записей:
<Property Id="AdminAccount" Value="S-1-5-32-544" />
<Property Id="EveryoneAccount" Value="S-1-1-0" />
Создайте CA, который установит свойство PROPERTY_TO_BE_TRANSLATED, а затем вызовет 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>
Наконец, планируйте CA перед CreateFolder
<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.
Ответ 4
вам нужно реализовать отложенные пользовательские действия для изменения разрешений. Пример пользовательского действия С#:
[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;
}
вы можете переносить это на С++, пользовательское действие должно быть отложено - чем вы должны получить доступ к своим свойствам сеанса с помощью CustomActionDatap >
Ответ 5
Как < Разрешение > элемент очищает наследование разрешений от родительских папок, вы можете попробовать использовать одиночный <Permission> элемент для пользователей "Все" или "Администраторы", за которыми следует < util: PermissionEx > элементы для установки разрешений для имен пользователей, которые не поддерживаются параметром <Permission> элемент, например:
<Permission User="Everyone" GenericRead="no" />
<util:PermissionEx User="Users" Domain="[LOCAL_MACHINE_NAME]" GenericRead="yes" Read="yes" GenericExecute="yes" ChangePermission="yes" />
Не требуется явно устанавливать разрешения для SYSTEM, так как они автоматически добавляются установщиком.