无法在C#/。NET中导出HKLM注册表项

时间:2019-06-15 04:19:25

标签: c# .net registry

我需要将注册表项从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导出而不是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语法,它就可以正常工作!

1 个答案:

答案 0 :(得分:1)

如果在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);