gpt4 book ai didi

C# Windows 服务问题

转载 作者:太空宇宙 更新时间:2023-11-03 21:48:20 29 4
gpt4 key购买 nike

我编写了一个 C# 应用程序,它每 5 分钟截取一次屏幕截图并将其保存到服务器。它是计时器、2 个线程、很少的方法(ping srv、检查文件夹、截屏等)。

作为进程 (exe),它运行良好,但我需要将其安装为服务。我正在通过 installutil(框架服务安装程序)安装它。

我的问题是,当它作为服务安装时,它不截屏。停止服务时拉出一些。不是正确的分辨率和黑色。

我假设执行代码放错了地方(参见主要部分)。我不知道把它放在哪里,因为我不能有不止一种主要方法。请帮忙。

主要应用代码:

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);
}
}
}

最佳答案

我认为屏幕截图都是黑色的。发生这种情况是因为 Windows 服务在 Session 0 Isolation 中运行

一种解决方案是每 5 分钟从服务中启动一个控制台应用程序(隐藏 UI)。控制台应用程序可以截屏并退出。

从 Windows 服务启动控制台应用程序的一些代码:

   string applicationPath = ...;
private ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(applicationPath);
//set working directiory
Directory.SetCurrentDirectory(Path.GetDirectoryName(applicationPath));
psi.WorkingDirectory = Path.GetDirectoryName(applicationPath);
//psi.CreateNoWindow = false;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
//psi.UseShellExecute = false;
prcs = System.Diagnostics.Process.Start(psi);

编辑:控制台应用程序将在 session 0 中启动。解决方法是使用 WIN API CreateProcessAsUser pinvoke 在用户 session 中调用并启动控制台应用程序。

有关如何实现此目的的代码示例的一些链接:
http://odetocode.com/blogs/scott/archive/2004/10/28/createprocessasuser.aspx

http://blogs.msdn.com/b/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx

http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/31bfa13d-982b-4b1a-bff3-2761ade5214f/

关于C# Windows 服务问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15764117/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com