c# - 无法在 C#/.NET 中导出 HKLM 注册表项
问题描述
我需要将 HKLM 配置单元中的注册表项导出到文件中。这是一个键,我在同一个程序中成功创建了几行。我正在使用 Process 对象让我的 C# 程序执行 shell 命令:
cmd.exe /c regedit.exe /e C:\temp\CDPRegExport.txt HKEY_LOCAL_MACHINE\SOFTWARE\NPTMigration
如果我执行我的程序,则不会创建文件C:\temp\CDPRegExport.txt 。但是,如果我直接运行上面的命令(在同一个管理控制台窗口中)它工作正常!
我尝试添加应用程序清单以确保我的 .NET 程序以管理员身份运行。
我尝试调用 reg.exe export 而不是 regedit.exe /e 但结果是一样的(我猜这两个程序最终使用的是同一个 DLL)。
这是主要的注册表导出方法:
static bool RegistryExport(string regKey, string destFile)
{
Cmd cmd = new Cmd()
{
CreateNoWindow = true
};
cmd.Exec(@"regedit.exe", @"/e", destFile, regKey);
Console.WriteLine("Standard Out:\r\n" + cmd.StandardOut);
Console.WriteLine("Standard Error:\r\n" + cmd.StandardErr);
if (!File.Exists(destFile))
{
AppContext.log.Critical(@"Registry export file ({0}) not found!", destFile);
return false;
}
return true;
}
...这里是 Cmd.Exe():
public void Exec(string command, params string[] Parameters)
{
string fullyQualifiedCommand = @"/c " + command + GetParameters(Parameters);
Console.WriteLine(fullyQualifiedCommand);
try
{
psi = new ProcessStartInfo(@"cmd", fullyQualifiedCommand)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
};
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
using (Process process = new Process())
{
process.StartInfo = psi;
process.Start();
if (RedirectIOStreams)
{
StandardOut = process.StandardOutput.ReadToEnd();
StandardErr = process.StandardError.ReadToEnd();
}
process.WaitForExit();
}
NormalExit = true;
}
catch (Exception ex)
{
StandardOut = string.Empty;
StandardErr = ex.ToString();
}
}
private static string GetParameters(string[] Parameters)
{
string expression = string.Empty;
if (Parameters.Length == 0)
return string.Empty;
for (int index=0; index<Parameters.Length; index++)
{
if (Parameters[index].Contains(" "))
expression += " \"" + Parameters[index] + "\"";
else
expression += " " + Parameters[index];
}
return expression;
}
当程序使用 regedit.exe 时,标准输出和标准错误都是空白的。
但是,当它使用reg.exe导出时,标准错误显示:“错误:系统无法找到指定的注册表项或值。”
同样,这很奇怪,因为如果我直接通过命令窗口调用完全相同的reg.exe 或 regedit.exe 语法,它就可以正常工作!
解决方案
如果 64 位操作系统上的 32 位进程,则必须禁用 WOW64 文件系统重定向
这个测试对我有用(Windows 10,VS 2015)=>
bool bWow64 = false;
IsWow64Process(Process.GetCurrentProcess().Handle, out bWow64);
if (bWow64)
{
IntPtr OldValue = IntPtr.Zero;
bool bRet = Wow64DisableWow64FsRedirection(out OldValue);
}
string sKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\NPTMigration";
string sFile = @"C:\temp\CDPRegExport.txt";
using (Process process = new Process())
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.FileName = "reg";
psi.Arguments = "export " + "" + sKey + "" + " " + "" + sFile + "";
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
process.StartInfo = psi;
process.Start();
using (StreamReader reader = process.StandardOutput)
{
string sResult = reader.ReadToEnd();
Console.Write(sResult);
}
}
声明:
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool IsWow64Process(IntPtr hProcess, out bool Wow64Process);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool Wow64DisableWow64FsRedirection(out IntPtr OldValue);
推荐阅读
- powershell - 可以修改带有note属性的字符串吗
- docker - flexVolume 无法挂载 SMB 驱动器
- html - 通过 VBA 选择 HTML 菜单项
- ruby - How to deal with a duplicate key from Faker in Ruby
- pandas - Python - 比较两个 csv 文件 - 基于列
- swift - 如何优化快速代码以在可以滚动和缩放的图形中实时绘制大型数据集
- javascript - 如何使用变量访问键/值对?
- javascript - 为制表器中的每一行动态设置列编辑器
- apache-kafka - Quarkus kafka多线程消息消费?
- java - 为什么在平面图中模拟 Mono.empty() 的响应会出错?