问题遇到的现象和发生背景
最近在做一个纯HWID的激活项目:https://github.com/MIAIONE/SPPClient
其中KeyManager.cs重写了部分slmgr.vbs,就是通过WMI直接实现了,因为cscript获取输出和执行process类都不太好控制
其中我重写了slmgr中循环遍历文件夹来安装xrm-ms的代码
系统环境:WIN11,VS2022,.NET6 SDK
问题相关代码,请勿粘贴截图
slmgr源实现方法代码:
Private Sub InstallLicenseFiles (strParentDirectory, fso)
Dim file, files, folder, subFolder
Set folder = fso.GetFolder(strParentDirectory)
Set files = folder.Files
' Install all license files in folder
For Each file In files
If Right(file.Name, 7) = ".xrm-ms" Then
InstallLicense strParentDirectory & "\" & file.Name
End If
Next
For Each subFolder in folder.SubFolders
InstallLicenseFiles subFolder, fso
Next
End Sub
Private Sub ReinstallLicenses()
Dim shell, fso, strOemFolder
Dim strSppTokensFolder, folder, subFolder
Set shell = WScript.CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
strOemFolder = shell.ExpandEnvironmentStrings("%SystemRoot%") & "\system32\oem"
strSppTokensFolder = shell.ExpandEnvironmentStrings("%SystemRoot%") & "\system32\spp\tokens"
LineOut GetResource("L_MsgReinstallingLicenses")
Set folder = fso.GetFolder(strSppTokensFolder)
For Each subFolder in folder.SubFolders
InstallLicenseFiles subFolder, fso
Next
If (fso.FolderExists(strOemFolder)) Then
InstallLicenseFiles strOemFolder, fso
End If
LineOut GetResource("L_MsgLicensesReinstalled")
End Sub
C#实现(核心遍历文件的代码):
private static List<string> GetAllXrmMSFiles(string rootPath)
{
return Directory.EnumerateFiles(rootPath, "*.xrm-ms", SearchOption.AllDirectories).ToList();
}
运行结果及报错内容
注意这两个目录:
strOemFolder = shell.ExpandEnvironmentStrings("%SystemRoot%") & "\system32\oem"
strSppTokensFolder = shell.ExpandEnvironmentStrings("%SystemRoot%") & "\system32\spp\tokens"
oem基本上不是品牌机不会有,spp\tokens肯定会有
有人试过了,WIN10可以通过管理员CMD 用xcopy复制出来strSppTokensFolder
WIN11资源管理器也可以右键复制出来,只不过要先改文件夹安全设置
C#既然遍历不出来,强制直接new 一个已知存在的路径,用NSUDO用SYSTEM账户+所有权限开启+C#提前添加账户获得完全控制试过了
但是,都直接报 NotFoundDirectory
错误信息:
Unhandled exception. System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Windows\System32\spp\tokens\issuance'.
at System.IO.Enumeration.FileSystemEnumerator1.CreateDirectoryHandle(String path, Boolean ignoreNotFound) at System.IO.Enumeration.FileSystemEnumerator
1.Init()
at System.IO.Enumeration.FileSystemEnumerator1..ctor(String directory, Boolean isNormalized, EnumerationOptions options) at System.IO.Enumeration.FileSystemEnumerable
1..ctor(String directory, FindTransform transform, EnumerationOptions options, Boolean isNormalized)
at System.IO.Enumeration.FileSystemEnumerableFactory.FileInfos(String directory, String expression, EnumerationOptions options, Boolean isNormalized)
at System.IO.DirectoryInfo.InternalEnumerateInfos(String path, String searchPattern, SearchTarget searchTarget, EnumerationOptions options)
at System.IO.DirectoryInfo.GetFiles(String searchPattern, EnumerationOptions enumerationOptions)
at System.IO.DirectoryInfo.GetFiles()
at SPPClient.Program.Main(String[] args) in D:.NET_6\SPPClient\Program.cs:line 384
而且不是完全遍历不了,里面C:\Windows\System32\spp\tokens\skus\csvlk-pack是可以的,但就只有这一个文件夹和pkeyconfig、legacy可以,其他文件夹当不存在就跳过去了
我的解答思路和尝试过的方法
我用了NSUDO的API和DM模式,这个DM模式我试过,连 System Volume Information 都能遍历,今天却不灵了
首先上面简写自动递归的方法是很好用的,我已经试过手写递归方法了,不行
而且根据这位老哥https://www.cnblogs.com/OpenCoder/p/10482974.html
我想要达到的结果
其实最终目的就是读取所有xrm-ms里面的内容,也就是说,复制出来再读取也可以,我想在C#里完全实现,直接用slmgr肯定是不行的,这样没有事件驱动,看异常应该可以通过直接引用win32api,如果有纯C#解决办法就更好了