Taking screenshots with Windows Service in Windows

2019-07-22 01:08发布

问题:

This question already has an answer here:

  • Windows service couldnt get screenshot in windows 7 2 answers

I know it's an old question about screenshots in Win 7 with winService on c#. I have read all articles about this on Stack Overflow and a lot on CodeProject...I know about 0 session for services , starting from Win Vista & about Allow service to interact with desktop checking... But I'm stuck (I can't take screenshot from service, because I don't know where display image(screen)) is saved.

   using System;
   using System.Collections.Generic;
   using System.ComponentModel;
   using System.Data;
   using System.Diagnostics;
   using System.Linq;
   using System.ServiceProcess;
   using System.Text;
   using System.Timers;

   namespace MyThirdTry
   {
public partial class Third : ServiceBase
{
    private static MyTimer aTimer;
    public Third()
    {
        InitializeComponent();
        if (!System.Diagnostics.EventLog.SourceExists("MySource"))
        {
            System.Diagnostics.EventLog.CreateEventSource(
                "MySource", "MyNewLog");
        }
        eventLog1.Source = "MySource";
        eventLog1.Log = "MyNewLog";
        aTimer = new MyTimer();
        aTimer.Elapsed += new System.Timers.ElapsedEventHandler(aTimer_Elapsed);
        aTimer.Interval = 10000;
    }

    protected override void OnStart(string[] args)
    {
        eventLog1.WriteEntry("Started\t" + DateTime.Now.ToString("G"));
        aTimer.Enabled = true;
    }

    protected override void OnStop()
    {
        aTimer.Enabled = false;
        eventLog1.WriteEntry("Stopped\t" + DateTime.Now.ToString("G"));
    }
    protected override void OnPause()
    {
        aTimer.Enabled = false;
        eventLog1.WriteEntry("Paused\t" + DateTime.Now.ToString("G"));
        base.OnPause();
    }
    protected override void OnContinue()
    {
        base.OnContinue();
        aTimer.Enabled = true;
        eventLog1.WriteEntry("Continued\t" + DateTime.Now.ToString("G"));
    }
    protected override void OnShutdown()
    {
        aTimer.Enabled = false;
        eventLog1.WriteEntry("Shutted down\t" + DateTime.Now.ToString("G"));
        base.OnShutdown();
    }
    private void aTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        eventLog1.WriteEntry("Evented\t" + aTimer.TimeTaker() + "\t" + Environment.CurrentDirectory);
        aTimer.TakeScreenShot();
    }
}
}

This is MyTimer class:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Timers;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Security.Principal;
    using System.IO;

    namespace MyThirdTry
    {
class MyTimer:Timer
{
    Bitmap mainBit;
    System.Windows.Forms.Screen main;

    public string TimeTaker()
    {
        return DateTime.Now.ToString("G");
    }

    public void TakeScreenShot()
    {
        string PathToSave = @"c:\results";
        System.IO.Directory.CreateDirectory(PathToSave);

        main = System.Windows.Forms.Screen.PrimaryScreen;
        mainBit = new Bitmap(main.Bounds.Width, main.Bounds.Height, PixelFormat.Format32bppArgb);
        Graphics gScreenShot = Graphics.FromImage(mainBit);

        gScreenShot.CopyFromScreen(main.Bounds.X,
                                   main.Bounds.Y,
                                   0, 0,
                                   main.Bounds.Size,
                                   CopyPixelOperation.SourceCopy);

        string fileName = "result" + Directory.GetFiles(PathToSave).Count().ToString().Trim() + ".png";
        mainBit.Save(System.IO.Path.Combine(PathToSave, fileName), System.Drawing.Imaging.ImageFormat.Png);
    }
}
}

And this code returns blind (empty) screenshots... All works , but service can`t get screenshot because it is in 0 session...how to get gui from session of current logined user?

回答1:

Since you need to access desktops other than session 0, consider using a task in Task Scheduler instead of a Windows service to capture the screenshots. TS makes starting a process within the user's session much easier. The task should be configured to be launched when any user logs in. You'll need to set the user account that the task runs as to a group, such as Users, and have the task run only when the user is logged on. These two security options are essential for creating the process with access to the user's desktop session. I've been able to successfully do this in the past using the User32 / Gdi32 API calls for taking screenshots.

If you still want to use a Windows service to aggregate the screenshots somehow, then use WCF to send the screenshots from the task processes to the Windows service.