从 Windows 服务启用/禁用 Aero

发布于 2024-07-08 01:03:40 字数 1949 浏览 9 评论 0原文

我有一些代码可以在 Vista 中启用/禁用 Windows Aero 服务,并且我想在 Windows 服务中运行它。 该代码在独立应用程序中运行,但是当我从服务运行它时,什么也没有发生。 不会引发任何错误或异常。

我意识到在服务中运行代码与在应用程序中运行代码的范围不同,但在这种情况下,我如何从服务中启用/禁用 Aero? 这可能吗?

这是我正在使用的代码:

public static readonly uint DWM_EC_DISABLECOMPOSITION = 0;
public static readonly uint DWM_EC_ENABLECOMPOSITION = 1;

[DllImport("dwmapi.dll", EntryPoint="DwmEnableComposition")]
protected static extern uint Win32DwmEnableComposition(uint uCompositionAction);

public static bool EnableAero() 
{
    Win32DwmEnableComposition(DWM_EC_ENABLECOMPOSITION);
}

编辑:

事实证明,DwmEnableComposition 调用返回 HRESULT 0x80070018 或 ERROR_BAD_LENGTH。 似乎是一个奇怪的错误,因为代码在不作为服务运行时可以工作。

我还尝试将整个内容更改为以下代码,但得到了相同的结果。 它设置了窗口站和桌面,看起来是正确的,但是调用 DwmEnableComposition 会导致相同的错误。 为简洁起见,我没有包含 PInvoke 声明。

    protected override void OnStop()
    {
        IntPtr winStation = OpenWindowStation("winsta0", true, 0x10000000 /* GENERIC_ALL */);
        if (winStation == null || winStation.ToInt32() == 0)
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }

        if (!SetProcessWindowStation(winStation))
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }

        uint thread = GetCurrentThreadId();

        IntPtr hdesk = OpenInputDesktop(0, false, 0x10000000 /* GENERIC_ALL */);
        if (hdesk == null || hdesk.ToInt32() == 0)
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }

        if (!SetThreadDesktop(hdesk))
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }

        uint result = Win32DwmEnableComposition(DWM_EC_DISABLECOMPOSITION);
        if (result != 0)
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }
    }

I have some code to enable/disable the Windows Aero service in Vista, and I would like to run it in a Windows Service. The code works in a standalone application, but when I run it from a Service, nothing happens. No errors or exceptions are thrown.

I realise that running code in a service is a different scope than running code in an application, but in this case, how would I enable/disable Aero from the service? Is this even possible?

Here is the code I am working with:

public static readonly uint DWM_EC_DISABLECOMPOSITION = 0;
public static readonly uint DWM_EC_ENABLECOMPOSITION = 1;

[DllImport("dwmapi.dll", EntryPoint="DwmEnableComposition")]
protected static extern uint Win32DwmEnableComposition(uint uCompositionAction);

public static bool EnableAero() 
{
    Win32DwmEnableComposition(DWM_EC_ENABLECOMPOSITION);
}

Edit:

It turns out that the DwmEnableComposition call is returning HRESULT 0x80070018, or ERROR_BAD_LENGTH. Seems like a strange error, since the code works when not running as a service.

I also tried changing the entire thing to the following code, but got the same result. It sets the window station and desktop, and it seems to be correct, but the call to DwmEnableComposition results in the same error. I've not included the PInvoke declarations for brevity.

    protected override void OnStop()
    {
        IntPtr winStation = OpenWindowStation("winsta0", true, 0x10000000 /* GENERIC_ALL */);
        if (winStation == null || winStation.ToInt32() == 0)
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }

        if (!SetProcessWindowStation(winStation))
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }

        uint thread = GetCurrentThreadId();

        IntPtr hdesk = OpenInputDesktop(0, false, 0x10000000 /* GENERIC_ALL */);
        if (hdesk == null || hdesk.ToInt32() == 0)
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }

        if (!SetThreadDesktop(hdesk))
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }

        uint result = Win32DwmEnableComposition(DWM_EC_DISABLECOMPOSITION);
        if (result != 0)
        {
            String err = new Win32Exception(Marshal.GetLastWin32Error()).Message;
        }
    }

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

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

发布评论

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

评论(2

-小熊_ 2024-07-15 01:03:40

通过在 64 位 Vista 下运行的服务创建 WPF FlowDocuments 时,我遇到了相同的错误代码。 深入研究后,我可以浏览 Microsoft Connect 上的这篇文章,其中指出

“...该问题是由 DWM 的互操作问题引起的...”

并且

“...它将修复所有 WPF 崩溃问题
服务包括 IIS7 ...”

这是修补程序下载的直接链接;KB 959209

这解决了通过运行 64 位 Vista 的 CruiseControl.Net (CCNet) 运行单元测试的问题,这些测试在不通过服务运行时表现良好。

I had the same error code, when creating WPF FlowDocuments through a service running under 64-bit Vista. After digging around I can accross this post on Microsoft Connect, which points out that

"... The problem is caused by an interop problem with the DWM ..."

and

"... it will fix the WPF crash in all
services including IIS7 ..."

Here is the direct link to the hot-fix downloads; KB 959209

This fixed our problems with running unit tests through CruiseControl.Net (CCNet) running 64-bit Vista. The tests where fine when not running through a service.

奈何桥上唱咆哮 2024-07-15 01:03:40

我不确定,但也许您需要将服务进程与当前桌面关联起来才能工作?

确保您的服务可以与桌面交互。 然后使用 SetThreadDesktop() 设置桌面用于传递名为“Default”的桌面句柄的服务线程。

我没有尝试过,也不能保证它会起作用。 但这可能是值得尝试的事情?

祝你好运 :)

I dont know for certain, but perhaps you need to associate your service's process with the current desktop before that will work?

Make sure that your service can interact with the desktop. Then use SetThreadDesktop() to set the desktop for the service thread passing in a handle to the desktop called "Default".

I haven't tried it, and I can't guarantee it'll work. But it might be something to try?

Good luck :)

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