我编写了一个 C# 应用程序,它每 5 分钟截取一次屏幕截图并将其保存到服务器。它是计时器、2 个线程、几个方法(ping srv、检查文件夹、截屏等)。
作为进程(exe)它运行良好,但我需要将它安装为服务。我正在通过 installutil (框架服务安装程序)安装它。
我的问题是,当它作为服务安装时,它不会截图。停止服务时拉出一些。不是正确的分辨率和黑色。
我假设执行代码放错了位置(见 main)。我不知道把它放在哪里,因为我不能有多个主要方法。请帮忙。
主要应用代码:
I've deleted some not important code.
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
//using System.Timers;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.ComponentModel;
using System.Configuration.Install;
namespace LogWriterService
{
static class Program
{
public static int TimeO = 5; // zpoždění časovače v minutách
private static bool Online;
private static bool active = false;
public static String GetIP()
{
// ...
// returns IP like xxx.xxx.xxx.xxx
// ...
}
// Test dostupnosti serveru
public static bool PingTest()
{
// ...
// return true if server is reachable
// ...
}
/*
* Z Windows.Forms _ screenů získá obrazová data, která uloží na
* server jako ../[IP]/[současný_systémový_čas].jpg
*/
public static void ScreenShot() //Bitmap
{
Int64 CurrTime = Int64.Parse(DateTime.Now.ToString("yyyyMMddhhmmss")); //yyyyMMddhhmmss
Rectangle bounds = Rectangle.Empty;
foreach (Screen s in Screen.AllScreens)
bounds = Rectangle.Union(bounds, s.Bounds);
Bitmap screenShotBMP = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb); // PixelFormat.Format32bppArgb
Graphics screenShotGraphics = Graphics.FromImage(screenShotBMP);
screenShotGraphics.CopyFromScreen(bounds.X, bounds.Y,
0, 0, bounds.Size, CopyPixelOperation.SourceCopy);
string path = null; //"D:/TEMP/" + CurrTime + ".jpg"; // GetIP()
// Ukládání obrázků do dočasné složky a přesun, pokud se připojí
if (PingTest() == true)
{
path = "//10.0.0.10/Upload/screen/test/" + GetIP() + "/" + CurrTime + ".jpg";
string path2 = "//10.0.0.10/Upload/screen/test/" + GetIP() + "/";
Online = true;
if (Directory.Exists(path2))
{
MoveCached();
}
else
{
Console.WriteLine("Online slozka neni dostupna.");
}
} else {
Console.WriteLine("Caching .. ");
path = "C:/TEMP/" + CurrTime + ".jpg"; // "C:/TEMP/" + GetIP() + "/" + CurrTime + ".jpg"
string LPath = @"c:\TEMP";
if (!Directory.Exists(LPath))
{
DirectoryInfo di = Directory.CreateDirectory(LPath);
di.Attributes = FileAttributes.Directory | FileAttributes.Hidden;
Console.WriteLine("Lokalni slozka neexistuje. Vytvarim ..");
}
Online = false;
}
screenShotBMP.Save(path, ImageFormat.Jpeg); // C:\\test\\test.jpg
screenShotGraphics.Dispose();
screenShotBMP.Dispose();
return; //screenShotBMP;
}
/*
* Přesune cache soubory (za dobu offline) na server
*/
public static void MoveCached()
{
// ...
// after conect, move localy saved screenshots to server
// ...
}
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
// Vytvoří událost signalizující hranici odpočtu ve
// zpětném volání časovače
AutoResetEvent autoEvent = new AutoResetEvent(false);
// Počet průchodů timeru
StatusChecker statusChecker = new StatusChecker(Timeout.Infinite); // 1440
// Vytvoří odvozeného delegáta, který vyvolá metody pro časovač
TimerCallback tcb = statusChecker.CheckStatus;
// Create a timer that signals the delegate to invoke
// CheckStatus after one second, and every 1/4 second
// thereafter.
System.Threading.Timer stateTimer = new System.Threading.Timer(tcb, autoEvent, 1000, TimeO * 1000); // TimeO * 1000 * 60 * 12 * 5, 250
// When autoEvent signals, change the period to every
// 1/2 second.
autoEvent.WaitOne(15000, false);
stateTimer.Change(0, TimeO * 1000 * 60); // TimeO * 1000 * 60
Console.WriteLine("menim poprve..");
// When autoEvent signals the second time, dispose of
// the timer.
autoEvent.WaitOne(Timeout.Infinite, false);
stateTimer.Change(0, TimeO * 1000 * 60); // TimeO * 1000 * 60
Console.WriteLine("menim podruhe..");
//stateTimer.Dispose();
// Garbage collector
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
class StatusChecker
{
private int invokeCount;
private int maxCount;
Int64 CurrTime = Int64.Parse(DateTime.Now.ToString("hh")); // screeny od 6:00 do 16:00
public StatusChecker(int count)
{
invokeCount = 0;
maxCount = count;
}
// Tato metoda je volána delegátem časovače
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
//if ((CurrTime > 6) & (CurrTime < 16)) // 16
//{
LogWriterService.Program.ScreenShot();
Console.WriteLine("ScreenShot ..");
//}
Console.WriteLine("{0} Kontroluji stav {1,2}.",
DateTime.Now.ToString("h:mm:ss.fff"),
(++invokeCount).ToString());
if (invokeCount == maxCount)
{
// Resetuje čítač a signál Main.
invokeCount = 0;
autoEvent.Set();
}
// Garbage collector
GC.Collect();
Console.WriteLine("Paměť uvolněna .. \n");
}
}
服务代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
namespace LogWriterService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
EventLog.WriteEntry("Sluzba screenshot se spustila.");
}
protected override void OnStop()
{
EventLog.WriteEntry("Sluzba screenshot se zastavila.");
}
}
}
我觉得问题可能出在这里:
public static void CreateProcessAsUser()
{
IntPtr hToken = WindowsIdentity.GetCurrent().Token;
IntPtr hDupedToken = IntPtr.Zero;
ProcessUtility.PROCESS_INFORMATION pi = new ProcessUtility.PROCESS_INFORMATION();
try
{
ProcessUtility.SECURITY_ATTRIBUTES sa = new ProcessUtility.SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
bool result = ProcessUtility.DuplicateTokenEx(
hToken,
ProcessUtility.GENERIC_ALL_ACCESS,
ref sa,
(int)ProcessUtility.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)ProcessUtility.TOKEN_TYPE.TokenPrimary,
ref hDupedToken
);
if (!result)
{
throw new ApplicationException("DuplicateTokenEx failed");
}
ProcessUtility.STARTUPINFO si = new ProcessUtility.STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = String.Empty;
string folder = "D:\\test"; //Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string path = folder + "\\LogWriter\\LogWriter.exe"; // "C:/TEMP/" + GetIP() + "/" + CurrTime + ".jpg"
result = ProcessUtility.CreateProcessAsUser(
hDupedToken,
@path, // C:\Users\ToXiC\AppData\Roaming\LogWriter\LogWriter.exe
String.Empty,
ref sa, ref sa,
false, 0, IntPtr.Zero,
@"D:\\test", ref si, ref pi
);
if (!result)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
throw new ApplicationException(message);
}
}
finally
{
if (pi.hProcess != IntPtr.Zero)
ProcessUtility.CloseHandle(pi.hProcess);
if (pi.hThread != IntPtr.Zero)
ProcessUtility.CloseHandle(pi.hThread);
if (hDupedToken != IntPtr.Zero)
ProcessUtility.CloseHandle(hDupedToken);
}
}
}