受欢迎的博客标签

How to make a 32bit ActiveX.exe (com server) with VB 6.0 calling by Excel 64bit vba step by step(ztz)?

Published

Table of Content

 

part 2:Register the Com Server on the system(windows)

Instancing property

 

Part 4: Other

 

You get everything when you use SysInternals' ProcMon utility. Start it up, then register the server with Regserver.exe. You'll see the trace of the program writing the registry keys in the ProcMon output.

Excel 64 bit version  vba call a 32bit DLL 

I have recently created a Visual Basic 6 application that is an ActiveX exe, running on Windows 7 64bit and Office 2013 64bit.

Excel 64 bit version  vba call a 32bit DLL (convert dll to active.exe with vb6)?

question:

How to do Excel 64bit version  vba call a 32bit DLL (convert dll to active.exe with vb6)? main executable app is MS Excel2013 64bit

answer:

Changing a VB 6 Add-In from a DLL to an EXE

converting from VB6 DLL to VB6 ActiveX EXE

 

an out of process COM server/ActiveX EXE

 

someone has an Add-In written using Visual Basic 6 and wants to use that add-in with the 64-bit version of Inventor.  In doing this there are some issues to be aware of:

64-bit Windows can run both 32-bit and 64-bit applications (exe’s and dll’s).
Visual Basic 6 can only create 32-bit applications (exe’s and dll’s).
A 64-bit exe can only load 64-bit dll’s.  It cannot use 32-bit dll’s.

ActiveX DLLs run ‘in-process’ and ActiveX EXEs run ‘out-of-process’

Out-of-process COM components (i.e. ActiveX EXE's) are always started by the COM Service Control Manager, not by the process that called CreateObject. This is why the parent process for the ActiveX EXE is svchost.exe.

As far as I am aware, a VB6 ActiveX EXE was essentially an out of process COM server.

大家应该遇到过64位office在vba里无法调用32位dll的问题。

微软公司的官方网站针对这个问题描述如下:

在64位的windows系统中,一个64位进程不能加载一个32位dll,同理一个32位进程也不能加载一个64位dll。

但是,64位windows支持64位和32位进程(包括本机或跨机)间进程间通信(RPC)。

在64位windows中,一个进程外32位COM服务器能够与64位客户端进行通信,同样一个进程外64位COM服务器也能与32位客户端进行通信。因此,如果你有一个32位COM无法识别的DLL,你可以将它封装到一个进程外COM服务器中并在一个64位进程中用COM配置调用DLL。

 

进程外COM服务器(EXE)创建步骤(简单说明)

This example has three parts:

Launch Visual Basic
step 1:Create a new 'ActiveX EXE' project. 创建一个进程外COM服务器(EXE)。
将32位DLL的接口函数封装为COM服务器的相关接口。
step 1.1:project Set Binary Compatibility to fix guids

Step 2:  register VB6 ActiveX EXE as com server.注册COM服务器*.exe /regserver (注销 *.exe /unregserver)。

Step 3:Client project(Excel vba) Add reference VB6 ActiveX EXE com server in you client project -64位进程调用32位COM服务器接口,成功。从而曲线实现了64位进程调用32位DLL
1.Create a new 'ActiveX EXE' project.
Start Visual Basic.
Create a new 'ActiveX EXE' project.
Rename the 'Class1' class to the name of your class.
Rename the project to something sensible.

Add reference: Microsoft Excel 15.0 Object Library (excel  brower Excel.exe)
(require that my Automation Add-in obtains a reference to the Excel instance)

Paste the code from Excel into the class code window.
Save the project and its files.
Build the .exe (File -> Make...).

vbacomserver:set Set Binary Compatibility to fix guids

2.register the  comserver.exe  on on the system(windows)

3. Calling the Com Server(ActiveX EXE) from Excel  VBA
Add reference comserver

 

Part one:Create a new 'ActiveX EXE' project with vb6

生成EXE文件

打开VB6开发工具,新建“标准 EXE”,对右边“工程-工程1”窗口进行操作
1、对着“工程1”右键,“工程1 属性”,“启动对象”改为“Sub Main”,“工程名称”改为你想要的名字,本演示里改为“VB6直接启动未设置宏安全的Excel代码”,确定
2、对着窗体“Form1”右键——移除,
3、右键“添加”——“添加模块”,在模块代码窗口里把代码复制粘帖进去。
4、VB6的菜单“工程”——“引用”,把代表Excel程序的“Microsoft Excel 14.0 Object Library”勾上。(这个是Excel2010版本的,如果是其他版本,可以对应勾上Microsoft Excel xx.0 Object Library)
5、VB6的菜单“文件”——“make .EXE”——选择保存位置后
成功生成一个EXE文件

step 1:首先用VB6创建一个32位的com服务器。就是Activex exe这玩意

step 2:Add reference  Microsoft Excel 15.0 Object Library

添加 excel 引用Microsoft Excel 15.0 Object Library (Office2013 64bit) ,绝对路径\Excel.EXE(好像64位的也可以)

Microsoft Excel 15.0 Object Library path=C:\Program Files\Microsoft Office\Office15\Excel.exe

D:\developer_jianshu_kunshan_zhantaizhi\jianshu_kunshan_haoruize\src\vbacomserver\vbacomserver.vbp

Type=OleExe
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\Windows\SysWOW64\stdole2.tlb#OLE Automation
Reference=*\G{00020813-0000-0000-C000-000000000046}#1.8#0#..\..\..\..\Thirdprogram\Microsoft Office2013\Office15\EXCEL.EXE#Microsoft Excel 15.0 Object Library
Class=Class1; Class1.cls
Startup="(None)"
HelpFile=""
Title="vbadllcomserver"
ExeName32="vbadllcomserver.exe"
Command32=""
Name="vbadllcomserver"
HelpContextID="0"
CompatibleMode="1"
CompatibleEXE32="vbadllcomserver.exe"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=1
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1

In the Class module(Class1), place the following code:

Sub Create_Batches_test()

MsgBox "结束序号 小于 起始序号", , "---- 提示 ----"

End Sub

 

You can use this dialog box to specify the following ActiveX server settings:

Project Type—Select whether the server is a ActiveX DLL (in process) or an ActiveX EXE (out of process)

1.Standard EXE

A standard exe application is one that is created using Standard EXE project. It is the most widely used Project type using VB6. Standard EXE application is normally the most widely used among the available Project types in Visual Basic. Stand-alone programs have an .EXE file extension.

A standard EXE application is normally used when you want to develop a stand-alone application. Examples include calculators, text editors, and other similar applications.

2.ActiveX EXE application

An ActiveX EXE application is one that is created using ActiveX EXE project. ActiveX EXE are widely used in conjunction with standard EXE applications. There are three types of widely used of ActiveX projects. These are:

a. ActiveX EXE
b. ActiveX DLL
c. ActiveX Control

ActiveX EXE: Unlike a stand-alone EXE file, an ActiveX EXE file is designed to work as an OLE server, which is nothing more than a program designed to share information with another program. It has an .EXE file extension.
ActiveX DLL: ActiveX DLL files are not meant to be used by themselves. Instead, these types of files contain subprograms designed to function as building blocks when creating a stand-alone program. It has a .DLL file extension.
ActiveX Control: Unlike an ActiveX DLL or ActiveX EXE file, an ActiveX Control file usually provides both subprograms and a user interface that you can reuse in other programs. It has an .OCX file extension.

part two:Register the Com Server on the system(windows)

step 1: Run Cmd as Administrator

You must be logged in as the administrator because registering applications require administrative privileges.

 

Win 10 Run Cmd as Administrator

 

Win7 Run Cmd as Administrator

 

To register, open a DOS command window and enter the executable's name followed by the /regserver option:

    C:\libraries\my_app.exe /regserver

To unregister, open a DOS command window and enter the executable's name followed by the /unregserver option:

    C:\libraries\my_app.exe /unregserver

ActiveX服务器采用可执行文件( .EXE )的形式。 在注册时一个. EXE 时,您必须使用 / RegServer 的来调用 .EXE 文件,步骤如下:

<.EXE 文件的完整路径> / RegServer

其中 <.EXE 文件的完整路径> 是 .EXE 服务器的位置。例如:
C:\ TestStand \ Bin \ REngine.exe / RegServer
要取消注册.EXE ActiveX服务器,请使用 / UnRegServer 。例如:
C:\ TestStand \ Bin \ REngine.exe / UnRegServer
D:\developer_jianshu_kunshan_zhantaizhi\jianshu_kunshan_haoruize\src\vbacomserver\vbadllcomserver.exe /regserver


D:\developer_jianshu_kunshan_zhantaizhi\jianshu_kunshan_haoruize\src\comserver\comserver.exe /regserver
D:\developer_jianshu_kunshan_zhantaizhi\jianshu_kunshan_haoruize\src\comserver\comserver.exe /unregserver

D:\developer_jianshu_kunshan_zhantaizhi\jianshu_kunshan_haoruize\src\vbacomserver\vbacomserver.exe /regserver
D:\developer_jianshu_kunshan_zhantaizhi\jianshu_kunshan_haoruize\src\vbacomserver\vbacomserver.exe /unregserver

 

D:\developer_jianshu_kunshan_zhantaizhi\jianshu_kunshan_haoruize\src\vbacomserver\vbadllcomserver.exe /unregserver

条件:close all opened excel   which is using  vbadllcomserver.exe

 

E:\SS-冲压\src\vbacomserver\vbadllcomserver.exe /regserver

E:\SS-冲压\src\vbacomserver\vbadllcomserver.exe /unregserver

E:\SS-冲压\src\vbacomserver\vbacomserver.exe /regserver

E:\SS-冲压\src\vbacomserver\vbacomserver.exe /unregserver

E:\SS-冲压\src\comserver\comserver.exe /regserver

E:\SS-冲压\src\comserver\comserver.exe /unregserver

you must register all the type and class information associated with the ActiveX exe.

注册表

regedit.exe

regspy2.exe vbacomserver.exe>>1.reg

regspy2 download url:
http://www.installsite.org/pages/en/tt_analyze.htm#RegSpy

 

 

ztz first install 

 

1.GUID

ActiveX EXE  register themselves creating an entry in the register.

Open regedit and search for your ActiveX EXE filename
If it is registered, you will find filename under a key that is under the TypeLib. The key will look like:

1.

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\TypeLib\{357AF534-2E3C-4360-8E14-578D1EF47130}]

[HKEY_CLASSES_ROOT\TypeLib\{357AF534-2E3C-4360-8E14-578D1EF47130}\4.0]
@="vbacomserver"

[HKEY_CLASSES_ROOT\TypeLib\{357AF534-2E3C-4360-8E14-578D1EF47130}\4.0\0]

[HKEY_CLASSES_ROOT\TypeLib\{357AF534-2E3C-4360-8E14-578D1EF47130}\4.0\0\win32]
@="E:\\SS-冲压\\src\\vbacomserver\\vbacomserver.exe"

[HKEY_CLASSES_ROOT\TypeLib\{357AF534-2E3C-4360-8E14-578D1EF47130}\4.0\FLAGS]
@="0"

[HKEY_CLASSES_ROOT\TypeLib\{357AF534-2E3C-4360-8E14-578D1EF47130}\4.0\HELPDIR]
@="E:\\SS-冲压\\src\\vbacomserver"

2.

A CLSID is a globally unique identifier that identifies a COM class object. If your server or container allows linking to its embedded objects, you need to register a CLSID for each supported class of objects.

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\vbacomserver.ClassModule1_Bar20190801]
@="vbacomserver.ClassModule1_Bar20190801"

[HKEY_CLASSES_ROOT\vbacomserver.ClassModule1_Bar20190801\Clsid]
@="{3DF7D3A4-20F8-4125-8616-1662366D5705}"

3.

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3DF7D3A4-20F8-4125-8616-1662366D5705}]
@="vbacomserver.ClassModule1_Bar20190801"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3DF7D3A4-20F8-4125-8616-1662366D5705}\Implemented Categories]

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3DF7D3A4-20F8-4125-8616-1662366D5705}\Implemented Categories\{40FC6ED5-2438-11CF-A3DB-080036F12502}]

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3DF7D3A4-20F8-4125-8616-1662366D5705}\LocalServer32]
@="E:\\SS-冲压\\src\\vbacomserver\\vbacomserver.exe"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3DF7D3A4-20F8-4125-8616-1662366D5705}\ProgID]
@="vbacomserver.ClassModule1_Bar20190801"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3DF7D3A4-20F8-4125-8616-1662366D5705}\Programmable]

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3DF7D3A4-20F8-4125-8616-1662366D5705}\TypeLib]
@="{357AF534-2E3C-4360-8E14-578D1EF47130}"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3DF7D3A4-20F8-4125-8616-1662366D5705}\VERSION]
@="4.0"

 

 

c#

[GuidAttribute("D26278EA-A7D0-4580-A48F-353D1E455E50"),
  ProgIdAttribute("My PROGID"),
  ComVisible(true),
  Serializable]
  public class MyCOMClass : IAlreadyRegisteredCOMInterface
  {
    public void MyMethod()
    {
    }

    [ComRegisterFunction]
    public static void RegisterFunction(Type t)
    {
      AttributeCollection attributes = TypeDescriptor.GetAttributes(t);
      ProgIdAttribute ProgIdAttr = attributes[typeof(ProgIdAttribute)] as ProgIdAttribute;

      string ProgId = ProgIdAttr != null ? ProgIdAttr.Value : t.FullName;

      GuidAttribute GUIDAttr = attributes[typeof(GuidAttribute)] as GuidAttribute;
      string GUID = "{" + GUIDAttr.Value + "}";

      RegistryKey localServer32 = Registry.ClassesRoot.CreateSubKey(String.Format("CLSID\\{0}\\LocalServer32", GUID));
      localServer32.SetValue(null, t.Module.FullyQualifiedName);

      RegistryKey CLSIDProgID = Registry.ClassesRoot.CreateSubKey(String.Format("CLSID\\{0}\\ProgId", GUID));
      CLSIDProgID.SetValue(null, ProgId);

      RegistryKey ProgIDCLSID = Registry.ClassesRoot.CreateSubKey(String.Format("CLSID\\{0}", ProgId));
      ProgIDCLSID.SetValue(null, GUID);

      //Registry.ClassesRoot.CreateSubKey(String.Format("CLSID\\{0}\\Implemented Categories\\{{63D5F432-CFE4-11D1-B2C8-0060083BA1FB}}", GUID));
      //Registry.ClassesRoot.CreateSubKey(String.Format("CLSID\\{0}\\Implemented Categories\\{{63D5F430-CFE4-11d1-B2C8-0060083BA1FB}}", GUID));
      //Registry.ClassesRoot.CreateSubKey(String.Format("CLSID\\{0}\\Implemented Categories\\{{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}}", GUID));
    }

    [ComUnregisterFunction]
    public static void UnregisterFunction(Type t)
    {
      AttributeCollection attributes = TypeDescriptor.GetAttributes(t);
      ProgIdAttribute ProgIdAttr = attributes[typeof(ProgIdAttribute)] as ProgIdAttribute;

      string ProgId = ProgIdAttr != null ? ProgIdAttr.Value : t.FullName;

      Registry.ClassesRoot.DeleteSubKeyTree("CLSID\\{" + t.GUID + "}");
      Registry.ClassesRoot.DeleteSubKeyTree("CLSID\\" + ProgId);
    }

  }

 

Part three:How to use in Excel VBA Code

You can bind your DLL or EXE either at runtime (late binding) or at design time (early binding). When you use early binding, you tell the main program all about the DLL. That lets it do things like provide intellisense for the DLL's methods. It is also faster than late binding.

s1:Early binding 

step 1:  Add an object library reference comserver in your VBA Project 

From the Tools menu, choose References to display the References dialog box.

The References dialog box shows all object libraries registered with the operating system. Scroll through the list for the application whose object library you want to reference.

If the application isn't listed, you can use the Browse button to search for object libraries (*.olb and *.tlb) or executable files (*.exe and *.dll on Windows). References whose check boxes are selected are used by your project;

vba的引用里面可以找到刚才注册的Comserver.勾选上我们就能在vba里调用里面的类了

 

step 2:vba code

 

'**************************************************************
Sub Create_Batches()
    
    Dim s As New vbacomserver.Class1
Dim sd As Object


 s.Create_BatchesNew
 
 Set s = Nothing



End Sub

 

s2:Late binding 

Another option is to have the CreateObject call in an ActiveX EXE which runs outside of your process.

Dim obj As Object
//Set obj = CreateObject("MyComponent.MyObject")
Set obj = CreateObject("vbacomserver.Class1")

CreateObject is used to start a new instance of an Automation server.

Late binding is used when variables are declared As Object, because the compiler doesn’t know the class ID of the objects and interfaces that may be assigned to the variable at run time. Applications that use late binding create instances of your classes using the CreateObject function and the programmatic ID.

The CreateObject function looks up the class ID in the Windows Registry, and uses it to create the object. Thus it will always create the most recent version of the object.

As long as you preserve binary compatibility, late-bound clients will continue to work successfully with your component.

If you make an incompatible version of your component using the same programmatic IDs for your objects, late-bound clients can still create the objects, because they’re looking up the class ID instead of having it compiled in. When they call methods whose arguments have changed, or methods you’ve deleted, program failure or data corruption may occur.

Depending on whether the server is designed as SingleUse or MultiUse, another server process may or may not be launched. This might be an important distinction for deciding whether you should forcibly shut down an Automation instance. For example, with a MultiUse server, if an instance is already running before you attach to it, then you might want to avoid shutting down the server programmatically when you are done automating it.

other:

Unattended Execution

ActiveX EXE, then set the Unattended Execution flag in the project properties. If this flag is set, then any user interaction elements are not shown but written to the event log. However, depending on your code this may obviously cause problems. Especially, if you are checking for Yes/No/Cancel. And no offense but that would be completely wrong in a server app.

Instancing property

MultiUse

https://www.developer.com/microsoft/visual-basic/the-com-course-part-3/

http://www.vb-helper.com/howto_activex_dll.html

ensure that MessageBox is ALWAYS on Top

Showing a modal form from an out-of-process OLE Server is generally not recommended. One reason is that the modal form may be displayed behind the client program, making it difficult for the user to see that it needs to be addressed.

Add vbSystemModal

vbMsgBoxSetForeground

 result = MsgBox("请确认以下信息的正确性,正确选 Y ,不正确选 N " & vbNewLine & "每批数量=" & Qty & "         班次= " & shift & vbNewLine & "起始序号= " & startLot & "           结束批次= " & endlot & vbNewLine & "原材料= " & PRaw & "       机台号=" & NMach & vbNewLine & "作业员= " & LOpra & "       检验员=" & MInsp, vbYesNo + vbSystemModal, "确认信息正确")
    If result = vbNo Then
        Exit Sub
    End If

register ActiveX exe

1.how can i register ActiveX exe?

An ActiveX-EXE can never be registered with regsvr32.exe.In other words EXE files are not registered via the normal regsvr32.exe mechanism. This is the tool used to register COM dll's and OCX files, but it does not handle EXE files. 

An ActiveX-EXE- this type of ActiveX component is self registered by the first execution of itself. So simply run the ActiveX-EXE to register it

to register activexDLL: regsvr32 /s yourFile.dll
to unregister activexDLL: regsvr32 /u yourFile.dll
to register activexEXE: yourexeName.exe /regserver
to unregister activexEXE: yourexeName.exe /unregserver

2.What happens if i manually register an activex exe with /regserver switch which is already registered?


 
It's harmless, it just re-writes the same registry entries that were already there.

Note that if you've changed the COM object ProgIds and such in the EXE in the meantime, it's really important to unregister the old before registering the new, or you end up with cruft in the registry. The registry is quite good enough at "crufting" itself, it doesn't need our help... ;-)

you can do:

REGEDIT4

; ActiveX DLLs

[HKEY_CLASSES_ROOT\.dll]
@="dllfile"

[HKEY_CLASSES_ROOT\dllfile\shell\regdll]
@="Register ActiveX DLL"

[HKEY_CLASSES_ROOT\dllfile\shell\regdll\command]
@="regsvr32.exe \"%L\""

[HKEY_CLASSES_ROOT\dllfile\shell\unregdll]
@="Unregister ActiveX DLL"

[HKEY_CLASSES_ROOT\dllfile\shell\unregdll\command]
@="regsvr32.exe /u \"%L\""

; ActiveX Controls

[HKEY_CLASSES_ROOT\.ocx]
@="ocxfile"

[HKEY_CLASSES_ROOT\ocxfile\shell\regocx]
@="Register OCX Control"

[HKEY_CLASSES_ROOT\ocxfile\shell\regocx\command]
@="regsvr32.exe \"%L\""

[HKEY_CLASSES_ROOT\ocxfile\shell\unregocx]
@="Unregister OCX Control"

[HKEY_CLASSES_ROOT\ocxfile\shell\unregocx\command]
@="regsvr32.exe /u \"%L\""

; ActiveX EXEs

[HKEY_CLASSES_ROOT\.exe]
@="exefile"

[HKEY_CLASSES_ROOT\exefile\shell\regexe]
@="Register ActiveX EXE"

[HKEY_CLASSES_ROOT\exefile\shell\regexe\command]
@="cmd /c \"%L\" /regserver"

[HKEY_CLASSES_ROOT\exefile\shell\unregexe]
@="Unregister Active EXE"

[HKEY_CLASSES_ROOT\exefile\shell\unregexe\command]
@="cmd /c \"%L\" /unregserver"

 

用VB6编写Active EXE时的注册过程
在VB中编写ActiveX EXE时,调试运行时,VB自动把注册信息临时性的写入到注册表中.
这个位置在HKEY_CLASSES_ROOT\VBKeySave5或
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\VBKeySave5中,里面的信息估计只
有VB能懂
示例如下:
VBKeySave5
    0000004b.S01381e94
        DeleteCL
            {EB21B48D-43F3-401D-BFB8-A0C95E743A37}
        DeleteIF
            {又一个老长的UUID}
        DeletePI
            Project1.Class1
    0000004b.T0000004
        DeleteTI
            {再一个不作用未详的UUID}
这样其它组件能生成该Active EXE中的对象.当调试终止时,VB又自动把注册表中的信
息删除了.当ActiveX EXE编译完成时,VB会自动注册,当在目标机器上第一次运行时,
ActiveX EXE自动也将自动注册.当注册后,把该Active EXE文件移动到其他目录位置运行时,
Active EXE并不会"修正"注册表中的注册信息(InprocServer32键中所指的原注册位置)
但当该Active EXE再次运行时,其它的组件却能生成该ActiveX EXE中的对象.对于Active EXE
来说,InprocServer32的意义是当ActiveXEXE没有运行时,客户调用CreateObject能自动找到
该ActiveX EXE组件并加载它以生成对象.

任何ActiveX组件注册时的写入下列信息:
向HKEY_CLASSES_ROOT\CLSID和HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
主键下写入该Active组件中每个COM类的信息,每个类
都有一个CLSID.如:

HKEY_CLASSES_ROOT\CLSID(或HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID)
    {EB21B48D-43F3-401D-BFB8-A0C95E743A37}(这是组件类的标识ID,即CLSID)
        Implemented Categories
            {40FC6ED5-2438-11CF-A3DB-080036F12502}
        LocalServer32(在哪个文件中实现的)
        ProgID(创建该类对象时所用的"编程名称",如Project1.Class1)
        Programmable(是否可编程)
        TypeLib(类型库ID,也是一个全局唯一标识符)
         VERSION(版本)

HKEY_CLASSES_ROOT(或HKEY_LOCAL_MACHINE\SOFTWARE\Classes)
    Project1.Class1
        Clsid(即上述的{EB21B48D-43F3-401D-BFB8-A0C95E743A37})

在编译并注册后,还在HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib和
HKEY_CLASSES_ROOT\TypeLib下写入代表该ActiveX EXE组件的类型库标识(UUID)

ActiveX EXE工程在编译的时候就自动注册了,可以在 “开始”->“运行”->输入dcomcnfg,在DCOM 配置属性中可以看到已注册的组件

ActiveX EXE的注册
  作为一种进程外运行的组件,ActiveX EXE的注册方法异于ActiveX控件和ActiveX DLL的注册,并且在运用中有一定的难度。在此,将它们的注册方法总结如下:
  (1)“浏览”的方法。以VB6.0为例。在VB6.0编程界面上,进入“工程”,在弹出的下拉菜单中间选择“引用”,然后在出现的新界面上点击“浏览”,找到并选中需要注册的组件,确定后,便可以在列表中间看到对应项了。
  (2)直接运行的方法。注册进程外组件ActiveX EXE时,只要在VB6.0的环境中运行一下该组件代码,便可以实现注册了。这时ActiveX EXE的信息被加入到Windows注册表中。但是,必须注意,此信息只是在VB开发环境中运行此程序时被临时加入。当程序停止时,有关如何访问这些对象的信息便从系统中清除掉。
  (3)利用安装制作工具。比如在VB6.0中,可以利用VB6.0本身自带的创建安装程序的工具软件:Package & Deployment Wizard。在创建安装程序的过程中,自动将其变为自注册。若不然,同样可以修改安装程序的安装文件列表 setup.lst。将相应宏中的参数设置为EXESelfRegister。如果不需要自注册,可以将该项删除(注意逗号要保留)。
  例如下面是作者自己编的一个进程外组件 ,利用上述方法创建安装程序后,其后面的参数变为:
  [Setup1 Files]
  [email protected],$(WinSysPath),$(EXESelfRegister),$(Shared),12/25/00 8:47:44 PM,57344,1.0.0.0
  其中,加粗的一项 $(EXESelfRegister) 就是标明自注册的宏参数设置。可以手工加或删。
  (4)如果打算把进程外服务器安装到另外一台机器上自注册,而且脱离编程环境时,可以先将文件拷贝到另外机器上,执行时在命令行上加上参数 “ /regserver”,如果取消注册,可以在命令行上加上“ /unregserver”。使用 /regserver命令选项注册进程外COM服务器时,可以不去理会手工启动时程序工作的正常方式。Sub Main或Class_Initialize程序都不会被调用,只有由当该编程环境包括在EXE文件中的注册逻辑才会运行。

 

 

VB6 COM Guid Regeneration during Build

1.I have a mass of dlls and ocxs built in VB6, each time I rebuild these projects all the guids representing the objects are changed. I build using VB6.exe /make.

This causes me a lot of problems with some .net code that uses these components, i.e. if I build the vb6 I have to regenerate the .net interop dlls to reflect the new GUIDs

So my question is: Is there a way to Fix the GUIDs so they never change no matter how many times the vb6 projects are rebuilt?

2.I did have binary compatability on, but still got new guids. However your answer led me to look at it in more detail and I discovered that the binary compatable dll referrenced had a different type lib version to the dll I was buildinf and hense generated new guids. I updated the dll reference and hey presto consistant guids.

Solution 1

Set Binary Compatibility in Component tab of project properties.

you can tell VB6 to reuse GUID's by changing the compatbility setting of the project to from "No Compatbility" to "Binary Compatibility". You can find these settings under Project->Your-Project Properties. The compatibility setting is on the Component tab of the Project Properties window.

Open the project.

From the Project menu, choose Project Properties to open the Project Properties dialog box, and select the Component tab.

Click Binary Compatibility to lock down the class IDs in the project.

Visual Basic’s Version Compatibility feature is a way of enhancing your components while maintaining backward compatibility with programs that were compiled using earlier versions. The Version Compatibility box, located on the Component tab of the Project Properties dialog box, contains three options:

No Compatibility: Each time you compile the component, new type library information is generated, including new class IDs and new interface IDs. There is no relation between versions of a component, and programs compiled to use one version cannot use subsequent versions.
Project Compatibility: Each time you compile the component the type library identifier is kept, so that your test projects can maintain their references to the component project. All class IDs from the previous version are maintained; interface IDs are changed only for classes that are no longer binary-compatible with their earlier counterparts.

Note   This is a change in Project Compatibility from Visual Basic 5.0, where all class IDs and interface IDs in the project changed if any one class was no longer binary-compatible.

Important   For the purpose of releasing compatible versions of a component, Project Compatibility is the same as No Compatibility.
Binary Compatibility: When you compile the project, if any binary-incompatible changes are detected you will be presented with a warning dialog. If you choose to accept the warning, the component will retain the type library identifier and the class IDs. Interface IDs are changed only for classes that are no longer binary-compatible. This is the same behavior as Project Compatibility.

If, however, you choose to ignore the warning, the component will also maintain the interface IDs. This option is only available when the compiler determines that the change was in the procedure ID or signature of a method.

Caution   You should only choose the Ignore button if you are absolutely sure that the changes you have made won't break compatibility. If you aren't absolutely sure, take the safe alternative and choose the Accept button to allow the interface ID's to be changed.

Important   The option to override the compiler's warning represents a change in behavior from Visual Basic 5.0. It is important that you fully understand the implications of incompatible changes before proceeding with this option.

Note   When people talk about Version Compatibility, they’re usually referring to Binary Compatibility.

The appropriate use of these options is described below:https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-basic-6/aa241689(v=vs.60)

 

 

 

 

 

Useful links

create com server (vb6 activex .exe)

https://blog.csdn.net/qq_24499417/article/details/104771705

Creating an ActiveX EXE Component(vb6 activex .exe)

https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-basic-6/aa262306(v=vs.60)

create com server (c++)

https://blog.csdn.net/nie2314550441/article/details/49867735 

create com server ActiveX EXE Wrappers step by step(with VB.NET applications and Visual Studio 2005)

https://www.codeproject.com/Articles/16499/ActiveX-EXE-Wrappers

ActiveX EXE实现多线程抓取网页

https://club.excelhome.net/thread-1163930-1-1.html

event and vba 进度条

https://docs.microsoft.com/en-us/previous-versions/bb397409(v=vs.80)?redirectedfrom=MSDN

 

 

COM interop技术理论/实践

https://q.cnblogs.com/q/28231/

COM跨进程组件开发实战系列

https://zhuanlan.zhihu.com/p/127357940