如何通过 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 权限?的主要内容,如果未能解决你的问题,请参考以下文章