GetWindowsDirectory() API 返回错误 (vba\vb6)

Posted

技术标签:

【中文标题】GetWindowsDirectory() API 返回错误 (vba\\vb6)【英文标题】:GetWindowsDirectory() API returns wrong (vba\vb6)GetWindowsDirectory() API 返回错误 (vba\vb6) 【发布时间】:2015-06-16 07:56:55 【问题描述】:

在我的 Windows-Terminal 用户上,我试图让两个应用程序指向同一个 Windows 目录,一个用 VBA 编写,一个用 VB6 编写。

当从 VB6 调用 GetWindowsDirectory() API 时,它会返回正确的路径

C:\documents and settings\%user%\Windows

从VBA宏调用时,返回

C:\Windows

请注意,GetSystemWindowsDirectory() 的结果相同

可能是 VBA 代码不知道它是一个终端站,我调用了 GetSystemMetrics(SM_REMOTESESSION) API 返回 1,这意味着它知道它是一个终端。

在 VB6 和 VBA 中使用完全相同的代码

Windows 2003R2,Office 版本是 2010 64bit(当我输入这个时,我想知道它是否相关,知道 vb6 是 32bit ...)

有什么想法吗?

编辑:如下 IInspectable 所述,vba 和 vb6 之间的区别在于 vb6 不像 Office 那样具有终端服务意识。

【问题讨论】:

"This function is provided primarily for compatibility with legacy applications."。你想做什么?用FOLDERID_Windows 代替SHGetKnownFolderPath 我的意思是“你期望什么”?什么是“同一个 Windows 目录”?你是说windows的安装目录吗?请参阅上面的更新评论。 GetWindowsDirectory: "如果应用程序是终端服务感知的(在图像标题中设置了 IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 标志),此函数返回的路径系统 Windows 目录,就像 GetSystemWindowsDirectory 函数一样。否则,它会为用户检索私有 Windows 目录的路径。" @CodeCaster SHGetKnownFolderPath 返回 **C:\Windows ** .. CreateObject("Shell.Application").Namespace(ssfWINDOWS).Self.Path “有什么想法吗?” 不应该在 SO 上提出问题。我将您最初的问题解释为:“为什么结果不同?” 和answered。也不建议更新问题以提出不同的问题。如果您还有其他问题,请改用ask a new question。 【参考方案1】:

您所观察到的行为已记录在案。查看GetWindowsDirectory的备注部分:

终端服务:如果应用程序在终端服务环境中运行,每个用户都有一个私有的 Windows 目录。系统还有一个共享的 Windows 目录。如果应用程序是终端服务感知的(在图像标题中设置了 IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 标志),则此函数返回系统 Windows 目录的路径,就像 GetSystemWindowsDirectory 函数一样。否则,它会为用户检索私有 Windows 目录的路径。

带有/HEADERS 选项的DUMPBIN 工具可用于验证是否为二进制文件设置了IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 标志。

dumpbin /HEADERS WINWORD.EXE

产生以下输出(Microsoft Office 2013 32 位):

OPTIONAL HEADER VALUES
             10B magic # (PE32)
                 ...
               2 subsystem (Windows GUI)
            8140 DLL characteristics
                   Dynamic base
                   NX compatible
                   Terminal Server Aware
                 ...

换句话说:Microsoft Office 支持终端服务,从托管在 Microsoft Office 中的 VBA 脚本调用 GetWindowsDirectory 将返回系统的共享 Windows 目录。

如果您使用 DUMPBIN 检查您的 VB6 应用程序,您会发现它不支持终端服务,调用 GetWindowsDirectory 将为用户返回私有 Windows 目录。


其他资源: /TSAWARE (Create Terminal Server Aware Application)

【讨论】:

完美解释。谢谢你。是否有绕过或其他建议如何在 VBA 的边界内从办公应用程序中检索实际的 win 文件夹? @polisha989:我不知道有一种方法可以强制GetWindowsDirectory 返回旧版(即非终端服务感知)结果。从您的 VBA 脚本调用 SHGetKnownFolderPath 和 FOLDERID_Windows 时会得到什么? 获取 C:\Windows,这不是我想要的。

以上是关于GetWindowsDirectory() API 返回错误 (vba\vb6)的主要内容,如果未能解决你的问题,请参考以下文章

dll隐式链接延迟加载

Delphi中String当数组用,多余的空格去除

获取系统信息(WINDOWS目录/系统目录/临时目录/我的文档/桌面)

握手API网关調用 API 网关 暴露的 开放 API

从 API 网关聊到 API 管理

API 到 API - 使用服务帐户