如何在使用 .NET 安装期间授予对文件夹的读/写权限

Posted

技术标签:

【中文标题】如何在使用 .NET 安装期间授予对文件夹的读/写权限【英文标题】:How to give Read/Write permissions to a Folder during installation using .NET 【发布时间】:2011-11-09 10:44:32 【问题描述】:

我有一个使用 Visual Studio 2010 构建的安装项目。

安装程序在将应用程序及其所有依赖项安装到其适当的子目录和程序数据目录方面工作正常。

但是,我注意到安装程序创建的每个目录(根文件夹及其所有子目录)都没有授予“写入”权限。添加到“用户”组目录的唯一权限是:

读取和执行 列出文件夹内容 阅读

无论用户是否以“管理员”身份安装应用程序,都会发生这种明显的默认权限设置。

在我看来,安装程序没有向正在安装的应用程序正在使用的文件夹授予“写入”权限,这似乎很奇怪 - 安装程序在 ProgramData 中创建的文件夹更加令人困惑应用程序数据库的文件夹没有获得“写入”权限。

我的问题是,有没有一种方法可以配置安装项目,以便当它创建一个文件夹时,我们可以告诉它授予它什么类型的权限以及授予谁。在我的例子中,我需要为(应用程序的)根目录及其所有子目录,以及位于ProgramData 文件夹中的文件夹提供“用户组”的“读/写”权限。从技术上讲,我很乐意将目录“完全控制”交给“用户组”。

【问题讨论】:

也许你应该重新考虑哪个是正确的答案 【参考方案1】:
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);
   

上面的代码将文件夹的访问权限设置为完全控制/读写每个用户(每个人)。

【讨论】:

这段代码不需要安装任何东西,只需运行你的VS并复制代码,它对每个用户都可以正常工作【参考方案2】:

在安装应用程序后尝试写入 SQLite 数据库时,我也偶然发现了文件系统权限。

正如这个线程中提到的,数据文件可以放在用户的 AppData 文件夹中,而不是在 Program Files 等中修改权限。 AppData 还设置了默认允许写入的用户权限。

在设置项目中,这是通过将“用户的应用程序数据文件夹”添加到设置文件系统中来完成的,在该文件系统下可以创建应用程序文件夹。然后将数据库文件添加到此应用程序文件夹中。应用程序文件夹和数据库文件将在 AppData 文件夹中的安装过程中创建。

创建指向AppData-folder的数据库连接字符串的代码如下:

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

我将此解决方案与 Visual Studio 2019 一起使用。

【讨论】:

【参考方案3】:

我将要复制的文件夹放在安装向导的“应用程序文件夹”部分的文件夹中,该文件夹位于 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

希望这会有所帮助。

【讨论】:

【参考方案4】:

将默认位置更改为: C:[制造商][产品名称] 您可以使用您喜欢的任何驱动器更改驱动器 C。 See this picture

【讨论】:

【参考方案5】:

如上所述,用户组在 Program Files 中没有写入权限。 如果您不想处理安装程序类或 Wix(如果它是一个简单程序),则更愿意将您的软件安装在 Windows 卷下。

我说的是 Visual Studio 安装向导: 更改应用程序文件夹“DefaultLocation”属性 从目标计算机上文件系统中的 [ProgramFilesFolder] 到 [WindowsVolume][Manufacturer][ProductName]。

【讨论】:

【参考方案6】:

我想我的另一篇文章因为过于笼统而被删除,所以我在下面对其进行了改进:

要做的是进行自定义操作。这非常简单,请查看 MSDN 演练以编写 C# 自定义操作 here。您将更改权限的代码放在 Install 方法中:

按照链接中的前几个步骤获取安装程序解决方案引用的新安装程序项目。您必须这样做,这样您才能构建一个在安装结束时调用的 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]"

【讨论】:

+1,除了我必须在覆盖方法的末尾添加base.Install(stateSaver); ACK for info [from your post] “我能得到的最接近的是为经过身份验证的用户设置”。有一个 BuiltinUsersSid 代表 Users 集合。 我必须添加更多权限才能使其正常工作。我在这里使用了代码示例中发布的权利***.com/a/4392394/433718 原始帖子中的 MSDN 链接损坏(至 C# 自定义操作演练)。我相信这是正确的链接:msdn.microsoft.com/en-us/library/vstudio/d9k65z2d(v=vs.100).aspx 正如我最近发现的那样,文档似乎建议将 base.Install(stateServer) 放在覆盖方法的开头,而不是结尾。听起来这会使您的依赖项首先安装(有意义)。来自文档:“如果您在派生类中重写 Install 方法,请务必在派生方法中首先调用基类的 Install 方法。Install 方法调用此实例的 Installers 属性中包含的每个安装程序的 Install 方法。 "来源:msdn.microsoft.com/en-us/library/…【参考方案7】:
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 文件夹中保存和访问多个文件,则设置继承部分也很重要。

【讨论】:

【参考方案8】:

默认情况下,用户组在程序文件等每台机器的位置没有写入权限。这是与安装无关的 Windows 标准。但是,在安装过程中,您可以设置所需的任何权限。

Windows Installer 确实支持自定义权限,但 Visual Studio 不提供设置它们的方法。因此,Visual Studio 中唯一的解决方案是自定义操作。

很遗憾,Visual Studio 不支持附加的自定义操作。因此,使用XCACLS.EXE 设置权限只有在您将其包含在您的包中时才有效(它将与您的文件一起安装在目标机器上)。

更简洁但更复杂的解决方案是自己编写自定义操作(使用自定义代码)来设置所需的权限。

最快和最简洁的解决方案是使用不同的设置创作工具,该工具提供对权限的更多控制。

【讨论】:

【参考方案9】:

行为是设计使然。这些程序不应该修改自己(因此它们的安装目录),但更新除外(这同样可以使用 Windows 安装程序完成,没有问题)。如果您使用 .NET,isolated storage 是存储用户数据的绝佳位置。

【讨论】:

以上是关于如何在使用 .NET 安装期间授予对文件夹的读/写权限的主要内容,如果未能解决你的问题,请参考以下文章

拖动跟踪期间的读/写访问、POSIX 权限和沙箱

设置 Mongodb 文件夹的读/写权限

不间断的读/写调用

在vagrant homestead上配置php.ini

对所有 Android 版本的“文档”文件夹的读/写访问权限?

如何使用Emacs更改文件的读/写模式?