Как создать папку или скопировать файл в ProgramData при установке приложения в Visual Studio 2017? - PullRequest
0 голосов
/ 03 октября 2018

Я создал установщик для приложения WPF в «Установщике Visual Studio» в Visual Studio 2017 Community Edition.В моем приложении есть файл настроек, который требует разрешения на запись, поскольку настройки меняются во время работы приложения.

Я хочу установить свое приложение в папку «Файлы программы», но в то же время я хочу создатьпапка в папке «ProgramData» для копирования файла настроек.

Я не могу создать папку и скопировать файл в «ProgramData», и я прошел через множество ресурсов, но в конце не повезло.

Я нашел соответствующий ответ в ссылке здесь , но он связан с Visual Studio 2010, и я не нашел упомянутую опцию [CommonAppDataFolder] в DefaultLocation в Visual Studio 2017.

Не могли бы вы помочь мне достичь этой цели?Спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Шаблоны файлов настроек : мы часто повторяем этот совет, но любые файлы, которые вы намереваетесь изменить во время работы вашего приложения, мы рекомендуем вам отвлечься от проблем развертыванияустановив файлы шаблонов только для чтения в ProgramFiles, которые ваше приложение создает, а затем сохраняет в профиле пользователя.Установка никогда не будет мешать файлам после их создания.Нет неожиданного уничтожения файла настроек.В профиле пользователя файлы будут иметь полный доступ для записи.

Общий файл настроек : если вы хотите, чтобы один файл настроек был доступен всем пользователям (в большинстве случаевплохая идея), вы можете скопировать его в CommonAppDataFolder в папке, которую вы открыли для доступа на запись для обычных пользователей с использованием прав доступа ACL.Не здорово, но возможно.В WiX, Advanced Installer и Installshield вы можете изменить ACL как встроенную функцию, но вы сделали пользовательское действие, используя проект Visual Studio Installer.Хорошо, но прочтите эти примечания об ограничениях проектов установщика Visual Studio .

Соответствующие ссылки :

0 голосов
/ 03 октября 2018

Хотя этот параметр недоступен в поле со списком DefaultLocation, вы можете вручную указать параметр [CommonAppDataFolder] .После того, как вы дадите эту опцию, пользовательская папка будет скопирована в папку ProgramData.

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

    [RunInstaller(true)]
    public partial class Installer1 : Installer
    {
        private string fullPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\YourFolder";

        public override void Install(IDictionary savedState)
        {
            base.Install(savedState);
            //Add custom code here


            if (!Directory.Exists(fullPath))
            {
                Directory.CreateDirectory(fullPath);

                // Create files on inside the folder to make them writable
                   ... 
            }

            // /4457121/kak-dat-polnoe-razreshenie-na-fail-sozdannyi-moim-prilozheniem-dlya-vseh-polzovatelei

            DirectoryInfo dInfo = new DirectoryInfo(fullPath);
            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);
        }

        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
            //Add custom code here

            if (Directory.Exists(fullPath))
            {
                Directory.Delete(fullPath, true);
            }
        }

        public override void Commit(IDictionary savedState)
        {
            base.Commit(savedState);
            //Add custom code here
        }

        public override void Uninstall(IDictionary savedState)
        {
            Process application = null;
            foreach (var process in Process.GetProcesses())
            {
                if (!process.ProcessName.ToLower().Contains("yourprocessname"))
                    continue;
                application = process;
                break;
            }

            if (application != null && application.Responding)
            {
                application.Kill();
                base.Uninstall(savedState);
            }

            if (Directory.Exists(fullPath))
            {
                Directory.Delete(fullPath, true);
            }
        }
    }
...