为什么 Windows 服务中的打印屏幕返回黑色图像?

发布于 2024-10-12 12:49:25 字数 589 浏览 2 评论 0原文

protected override void OnStart(string[] args)
{
    base.OnStart(args);
    CaptureScreen();

}

protected override void OnStop()
{
    base.OnStop();

}

private void CaptureScreen()
{

    Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

    Graphics graphics = Graphics.FromImage(printscreen as Image);

    graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);

    printscreen.Save(@"L:\" + Counter++ + ".jpg", ImageFormat.Jpeg);
}
  • 我检查了与桌面的交互,
  • 尝试了 localService 帐户 &用户
protected override void OnStart(string[] args)
{
    base.OnStart(args);
    CaptureScreen();

}

protected override void OnStop()
{
    base.OnStop();

}

private void CaptureScreen()
{

    Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

    Graphics graphics = Graphics.FromImage(printscreen as Image);

    graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);

    printscreen.Save(@"L:\" + Counter++ + ".jpg", ImageFormat.Jpeg);
}
  • I checked interact with desktop
  • tried the the localService account & user

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

秉烛思 2024-10-19 12:49:25

这是 Vista 中添加的会话 0 隔离功能的一部分。服务现在使用自己的工作站和桌面运行自己的会话。与运行登录提示和屏幕保护程序的会话非常相似。您正在对该会话的桌面进行屏幕截图,其中没有任何内容。无法再访问用户桌面。这是一项安全功能,可以防止粉碎攻击。诚然,我不明白为什么“与桌面交互”复选框没有被删除。

您需要将程序更改为作为“Windows 应用程序”运行,而不是作为服务运行。将快捷方式放入“启动”文件夹中或使用“运行”注册表项。没关系,当没有用户登录时,没有什么值得抓拍的。

This is part of the session 0 isolation feature that was added to Vista. Services now run their own session with their own workstation and desktop. Much like the session that the login prompt and screen saver run in. You are taking a screenshot of that session's desktop, there's nothing in it. Getting access to the user desktop is no longer possible. It is a security feature, it prevents shatter attacks. Admittedly, I don't understand why the 'interact with desktop' checkbox wasn't removed.

You'll need to change your program to run as a "windows application", not a service. Put a shortcut in the Startup folder or use the Run registry key. Which is okay, there's nothing much worth snapping when no user is logged in.

烛影斜 2024-10-19 12:49:25

您需要将服务设置为用户 Windows Station。这不是我的代码,我不记得从哪里得到它。
添加这两个类
然后你可以创建一个 Desktop 对象

Desktop userDesk = new Desktop();

然后,当您需要服务与用户会话交互时,您可以编写

userDesk.BeginInteraction();

最后要返回到您的服务会话,您可以调用

userDesk.EndInteraction();

internal class Desktop
{
    private IntPtr m_hCurWinsta = IntPtr.Zero;
    private IntPtr m_hCurDesktop = IntPtr.Zero;
    private IntPtr m_hWinsta = IntPtr.Zero;
    private IntPtr m_hDesk = IntPtr.Zero;

    /// <summary>
    /// associate the current thread to the default desktop
    /// </summary>
    /// <returns></returns>
    internal bool BeginInteraction()
    {
        EndInteraction();
        m_hCurWinsta = User32DLL.GetProcessWindowStation();
        if (m_hCurWinsta == IntPtr.Zero)
            return false;

        m_hCurDesktop = User32DLL.GetDesktopWindow();
        if (m_hCurDesktop == IntPtr.Zero)
            return false;

        m_hWinsta = User32DLL.OpenWindowStation("winsta0", false,
            WindowStationAccessRight.WINSTA_ACCESSCLIPBOARD |
            WindowStationAccessRight.WINSTA_ACCESSGLOBALATOMS |
            WindowStationAccessRight.WINSTA_CREATEDESKTOP |
            WindowStationAccessRight.WINSTA_ENUMDESKTOPS |
            WindowStationAccessRight.WINSTA_ENUMERATE |
            WindowStationAccessRight.WINSTA_EXITWINDOWS |
            WindowStationAccessRight.WINSTA_READATTRIBUTES |
            WindowStationAccessRight.WINSTA_READSCREEN |
            WindowStationAccessRight.WINSTA_WRITEATTRIBUTES
            );
        if (m_hWinsta == IntPtr.Zero)
            return false;

        User32DLL.SetProcessWindowStation(m_hWinsta);

        m_hDesk = User32DLL.OpenDesktop("default", OpenDesktopFlag.DF_NONE, false,
                DesktopAccessRight.DESKTOP_CREATEMENU |
                DesktopAccessRight.DESKTOP_CREATEWINDOW |
                DesktopAccessRight.DESKTOP_ENUMERATE |
                DesktopAccessRight.DESKTOP_HOOKCONTROL |
                DesktopAccessRight.DESKTOP_JOURNALPLAYBACK |
                DesktopAccessRight.DESKTOP_JOURNALRECORD |
                DesktopAccessRight.DESKTOP_READOBJECTS |
                DesktopAccessRight.DESKTOP_SWITCHDESKTOP |
                DesktopAccessRight.DESKTOP_WRITEOBJECTS
                );
        if (m_hDesk == IntPtr.Zero)
            return false;

        User32DLL.SetThreadDesktop(m_hDesk);

        return true;
    }

    /// <summary>
    /// restore
    /// </summary>
    internal void EndInteraction()
    {
        if (m_hCurWinsta != IntPtr.Zero)
            User32DLL.SetProcessWindowStation(m_hCurWinsta);

        if (m_hCurDesktop != IntPtr.Zero)
            User32DLL.SetThreadDesktop(m_hCurDesktop);

        if (m_hWinsta != IntPtr.Zero)
            User32DLL.CloseWindowStation(m_hWinsta);

        if (m_hDesk != IntPtr.Zero)
            User32DLL.CloseDesktop(m_hDesk);
    }
}
public static class User32DLL
{
    /// <summary>
    /// The GetDesktopWindow function returns a handle to the desktop window. 
    /// The desktop window covers the entire screen. 
    /// The desktop window is the area on top of which other windows are painted. 
    /// </summary>
    /// <returns>The return value is a handle to the desktop window. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr GetDesktopWindow();


    /// <summary>
    /// Retrieves a handle to the current window station for the calling process.
    /// </summary>
    /// <returns>If the function succeeds,
    /// the return value is a handle to the window station.
    /// If the function fails, the return value is NULL.</returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr GetProcessWindowStation();


    /// <summary>
    /// Retrieves a handle to the desktop assigned to the specified thread.
    /// </summary>
    /// <param name="dwThread">[in] Handle to the thread
    ///     for which to return the desktop handle.</param>
    /// <returns>If the function succeeds, the return value is a handle to the 
    /// desktop associated with the specified thread. 
    /// If the function fails, the return value is NULL.</returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr GetThreadDesktop(uint dwThread);


    /// <summary>
    /// Opens the specified window station.
    /// </summary>
    /// <param name="lpszWinSta">Pointer to a null-terminated
    ///           string specifying the name of the window station 
    /// to be opened. Window station names are case-insensitive.
    /// This window station must belong to the current session.
    /// </param>
    /// <param name="fInherit">[in] If this value
    ///            is TRUE, processes created by this process 
    /// will inherit the handle. Otherwise, 
    /// the processes do not inherit this handle. 
    /// </param>
    /// <param name="dwDesiredAccess">[in] Access to the window station</param>
    /// <returns>If the function succeeds, the return value
    ///          is the handle to the specified window station.
    /// If the function fails, the return value is NULL.</returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr OpenWindowStation(string lpszWinSta
        , bool fInherit
        , WindowStationAccessRight dwDesiredAccess
        );


    /// <summary>
    /// Assigns the specified window station to the calling process. 
    /// This enables the process to access objects in the window
    /// station such as desktops, the clipboard, and global atoms. 
    /// All subsequent operations on the window station
    /// use the access rights granted to hWinSta.
    /// </summary>
    /// <param name="hWinSta">[in] Handle to the window
    ///         station to be assigned to the calling process</param>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr SetProcessWindowStation(IntPtr hWinSta);


    /// <summary>
    /// Closes an open window station handle.
    /// </summary>
    /// <param name="hWinSta">[in] Handle
    ///         to the window station to be closed.</param>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr CloseWindowStation(IntPtr hWinSta);


    /// <summary>
    /// Opens the specified desktop object.
    /// </summary>
    /// <param name="lpszDesktop">[in] Pointer to null-terminated string 
    /// specifying the name of the desktop to be opened. 
    /// Desktop names are case-insensitive.
    /// This desktop must belong to the current window station.</param>
    /// <param name="dwFlags">[in] This parameter can
    ///          be zero or DF_ALLOWOTHERACCOUNTHOOK=0x0001</param>
    /// <param name="fInherit">[in] If this value is TRUE, processes created by 
    /// this process will inherit the handle. 
    /// Otherwise, the processes do not inherit this handle. </param>
    /// <param name="dwDesiredAccess">[in] Access
    ///         to the desktop. For a list of access rights</param>
    /// <returns>If the function succeeds, the return value is a handle to the opened desktop. 
    /// When you are finished using the handle, call the CloseDesktop function to close it.
    /// If the function fails, the return value is NULL.
    /// </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr OpenDesktop(string lpszDesktop
        , OpenDesktopFlag dwFlags
        , bool fInherit
        , DesktopAccessRight dwDesiredAccess
        );


    /// <summary>
    /// Closes an open handle to a desktop object.
    /// </summary>
    /// <param name="hDesktop">[in] Handle to the desktop to be closed.</param>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr CloseDesktop(IntPtr hDesktop);

    /// <summary>
    /// Assigns the specified desktop to the calling thread. 
    /// All subsequent operations on the desktop use the access rights granted to the desktop.
    /// </summary>
    /// <param name="hDesktop">[in] Handle to the desktop
    ///           to be assigned to the calling thread.</param>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool SetThreadDesktop(IntPtr hDesktop);
}

/// <summary>
/// REF MSDN:Window Station Security and Access Rights
/// ms-help://MS.MSDN.vAug06.en/dllproc/base/window_station_security_and_access_rights.htm
/// </summary>
[FlagsAttribute]
public enum WindowStationAccessRight : uint
{
    /// <summary>All possible access rights for the window station.</summary>
    WINSTA_ALL_ACCESS = 0x37F,

    /// <summary>Required to use the clipboard.</summary>
    WINSTA_ACCESSCLIPBOARD = 0x0004,

    /// <summary>Required to manipulate global atoms.</summary>
    WINSTA_ACCESSGLOBALATOMS = 0x0020,

    /// <summary>Required to create new desktop
    /// objects on the window station.</summary>
    WINSTA_CREATEDESKTOP = 0x0008,

    /// <summary>Required to enumerate existing desktop objects.</summary>
    WINSTA_ENUMDESKTOPS = 0x0001,

    /// <summary>Required for the window station to be enumerated.</summary>
    WINSTA_ENUMERATE = 0x0100,

    /// <summary>Required to successfully call the ExitWindows or ExitWindowsEx function. 
    /// Window stations can be shared by users and this access type can prevent other users 
    /// of a window station from logging off the window station owner.</summary>
    WINSTA_EXITWINDOWS = 0x0040,

    /// <summary>Required to read the attributes of a window station object. 
    /// This attribute includes color settings 
    /// and other global window station properties.</summary>
    WINSTA_READATTRIBUTES = 0x0002,

    /// <summary>Required to access screen contents.</summary>
    WINSTA_READSCREEN = 0x0200,

    /// <summary>Required to modify the attributes of 
    /// a window station object. 
    /// The attributes include color settings 
    /// and other global window station properties.</summary>
    WINSTA_WRITEATTRIBUTES = 0x0010,
}

/// <summary>
/// OpenDesktop 2nd param
/// </summary>
public enum OpenDesktopFlag : uint
{
    /// <summary>
    /// Default value
    /// </summary>
    DF_NONE = 0x0000,

    /// <summary>
    /// Allows processes running in other accounts on the desktop
    /// to set hooks in this process.
    /// </summary>
    DF_ALLOWOTHERACCOUNTHOOK = 0x0001,
}

/// <summary>
/// REF MSDN:Desktop Security and Access Rights
/// ms-help://MS.MSDN.vAug06.en/dllproc/base/desktop_security_and_access_rights.htm
/// </summary>
[FlagsAttribute]
public enum DesktopAccessRight : uint
{
    /// <summary>Required to create a menu on the desktop. </summary>
    DESKTOP_CREATEMENU = 0x0004,

    /// <summary>Required to create a window on the desktop. </summary>
    DESKTOP_CREATEWINDOW = 0x0002,

    /// <summary>Required for the desktop to be enumerated. </summary>
    DESKTOP_ENUMERATE = 0x0040,

    /// <summary>Required to establish any of the window hooks. </summary>
    DESKTOP_HOOKCONTROL = 0x0008,

    /// <summary>Required to perform journal playback on a desktop. </summary>
    DESKTOP_JOURNALPLAYBACK = 0x0020,

    /// <summary>Required to perform journal recording on a desktop. </summary>
    DESKTOP_JOURNALRECORD = 0x0010,

    /// <summary>Required to read objects on the desktop. </summary>
    DESKTOP_READOBJECTS = 0x0001,

    /// <summary>Required to activate the desktop
    ///          using the SwitchDesktop function. </summary>
    DESKTOP_SWITCHDESKTOP = 0x0100,

    /// <summary>Required to write objects on the desktop. </summary>
    DESKTOP_WRITEOBJECTS = 0x0080,
}

You need to set your service to the users windows station. This is not my code and I can't remember where I got it from.
Add these two classes
then you can create a Desktop object

Desktop userDesk = new Desktop();

Then when you need your service to interact with the user session you would write

userDesk.BeginInteraction();

and finally to return to your service's session you call

userDesk.EndInteraction();

internal class Desktop
{
    private IntPtr m_hCurWinsta = IntPtr.Zero;
    private IntPtr m_hCurDesktop = IntPtr.Zero;
    private IntPtr m_hWinsta = IntPtr.Zero;
    private IntPtr m_hDesk = IntPtr.Zero;

    /// <summary>
    /// associate the current thread to the default desktop
    /// </summary>
    /// <returns></returns>
    internal bool BeginInteraction()
    {
        EndInteraction();
        m_hCurWinsta = User32DLL.GetProcessWindowStation();
        if (m_hCurWinsta == IntPtr.Zero)
            return false;

        m_hCurDesktop = User32DLL.GetDesktopWindow();
        if (m_hCurDesktop == IntPtr.Zero)
            return false;

        m_hWinsta = User32DLL.OpenWindowStation("winsta0", false,
            WindowStationAccessRight.WINSTA_ACCESSCLIPBOARD |
            WindowStationAccessRight.WINSTA_ACCESSGLOBALATOMS |
            WindowStationAccessRight.WINSTA_CREATEDESKTOP |
            WindowStationAccessRight.WINSTA_ENUMDESKTOPS |
            WindowStationAccessRight.WINSTA_ENUMERATE |
            WindowStationAccessRight.WINSTA_EXITWINDOWS |
            WindowStationAccessRight.WINSTA_READATTRIBUTES |
            WindowStationAccessRight.WINSTA_READSCREEN |
            WindowStationAccessRight.WINSTA_WRITEATTRIBUTES
            );
        if (m_hWinsta == IntPtr.Zero)
            return false;

        User32DLL.SetProcessWindowStation(m_hWinsta);

        m_hDesk = User32DLL.OpenDesktop("default", OpenDesktopFlag.DF_NONE, false,
                DesktopAccessRight.DESKTOP_CREATEMENU |
                DesktopAccessRight.DESKTOP_CREATEWINDOW |
                DesktopAccessRight.DESKTOP_ENUMERATE |
                DesktopAccessRight.DESKTOP_HOOKCONTROL |
                DesktopAccessRight.DESKTOP_JOURNALPLAYBACK |
                DesktopAccessRight.DESKTOP_JOURNALRECORD |
                DesktopAccessRight.DESKTOP_READOBJECTS |
                DesktopAccessRight.DESKTOP_SWITCHDESKTOP |
                DesktopAccessRight.DESKTOP_WRITEOBJECTS
                );
        if (m_hDesk == IntPtr.Zero)
            return false;

        User32DLL.SetThreadDesktop(m_hDesk);

        return true;
    }

    /// <summary>
    /// restore
    /// </summary>
    internal void EndInteraction()
    {
        if (m_hCurWinsta != IntPtr.Zero)
            User32DLL.SetProcessWindowStation(m_hCurWinsta);

        if (m_hCurDesktop != IntPtr.Zero)
            User32DLL.SetThreadDesktop(m_hCurDesktop);

        if (m_hWinsta != IntPtr.Zero)
            User32DLL.CloseWindowStation(m_hWinsta);

        if (m_hDesk != IntPtr.Zero)
            User32DLL.CloseDesktop(m_hDesk);
    }
}
public static class User32DLL
{
    /// <summary>
    /// The GetDesktopWindow function returns a handle to the desktop window. 
    /// The desktop window covers the entire screen. 
    /// The desktop window is the area on top of which other windows are painted. 
    /// </summary>
    /// <returns>The return value is a handle to the desktop window. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr GetDesktopWindow();


    /// <summary>
    /// Retrieves a handle to the current window station for the calling process.
    /// </summary>
    /// <returns>If the function succeeds,
    /// the return value is a handle to the window station.
    /// If the function fails, the return value is NULL.</returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr GetProcessWindowStation();


    /// <summary>
    /// Retrieves a handle to the desktop assigned to the specified thread.
    /// </summary>
    /// <param name="dwThread">[in] Handle to the thread
    ///     for which to return the desktop handle.</param>
    /// <returns>If the function succeeds, the return value is a handle to the 
    /// desktop associated with the specified thread. 
    /// If the function fails, the return value is NULL.</returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr GetThreadDesktop(uint dwThread);


    /// <summary>
    /// Opens the specified window station.
    /// </summary>
    /// <param name="lpszWinSta">Pointer to a null-terminated
    ///           string specifying the name of the window station 
    /// to be opened. Window station names are case-insensitive.
    /// This window station must belong to the current session.
    /// </param>
    /// <param name="fInherit">[in] If this value
    ///            is TRUE, processes created by this process 
    /// will inherit the handle. Otherwise, 
    /// the processes do not inherit this handle. 
    /// </param>
    /// <param name="dwDesiredAccess">[in] Access to the window station</param>
    /// <returns>If the function succeeds, the return value
    ///          is the handle to the specified window station.
    /// If the function fails, the return value is NULL.</returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr OpenWindowStation(string lpszWinSta
        , bool fInherit
        , WindowStationAccessRight dwDesiredAccess
        );


    /// <summary>
    /// Assigns the specified window station to the calling process. 
    /// This enables the process to access objects in the window
    /// station such as desktops, the clipboard, and global atoms. 
    /// All subsequent operations on the window station
    /// use the access rights granted to hWinSta.
    /// </summary>
    /// <param name="hWinSta">[in] Handle to the window
    ///         station to be assigned to the calling process</param>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr SetProcessWindowStation(IntPtr hWinSta);


    /// <summary>
    /// Closes an open window station handle.
    /// </summary>
    /// <param name="hWinSta">[in] Handle
    ///         to the window station to be closed.</param>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr CloseWindowStation(IntPtr hWinSta);


    /// <summary>
    /// Opens the specified desktop object.
    /// </summary>
    /// <param name="lpszDesktop">[in] Pointer to null-terminated string 
    /// specifying the name of the desktop to be opened. 
    /// Desktop names are case-insensitive.
    /// This desktop must belong to the current window station.</param>
    /// <param name="dwFlags">[in] This parameter can
    ///          be zero or DF_ALLOWOTHERACCOUNTHOOK=0x0001</param>
    /// <param name="fInherit">[in] If this value is TRUE, processes created by 
    /// this process will inherit the handle. 
    /// Otherwise, the processes do not inherit this handle. </param>
    /// <param name="dwDesiredAccess">[in] Access
    ///         to the desktop. For a list of access rights</param>
    /// <returns>If the function succeeds, the return value is a handle to the opened desktop. 
    /// When you are finished using the handle, call the CloseDesktop function to close it.
    /// If the function fails, the return value is NULL.
    /// </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr OpenDesktop(string lpszDesktop
        , OpenDesktopFlag dwFlags
        , bool fInherit
        , DesktopAccessRight dwDesiredAccess
        );


    /// <summary>
    /// Closes an open handle to a desktop object.
    /// </summary>
    /// <param name="hDesktop">[in] Handle to the desktop to be closed.</param>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr CloseDesktop(IntPtr hDesktop);

    /// <summary>
    /// Assigns the specified desktop to the calling thread. 
    /// All subsequent operations on the desktop use the access rights granted to the desktop.
    /// </summary>
    /// <param name="hDesktop">[in] Handle to the desktop
    ///           to be assigned to the calling thread.</param>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero. </returns>
    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool SetThreadDesktop(IntPtr hDesktop);
}

/// <summary>
/// REF MSDN:Window Station Security and Access Rights
/// ms-help://MS.MSDN.vAug06.en/dllproc/base/window_station_security_and_access_rights.htm
/// </summary>
[FlagsAttribute]
public enum WindowStationAccessRight : uint
{
    /// <summary>All possible access rights for the window station.</summary>
    WINSTA_ALL_ACCESS = 0x37F,

    /// <summary>Required to use the clipboard.</summary>
    WINSTA_ACCESSCLIPBOARD = 0x0004,

    /// <summary>Required to manipulate global atoms.</summary>
    WINSTA_ACCESSGLOBALATOMS = 0x0020,

    /// <summary>Required to create new desktop
    /// objects on the window station.</summary>
    WINSTA_CREATEDESKTOP = 0x0008,

    /// <summary>Required to enumerate existing desktop objects.</summary>
    WINSTA_ENUMDESKTOPS = 0x0001,

    /// <summary>Required for the window station to be enumerated.</summary>
    WINSTA_ENUMERATE = 0x0100,

    /// <summary>Required to successfully call the ExitWindows or ExitWindowsEx function. 
    /// Window stations can be shared by users and this access type can prevent other users 
    /// of a window station from logging off the window station owner.</summary>
    WINSTA_EXITWINDOWS = 0x0040,

    /// <summary>Required to read the attributes of a window station object. 
    /// This attribute includes color settings 
    /// and other global window station properties.</summary>
    WINSTA_READATTRIBUTES = 0x0002,

    /// <summary>Required to access screen contents.</summary>
    WINSTA_READSCREEN = 0x0200,

    /// <summary>Required to modify the attributes of 
    /// a window station object. 
    /// The attributes include color settings 
    /// and other global window station properties.</summary>
    WINSTA_WRITEATTRIBUTES = 0x0010,
}

/// <summary>
/// OpenDesktop 2nd param
/// </summary>
public enum OpenDesktopFlag : uint
{
    /// <summary>
    /// Default value
    /// </summary>
    DF_NONE = 0x0000,

    /// <summary>
    /// Allows processes running in other accounts on the desktop
    /// to set hooks in this process.
    /// </summary>
    DF_ALLOWOTHERACCOUNTHOOK = 0x0001,
}

/// <summary>
/// REF MSDN:Desktop Security and Access Rights
/// ms-help://MS.MSDN.vAug06.en/dllproc/base/desktop_security_and_access_rights.htm
/// </summary>
[FlagsAttribute]
public enum DesktopAccessRight : uint
{
    /// <summary>Required to create a menu on the desktop. </summary>
    DESKTOP_CREATEMENU = 0x0004,

    /// <summary>Required to create a window on the desktop. </summary>
    DESKTOP_CREATEWINDOW = 0x0002,

    /// <summary>Required for the desktop to be enumerated. </summary>
    DESKTOP_ENUMERATE = 0x0040,

    /// <summary>Required to establish any of the window hooks. </summary>
    DESKTOP_HOOKCONTROL = 0x0008,

    /// <summary>Required to perform journal playback on a desktop. </summary>
    DESKTOP_JOURNALPLAYBACK = 0x0020,

    /// <summary>Required to perform journal recording on a desktop. </summary>
    DESKTOP_JOURNALRECORD = 0x0010,

    /// <summary>Required to read objects on the desktop. </summary>
    DESKTOP_READOBJECTS = 0x0001,

    /// <summary>Required to activate the desktop
    ///          using the SwitchDesktop function. </summary>
    DESKTOP_SWITCHDESKTOP = 0x0100,

    /// <summary>Required to write objects on the desktop. </summary>
    DESKTOP_WRITEOBJECTS = 0x0080,
}
墨落画卷 2024-10-19 12:49:25

该服务是“无头”的,没有 UI,也没有 100% 确定(CopyFromScreen 的文档相当模糊),我预计在无头运行时会失败。在多个用户同时登录的情况下,服务如何知道要复制哪个屏幕?

另请参阅问题

The service is "headless", no UI and without being a 100% sure (The documentation for CopyFromScreen is rather vague) I'd expect that to fail when running headless. How would the service know which screen to copy in the case where multiple users are logged on at the same time?

see this questions as well

时光清浅 2024-10-19 12:49:25

对于 XP/2003,Interact with Desktop 应该会有所帮助。
对于 Windows 7/Windows 2008,Interact with Desktop 的工作方式有所不同。

最适合您的解决方案是分析来自服务的登录会话,对于新会话,在用户会话中启动“桌面”进程并与该进程通信以获取屏幕。

In the case of XP/2003 the Interact with Desktop should help.
In the case of Windows 7/Windows 2008 an Interact with Desktop works differently.

The best solution for you would be to analyze logon sessions from the service and, for new session, start the "desktop" process in user session and communicate with that process to get screens.

街道布景 2024-10-19 12:49:25

这可能就像关闭浏览器中的加速器一样简单。这对我有用。在 Chrome 中,它位于系统菜单下。

It may just be as simple as turning the accelerator off in your browser. That worked for me. In Chrome it's under the System menu.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文