是否可以从另一个应用程序检查空闲应用程序?

时间:2018-05-15 08:24:25

标签: c#

我有几个已经发布的程序。我想创建新程序来读取已发布的正在运行的程序 - 它们是否空闲约5分钟。如果他们处于闲置状态,我想终止他们。

IDLE表示用户不在该程序中使用鼠标和键盘或没有进程。

例如,这些是我发布的几个程序:

  • pgrA.exe - 正在运行 - 闲置3分钟
  • pgrB.exe - 已停止
  • pgrC.exe - 正在运行 - 闲置7分钟
  • pgrD.exe - 正在运行 - 不闲置
  • pgrE.exe - 正在运行 - 闲置11分钟

终止空闲程序的程序(在单台PC上):

  • IdleReader.exe(将终止pgrC.exe和pgrE.exe)

全部在1台PC上运行。

这个新程序的一些代码终止空闲程序:

private void refresh_PrgList()
    {

        using (var con = new SqlConnection(ConfigurationManager.AppSettings["ConnectionStr"]))
        using (var cmd = con.CreateCommand())
        {
            con.Open();
            cmd.CommandText = "select ProgramID, ProgramName from MKTPrograms";
            var reader = cmd.ExecuteReader();
            var yy = false;
            dgvPrgList.Rows.Clear();
            while (reader.Read())
            {
                yy = false;
                foreach (var xx in Process.GetProcesses())
                    if (xx.ProcessName.Replace(".exe", string.Empty).ToUpper() == reader[0].ToString().Replace(" ", string.Empty).ToUpper())
                    {
                        //----- I want to Detect the Idle Program here -----//

                        //--------------------------------------------------//
                        dgvPrgList.Rows.Add(new object[] { reader[0].ToString(), reader[0].ToString(), "Running", xx.StartTime, System.DateTime.Now - xx.StartTime });
                        yy = true;
                    }
                if (yy == false)
                    dgvPrgList.Rows.Add(new object[] { reader[0].ToString(), reader[1].ToString(), "Stopped", "" });
            }

            for (int x = 1 ; x < dgvPrgList.Columns.Count ; x++ )
            {
                dgvPrgList.Columns[x-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
            }
        }
    }

谢谢,

1 个答案:

答案 0 :(得分:1)

当然,有很多方法可以做到这一点。

查看处理时间(UserProcessorTime,TotalProcessorTime),存储并比较它。经过一段时间后你会对“空闲”感觉良好。

然后只需在System.Diagnostics.Process类上调用Kill即可终止它。

在.net中可以做到:

var processName= "yourApp";
if (Process.GetProcessesByName(processName) == null)
    Assert.Inconclusive("Skipped: {processName} is not running");

上面的代码是一个单元测试,它可以用来获取特定的进程,你可以在资源监视器中找到你要查找的名称: Resource Monitor

要查看是否安装了某个应用程序,可以对该应用程序的调用进行symulate,您可以这样做:

/// <summary>
/// Determines whether the specified application executable is installed.
/// </summary>
/// <param name="name">The command line name.</param>
/// <returns><c>true</c> if the specified name is installed; otherwise, <c>false</c>.</returns>
public static bool IsInstalled(string name)
{
    using (var key = Registry.ClassesRoot.OpenSubKey($"{name}\\shell\\open\\command"))
        return key != null;
}

通过查看主窗口,可以检查应用程序是否具有正确的状态。你通过如前所示的过程来做到这一点 我该怎么做才能看到应用程序是否已启动但用户仍在登录时是:

if (MyAppProcess.MainWindowTitle.Contains("Login"))
    return true;

我用:

if (!TCP.IsListing(login.ServerName, login.Port))
                    Assert.Inconclusive($"Skipped: TWS not accepting connection port {login.Port}");

看一个方法是否在没有实际创建连接的情况下接受连接,当你只是打开套接字端口时,没有所有应用程序都喜欢它,有些崩溃,有些损坏....

下面列出的代码只能在本地运行,你不能这样做远程。我使用主机,因为我的服务器有超过1个IP并且无法监听将导致我的应用程序启动回退实例并更新DNS服务器。无需为所有多插槽多核服务器提供企业许可即可轻松创建应用程序故障转移群集; - )

public static bool IsListing(string hostUri, int portNumber, int millisecondTimeOut=500)
{
    try
    {
        var info = new ProcessStartInfo() {
            Arguments = "-a -p TCP",
            CreateNoWindow=false,
            FileName="netstat",
            WindowStyle= ProcessWindowStyle.Hidden,
            UseShellExecute = false,
            RedirectStandardOutput = true
        };
        using (var p = Process.Start(info))
        using (StreamReader reader = p.StandardOutput)
        {
            while (!reader.EndOfStream)
            {
                var line = reader.ReadLine();
                if (line.Contains($":{portNumber}"))
                {
                    return true;
                }
            }

        }
        return false;

    }
    catch (SocketException)
    {
        return false;
    }

}

您可以查看是否可以使用ping访问主机(远程或本地), 您可以使用以下方式执行此操作:

public static async Task<bool> IsOnline(string hostUri)
{
    try
    {
        object token = Guid.NewGuid().ToString();
        using (var p = new Ping())
        {
            var result= await p.SendPingAsync(hostNameOrAddress: hostUri, timeout: 1000);
            return result.Status == IPStatus.Success;
        }
    }
    catch (Exception)
    {                
        return false;
    }
}

您是否想要测试别的东西?让我知道

沃尔特