我试图在zh-CN Windows 10 PC上迭代开始菜单项,但是失败就像标题所说的那样。
有问题的代码:
public static readonly string[] ItemSearchPath = new[]
{
Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu),
Environment.GetFolderPath(Environment.SpecialFolder.StartMenu)
};
public static readonly string[] ItemSearchPattern = new[] {@"*.lnk", @"*.url"};
// ...
foreach (var item in ItemSearchPath.SelectMany(x => ItemSearchPattern.SelectMany(y =>
Directory.GetFiles(x, y, SearchOption.AllDirectories))) /* <- here */ { ... }
堆栈跟踪:
System.UnauthorizedAccessException : Access to the path 'C:\ProgramData\Microsoft\Windows\Start Menu\程序' is denied.
起初我认为这是由于文件权限,因此我提升了Visual Studio并强制程序在app.manifest
中使用管理员权限,但仍然抛出异常。很快我意识到路径实际指向C:\ProgramData\Microsoft\Windows\Start Menu\Programs
。
“运行”对话框也拒绝本地化路径,因此它是打开目录级别的预期行为。但是从Google告诉我的本地化名称只不过是desktop.ini
中的一个关键字,所以在标准方法中获取它而不是“真实”的名称是奇怪的。我只是用错了方法吗?
答案 0 :(得分:0)
在解析系统路径时,总是有机会面对拒绝尝试访问没有所需访问权限的目录/文件的拒绝。
但是,您可以在尝试对该目录/文件进行任何操作之前,检查是否已授予当前用户这些权限。
我在这里使用WindowsIdentity.GetCurrent()检索用户ACL身份,然后使用Directory.GetAccessControl()验证用户权限是否符合至少需要访问的AuthorizationRule路径。
我添加了一个执行测试的方法UserHasDirectoryAccesRight(string DirPath) { }
。
请注意,这是一种通用方法,必须将其调整为特定方法 文化。我已经添加了一个字符串转换
CultureInfo.CurrentCulture
,在目录路径上尝试适应。 根据需要修改此设置。
using System.Security;
using System.Security.Principal;
using System.Security.AccessControl;
string[] ItemSearchPath = new[] {
Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu),
Environment.GetFolderPath(Environment.SpecialFolder.StartMenu)
};
string[] itemSearchPattern = new[] { @"*.lnk", @"*.url" };
List<string> linksList = itemSearchPath.SelectMany(sPath =>
itemSearchPattern.SelectMany(sPatt =>
{
return UserHasDirectoryAccesRight(sPath)
? Directory.GetFiles(
sPath.ToString(CultureInfo.CurrentCulture),
sPatt.ToString(CultureInfo.CurrentCulture),
SearchOption.AllDirectories)
: new string[] { "" };
})).ToList();
private bool UserHasDirectoryAccesRight(string DirPath)
{
WindowsIdentity identity = WindowsIdentity.GetCurrent(false);
AuthorizationRuleCollection dSecurity =
Directory.GetAccessControl(DirPath, AccessControlSections.Access)
.GetAccessRules(true, true, typeof(SecurityIdentifier));
bool hasRight = dSecurity.Cast<AuthorizationRule>()
.Any(x => x.IdentityReference.Value.Equals(identity.Owner.Value));
return hasRight;
}