我有一些代码可以在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;
}
}
答案 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”的桌面。
我没有尝试过,我不能保证它会起作用。但是可能需要尝试一下?
祝你好运:)