32位VB6应用程序需要自动64位Outlook发送电子邮件而不提示用户
我有一个 32 位旧版 VB6 应用程序,它使用 COM 组件自动 Outlook 发送电子邮件。要求是电子邮件需要出现在 Outlook 的“已发送邮件”文件夹中。更糟糕的是,应用程序不允许弹出通常的安全、警告或确认消息。
在 64 位 Office 出现之前,该应用程序运行没有任何问题。 32 位进程无法自动执行 64 位 Outlook。
我的想法如下:
用一个组件替换 COM 组件 在 CCW 中运行的 .NET WCF 客户端 (.NET 假装是 COM)
此 COM 组件调用 WCF 使用 netTcpBinding 作为 64 位进程运行的服务。
WCF 服务(作为本地系统运行)然后启动 64 位 作为用户的控制台应用程序,以及 使用扩展 MAPI 库来发送电子邮件。
第三步的原因有两个:
如果满足以下条件,MAPI 将要求确认: 你告诉它发送电子邮件。 扩展 MAPI 则不然。这意味着 我们必须编译一个 C++ 扩展 具有正确 64 位的 MAPI 库 来自 Microsoft 的头文件,并“调用” 来自我们的 .NET 代码。
在 WCF 中冒充(宽松使用的术语)用户 导致注册表不正确 蜂巢加载。换句话说,当 扩展 MAPI 尝试加载 来自 HKCU 的配置文件失败。这 意味着我们必须启动一个新流程,以本质上“RunAs”正确的用户。
这一切实际上都在实践中起作用,但我需要对以下内容进行一些解释:
如果我使用命令行参数中所需的所有信息运行控制台应用程序,则 MAPI 将无法登录。但是,如果我使用 1 个表单将相同的代码编译为 Windows 应用程序,并在表单的 OnLoad() 方法中使用完全相同的代码,那么它就会成功。谁能解释为什么?
要以当前登录用户(不是本地系统)身份从 WCF 服务运行“WinForms”应用程序,我执行了以下操作来获取正确的令牌:
sessionID = (int)WTSGetActiveConsoleSessionId();
ret = WTSQueryUserToken(sessionID, out currentToken);
有没有办法解决这个问题?当然,使用 WCF 的内置模拟会更好。
I have a 32bit legacy VB6 application that uses a COM component to automate Outlook to send an email. The requirement is that the email needs to appear in the Sent Items folder in Outlook. To make matters worse the application is not allowed to pop up the usual security, warning or confirmation messages.
This application was working without any issues until 64bit Office came along. There is no way for a 32bit process to automate a 64bit Outlook.
The idea I came up with was the following:
Swap out the COM component with a
.NET WCF Client that runs in the CCW
(.NET pretending to be COM)This COM component calls a WCF
service running as a 64bit process, using the netTcpBinding.The WCF service (running as LOCAL SYSTEM) then launches a 64bit
Console application as the user, and
makes use of the Extended MAPI
library to send the email.
The reason for the 3rd step is two-fold:
MAPI will ask for confirmation if
you tell it to send an email.
Extended MAPI does not. This meant
we had to compile a C++ Extended
MAPI library with the correct 64bit
header files from Microsoft, and "invoke"
that from our .NET code.Impersonating (term used loosely) the user in WCF
results in the incorrect Registry
hive loading. In other words when
Extended MAPI tries to load the
profile from HKCU it fails. This
meant we had to launch a new process to essentially "RunAs" the correct user.
This all actually works in practice, but I need some explanations for the following:
If I run the Console application with all the information it needs in command line parameters, MAPI fails to login. However, if I compile this same code as a Windows application with 1 Form, with exactly the same code in the form's OnLoad( ) method, then it succeeds. Can anyone explain why?
To run the "WinForms" application from the WCF service as the currently logged on user (not LOCAL SYSTEM) I did the following to get the correct token:
sessionID = (int)WTSGetActiveConsoleSessionId();
ret = WTSQueryUserToken(sessionID, out currentToken);
Is there any way around this? Surely it would be better to use WCF's built-in impersonation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不完全正确,如果您可以在进程外创建 COM 对象,那么它就可以工作。选项包括创建一个小的 .exe,作为 COM 对象的工厂。
请参阅 这篇文章
Not entirely true, if you can create the COM object out of process it will work. Options include creating a small .exe that services as a factory for your COM objects.
See this SO post