进程正在退出,但实际上尚未完成
本文关键字:实际上 未完成 退出 进程 | 更新日期: 2023-09-27 18:36:53
我正在尝试使用简单的代码调用应用程序,例如
public void Run(string command)
{
Process proc = new Process();
proc.StartInfo.FileName = "acvTemp.exe";
proc.StartInfo.Arguments = command;
proc.Start();
proc.WaitForExit();
}
我正在启动的文件名进程实际上会生成一个新窗口。它使用一些命令启动,使其无法退出。即
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:") 时,其中许多文件名因"资源不可用"错误而失败,这就是为什么我认为应用程序甚至在释放其资源之前就可能退出的原因谢谢你的关注。
这是应用程序的问题吗?我能做的任何事情都可以工作 周围?
我会说该应用程序可能根本没有问题。 很可能该文件根本没有完全由操作系统本身发布。
一种常见的解决方法是将读取文件的尝试包装在 Try/Catch 块中,并将其包含在带有延迟的 while 循环中,或者从计时器调用该代码。
这里提出了文件锁定问题的一种解决方案。然后,您可以提取感兴趣过程的 PID。
再说一次,如果日志文件保持打开状态,直到进程退出,则那里有您的"信号量"。
您可以尝试使用以下代码以只读方式打开文件
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");
}
类如下所示:
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)
{
}
}
}
我希望这有帮助;-)