1

我有一些代码可以在 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;
        }
    }
4

2 回答 2

4

通过在 64 位 Vista 下运行的服务创建 WPF FlowDocuments 时,我遇到了相同的错误代码。在四处挖掘之后,我可以在Microsoft Connect 上看到这篇文章,其中指出

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

“......它将修复包括 IIS7 在内的所有服务中的 WPF 崩溃......”

这是热修复下载的直接链接;知识库 959209

这解决了我们通过运行 64 位 Vista 的 CruiseControl.Net (CCNet) 运行单元测试的问题。不通过服务运行时的测试很好。

于 2009-07-31T07:33:58.257 回答
1

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

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

我没有尝试过,我不能保证它会起作用。但这可能是要尝试的东西?

祝你好运 :)

于 2008-11-11T10:13:39.267 回答