我正在实现一个屏幕保护程序来重新启动后台应用程序。我需要重新启动 Firefox 以重置 Windows kiosk 中的主页。我想用屏幕保护程序来做到这一点。我使用的语言是C#。
复制和粘贴的
代码并不复杂,是从http://msdn.microsoft.com/en-us/library/windows/desktop/ms686421(v=vs.85).aspx
和
http://www.harding.edu/fmccown/screensaver/screensaver.html
它应该以这种方式工作:屏幕保护程序启动,然后 10 秒后。杀死应用程序(如果存在),然后 10 秒后。它再次重新启动应用程序。所有屏幕保护程序退出后(有一个计时器驱动它)。
问题是,屏幕保护程序启动的进程有一种到被杀死的屏幕保护程序的链接,因为直到用户不终止应用程序,屏幕保护程序才重新启动!
我使用此函数来重新启动应用程序:
public static void StartAProcess(string executableName)
{
//Process.Start(new ProcessStartInfo(executableName));
RunThread ext = new RunThread();
Thread t = new Thread(new ParameterizedThreadStart(ext.OpenProcess));
t.Start(executableName.ToString());
}
public class RunThread
{
public void OpenProcess(object executableName)
{
ProcessStartInfo si = new ProcessStartInfo();
si.UseShellExecute = true;
si.FileName = (string) executableName;
Process proc = Process.Start(si);
---> if (null != proc)
proc.WaitForExit(); // Block until exit**
}
}
根据操作系统和 WaitForExit 指令,行为有所不同:
- 使用 WaitForExit:在 7、Vista 和 XP 上,启动应用程序后,屏幕保护程序不会重新启动;
- 没有 WaitForExit:在 Vista/7 上,同样的道理,在 Windows XP 上,当屏幕保护程序退出时,它也会杀死应用程序!
I'm implementing a screensaver to restart a background application. My need is to restart firefox to reset the home page in a windows kiosk. I would like to do this with a Screen Saver. The language I use is C#.
The code is not so complex and is a sort of copy and paste from
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686421(v=vs.85).aspx
and
http://www.harding.edu/fmccown/screensaver/screensaver.html
It should work in this manner: the screensaver starts, then after 10 sec. kills the application (if it exists) and then, after 10 sec. again it restarts the application. After all the screensaver quit (there is a timer that drives this).
The problem is that the process started by the screensaver has a sort of link to the killed screensaver, because until the user doesn't kill the application, the screensaver doesn't restart!
I use this function to restart the application:
public static void StartAProcess(string executableName)
{
//Process.Start(new ProcessStartInfo(executableName));
RunThread ext = new RunThread();
Thread t = new Thread(new ParameterizedThreadStart(ext.OpenProcess));
t.Start(executableName.ToString());
}
public class RunThread
{
public void OpenProcess(object executableName)
{
ProcessStartInfo si = new ProcessStartInfo();
si.UseShellExecute = true;
si.FileName = (string) executableName;
Process proc = Process.Start(si);
---> if (null != proc)
proc.WaitForExit(); // Block until exit**
}
}
The behaviour is different depending on the OS and the WaitForExit instruction:
- with WaitForExit: on Seven, Vista and XP, after the start of the application, the screensaver doesn't restart;
- without WaitForExit: on Vista/Seven the same of prec point, on Windows XP when the screensaver exit it kills the application too!
发布评论
评论(1)
Windows 通过在 作业对象,防止任何启动的进程从作业中“逃逸”。这样,屏幕保护程序就不会在用户不期望的情况下让任何进程继续运行。当屏幕保护程序进程终止 (WinXP) 时,Windows 将终止作业(以及其中启动的所有进程),或者将等到作业对象本身终止(即作业中的每个进程终止)。
目前尚不清楚您为什么要使用屏幕保护程序。我可能会使用启动时运行的程序或服务来执行类似的操作。
无论如何,如果您必须使用屏幕保护程序,则必须找到一种从作业对象外部创建流程的方法。需要考虑的一件事是 Win32_Process 类的 Create 方法。
根据您想要重新启动 Firefox 的指示,听起来您有一个 Internet kiosk 类型的应用程序,您希望在用户离开 kiosk 时重新启动浏览器。在这种情况下,我会推荐完全不同的东西:
创建一个程序来启动 Firefox,等待它退出,然后重新启动它,所有这些都在无限循环中运行。使用某种类似 AutoRuns 的机制运行此程序。
让你的屏幕保护程序直接杀死 Firefox 并退出。当屏幕保护程序激活时,它将终止 Firefox 并退出,导致循环程序重新启动。
Windows protects itself from the behavior you're trying to code by running the screen saver in a job object that prevents any process started from "escaping" from the job. That way the screensaver can't leave any processes running when the user doesn't expect. Windows will either terminate the job (and thus all of the processes started within it) when the screensaver process terminates (WinXP) or it will wait until the the job object itself terminates (i.e. every process in the job terminates).
It's not clear why you're using a screensaver for this. I probably would either use a program that runs on startup or a service to do something like this.
Regardless, if you have to use a screensaver, you have to find a way to create a process from outside your job object. One thing to consider is the Create method of the Win32_Process Class.
Based on your indication that you want to restart Firefox, it sounds like you have an Internet kiosk type of application where you want to restart the browser when the user has left the kiosk. In that case I would recommend something else entirely:
Create a program that starts Firefox, waits for it to exit, then restarts it, all running in an infinite loop. Run this program using some sort of AutoRuns-like mechanism.
Make your screensaver simply kill Firefox and exit. When the screensaver activates, it will kill Firefox and exit, causing the looping program to restart it.