从Windows服务启用/禁用Aero

时间:2008-11-11 09:59:25

标签: windows-services aero

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

2 个答案:

答案 0 :(得分:4)

通过在64位Vista下运行的服务创建WPF FlowDocuments时,我有相同的错误代码。在挖掘之后,我可以看到this post on Microsoft Connect,这指出

  

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

  

“......它将解决所有WPF崩溃问题   服务包括IIS7 ......“

以下是热修复下载的直接链接; KB 959209

这解决了运行64位Vista的CruiseControl.Net(CCNet)运行单元测试的问题。没有运行服务的测试很好。

答案 1 :(得分:1)

我不确定,但也许您需要将服务的流程与当前桌面相关联才能生效?

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

我没有尝试过,我不能保证它会起作用。但是可能需要尝试一下?

祝你好运:)