如何通过 C# 应用程序在文件级别授予 Windows 权限?

Posted

技术标签:

【中文标题】如何通过 C# 应用程序在文件级别授予 Windows 权限?【英文标题】:How can I grant windows permissions at the file level via C# app? 【发布时间】:2020-01-03 23:19:08 【问题描述】:

我已经阅读了几篇关于如何通过 c# 应用程序授予文件夹或文件权限的 Stack 帖子和其他文章,但我无法从我的 C# 应用程序中成功完成。

这是我的用例:我的 c# 应用程序通过 AZCopy(一个免费的 Azure Blob 存储实用程序)下载了一堆 CSV 文件。 AZCopy 将下载的文件转储到我在服务器 (Windows Server 2016 Datacenter) 上创建的名为 CSV 的文件夹中。 CSV 文件夹具有完全开放的权限,并设置为让所有子对象继承这些完全开放的权限。然而,当 AZCopy 写入文件时,权限很小,因此下游进程 (MSSQL BULKINSERT) 无法读取它们。

    我使用在服务器上具有 ADMIN 权限的帐户登录服务器。 我运行我的 .NET/C# EXE,它在内部调用 Process.Start(startInfo) 来运行 AZCopy。 AZCopy 从远程 azure blob 存储服务器获取文件,并以最小权限将它们写入我的 CSV 文件夹。 我尝试以管理员身份运行 EXE - 没有任何区别。 CSV 文件始终以最低权限写入。 我尝试在文件写入后授予额外权限。 我尝试将清单文件添加到我的 .NET 项目中,其中包含 <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />。没有区别。 我尝试在文件夹级别而不是文件级别以编程方式授予权限 - 没有成功。 (CSV 文件夹已经拥有完全开放的权限,所以我对这次尝试并不抱太大希望。)

所以这是我在源代码中尝试过的:

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);

它执行没有错误,但不会更改文件的权限。所以我尝试了这个:

DirectoryInfo dInfo = new DirectoryInfo(fullPath);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
dSecurity.AddAccessRule(new FileSystemAccessRule("Everyone",FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit,PropagationFlags.InheritOnly,AccessControlType.Allow));    
dInfo.SetAccessControl(dSecurity);

它再次执行没有错误,但不会更改文件的权限。

然后我在服务器上打开一个命令 shell 并手动运行它:

ICACLS "C:\Toyota\Importer\CSV\84834945.csv" /grant "Everyone":F

效果很好!但我仍然需要在我的 .NET exe 中以编程方式完成它。因此,在 c# 中,我遍历文件并对每个文件运行相同的 ICACLS 命令(再次使用Process.Start(startInfo))。没有错误,它报告成功...但是文件的权限没有改变。

似乎在 .NET 应用程序中尝试此操作时似乎成功,但操作系统忽略了权限更新请求。

我该如何解决这个问题?

【问题讨论】:

AZCopy 完成后,文件上设置了哪些权限确切?哪个用户运行 AZCopy 进程?哪个用户运行下游 BULKINSERT 流程?可以协调这些用户帐户吗? 【参考方案1】:

我找到了解决办法。

在 AZCopy 下载之后和 BULKINSERT 之前,我正在这样做:

public static void FormatCSV(string csvFilePath) 
 bool foundFooter = false;
 string tempFilePath = Path.GetTempFileName();

 using(var sr = new StreamReader(csvFilePath)) 
  using(var sw = new StreamWriter(tempFilePath)) 
   string line;
   bool isFirstLine = true;

   while ((line = sr.ReadLine()) != null) 
    if (!isFirstLine && !line.StartsWith("F|")) 
     sw.WriteLine(line);
     else if (line.StartsWith("F|")) 
     foundFooter = true;
     break; // we're now on the footer line, so don't go any further - sometimes the footer line has another blank line after it
    

    isFirstLine = false;
   
  
 

 if (foundFooter) 
  // the file did NOT previously have its header and footer removed, but that has been done just now, so go ahead and save the modified file
  File.Delete(csvFilePath);
  File.Move(tempFilePath, csvFilePath);
  else 
  // the file previously had its header and footer removed, so do not change it
  File.Delete(tempFilePath);
 

 GrantWideOpenFilePermissions(csvFilePath);

在那里的某个地方,文件权限被删除了。所以我在此之后重新应用权限:

public static void GrantWideOpenFilePermissions(string fullPath) 
   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);

谜团解开了。很抱歉因程序员错误而打扰大家,但这可能会对遇到类似问题的人有所帮助。

【讨论】:

以上是关于如何通过 C# 应用程序在文件级别授予 Windows 权限?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中为 IIS 用户授予文件夹权限?

MySQL的安全设置

如何授予用户级别访问私有 GitLab 存储库的权限?

在 C# 中设置文件的 UAC 设置

如何使用c#在winforms中为每个用户授予权限

如何从 C# 授予 Windows 10 中 Pcap 库的权限?