You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用GetFileSaveName时CommDlgExtendedError返回65535错误咨询

问题描述

我方通过C代码调用GetFileSaveName函数,该C代码由PowerBuilder调用,经评估该因素与当前问题无关。目前问题仅在1台已安装全部更新的Windows 10设备上复现:函数返回0,调用CommDlgExtendedError返回错误码65535(CDERR_DIALOGFAILURE),官方文档说明该错误含义为“对话框无法创建,通用对话框函数调用DialogBox失败,例如传入无效窗口句柄时会触发该错误”。
已确认该用户设备的系统通用对话框未完全损坏,可正常唤起记事本的文件打开、保存对话框。此前我方代码曾因传入GetOpenFileName的OPENFILENAME结构中hWndOwner指向已销毁窗口句柄触发同错误码,但本次场景中该参数设为0,可排除该原因。同版本代码在数千名用户设备上均正常运行。

可能触发原因

  • OPENFILENAME结构大小不匹配:代码中lStructSize赋值用的是ll_sizeof变量,首先要确认该变量在目标Windows 10设备上计算的大小是否正确。Vista及以上版本的Windows对OPENFILENAME结构有扩展,若PowerBuilder运行时计算的结构大小和当前系统预期的大小不匹配,会直接触发DialogBox创建失败。仅单设备复现的话,可能是该设备存在罕见的shell扩展修改了通用对话框的结构校验逻辑。
  • 筛选器字符串格式错误:通用对话框要求筛选器字符串是双零结尾的格式,每组说明和后缀之间用单个零分隔。代码中的of_Parse和of_StringToChar如果在处理特殊字符(比如该用户场景下的筛选器里包含\0字符、多字节特殊符号)时没有正确补零,会导致结构校验失败,单设备场景下可能是该用户的筛选器配置和其他用户不同。
  • lpstrFile缓冲区参数异常:虽然代码调用了LocalAlloc带LMEM_ZEROINIT,但要确认MAX_LENGTH的取值是否超过该设备上通用对话框允许的最大路径长度限制。部分Windows 10设备如果关闭了长路径支持,且传入的初始路径+文件名长度接近260字符阈值时,会偶发对话框创建失败。
  • 第三方shell扩展注入冲突:仅单设备复现的最高概率原因是该设备安装了特殊的资源管理器shell扩展,会注入到所有调用通用对话框的进程里。记事本可以正常调用是因为记事本作为系统签名程序,部分安全类shell扩展会跳过对它的注入,而你的程序没有微软签名,被扩展注入后修改了对话框初始化逻辑导致创建失败,可让用户禁用所有非微软的shell扩展后重试验证。
  • 权限配置异常:如果你的程序以管理员权限运行,而当前登录用户是标准用户,UAC虚拟化开启的状态下,部分Win10小版本会存在通用对话框创建失败的兼容性问题,可检查该设备的UAC配置和程序运行权限是否和其他用户不同。
  • 字符编码不匹配:代码里固定用CHARSIZE=2对应Unicode编码,如果该设备的系统默认编码被修改为非Unicode的特殊编码,且PowerBuilder运行时的字符编码和系统预期不符,会导致传入的字符串参数乱码,触发结构校验失败。

所用OPENFILENAME结构初始化代码(PowerScript)

OPENFILENAME iOFN
CONSTANT long CHARSIZE = 2
aul_flags = OFN_HIDEREADONLY + OFN_EXPLORER + 
    OFN_FILEMUSTEXIST+ OFN_NOCHANGEDIR + OFN_DONTADDTORECENT

RtlZeroMemory(iOFN, ll_sizeof)

// initialize structure
iOFN.lStructSize = ll_sizeof
iOFN.nFilterIndex = 1
iOFN.nMaxFile = MAX_LENGTH
iOFN.hWndOwner = il_hWnd
iOFN.Flags = aul_flags + OFN_ENABLESIZING /* needed when using hook procedure */

// allocate memory and copy title
ll_length = Len(as_title) * CHARSIZE
iOFN.lpstrTitle = LocalAlloc(LMEM_ZEROINIT, ll_length + 2)
RtlMoveMemory(iOFN.lpstrTitle, as_title, ll_length)

// allocate memory and copy filter
this.of_Parse(",", as_filter, ls_filter)
li_max = UpperBound(ls_filter) /* count of 1-based array elements */
For li_cnt = 1 To li_max
    ll_length = this.of_StringToChar(Trim(ls_filter[li_cnt]), lc_filter)
Next
ll_length = UpperBound(lc_filter) * CHARSIZE
iOFN.lpstrFilter = LocalAlloc(LMEM_ZEROINIT, ll_length)
RtlMoveMemory(iOFN.lpstrFilter, lc_filter, ll_length)

// allocate memory and copy default extension (if given)
If as_extension <> "" Then
    ll_length = Len(as_extension) * CHARSIZE
    iOFN.lpstrDefExt = LocalAlloc(LMEM_ZEROINIT, ll_length)
    RtlMoveMemory(iOFN.lpstrDefExt, as_extension, ll_length)
End If

// allocate memory and copy initialdir (if given)
If as_initdir <> "" Then
    ll_length = Len(as_initdir) * CHARSIZE
    iOFN.lpstrInitialDir = LocalAlloc(LMEM_ZEROINIT, ll_length)
    RtlMoveMemory(iOFN.lpstrInitialDir, as_initdir, ll_length)
End If

// allocate memory for returned data
lc_pathname = Space(MAX_LENGTH)
iOFN.nMaxFile = MAX_LENGTH
iOFN.lpstrFile = LocalAlloc(LMEM_ZEROINIT, MAX_LENGTH)
If as_initialfile <> "" Then
    ll_length = Len(as_initialfile) * CHARSIZE
    RtlMoveMemory(iOFN.lpstrFile, as_initialfile, ll_length)
End If

// display dialog box
lb_return = GetOpenFileName(iOFN)

内容的提问来源于stack exchange,提问作者Dan Cooperstock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 09:36:01