如何将 STDOUT 输出保存到文本文件?

发布于 2024-10-07 12:40:10 字数 3012 浏览 2 评论 0原文

我有一个程序,它利用第三方命令行工具来生成日志。第 3 方将其所有输出生成到 STDOUT,然后用户必须使用 " > test.txt" 命令保存文件。

然而,该程序以某种方式生成一定数量的报告,但不是整个报告。这是使用命令

C:\Test\ftk\ripxp>ripxp.exe -r C:\test\ftk\ntuser.dat -d "C:\System Volume\_rest ore{BB12863B-2C77-46C9-BCDA-1810E52F1089}" -p runmru > C:\test\test05.txt

在命令行控制台上可以工作,在程序上只能部分工作。

错误已缩小归因于参数错误或文件保存错误部分(streamReader)。因此,该错误可能是由于 STDOUT 未正确保存所致,

因此有人可以提供有关代码的建议吗?谢谢

! H. Carvey):

RipXP v.20081001 - CLI RegRipper tool
RipXP [-r Reg hive file] [-p plugin module][-d RP dir][-lgh]
Parse Windows Registry files, using either a single module from the plugins folder.
Then parse all corresponding hive files from the XP Restore Points (extracted from
image) using the same plugin.

-r Reg hive file...Registry hive file to parse
-g ................Guess the hive file (experimental)
-d RP directory....Path to the Restore Point directory
-p plugin module...use only this module
-l ................list all plugins
-h.................Help (print this information)

Ex: C:\>rip -g
C:\>rip -r d:\cases\ntuser.dat -d d:\cases\svi -p userassist

All output goes to STDOUT; use redirection (ie, > or >>) to output to a file.

copyright 2008 H. Carvey

守则:

static void Main(string[] args)
    {
        // Automatically finds folder that starts with _restore
        DirectoryInfo directoryInfo = new DirectoryInfo(@"C:\System Volume\");
        DirectoryInfo restoreFolder = directoryInfo.GetDirectories().FirstOrDefault(d => d.Name.StartsWith("_restore"));

        // Gets the folder name
        String baka = restoreFolder.Name;

        if (restoreFolder == null)
            throw new DirectoryNotFoundException();

            Process process = new Process();
            process.StartInfo.FileName = @"C:\test\ftk\ripxp\ripxp.exe";
            process.StartInfo.Arguments = @"-r C:\test\ftk\ntuser.dat -d C:\System Volume\" + restoreFolder.Name + " -p runmru";
            process.StartInfo.CreateNoWindow = false;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.RedirectStandardError = true;
            process.Start();

            String text = @"-r C:\test\ftk\ntuser.dat -d C:\System Volume\" +restoreFolder.Name  + " -p runmru";
            Console.WriteLine(baka);
            Console.WriteLine(text);

            // Strangely the program only outputs the first section "-r C:\test\ftk\ntuser.dat" argument results.....
            System.IO.StreamReader reader = process.StandardOutput;
            String sRes = reader.ReadToEnd();
            StreamWriter SW;
            SW = File.CreateText(@"C:\test\test01.txt");
            SW.WriteLine(sRes);
            SW.Close();
            Console.WriteLine("File Created Successfully");
            reader.Close();

    }

I have a program which utilizes a 3rd party command line tool to generate logs. The 3rd party generates all its output to the STDOUT which the user must then use the " > test.txt" command to save the file.

However the program somehow generates a certain amount of report generated but not the entire report. This was test by using the command

C:\Test\ftk\ripxp>ripxp.exe -r C:\test\ftk\ntuser.dat -d "C:\System Volume\_rest
ore{BB12863B-2C77-46C9-BCDA-1810E52F1089}" -p runmru > C:\test\test05.txt

on the command line console which works and on the program which works only partially.

The errors were narrowed down to either the arguments error or the file saving error part (streamReader). Therefore the error could be due to the STDOUT not being properly saved.

Therefore may someone please advise on the codes? Thanks!

The Arguments for the 3rd party tool(2008 H. Carvey):

RipXP v.20081001 - CLI RegRipper tool
RipXP [-r Reg hive file] [-p plugin module][-d RP dir][-lgh]
Parse Windows Registry files, using either a single module from the plugins folder.
Then parse all corresponding hive files from the XP Restore Points (extracted from
image) using the same plugin.

-r Reg hive file...Registry hive file to parse
-g ................Guess the hive file (experimental)
-d RP directory....Path to the Restore Point directory
-p plugin module...use only this module
-l ................list all plugins
-h.................Help (print this information)

Ex: C:\>rip -g
C:\>rip -r d:\cases\ntuser.dat -d d:\cases\svi -p userassist

All output goes to STDOUT; use redirection (ie, > or >>) to output to a file.

copyright 2008 H. Carvey

The Codes:

static void Main(string[] args)
    {
        // Automatically finds folder that starts with _restore
        DirectoryInfo directoryInfo = new DirectoryInfo(@"C:\System Volume\");
        DirectoryInfo restoreFolder = directoryInfo.GetDirectories().FirstOrDefault(d => d.Name.StartsWith("_restore"));

        // Gets the folder name
        String baka = restoreFolder.Name;

        if (restoreFolder == null)
            throw new DirectoryNotFoundException();

            Process process = new Process();
            process.StartInfo.FileName = @"C:\test\ftk\ripxp\ripxp.exe";
            process.StartInfo.Arguments = @"-r C:\test\ftk\ntuser.dat -d C:\System Volume\" + restoreFolder.Name + " -p runmru";
            process.StartInfo.CreateNoWindow = false;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.RedirectStandardError = true;
            process.Start();

            String text = @"-r C:\test\ftk\ntuser.dat -d C:\System Volume\" +restoreFolder.Name  + " -p runmru";
            Console.WriteLine(baka);
            Console.WriteLine(text);

            // Strangely the program only outputs the first section "-r C:\test\ftk\ntuser.dat" argument results.....
            System.IO.StreamReader reader = process.StandardOutput;
            String sRes = reader.ReadToEnd();
            StreamWriter SW;
            SW = File.CreateText(@"C:\test\test01.txt");
            SW.WriteLine(sRes);
            SW.Close();
            Console.WriteLine("File Created Successfully");
            reader.Close();

    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ぃ双果 2024-10-14 12:40:10

您是否正在等待子进程完成?看来您太早开始阅读其输出了。可以这样完成:

process.Start();
process.WaitForExit();

此外,您可以在完成之前开始通过委托接收输出。像这样(每行文本都调用委托):

process.OutputDataReceived += delegate(object sender, DataReceivedEventArgs e)
{
    // Store e.Data somewhere.
};

Are you waiting for the child process to finish? It looks like you start reading its output too early. It could be done like this:

process.Start();
process.WaitForExit();

Also, you can start receiving the output via delegates before it finishes. Like this (the delegate is called for each line of text):

process.OutputDataReceived += delegate(object sender, DataReceivedEventArgs e)
{
    // Store e.Data somewhere.
};
初见你 2024-10-14 12:40:10

您可以让 .NET 在进程退出时通知您,然后读取输出。因为,正如 detunized 在他的回答+评论中提到的那样,如果您在 Reader.ReadToEnd() 完成之前调用它,您将无法获得所有输出。如果你想一想,那就很明显了——数据还没有产生,你怎么能指望读者阅读它呢?

通过使用事件,您将不会阻止启动线程的方法,如果您有 GUI 应用程序并且不想在子进程运行时冻结用户界面,这将非常有用。

// tell it to raise events and hook up a callback to when it completes
process.EnableRaisingEvents = true;
process.Exited += process_Exited;
process.Start();

该过程完成后将调用此方法:

void process_Exited(object sender, EventArgs e)
{
    var process = (Process)sender;
    using (var f = File.CreateText(@"..."))
    {
        f.WriteLine(process.StandardOutput.ReadToEnd());
    }
}

You can have .NET inform you when the process has exited and then read the output. Because, as detunized mentioned in his answer+comment, if you call reader.ReadToEnd() before it has completed, you won't get all the output. If you think of it, it's quite obvious - the data hasn't been produced yet, so how can you expect the reader to read it?

By using events you will not block the method that starts the thread which can be quite useful if you have a GUI application and don't want to freeze the user interface while the child process is running.

// tell it to raise events and hook up a callback to when it completes
process.EnableRaisingEvents = true;
process.Exited += process_Exited;
process.Start();

This method will be called when the process has completed:

void process_Exited(object sender, EventArgs e)
{
    var process = (Process)sender;
    using (var f = File.CreateText(@"..."))
    {
        f.WriteLine(process.StandardOutput.ReadToEnd());
    }
}
一梦浮鱼 2024-10-14 12:40:10

System.Console 类有一个 SetOut 方法应该可以满足您的需要。

您应该在程序执行开始时调用Console.SetOut(yourTextWriter)。

只需将其添加到程序的第一行:

Console.SetOut(File.CreateText(locationToSaveLogs));

The System.Console class has a SetOut method that should do what you need.

You should call Console.SetOut(yourTextWriter) at the beginning of your program's execution.

Just add this at the first line of the program:

Console.SetOut(File.CreateText(locationToSaveLogs));
生生漫 2024-10-14 12:40:10

您需要使用 OutputDataReceived 事件。此 MSDN 文章解释了如何完成此操作:

https://msdn.microsoft.com/en-us/library/system.diagnostics.process.outputdatareceived(v=vs .110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2

在处理程序内部使用 StreamWriter 将输出写入文件,如下所示:

    StreamWriter sw = new StreamWriter(sOutputFilePath);
    Process process = new Process();
    process.StartInfo.FileName = "ipconfig.exe";
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
    {
        if (!String.IsNullOrEmpty(e.Data))
        {
            sw.WriteLine(e.Data);
        }
    });

    process.Start();
    process.BeginOutputReadLine();
    process.WaitForExit();
    sw.Close();

You need to use the OutputDataReceived event. This MSDN article explains how this is done:

https://msdn.microsoft.com/en-us/library/system.diagnostics.process.outputdatareceived(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2

Inside of the handler write the output to a file using the StreamWriter like:

    StreamWriter sw = new StreamWriter(sOutputFilePath);
    Process process = new Process();
    process.StartInfo.FileName = "ipconfig.exe";
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
    {
        if (!String.IsNullOrEmpty(e.Data))
        {
            sw.WriteLine(e.Data);
        }
    });

    process.Start();
    process.BeginOutputReadLine();
    process.WaitForExit();
    sw.Close();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文