WIX: предоставление разрешений для папки

Я прочитал все связанные темы и не нашел полного ответа на мою проблему.

Я хотел бы предоставить полные разрешения для SYSTEM и разрешения "Чтение и выполнение" для группы "Пользователи" для папки в разделе "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 под каждым файлом в каталоге 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) PermissionEx с Sddl:

Проблема: Этот элемент доступен только при установке с MSI 5.0. Я использую установщик 3.01.

Я буду рад получить любое решение, в том числе решения с пользовательскими действиями...

5 ответов

У меня была точно такая же проблема, и я говорил об этом с Робом М. Я собирался сделать ответ Кристиана Дж ( /questions/4038227/wix-predostavlenie-razreshenij-dlya-papki/4038234#4038234), но Роб предложил использовать 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.

Используйте следующий код для выполнения этого без специальных действий. Я проверил это работает (также на дочерних папках). Также Пользователь Каждый отображается в локализованных операционных системах Windows.

<CreateFolder>
      <Permission User="Everyone" GenericAll="yes" ChangePermission="yes"/>
</CreateFolder>

Другой вариант - иметь простой CA, который будет просто преобразовывать свойство msi, содержащее SID, в фактическое имя группы из локализованной ОС. CA не нужно откладывать, и он не выполняет фактическую работу по настройке разрешений.

Ниже приведен пример CA, который считывает значение свойства msi PROPERTY_TO_BE_TRANSLATED и транслирует указанное им свойство 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.

Вам нужно реализовать отложенное пользовательское действие для изменения разрешений. Пример пользовательского действия 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

Поскольку элемент очищает наследование разрешений от родительских папок, вы можете попробовать использовать один элемент для пользователей "Все" или "Администраторы", а затем элементы для установки разрешений для имен пользователей, которые являются не поддерживается элементом , например:

<Permission User="Everyone" GenericRead="no" />
<util:PermissionEx User="Users" Domain="[LOCAL_MACHINE_NAME]" GenericRead="yes" Read="yes" GenericExecute="yes" ChangePermission="yes" />

Нет необходимости явно устанавливать разрешения для SYSTEM, так как они добавляются автоматически установщиком.

Другие вопросы по тегам