CSharp引用在Delphi XE2中编译的x64 OCX(CSharp referencing x64 OCX compiled in Delphi XE2)

编程入门 行业动态 更新时间:2024-10-18 06:10:19
CSharp引用在Delphi XE2中编译的x64 OCX(CSharp referencing x64 OCX compiled in Delphi XE2)

在引用在Delphi XE2中编译的x64 OCX时,我的C#项目出了问题。 OCX位于system32目录中并注册。 但是,当我尝试使用Visual Studio 2010引用它时,它不会在浏览引用窗口中列出,除非我将OCX移动到另一个目录,例如c:\ test \,然后显示它。

当我将OCX的x32版本复制到syswow64目录时,如果没有在此目录中注册,则IDE会在浏览引用窗口中将其列出。 但是当我尝试实例化类时,我会遇到以下异常:

System.Runtime.InteropServices.COMException未处理Message =检索具有CLSID {58465503-4991-4578-8478-FF7A6CBAA8CE}的组件的COM类工厂因以下错误而失败:80040111 ClassFactory无法提供请求的类(HRESULT异常:0x80040111 (CLASS_E_CLASSNOTAVAILABLE))。 Source = mscorlib ErrorCode = -2147221231

当我使用另一个目录,如c:\ test \并在那里注册OCX,并在我的项目中引用并实例化它,一切正常。

如果它是一个IDE错误或OCX中的问题,我不知道是什么原因导致了这个问题。 OCX,x32和x64具有不同的UID。

谁知道会发生什么?

谢谢

编辑:IDE是x32

Im having a problem in my C# project when referencing a x64 OCX compiled in Delphi XE2. The OCX is located and registered in the system32 directory. However when I try to reference it using Visual Studio 2010 it isn't listed in the browse references window, except when I move the OCX to another directory like for instance c:\test\, then it is shown.

When I copy the x32 version of the OCX to the syswow64 directory, without registering in this directory, then the IDE lists it in the browse references window. But when I try to instantiate the class I ge the following exception:

System.Runtime.InteropServices.COMException was unhandled Message=Retrieving the COM class factory for component with CLSID {58465503-4991-4578-8478-FF7A6CBAA8CE} failed due to the following error: 80040111 ClassFactory cannot supply requested class (Exception from HRESULT: 0x80040111 (CLASS_E_CLASSNOTAVAILABLE)). Source=mscorlib ErrorCode=-2147221231

When I use another directory like c:\test\ and register the OCX there, and reference in my project and instantiate it, everything works fine.

I have no idea what could be causing this problem, if it is an IDE bug or a problem in the OCX. Bothe OCXs, x32 and x64, have different UIDs.

Anyone knows what could be happening?

thanks

EDIT: The IDE is x32

最满意答案

WOW64(Windows-on-Windows 64位)的一个基本规则是简单的硬关系。

Win32 EXE可以加载Win32 DLL并且无法加载Win64 DLL Win64 EXE可以加载Win64 DLL并且无法加载Win32 DLL

与1993年推出的Win32s以及随后的所有32位Windows版本不同。 特殊的系统工具 - thunks - 用于确保跨越16/32位边界的EXE和DLL的互操作。 但对于32/64的界限,微软做出了相反的决定。

你描述的内容通过以下方式向我看:

看起来Visual Studio IDE本身就是Win32应用程序,而不是Win64应用程序。 您可以通过在Windows任务管理器中查看IDE进程来检查它(启动IDe并按Ctrl + Shift + Esc,然后单击IDe并选择“查找进程”),或者在ntCore CFF Explorer中打开IDE的exe文件。 或者通过Total Commander或任何其他方式。 因此,它无法加载您为其创建的64位OCX。 它只是不起作用。 但它确实成功加载了32位DLL(OCX)。

你写道“两个OCX,x32和x64都有不同的GUID。” - 实际上这是一个相当奇怪的决定。 如果它们实现相同的COM接口,为什么它应该有不同的GUID? 它看起来像是违反了基本的COM原则。 相同的接口意味着相同的GUID,反之亦然。 我相信你应该使它们成为相同的GUID,因为它们通过相同的接口提供相同的服务。

我相信你必须在你的Windows中注册32位和64位OCX(具有相同的GUID!)。 因此,应用程序将加载正确的应用程序,具体取决于它自己的位数。

您将了解Vista Win64中引入的文件系统和注册表虚拟化。 简而言之,对于注册表和磁盘上的某些选定路径,Win32和Win64应用程序将重定向到两个单独的数据容器。 这包括System32和SysWOW64文件夹,其中包括一些寄存器键,用于注册/查找/加载OCX DLL。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/aa965884.aspx http://support.microsoft.com/kb/305097 http://en.wikipedia.org/wiki/WoW64

System32文件夹运行RegEdit.exe并查看HKLM \ Software \ Classes ,然后从SysWOW64运行RegEdit.exe并在相同的密钥下看到不同的内容可能很有见地!

您可以运行Microsoft Process Monitor(从http://www.SysInternals.com下载)以查看哪些文件和注册密钥实际上由不同的应用程序访问。 例如 - 您可以了解尽管从相同的源编译,但Win32和Win64 OCX的注册有何不同。 您将看到Visual Studio IDE和您的应用程序使用哪些实际路径来查找您的OCX。

将OCX放入c:\ test时 - 将其置于FS Vistualization范围之外。 因此,Win64和Win32应用程序都会加载相同的真实文件路径。 您绕过Windows内置的特殊攻击,以获得Win64 / Win32旧版兼容性。

总而言之,我建议你:

确保Win32和Win64 OCX都提供相同的API,并通过使所有使用的GUID相同来明确指定。

将两个OCX放在计算机上,可以是c:\test不同文件,也可以是c:\test\32和c:\test\64同名文件,或者安装程序的任何其他文件夹。 使用System32文件夹虽然技术上可能是一个有争议的“快速和丑陋”的决定。

http://msdn.microsoft.com/en-us/library/windows/desktop/ms724373.aspx http://en.wikipedia.org/wiki/WinSxS http://en.wikipedia.org/wiki/DLL_hell#DLL_stomping

传统的(读取:遗留)方式是将64位OCX放入c:\Windows\System32 ,将32位OCX放入c:\Windows\SysWOW64 。 但是,这种做法被认为已被弃用,并可能导致DLL-Hell。 相反,在这个新的千禧年中,微软建议使用WinSxS多版本存储库来放置系统范围的DLL。 OTOH,因为你在注册的ActiveX组件的注册表列表中没有版本,我不确定这些参数是否适用于OCX,而不是传统的非注册DLL。 然而,一些第三方程序可能 - 仅仅是由于不幸 - 将其命名为与您的OCX命名相同的方式,并在Windows32等全局文件夹中覆盖它。 因此,将OCX放在Program Files中他们自己的文件夹中可能比使用SxS更容易,并且比使用System32的[mis]更可靠。

注册Win32和Win64 OCX。 除非您采取特殊措施来禁止虚拟化,否则使用相同的源,OCX将在Win32one和Win64中注册不同的真实注册表存储。 因为COM / OCX目录是由系统包含在32/64虚拟化中的Registry的一部分。 所以他们不会互相干扰,而是为Win32 EXE注册一个,为Win64 EXE注册另一个。

您是否决定使用WinSxS保留您的OCX,然后看起来您甚至不必注册它们。 请参阅COM组件的免注册激活

在调试时使用Process Explorer来检查IDE和您的应用程序的库注册及其搜索/加载是否按预期进行。

One base rule of WOW64 (Windows-on-Windows 64-bit) is the simple hard relation.

Win32 EXE can load Win32 DLL and can not load Win64 DLL Win64 EXE can load Win64 DLL and can not load Win32 DLL

It was different with introducing Win32s for Windows in 1993 and in all subsequent 32-bit Windows releases. Special system tooling - thunks - were used to ensure interop of EXEs and DLLs across 16/32 bitness boundary. But for 32/64 boundary Microsoft made the opposite decision.

What you describe looks to me the following way:

It looks like Visual Studio IDE is by itself Win32 application, not Win64 one. You can check it by seeing the IDE process in Windows Task Manager (launch IDe and press Ctrl+Shift+Esc, then r-click the IDe and choose "Find Process"), or by opening the IDE's exe-file in ntCore CFF Explorer. Or by Total Commander, or by any other means. Thus it can not load 64-bit OCX that you made for it. It just does not work. But it does succesfully load 32-bit DLL(OCX).

You wrote that "Both OCXs, x32 and x64, have different GUIDs." - actually that is a rather weird decision. Why should it have different GUIDs, if they implement the same COM Interface ? It looks like violating the basic COM principle to me. The same interface means the same GUID and vice versa. I believe you should make them the same GUID, because they provide the same service by the same interface.

I believe you have to have both 32-bit and 64-bit OCXs (with the same GUID!) registered in your Windows. So that the application would load the correct one, depending on its own bitness.

You are to learn about filesystem and registry virtualization introduced in Vista Win64. In short, for some selected paths in registry and on disk, Win32 and Win64 applications are redirected to two separate data containers. That includes System32 and SysWOW64 folders and that includes some register keys, used to register/find/load OCX DLLs.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/aa965884.aspx http://support.microsoft.com/kb/305097 http://en.wikipedia.org/wiki/WoW64

It may be insightful to you to run RegEdit.exe from System32 folder and looking into HKLM\Software\Classes, then running RegEdit.exe from SysWOW64 and under the same key you would see different content!

You can run Microsoft Process Monitor (download from http://www.SysInternals.com) to see which files and register keys are actually accessed by different applications. For example - you can learn how different is registration of your Win32 and Win64 OCXes despite being compiled from the same sources. Same way you would see which actual paths to find your OCXs are used by Visual Studio IDE and by your application.

When you put your OCX in c:\test - you put it outside of FS Vistualization scope. So both Win64 and Win32 application loads them the same real file path. You bypass the Windows built-in special hack for Win64/Win32 legacy compatibility.

So all in all i suggest to you the following:

Ensure that both Win32 and Win64 OCX do provide the same APIs and explicitly specify that by making all the used GUIDs the same.

Put both OCXs on the machine, either as different files in c:\test or same-named files in c:\test\32 and c:\test\64 or any other folders, that your program would be installed into. Using of System32 folder for it is while technicalyl possible a controversial "fast and ugly" decision.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms724373.aspx http://en.wikipedia.org/wiki/WinSxS http://en.wikipedia.org/wiki/DLL_hell#DLL_stomping

The traditional (read: legacy) way would be to put 64-bit OCX into c:\Windows\System32 and 32-bit OCX into c:\Windows\SysWOW64. However this practice is considered deprecated and potentially leading to DLL-Hell. Instead, in this new millenium, Microsoft suggests using WinSxS multi-version repository for placing system-wide DLLs. OTOH, since you don't have versions in the registry list of registered ActiveX components, I ain't sure those arguments apply well to OCXs, rather than traditional non-registered DLLs. However, some third-party program may - by sheer misfortune - name its DLL the same way as your OCX is named and overwrite it in Windows-global folders like System32. So, placing OCXs in their own folder in Program Files would probably be easier than using SxS and more reliable than [mis]using System32 for it.`

Register both Win32 and Win64 OCXs. Unless you took special measures to inhibit the virtualization, using the same sources, the OCXs would register in different real registry storages, in Win32one and Win64 one. Because COM/OCX directory is that part of Registry that is included into 32/64 virtualization by system. So they would not interfere with each another, but rather one would be registered for Win32 EXEs and another for Win64 EXEs.

Would you decide to keep your OCXs moder nand use WinSxS- then it appears you don't have to even register them. See Registration-Free Activation of COM Components

Use Process Explorer while debugging to check that both registration of libraries and their search/load by IDE and your application proceeded as expected.

更多推荐

本文发布于:2023-08-06 22:24:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1456649.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Delphi   CSharp   compiled   referencing   OCX

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!