1

我正在尝试使用简单的代码调用应用程序,例如

public void Run(string command)
{
    Process proc = new Process();
    proc.StartInfo.FileName = "acvTemp.exe";
    proc.StartInfo.Arguments = command;             

    proc.Start();

    proc.WaitForExit();
}

我正在启动的 fileName 进程实际上会生成一个新窗口。它使用一些使其无法退出的命令启动。IE

command = acvtest.exe /launch /wait /log:<temp.log>

所以 acvtest.exe 开始在机器上运行,实际上仍在运行,所以我可以运行其他命令,如

acvtest.exe /getid:<name>

这就是我将手动使用该应用程序的方式。

acvtest.exe /launch /wait /log:<temp.log>
acvtest.exe /getid:<name>

注意实际的 /launch 进程返回到 shell 命令提示符,因为 /launch 会打开一个新的命令窗口,并且 /getid 的输出实际上会写入日志。

我的问题是,当第一个 /launch 或 /getid 命令运行时,waitforexit() 似乎在日志上释放句柄之前就退出了。(可能在某些子线程退出之前?)

即以下命令失败,直到我在两者之间放置一些睡眠或等待。即使使用 waitforexit()

 Run("/launch /wait /log:<temp.log>");
 Run("/getid:<name>");
 Run("shutdown");

 //Needs some sleep or wait here

 using (StreamReader reader = new StreamReader("temp.log"))
 {
     Console.WriteLine(reader.ReadToEnd());
 }

在上述两个部分之间没有任何睡眠或等待,访问日志将失败,并显示它已被另一个进程使用。看起来应用程序甚至在它实际完成其进程之前就退出了。这是应用程序的问题吗?我能做些什么来解决它?

我怀疑我可能需要一些不同的 Run() 代码,因为启动了一个新的 shell。

[更新]

问题不仅在于日志文件。当我在说大约 100,000 个文件名上运行 Run("/getid:") 时,其中许多都因“资源不可用”错误而失败,这就是为什么我认为应用程序可能在释放其资源之前就退出了看着。

4

3 回答 3

0

我想您可以尝试使用以下代码以只读方式打开文件

FileStream fs = File.Open("temp.log", FileMode.Open, FileAccess.Read);

或者你使用一些像这样的代码:

try
{
    // some code here ...

    // Try to access the file within 1000 (or whatever is specified) ms.
    FileAccessHelper.WaitForFileAccessibility("test.log", 1000);

    // and here ...
}
catch (FileAccessHelperException e)
{
    // your error handling here...
    Console.WriteLine("Unable to open the file within 1000ms");
}

FileAccessHelper 类如下所示:

namespace CodingFun
{
    using System;
    using System.IO;
    using System.Threading;

    /// <summary>
    /// Represents our FileAccessHelper class.
    /// </summary>
    public static class FileAccessHelper
    {
        /// <summary>
        /// Blocks until the specified file can be accessed or a timeout occurs.
        /// </summary>
        /// <param name="filename">The file which shall be accessed.</param>
        /// <param name="timeout">The timeout in milliseconds.</param>
        /// <param name="accessMode">Specifies the file access mode, default is read only.</param>
        public static void WaitForFileAccessibility(string filename, int timeout, FileAccess accessMode = FileAccess.Read)
        {
            int tries = 0;
            bool readDone = false;

            do
            {
                try
                {
                    // Try to open the file as read only.
                    FileStream fs = File.Open(filename, FileMode.Open, accessMode);

                    // Close it if it worked and...
                    fs.Close();

                    // ... set a flag so that we know we have successfully opened the file.
                    readDone = true;
                }
                catch (Exception e)
                {
                    // increase the counter and...
                    tries++;

                    // ... check if a timeout occured.
                    if ((100 * tries) >= timeout)
                    {
                        throw new FileAccessHelperException(string.Format("Unable to access the file {0} within the specified timeout of {1}ms", filename, timeout), e);
                    }
                    else
                    {
                        // If not just sleep 100 ms.
                        Thread.Sleep(100);
                    }
                }
            }
            while (!readDone);
        }
    }
}

FileAccessHelperException 类如下所示:

namespace CodingFun
{
    using System;
    using System.Runtime.Serialization;
    using System.Security;

    /// <summary>
    /// Represents the FileAccessHelperException class.
    /// </summary>
    public class FileAccessHelperException : Exception
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="FileAccessHelperException"/> class.
        /// </summary>
        public FileAccessHelperException()
            : base()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FileAccessHelperException"/> class.
        /// </summary>
        /// <param name="message">The message that describes the error.</param>
        public FileAccessHelperException(string message)
            : base(message)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FileAccessHelperException"/>
        /// class with a specified error message and a reference to the inner
        /// exception that is the cause of this exception.
        /// </summary>
        /// <param name="message">The error message that explains the reason for the exception.</param>
        /// <param name="innerException">
        /// The exception that is the cause of the current exception, or a null reference
        /// if no inner exception is specified.
        /// </param>
        public FileAccessHelperException(string message, Exception innerException)
            : base(message, innerException)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FileAccessHelperException"/> class with serialized data.
        /// </summary>
        /// <param name="info">
        /// The System.Runtime.Serialization.SerializationInfo that holds the serialized
        /// object data about the exception being thrown.
        /// </param>
        /// <param name="context">
        /// The System.Runtime.Serialization.StreamingContext that contains contextual
        /// information about the source or destination.
        /// </param>
        /// <exception cref="System.ArgumentNullException">
        /// The info parameter is null.
        /// </exception>
        /// <exception cref="System.Runtime.Serialization.SerializationException">
        /// The class name is null or System.Exception.HResult is zero (0).
        /// </exception>
        [SecuritySafeCritical]
        protected FileAccessHelperException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
    }
}

我希望这会有所帮助;-)

于 2013-10-25T23:18:09.283 回答
0

这里提出了文件锁定问题的一种解决方案。然后,您可以提取感兴趣的进程的 PID。

再说一次,如果日志文件在进程退出之前一直保持打开状态,那么您的“信号量”就在那里。

于 2013-10-25T22:44:31.190 回答
0

这是应用程序的问题吗?我能做些什么来解决它?

我会说应用程序可能根本没有问题。很可能该文件根本没有被操作系统本身完全释放。

一种常见的解决方法是将读取文件的尝试包装在 Try/Catch 块中,然后将其包含在带有延迟的 while 循环中,或者从 Timer 调用该代码。

于 2013-10-25T22:37:41.757 回答