GetDoubleClickTime returns 0 意外
GetDoubleClickTime returns 0 unexpectedly
我们发现一些客户在将 Windows 10 安装升级到版本 2004(2020 年 5 月更新)后,我们的软件出现了问题。
Web 服务应用程序中的服务器端代码创建了 DevExpress PDF 查看器控件,但失败并显示错误消息“间隔不能为 0”。 (我知道在 web 服务中创建可视化控件不是一个好主意,但这是遗留代码,更改起来并不容易)。
分析表明问题在于控件试图创建 .net WinForms Timer
组件并将其 Interval
属性 设置为 SystemInformation.DoubleClickTime
的结果(这只是 GetDoubleClickTime
winapi 函数的包装器)。发生错误是因为 DoubleClickTime
值意外为 0。
为什么会发生这种情况,是否有一些解决方法?
WindowsAPI函数“GetDoubleClickTime”用于查询两次鼠标点击之间的最大毫秒数,以便将两次点击计为一次双击。
在Windows10 Version 2004这个函数意外地returns 0当在批量登录的上下文中执行时,这意味着例如:
- Windows 服务中的代码
- 从 Windows 服务启动的应用程序中的代码
- Server-side IIS 中 Web 应用程序中的代码
- 应用程序中的代码从 Windows 中的“计划任务”开始
设置“运行 用户是否登录”
在所有这些情况下,都没有用户界面。执行的代码(在我的例子中,它是非常古老的遗留代码,还没有在用户界面和业务规则之间进行分离)仍然可以查询该值,然后如果 0 被意外 returned 则失败。例如,在我的例子中,第三方用户界面控件被实例化,当尝试根据系统双击时间设置 .net Windows Forms Timer 时失败。
更新到版本 2004 之前 returned 值 > 0 in Windows 10。
如何重现错误
使用以下简单的 C# 应用程序
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WindowsFormsApp14
{
static class Program
{
[DllImport("user32.dll")]
static extern uint GetDoubleClickTime();
[STAThread]
static void Main()
{
// Same result with var doubleClickTime =
// System.Windows.Forms.SystemInformation.DoubleClickTime;
var doubleClickTime = GetDoubleClickTime();
Trace.WriteLine("DoubleClickTime: " + doubleClickTime);
}
}
}
使用 Microsoft 工具 DebugView(启用“捕获全局 Win32”设置)查看 Trace.WriteLine.
的输出
然后在Windows任务调度器中创建一个任务来执行编译后的应用程序。使用设置“运行 用户是否登录”。你会看到输出是
DoubleClickTime: 0
如果你直接执行编译后的应用程序,你会看到正确的输出
DoubleClickTime: 500
(或其他值,具体取决于您的鼠标设置)。
在之前的 Windows 10 个版本中,在这两种情况下都 return 编辑了大于 0 的值。
当代码在 Windows 服务或 IIS 应用程序池中的 Web 应用程序中运行时,可以看到相同的效果。也可能在其他情况下,每当代码在批登录的上下文中运行时。
如何解决问题
- 等待 Microsoft 在未来的更新中修复此问题。
- 建议客户不要安装 Windows 10 2004 更新或 return 到以前的 Windows 10 版本(如有必要)
- 修补您的代码并确保它可以处理 GetDoubleClickTime returns 0 的情况。如有必要,请联系 third-party 库的供应商以修补他们的库。
参考资料
我也将其发布为博客 post:
DevExpress 正在为其 PDF 查看器组件发布补丁:
主要是你在不同的windows站下,操作需要互动window站..
直接运行的话,你会运行在互动window站:"WinSta0"
;
而在“运行用户是否登录”的情况下,后台会运行ning,站名类似"Service -0x*-*$"
.
我可以重现这个问题,并得到一个错误代码ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION(1459)
:这个操作需要一个交互式window站。(虽然文档没有提到可以使用GetLastError
,错误码仅供参考)
作为解决方法,数据存储在注册表中:
HKEY_CURRENT_USER\Control Panel\Mouse\DoubleClickSpeed
Type = REG_SZ
Data = 500
您可以尝试将字符串转换为 UINT
。
我遇到了同样的问题。我什至尝试直接使用 WinAPI:
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern int GetDoubleClickTime();
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern bool SetDoubleClickTime(int newValue);
但令人惊讶的是,设置 SetDoubleClickTime 没有效果(returns false)和 Marshal.GetLastWin32Error() returns ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION(1459)...
当我从交互式会话 运行 时,一切都按预期进行。我的问题在于遗留的第 3 部分组件,我们无法修改构造函数...:-(
到目前为止,解决方法是 运行 构建过程(我们通过 LC.exe 在构建过程中获取它)使用“psexec -s -i”...但也许任何人都有another/better方法?
我忘了说,这是发生在
Windows 10 20H2 (Build 19042.985)
BR
佩德罗
我们发现一些客户在将 Windows 10 安装升级到版本 2004(2020 年 5 月更新)后,我们的软件出现了问题。
Web 服务应用程序中的服务器端代码创建了 DevExpress PDF 查看器控件,但失败并显示错误消息“间隔不能为 0”。 (我知道在 web 服务中创建可视化控件不是一个好主意,但这是遗留代码,更改起来并不容易)。
分析表明问题在于控件试图创建 .net WinForms Timer
组件并将其 Interval
属性 设置为 SystemInformation.DoubleClickTime
的结果(这只是 GetDoubleClickTime
winapi 函数的包装器)。发生错误是因为 DoubleClickTime
值意外为 0。
为什么会发生这种情况,是否有一些解决方法?
WindowsAPI函数“GetDoubleClickTime”用于查询两次鼠标点击之间的最大毫秒数,以便将两次点击计为一次双击。
在Windows10 Version 2004这个函数意外地returns 0当在批量登录的上下文中执行时,这意味着例如:
- Windows 服务中的代码
- 从 Windows 服务启动的应用程序中的代码
- Server-side IIS 中 Web 应用程序中的代码
- 应用程序中的代码从 Windows 中的“计划任务”开始 设置“运行 用户是否登录”
在所有这些情况下,都没有用户界面。执行的代码(在我的例子中,它是非常古老的遗留代码,还没有在用户界面和业务规则之间进行分离)仍然可以查询该值,然后如果 0 被意外 returned 则失败。例如,在我的例子中,第三方用户界面控件被实例化,当尝试根据系统双击时间设置 .net Windows Forms Timer 时失败。
更新到版本 2004 之前 returned 值 > 0 in Windows 10。
如何重现错误
使用以下简单的 C# 应用程序
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WindowsFormsApp14
{
static class Program
{
[DllImport("user32.dll")]
static extern uint GetDoubleClickTime();
[STAThread]
static void Main()
{
// Same result with var doubleClickTime =
// System.Windows.Forms.SystemInformation.DoubleClickTime;
var doubleClickTime = GetDoubleClickTime();
Trace.WriteLine("DoubleClickTime: " + doubleClickTime);
}
}
}
使用 Microsoft 工具 DebugView(启用“捕获全局 Win32”设置)查看 Trace.WriteLine.
的输出然后在Windows任务调度器中创建一个任务来执行编译后的应用程序。使用设置“运行 用户是否登录”。你会看到输出是
DoubleClickTime: 0
如果你直接执行编译后的应用程序,你会看到正确的输出
DoubleClickTime: 500
(或其他值,具体取决于您的鼠标设置)。
在之前的 Windows 10 个版本中,在这两种情况下都 return 编辑了大于 0 的值。
当代码在 Windows 服务或 IIS 应用程序池中的 Web 应用程序中运行时,可以看到相同的效果。也可能在其他情况下,每当代码在批登录的上下文中运行时。
如何解决问题
- 等待 Microsoft 在未来的更新中修复此问题。
- 建议客户不要安装 Windows 10 2004 更新或 return 到以前的 Windows 10 版本(如有必要)
- 修补您的代码并确保它可以处理 GetDoubleClickTime returns 0 的情况。如有必要,请联系 third-party 库的供应商以修补他们的库。
参考资料
我也将其发布为博客 post:
DevExpress 正在为其 PDF 查看器组件发布补丁:
主要是你在不同的windows站下,操作需要互动window站..
直接运行的话,你会运行在互动window站:"WinSta0"
;
而在“运行用户是否登录”的情况下,后台会运行ning,站名类似"Service -0x*-*$"
.
我可以重现这个问题,并得到一个错误代码ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION(1459)
:这个操作需要一个交互式window站。(虽然文档没有提到可以使用GetLastError
,错误码仅供参考)
作为解决方法,数据存储在注册表中:
HKEY_CURRENT_USER\Control Panel\Mouse\DoubleClickSpeed
Type = REG_SZ
Data = 500
您可以尝试将字符串转换为 UINT
。
我遇到了同样的问题。我什至尝试直接使用 WinAPI:
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern int GetDoubleClickTime();
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern bool SetDoubleClickTime(int newValue);
但令人惊讶的是,设置 SetDoubleClickTime 没有效果(returns false)和 Marshal.GetLastWin32Error() returns ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION(1459)...
当我从交互式会话 运行 时,一切都按预期进行。我的问题在于遗留的第 3 部分组件,我们无法修改构造函数...:-(
到目前为止,解决方法是 运行 构建过程(我们通过 LC.exe 在构建过程中获取它)使用“psexec -s -i”...但也许任何人都有another/better方法?
我忘了说,这是发生在
Windows 10 20H2 (Build 19042.985)
BR
佩德罗