Как предоставить разрешения на чтение / запись для папки во время установки с использованием .NET

У меня есть проект установки, который я создал с помощью Visual Studio 2010.

Установщик отлично работает с точки зрения установки приложения и всех его зависимостей в соответствующие подкаталоги и каталоги данных программы.

Однако я заметил, что каждый каталог (корневая папка и все ее подкаталоги), созданный установщиком, не дает разрешения «Запись». Единственные разрешения, которые добавляются к каталогам для группы «Пользователи»:

  • Прочитать и выполнить
  • Список содержимого папки
  • Читать

Это очевидная настройка разрешений по умолчанию будет происходить независимо от того, устанавливает ли пользователь приложение как «Администратор» или нет.

Мне кажется странным, что установщик не дает разрешения «Запись» в папку, которая используется устанавливаемым приложением. Еще больше сбивает с толку то, что папка, которую установщик создает в папке ProgramData для базы данных приложения. не получает разрешения на «Запись».

Мой вопрос в том, есть ли способ настроить проект установки так, чтобы при создании папки мы могли сообщить ей, какие разрешения предоставить ей и кому. В моем случае мне нужно предоставить корневому каталогу (приложения) и всем его подкаталогам, а также папке, которая находится в ProgramData папке разрешения «Чтение / запись» для «Группы пользователей». Технически, я нормально отношусь к тому, чтобы предоставить каталогам «Полный доступ» «Группе пользователей».


person Jed    schedule 02.09.2011    source источник
comment
Может быть, тебе стоит подумать над правильным ответом   -  person oo_dev    schedule 21.12.2016


Ответы (9)


По умолчанию группа «Пользователи» не имеет доступа на запись в локальных папках, таких как Program Files. Это стандарт Windows, не имеющий отношения к установке. Однако во время установки вы можете установить любые разрешения, которые захотите.

Установщик Windows поддерживает настраиваемые разрешения, но Visual Studio не предлагает способ их установки. Таким образом, единственное решение в Visual Studio - это настраиваемое действие.

К сожалению, Visual Studio не поддерживает прикрепленные настраиваемые действия. Таким образом, использование XCACLS.EXE для установки разрешений будет работать, только если вы включите его в свой пакет (он будет быть установленным на целевой машине вместе с вашими файлами).

Более чистое, но более сложное решение - написать собственное действие (используя собственный код) для установки необходимых разрешений.

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

person cosmin    schedule 02.09.2011

Думаю, мой другой пост был удален из-за того, что он слишком общий, поэтому я уточнил его ниже:

Нужно сделать настраиваемое действие. Это довольно просто, ознакомьтесь с пошаговым руководством MSDN по написанию настраиваемого действия C # здесь < / а>. Вы поместите свой код изменения разрешений в метод установки:

Выполните первые несколько шагов по ссылке, чтобы получить новый проект установщика, на который ссылается ваше решение установщика. Вы должны сделать это таким образом, чтобы вы могли создать dll, который вызывается в конце установки.

На самом деле установка прав чтения / записи для пользователей была немного сложнее, и самое близкое, что я мог найти, - это установить для аутентифицированных пользователей. Я собрал несколько других решений, которые нашел в Интернете, чтобы придумать это:

public override void Install(IDictionary stateSaver)
{
    // This gets the named parameters passed in from your custom action
    string folder = Context.Parameters["folder"];

    // This gets the "Authenticated Users" group, no matter what it's called
    SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);

    // Create the rules
    FileSystemAccessRule writerule = new FileSystemAccessRule(sid, FileSystemRights.Write, AccessControlType.Allow);

    if (!string.IsNullOrEmpty(folder) && Directory.Exists(folder))
    {
        // Get your file's ACL
        DirectorySecurity fsecurity = Directory.GetAccessControl(folder);

        // Add the new rule to the ACL
        fsecurity.AddAccessRule(writerule);

        // Set the ACL back to the file
        Directory.SetAccessControl(folder, fsecurity);
    }

    // Explicitly call the overriden method to properly return control to the installer
    base.Install(stateSaver);
}

Затем, когда вы создаете свое настраиваемое действие, отредактируйте его свойства и добавьте что-то подобное в свойстве CustomActionData:

/folder="[CommonAppDataFolder][ProductName]"
person ACK_stoverflow    schedule 10.05.2012
comment
+1, за исключением того, что мне пришлось добавить base.Install(stateSaver); в конце метода переопределения. - person Dejan Janjušević; 16.05.2012
comment
@ DejanJanjušević Хороший звонок, я отредактировал свой ответ, включив это. - person ACK_stoverflow; 16.05.2012
comment
ACK для информации [из вашего сообщения] , и самое близкое, что я мог найти, это установить для прошедших проверку пользователей. Существует BuiltinUsersSid, который представляет коллекцию Users. - person Kevin Roche; 01.10.2012
comment
Неработающая ссылка MSDN в исходном сообщении (пошаговое руководство по настройке C #). Я считаю, что это правильная ссылка: msdn .microsoft.com / en-us / library / vstudio / d9k65z2d (v = vs.100) .aspx. - person nmarler; 15.05.2013
comment
Как я недавно обнаружил, в документации предлагается разместить base.Install (stateServer) в начале, а не в конце метода переопределения. Похоже, что это заставляет ваши зависимости сначала устанавливаться (имеет смысл). Из документации: если вы переопределяете метод Install в производном классе, обязательно сначала вызовите метод Install базового класса в производном методе. Метод Install вызывает метод Install каждого установщика, содержащегося в свойстве Installers этого экземпляра. Источник: msdn .microsoft.com / en-us / library / - person chadjoan; 19.10.2017

private static void GrantAccess(string file)
{
    bool exists = System.IO.Directory.Exists(file);
    if (!exists)
    {
        DirectoryInfo di = System.IO.Directory.CreateDirectory(file);
        Console.WriteLine("The Folder is created Sucessfully");
    }
    else
    {
        Console.WriteLine("The Folder already exists");
    }
    DirectoryInfo dInfo = new DirectoryInfo(file);
    DirectorySecurity dSecurity = dInfo.GetAccessControl();
    dSecurity.AddAccessRule(new FileSystemAccessRule(
            new SecurityIdentifier(WellKnownSidType.WorldSid, null), 
            FileSystemRights.FullControl, 
            InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit,
            PropagationFlags.NoPropagateInherit, 
            AccessControlType.Allow));
    dInfo.SetAccessControl(dSecurity);
   
}

Приведенный выше код установит права доступа к папке на полный контроль / чтение-запись для каждого пользователя (всех).

person Richendra kumar ravi    schedule 02.08.2016
comment
Этот код не нужно ничего устанавливать, просто запустите свой VS и скопируйте код, он отлично работает для меня для каждого пользователя - person Richendra kumar ravi; 02.08.2016

Такое поведение было задумано. Программы не должны изменять себя (отсюда и их каталог установки) для чего-либо, кроме обновлений (что снова без проблем можно сделать с помощью установщика Windows). Если вы используете .NET, изолированное хранилище - отличное место для хранить пользовательские данные.

person Teoman Soygul    schedule 02.09.2011

DirectoryInfo info = new DirectoryInfo(path[x]);

DirectorySecurity security = info.GetAccessControl();

security.AddAccessRule(new FileSystemAccessRule(logonName, FileSystemRights.Modify, InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));

security.AddAccessRule(new FileSystemAccessRule(logonName, FileSystemRights.Modify, InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));

info.SetAccessControl(security); 

Установка наследуемой части также важна, если вы хотите сохранить и получить доступ к более чем одному файлу в папке ProgramData.

person Kristian Søgaard    schedule 14.11.2013

Как уже упоминалось выше, группа пользователей не имеет прав на запись в Program Files. Если вы не хотите иметь дело с классом установщика или Wix (если это простая программа), просто предпочтите установить свое программное обеспечение на томе Windows.

Я говорю о мастере установки Visual Studio: измените свойство папки приложения 'DefaultLocation' с [ProgramFilesFolder] на [WindowsVolume] [Manufacturer] [ProductName] в файловой системе на целевой машине. .

person depicci    schedule 20.11.2015

Измените defaultLocation на: C: [Производитель] [ProductName], вы можете заменить диск C любым диском, который вам нравится. См. это изображение

person beginner2020    schedule 22.12.2019

Я помещаю папки, которые хочу скопировать, в папку в разделе «Папка приложения» мастера установки, который находится в каталоге C: \ Program Files (x86).

Затем, когда программа запускается, она проверяет, находятся ли необходимые папки в нужном месте, и, если нет, копирует их в правильный каталог.

Итак, код будет:

If Not My.Computer.FileSystem.DirectoryExists("directory") And My.Computer.FileSystem.DirectoryExists("directory") Then
    My.Computer.FileSystem.CopyDirectory("C:\Program Files (x86)\APPFOLDER", "C:\ProgramData\APPFOLDER")
Else
End If

Надеюсь это поможет.

person Josh Face    schedule 09.03.2020

Я также столкнулся с разрешениями файловой системы при попытке записи в базу данных SQLite после установки приложения.

Как упоминалось в этом потоке, файлы данных могут быть помещены в папку AppData пользователя вместо изменения разрешений в Program Files и тому подобном. AppData также имеет права пользователя, разрешающие запись по умолчанию.

В проекте установки это делается путем добавления папки данных приложения пользователя в файловую систему установки, в которой может быть создана папка приложения. Затем в эту папку приложения добавляется файл базы данных. Папка приложения с файлом базы данных будет создана при установке внутри папки AppData.

Код для создания строки подключения к базе данных, указывающей на папку AppData, выглядит следующим образом:

public static Environment.SpecialFolder DataPath = Environment.SpecialFolder.ApplicationData;
public static string ConnectionString = "Data Source=" + Environment.GetFolderPath(DataPath) + "\\ApplicationName\\database.SQLite";

Я использовал это решение с Visual Studio 2019.

person voidviewer    schedule 24.07.2020