如何通过PowerShell获取EFS加密文件所有者?求.NET替代方案
获取EFS加密文件所有者的PowerShell与.NET方案
一、优化PowerShell解析cipher.exe /c输出
直接调用cipher.exe /c后,可通过正则匹配批量提取所有者信息,替代手动查看:
$targetPath = "C:\Path\To\Your\EncryptedFile.txt" # 跳过cipher输出的前4行表头内容 $cipherOutput = cipher.exe /c $targetPath | Select-Object -Skip 4 foreach ($line in $cipherOutput) { if ($line -match "^.*?Owner:\s+(.*)$") { $owner = $matches[1].Trim() Write-Host "EFS所有者: $owner" } }
二、.NET方案:通过P/Invoke调用Win32 API
.NET无原生类直接暴露EFS所有者信息,但可调用Windows系统APIQueryUsersOnEncryptedFile实现:
using System; using System.Runtime.InteropServices; using System.Text; public class EfsHelper { [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool QueryUsersOnEncryptedFile( string lpFileName, ref uint lpdwUsers, IntPtr lpUserSidList, ref uint lpdwSidListSize, IntPtr lpUserDisplayNameList, ref uint lpdwDisplayNameListSize); [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool ConvertSidToStringSid(IntPtr pSid, out IntPtr lpString); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr LocalFree(IntPtr hMem); public static string GetEfsOwner(string filePath) { uint userCount = 0; uint sidListSize = 0; uint displayNameSize = 0; // 首次调用获取所需缓冲区大小 QueryUsersOnEncryptedFile(filePath, ref userCount, IntPtr.Zero, ref sidListSize, IntPtr.Zero, ref displayNameSize); IntPtr sidList = Marshal.AllocHGlobal((int)sidListSize); IntPtr displayNameList = Marshal.AllocHGlobal((int)displayNameSize); try { if (QueryUsersOnEncryptedFile(filePath, ref userCount, sidList, ref sidListSize, displayNameList, ref displayNameSize)) { // 第一个SID对应文件所有者 IntPtr firstSid = Marshal.ReadIntPtr(sidList); if (ConvertSidToStringSid(firstSid, out IntPtr sidString)) { string sid = Marshal.PtrToStringUni(sidString); LocalFree(sidString); return sid; } } throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); } finally { Marshal.FreeHGlobal(sidList); Marshal.FreeHGlobal(displayNameList); } } }
在PowerShell中直接加载该类并使用:
Add-Type -TypeDefinition @" // 粘贴上述C#代码 "@ $ownerSid = [EfsHelper]::GetEfsOwner("C:\Path\To\Your\EncryptedFile.txt") Write-Host "EFS所有者SID: $ownerSid" # 可选:将SID转换为可读用户名 $account = New-Object System.Security.Principal.SecurityIdentifier($ownerSid) $ownerName = $account.Translate([System.Security.Principal.NTAccount]).Value Write-Host "EFS所有者用户名: $ownerName"
三、补充方案:WMI/CIM查询(卷级场景适用)
若需结合卷级加密信息,可通过Win32_EncryptableVolume类间接关联,但更适合批量卷管理,文件级场景优先使用前两种方案:
$filePath = "C:\Path\To\Your\EncryptedFile.txt" $volume = Get-CimInstance -ClassName Win32_EncryptableVolume -Filter "DriveLetter='$((Get-Item $filePath).PSDrive.Name):'" # 可结合其他WMI类进一步提取EFS用户信息
内容的提问来源于stack exchange,提问作者Zaver
相关产品推荐
相关产品推荐

