- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我需要一些方法来监控桌面应用程序并在它死机时重新启动它。
最初我认为最好的方法是从 Windows 服务监视/重启进程,直到我发现自 Vista Windows services should not interact with the desktop
我已经看到几个关于这个问题的问题,但我看到的每个答案都涉及某种微软不鼓励的黑客攻击,并且可能会在未来的操作系统更新中停止工作。
因此,Windows 服务可能不再是一种选择。我可能只需要创建一个不同的桌面/控制台应用程序来执行此操作,但那样做就违背了它的目的。
在您看来,实现这一目标的最优雅方法是什么?
编辑:这既不是恶意软件也不是病毒。需要监控的应用程序是一个将在嵌入式系统上运行的媒体播放器,尽管我试图涵盖所有可能的崩溃场景,我不能冒险让它因意外错误而崩溃(s**t 发生)。这个看门狗只是一种保护措施,以防万一出现其他问题。此外,由于播放器会显示第 3 方 Flash 内容,因此增加的功能包括监控资源使用情况,并在某些糟糕的 Flash 电影开始泄漏内存时重启播放器。
编辑 2:我忘了说,我想监控/重启的应用程序绝对不需要在 LocalSystem 帐户上运行,也根本不需要任何管理权限。实际上,我更喜欢它使用当前登录的用户凭据运行。
最佳答案
我最终实现了@A_nto2 建议的解决方案,它实现了我一直在寻找的东西:我现在有一个 Windows 服务,它监视进程列表,每当它们关闭时,它们会使用事件用户的凭据和 session ,因此 GUI 是可见的。
但是,由于他发布的链接显示的是 VC++ 代码,我将与处理相同问题的任何人分享我的 C# 实现:
public static class ProcessExtensions
{
public enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
[StructLayout(LayoutKind.Sequential)]
public class SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
public enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
[Flags]
public enum CREATE_PROCESS_FLAGS : uint
{
NONE = 0x00000000,
DEBUG_PROCESS = 0x00000001,
DEBUG_ONLY_THIS_PROCESS = 0x00000002,
CREATE_SUSPENDED = 0x00000004,
DETACHED_PROCESS = 0x00000008,
CREATE_NEW_CONSOLE = 0x00000010,
NORMAL_PRIORITY_CLASS = 0x00000020,
IDLE_PRIORITY_CLASS = 0x00000040,
HIGH_PRIORITY_CLASS = 0x00000080,
REALTIME_PRIORITY_CLASS = 0x00000100,
CREATE_NEW_PROCESS_GROUP = 0x00000200,
CREATE_UNICODE_ENVIRONMENT = 0x00000400,
CREATE_SEPARATE_WOW_VDM = 0x00000800,
CREATE_SHARED_WOW_VDM = 0x00001000,
CREATE_FORCEDOS = 0x00002000,
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000,
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000,
INHERIT_PARENT_AFFINITY = 0x00010000,
INHERIT_CALLER_PRIORITY = 0x00020000,
CREATE_PROTECTED_PROCESS = 0x00040000,
EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000,
PROCESS_MODE_BACKGROUND_END = 0x00200000,
CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
CREATE_DEFAULT_ERROR_MODE = 0x04000000,
CREATE_NO_WINDOW = 0x08000000,
PROFILE_USER = 0x10000000,
PROFILE_KERNEL = 0x20000000,
PROFILE_SERVER = 0x40000000,
CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000,
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
public class Kernel32
{
[DllImport("kernel32.dll", EntryPoint = "WTSGetActiveConsoleSessionId")]
public static extern uint WTSGetActiveConsoleSessionId();
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
}
public class WtsApi32
{
[DllImport("Wtsapi32.dll", EntryPoint = "WTSQueryUserToken")]
public static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr phToken);
}
public class AdvApi32
{
public const uint MAXIMUM_ALLOWED = 0x2000000;
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateTokenEx
(
IntPtr hExistingToken,
uint dwDesiredAccess,
SECURITY_ATTRIBUTES lpTokenAttributes,
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
TOKEN_TYPE TokenType,
out IntPtr phNewToken
);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CreateProcessAsUser
(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
SECURITY_ATTRIBUTES lpProcessAttributes,
SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
CREATE_PROCESS_FLAGS dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation
);
}
public class UserEnv
{
[DllImport("userenv.dll", SetLastError = true)]
public static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);
[DllImport("userenv.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment);
}
public static void StartAsActiveUser(this Process process)
{
// Sanity check.
if (process.StartInfo == null)
{
throw new InvalidOperationException("The StartInfo property must be defined");
}
if (string.IsNullOrEmpty(process.StartInfo.FileName))
{
throw new InvalidOperationException("The StartInfo.FileName property must be defined");
}
// Retrieve the active session ID and its related user token.
var sessionId = Kernel32.WTSGetActiveConsoleSessionId();
var userTokenPtr = new IntPtr();
if (!WtsApi32.WTSQueryUserToken(sessionId, out userTokenPtr))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
// Duplicate the user token so that it can be used to create a process.
var duplicateUserTokenPtr = new IntPtr();
if (!AdvApi32.DuplicateTokenEx(userTokenPtr, AdvApi32.MAXIMUM_ALLOWED, null, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TOKEN_TYPE.TokenPrimary, out duplicateUserTokenPtr))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
// Create an environment block for the interactive process.
var environmentPtr = new IntPtr();
if (!UserEnv.CreateEnvironmentBlock(out environmentPtr, duplicateUserTokenPtr, false))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
// Create the process under the target user’s context.
var processFlags = CREATE_PROCESS_FLAGS.NORMAL_PRIORITY_CLASS | CREATE_PROCESS_FLAGS.CREATE_NEW_CONSOLE | CREATE_PROCESS_FLAGS.CREATE_UNICODE_ENVIRONMENT;
var processInfo = new PROCESS_INFORMATION();
var startupInfo = new STARTUPINFO();
startupInfo.cb = Marshal.SizeOf(startupInfo);
if (!AdvApi32.CreateProcessAsUser
(
duplicateUserTokenPtr,
process.StartInfo.FileName,
process.StartInfo.Arguments,
null,
null,
false,
processFlags,
environmentPtr,
null,
ref startupInfo,
out processInfo
))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
// Free used resources.
Kernel32.CloseHandle(processInfo.hProcess);
Kernel32.CloseHandle(processInfo.hThread);
if (userTokenPtr != null)
{
Kernel32.CloseHandle(userTokenPtr);
}
if (duplicateUserTokenPtr != null)
{
Kernel32.CloseHandle(duplicateUserTokenPtr);
}
if (environmentPtr != null)
{
UserEnv.DestroyEnvironmentBlock(environmentPtr);
}
}
}
下面是调用代码的方式:
var process = new Process();
process.StartInfo = new ProcessStartInfo { FileName = @"C:\path-to\target.exe", Arguments = "-arg1 -arg2" };
process.StartAsActiveUser();
希望对您有所帮助!
关于c# - 看门狗桌面应用程序的最佳方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11146381/
ATtiny88初体验(四):看门狗 ATtiny88单片机的看门狗使用内部独立的128KHz时钟源,拥有3种工作模式: Interrupt模式:超时产生中断; Syste
1、前言 假设现在有一个应用场景,需要对文件系统进行监控,发生变化时产生日志,对新增的文件做一些相应的操作。 比如说应用到我们之前的音乐高潮提取器:若当前文件夹下增加了一个音乐文件,监控器就调
我正在尝试编写一个程序,该程序可以检测是否已插入或拔出了耳机,并因此执行了某些操作。我使用的是Ubuntu 14.04,经过一番搜索,我发现耳机/耳机的连接状态已写入此路径下的编解码器文件-/ pro
我是 Python 的新手,我正在尝试实现良好的“文件创建”检测。如果我不放置 time.sleep(x),我的文件将以错误的方式详细说明,因为它们仍在文件夹中“创建”。 (缓冲区不为空)我如何在每次
Linux 上是否有用于以下目的的看门狗工具或库?我想构建一个看门狗可执行文件,它启动 2 个进程并在以下情况下重新启动它们: 进程崩溃 进程变得无响应(例如由于某种原因挂起) 互联网搜索找到了 wa
我正在尝试从 C 向 Raspbian 中的看门狗设备 - /dev/watchdog 提供数据。 问题是无论我如何尝试访问设备总是抛出忙碌或权限被拒绝的错误(因为进程已经在运行并由系统提供.....
嗨,我正在考虑使用 Python 在 Windows XP 上制作一个看门狗应用程序,它将执行以下操作: 在给定时间重新启动 Windows。 启动一个 exe 应用程序。 运行计时器以检查:应用程序
我打算使用 Python 看门狗来处理写入文件的目录,我只对图像文件感兴趣,麻烦的是我不太理解 this page 上的代码.这是我的尝试: from watchdog.observers impor
我正在使用 Watchdog监视网络目录,非递归的,随着时间的推移要创建的特定文件模式。我看到的问题是,虽然它在本地测试时效果很好,但如果我从远程计算机更改受监控的目录,则不会触发事件。 这里是我配置
Watchdog 非常棒,可以让您对特定目录进行递归快照。它甚至可以让您使用名为 DirectorySnapshotDiff 的函数比较快照. 我的程序会实时观察目录的变化,因此需要使用此函数的输出。
我在 threaded 进程环境中长时间运行 boost::regex_match(...) 调用时遇到问题。但它可能是另一个具有相同问题的库(API 调用)。 有没有通用的方法来设置看门狗? 对于非
我正在 Raspberry Pi 上开发一个系统,该系统使用 Web 界面与之交互,并具有自定义 C++ 服务器。这个想法是,您只需插入 Pi,不需要手动启动服务器。虽然这不是问题,但服务器有时会出现
我正在尝试实现一个看门狗,它将 ping 主机,如果它已启动,那么它将让 midori 打开远程页面,如果没有,那么它将打开本地页面。 我已根据此处的代码进行了改编:https://raspberry
我有一个无限期运行的实时数据采集器,每隔几秒通过 HTTP 采集数据并将其放入 MySQL 数据库中。 在我的程序中,我有一个 while True 循环,每当最后生成的时间大于 X 秒时,它就会生成
之前我是在Windows系统上开发OpenCl内核,现在我用的是Linux。在 Windows 上,有一个名为 watchdog 的巧妙功能,如果它持续超过 5 秒(默认情况下),它会自动停止 Ope
我正在使用 Watchdog 来监控目录并使其与 Dropbox 保持同步。 我遇到这样一种情况,每次我从 Dropbox 下载文件时,我都会触发一个上传事件,因为我需要写入 Watchdog 正在监
现在我遇到一个关于 Linux NMI Watchdog 的问题。我想使用 Linux NMI 看门狗来检测和恢复操作系统挂起。因此,我将“nmi_watchdog=1”添加到 grub.cfg 中。
我已经在 Ubuntu 10.04 上使用 Apache2 完成了 Phusion Passenger 设置。每当我重新启动 Apache 服务器时,我都会收到以下错误消息,并且 Rails 应用程序
我有一个运行 Debian 的 Beaglebone Black,我需要一个在后台运行的脚本,它会每隔几秒检查一次系统是否仍在运行。据我了解,BBB 中的看门狗是基于硬件的,独立于操作系统运行,因此即
我正在尝试使用 passenger 和 nginx 运行 rails。 Nginx 不会重定向到我的 Rails 应用程序,而是继续到其默认的 index.html 页面,我得到了这个错误: Unab
我是一名优秀的程序员,十分优秀!