Как да дадете разрешения за четене/запис на папка по време на инсталация с помощта на .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 Installer поддържа персонализирани разрешения, но 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, който представлява колекцията Потребители. - person Kevin Roche; 01.10.2012
comment
Трябваше да добавя още малко права, за да работи. Използвах правата, публикувани в примерния код тук stackoverflow.com/a/4392394/433718 - person OneWorld; 25.02.2013
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 на всеки инсталатор, съдържащ се в свойството 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

Променете местоположението по подразбиране на: C:[Manufacturer][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