You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中可独立使用的SID-所有者映射Dictionary实现咨询

How to Create a Reusable SID-to-Owner Dictionary in C#

Hey there! Let's break down how to build that reusable, cacheable Dictionary for SID-to-Owner mappings you need, while fixing some potential pitfalls in your current code. Your core idea is smart—caching these mappings avoids redundant SID translations, which will definitely save you time.

First, Let's Fix the Key Issue in Your Current Code

Right now, you're collecting all SIDs and Owners in separate arrays, then running Distinct() on both. This is risky because:

  • The order of unique SIDs and unique Owners might not line up (e.g., if two different SIDs map to the same Owner, your Owner_Unique list will be shorter than SID_Unique, breaking the index-based mapping).
  • You're still translating every SID every time you encounter it, even if it's a duplicate—defeating the purpose of caching!

Step 1: Build a Static Cache Dictionary

To make the dictionary reusable and only initialize once, we can create a static dictionary (either inside your Program class or a dedicated utility class). This way, it persists for the lifetime of your app and updates automatically when new SIDs are encountered.

Here's a dedicated utility class you can reuse anywhere in your project:

using System.Security.Principal;
using System.Collections.Generic;

public static class SidOwnerCache
{
    // Static dictionary: only one instance exists, initialized once
    private static readonly Dictionary<SecurityIdentifier, NTAccount> _sidToOwnerMap = new Dictionary<SecurityIdentifier, NTAccount>();

    // Get owner from cache or translate and cache if new
    public static NTAccount GetOwnerForSid(SecurityIdentifier sid)
    {
        // Check if we already have this SID in the cache
        if (_sidToOwnerMap.TryGetValue(sid, out NTAccount owner))
        {
            return owner;
        }

        // If not, translate the SID to NTAccount and add to cache
        NTAccount newOwner = (NTAccount)sid.Translate(typeof(NTAccount));
        _sidToOwnerMap.Add(sid, newOwner);
        return newOwner;
    }

    // Optional: Manually add a mapping if needed
    public static void AddManualMapping(SecurityIdentifier sid, NTAccount owner)
    {
        if (!_sidToOwnerMap.ContainsKey(sid))
        {
            _sidToOwnerMap.Add(sid, owner);
        }
    }

    // Optional: Get all cached mappings
    public static IReadOnlyDictionary<SecurityIdentifier, NTAccount> GetAllMappings()
    {
        return _sidToOwnerMap.AsReadOnly();
    }
}

Step 2: Refactor Your Main Logic to Use the Cache

Now, update your file-traversal code to use this cache. We'll also simplify the file iteration (since you're using Alphaleonis for long paths, let's lean into that to avoid System.IO limitations) and handle potential permissions issues with try/catch blocks.

Here's the revised Main method:

using System;
using System.Diagnostics;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
using Alphaleonis.Win32.Filesystem;

namespace Get_SID_Owner_Info
{
    internal class Program
    {
        private static void Main()
        {
            Console.Write("Please enter the Directory Path -- ");
            string foldr = Console.ReadLine();
            Console.Write("Please enter the result path location e.g. D:\\Folder\\Outfile.csv -- ");
            string outfile = Console.ReadLine();

            // Delete existing output file if it exists
            if (File.Exists(outfile))
            {
                File.Delete(outfile);
            }

            var watch = Stopwatch.StartNew();

            // Use Alphaleonis to get all files (supports long paths)
            using (StreamWriter sw = File.CreateText(outfile))
            {
                sw.WriteLine("SID,Owner Name");

                foreach (string filePath in Directory.EnumerateFiles(foldr, "*", SearchOption.AllDirectories))
                {
                    try
                    {
                        FileInfo fi = new FileInfo(filePath);
                        FileSecurity fs = File.GetAccessControl(fi.FullName);
                        SecurityIdentifier sid = (SecurityIdentifier)fs.GetOwner(typeof(SecurityIdentifier));
                        
                        // Get owner from our cache (no redundant translation!)
                        NTAccount owner = SidOwnerCache.GetOwnerForSid(sid);

                        // Optional: If you want to log every file's SID/Owner, uncomment below
                        // sw.WriteLine($"{sid},{owner}");
                    }
                    catch (UnauthorizedAccessException)
                    {
                        // Skip files we don't have access to
                        Console.WriteLine($"Skipping file: {filePath} (access denied)");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Error processing {filePath}: {ex.Message}");
                    }
                }

                // Write all unique SID-Owner mappings from the cache to the CSV
                foreach (var entry in SidOwnerCache.GetAllMappings())
                {
                    sw.WriteLine($"{entry.Key},{entry.Value}");
                }
            }

            watch.Stop();
            Console.WriteLine($"Execution Time: {watch.ElapsedMilliseconds} ms");
            Console.WriteLine($"Cached {SidOwnerCache.GetAllMappings().Count} unique SID-Owner pairs");
            Console.ReadKey();
        }
    }
}

Why This Works Better

  • No redundant translations: Every SID is only translated once, even if it appears in 1000 files.
  • Guaranteed mapping accuracy: The dictionary directly links each SID to its correct Owner, so no mismatched indexes.
  • Reusable: The SidOwnerCache class can be imported and used in any other part of your project without reinitializing the dictionary.
  • Cleaner code: We merged your two file-traversal loops into one and added error handling to prevent crashes from inaccessible files.

Making the Dictionary Truly Independent

By putting the cache in a separate SidOwnerCache static class, you can use it anywhere in your solution—just reference the class and call SidOwnerCache.GetOwnerForSid(sid). The dictionary stays alive for the entire app session, and new mappings are added automatically when you encounter a new SID.

内容的提问来源于stack exchange,提问作者Vishwas Joshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:11:57