我自己制作了一个控件(my.ocx),这个控件在制作该控件的计算机上运行正常。但是,将带有这个控件的一个程序打包(打包已包括了my.ocx,并安装到c:\windows\system目录下)后,安装到别的计算机中,程序却不能正常运行,连窗体都没有打开就结束了。但是,如果将这个程序的源代码复制到该计算机,重新编译程序,程序却能正常运行。这是什么原因呢?如何使自制的控件可以自由地安装到别的计算机?
问题解决,立即给分。

解决方案 »

  1.   

    在安装时,要同时给MY.OCX注册,你可以在你的打包工具里看看有没有注册OCX的方法
      

  2.   

    这个是没有注册的原因了,VB自带的打包工具好像不能自动注册
    你用install sheild 肯定不会有这种问题的楼主搜索一下以前的帖子,自动注册解决了,你的问题就解决了
      

  3.   

    自动注册可以调用windows的程序来完成、、、、、
      

  4.   

    可以用一个笨办法,就是做一个bat文件
    先写入regsvr32 xxx.ocx,然后在写入setup.exe,这样就可以在注册后再运行安装程序了
      

  5.   

    程序注册
    用安装工厂或者install sheild打包手工注册
    regsvr32 xxx.ocx
      

  6.   

    我运用了 regsvr32 my.ocx 手工注册,并且提示注册成功,但是故障依然如故?什么原因?在编译后的文件夹中,除my.ocx外,还有三个文件:my.lib、my.exp、my.oca,它们分别是什么文件?有什么用?
      

  7.   

    你试一下吧,估计是因为控件的版本或兼容性闹的。
    假设你主程序的工程是prjA,你ocx的工程是prjB,首先你要单独编译prjB,然后在单独编译prjA,注意,编译prjA的时候不要包含prjB的工程。然后在用VB自带的打包程序打包,打包的时候注意,VB自带的打包程序会提示“编译好的文件比工程旧”,问你是否重新编译,这个时候选否。
    这样你再试试。
      

  8.   

    顺便说一句,oca是控件保存一些自身设置的属性等临时数据的地方,不用去管他;lib和exp好像是记录了ocx的接口,记不清了。
      

  9.   

    在打包时是否也要打包my.lib、my.exp、my.oca这三个文件呢?
      

  10.   

    ocx控件的注册信息存在注册表什么地方?
    同样是这个my.ocx控件,有一次我试过只是指导它与exe文件复制到别的计算机就能正常运行了,连注册也不用,这次却注册也不行,为什么呢?
      

  11.   

    调用控件的窗体文件中有这么一串字符:
    Object = "{FF4B3869-D68C-11E0-8D08-9552CDFA083B}#1.0#0"; "my.ocx"
    每次编译后正常使用时它的内容都不同,故计问题出在这里,如果自己写程序将控件注册的话,应如何注册,是否应将这一串字符写入注册表,写到哪里?
    我把控件的工程设为“二进制兼容”,为何却出现版本不同的现象呢?
      

  12.   

    打包时不用打那三个文件。
    ocx注册信息你可以以他的工程名的方式去搜索。
    Object = "{FF4B3869-D68C-11E0-8D08-9552CDFA083B}#1.0#0"; "my.ocx"
    上面这一行中,那一长串的字符被称为CLsID,是判断一个ocx身份重要依据,也就是ocx和dll的身份证,如果他改变了,那么windows就会认为这个ocx和原先的不是一个。
    保持2进制兼容,有几个要求:首先,在工程的属性中,你必须为2进制兼容选择上被兼容的源文件,否则,就只能使用不兼容或工程兼容;其次,两次编译中,要保持2进制兼容,必须要保持接口一致,包括公有函数的函数名、参数类型等,这些是绝对不能被修改的,不过有些也可以,我印象当中,比如原先的一个参数是TextBox类型,那你可以改成Object类型而不破坏2进制兼容。容易被忽略的接口包括一些常数的定义。另外,2进制兼容下允许新增接口,所以在需要对现有接口扩充的时候,还是新增几个接口比较好。
      

  13.   

    百思不得其解,谁能解答,额外给50分。
    为弄清楚OCX控件是如何注册的,我做了如下操作,出现的现象如下:
    1、单独编译my.ocx控件,正常
    2、打开VB工程,加载my.ocx控件,编译工程成exe文件。生成的程序能正常运行。
    3、重新启动计算机,进入Dos,用原来备份的旧的注册表覆盖现有的注册表。重新进入windows,VB工程与编译后的exe文件都不能正常运行。
    3、用regsvr32注册控件,成功后,在注册表中找到如下的四个个相关主键:(1)HKEY_LOCAL_MACHINE\Software\CLASSES\CLSID\{FF4B3877-D68C-11E0-8D08-9552CDFA083B}
    (2)HKEY_LOCAL_MACHINE\Software\CLASSES\TypeLib\{FF4B3869-D68C-11E0-8D08-9552CDFA083B}
    (3)HKEY_CLASSES_BOOT\CLSID\{FF4B3877-D68C-11E0-8D08-9552CDFA083B}
    (4)HKEY_CLASSES_BOOT\TypeLib\{FF4B3869-D68C-11E0-8D08-9552CDFA083B}4、重新试启动相关VB工程,工程运行正常。
    5、重新试运行相关的编译后的EXE程序,程序运行不正常,故障依旧。
    6、重新编译EXE程序,程序运行正常。
    7、删除主键(1),发现VB工程可以正常启动,但不能调试运行,提示找不到相关控件的CLSID信息。说明这一主键与VB工程的调试运行有关。
    8、删除主键(2),发现VB工程无法加载,说明这人主键记录的是工程部件中的信息。
    9、再次试运行EXE程序,程序居然能正常运行,而且它自动在注册表中添加相关的主键(1),即:
    10、删除(3)、(4),程序仍能运行,并自动创建(3)、(4)
    HKEY_LOCAL_MACHINE\Software\CLASSES\CLSID\{FF4B3877-D68C-11E0-8D08-9552CDFA083B}
    10、试启动VB工程,仍无法加载,因为仍缺少主键(2)的信息。结论:主键(1)与程序的运行有关,主键(2)与工程的加载有关。问题:1、为什么用旧的注册表覆盖现有的注册表后,工程与程序无论如何都不能正常运行(包括用regsvr32注册),而在重编译后,虽然删除了主键(1)与主键(2),但程序仍能运行,而且自动添加主键(1),是不是在程序编译时,在注册表中还记录了一些相关信息呢(我想一定是有的)?它们在哪里呢?(目前我找不到这些信息)请高手帮解决这个疑问,分一定送上。最新的发现:我的这个OCX故障与OCX本身的注册与否无关(即使OCX控件没有注册,运行相关的exe程序,OCX控件将会自动注册),问题的出现与程序的编译有关,也与OCX控件脱不了关系,有关的代码我也已找到,但还没有弄清其内在原因,现将相关代码贴出,请高手分析一下。一、OCx控件中相关的代码:
    (1)OCX中相关的结构体及变量的定义:
    Public Type PrinterInfos
      POjbect As Object '打印机
      PageType As Integer  '纸张类型
      SheetAspect As pshat   '纸张方向
      TitleText As String 'bttxt,标题
      TitleFont As StdFont '标题字体
      TableHeadFont As StdFont  '表头字体
      MainFont As StdFont '主字体
      Ltext As String 'ltxt,左边页眉
      Btext As String 'Btxt,居中页眉
      Rtext As String 'Rtxt,右边页眉
      LeftSx As Double 'Leftx左边距
      TopSy As Double 'TopY上边距
      RightSx As Double '右边距
      DownSy As Double '下边距
      TableTop As Double '表格主体顶端
      LineWidth As Long '表格线宽
      CenterMode As Boolean 'JzMode对齐模式
      ZoomScale As Double 'MyZoom缩放比例
      RowH As Long '表格行高
      ListScale As Double '表格列比例
      ULtext As String '左边页脚
      UBtext As String '居中页脚
      URtest As String  '右中页脚
      TellText As String  '说明文字
      ColorOrBlack As Boolean '决定彩色或黑白打印
    End Type
    dim printerinfo as printerinfos(2)UserControl_Initialize()事件中相关代码:
    Private Sub UserControl_Initialize()
    ……
    With PrinterInfo
      Set .POjbect = Printer
      .PageType = 9
      .SheetAspect = 1
      .TitleText = ""
      Set .TitleFont = New StdFont
      .TitleFont.name = "黑体"
      .TitleFont.Size = 16
      .TitleFont.Bold = True
      Set .TableHeadFont = New StdFont  '表头字体
      .TableHeadFont.name = "黑体"
      .TableHeadFont.Size = 12
      .TableHeadFont.Bold = True
      Set .MainFont = New StdFont '主字体
      .MainFont.name = "宋体"
      .MainFont.Size = 12
      .Ltext = "" 'ltxt,左边页眉
      .Btext = "" 'Btxt,居中页眉
      .Rtext = "" 'Rtxt,右边页眉
      .LeftSx = 2.5 'Leftx左边距
      .TopSy = 3 'TopY上边距
      .RightSx = 2.5 '右边距
      .DownSy = 3 '下边距
      .LineWidth = 1 '表格线宽
      .CenterMode = True 'JzMode对齐模式
      .ZoomScale = 1 'MyZoom缩放比例
      .RowH = 400 '表格行高
      .ListScale = 1 '表格列比例
      .ULtext = "" '左边页脚
      .UBtext = "" '居中页脚
      .URtest = "" '右边页脚
      .TellText = "" '说明文字
      .ColorOrBlack = False
    End With(3) PrinterInfoGet方法
    Public Function PrinterInfoGet() As PrinterInfos
       With PrinterInfoGet
          Set .POjbect = PrinterInfo.POjbect
          .Btext = PrinterInfo.Btext
          .CenterMode = PrinterInfo.CenterMode
          .LeftSx = PrinterInfo.LeftSx
          .ListScale = PrinterInfo.ListScale
          .Ltext = PrinterInfo.Ltext
          Set .MainFont = PrinterInfo.MainFont
          .PageType = PrinterInfo.PageType
          .RowH = PrinterInfo.RowH
          .Rtext = PrinterInfo.Rtext
          .SheetAspect = PrinterInfo.SheetAspect
          Set .TableHeadFont = PrinterInfo.TableHeadFont
          .TellText = PrinterInfo.TellText
          Set .TitleFont = PrinterInfo.TitleFont
          .TitleText = PrinterInfo.TitleText
          .TopSy = PrinterInfo.TopSy
           .RightSx = PrinterInfo.RightSx
           .DownSy = PrinterInfo.DownSy
           .LineWidth = PrinterInfo.LineWidth
          .UBtext = PrinterInfo.UBtext
          .ULtext = PrinterInfo.ULtext
          .URtest = PrinterInfo.URtest
          .ZoomScale = PrinterInfo.ZoomScale
          .ColorOrBlack = PrinterInfo.ColorOrBlack
       End With
    End Function(4)PrinterInfoSet 方法
    Public Sub PrinterInfoSet(NewPrinterInfo As PrinterInfos)
       With PrinterInfo
          Set .POjbect = NewPrinterInfo.POjbect
          .Btext = NewPrinterInfo.Btext
          .CenterMode = NewPrinterInfo.CenterMode
          .LeftSx = NewPrinterInfo.LeftSx
          .ListScale = NewPrinterInfo.ListScale
          .Ltext = NewPrinterInfo.Ltext
          Set .MainFont = NewPrinterInfo.MainFont
          .PageType = NewPrinterInfo.PageType
          .RowH = NewPrinterInfo.RowH
          .Rtext = NewPrinterInfo.Rtext
          .SheetAspect = NewPrinterInfo.SheetAspect
          Set .TableHeadFont = NewPrinterInfo.TableHeadFont
          .TellText = NewPrinterInfo.TellText
          Set .TitleFont = NewPrinterInfo.TitleFont
          .TitleText = NewPrinterInfo.TitleText
          .TopSy = NewPrinterInfo.TopSy
           .RightSx = NewPrinterInfo.RightSx
           .DownSy = NewPrinterInfo.DownSy
           .LineWidth = NewPrinterInfo.LineWidth
          .UBtext = NewPrinterInfo.UBtext
          .ULtext = NewPrinterInfo.ULtext
          .URtest = NewPrinterInfo.URtest
          .ZoomScale = NewPrinterInfo.ZoomScale
          .ColorOrBlack = NewPrinterInfo.ColorOrBlack
       End With
    End Sub二、VB工程中的相关代码
    Private Sub Command7_Click()
    Dim pr As myv10.PrinterInfos 'myv10是控件的库名称
    pr = my1.PrinterInfoGet 'my1是控件实例的名称
    pr.TitleText = "2004年初中教师花名册"
    pr.TableHeadFont.Size = 9
    pr.TableHeadFont.Name = "宋体"
    pr.TableHeadFont.Bold = False
    pr.MainFont.Size = 9
    pr.Ltext = "填表单位:"
    pr.TableTop = pr.TableTop - 0.6
    pr.ULtext = "制表人:"
    pr.UBtext = "审核人:"
    pr.URtest = "单位负责人:"
    pr.LineWidth = 1
    pr.TellText = "注:(1)公办教师。" & Chr(13) & "    (2)代课教师。"
    my1.PrinterInfoSet pr
    End Sub现象:如果在Private Sub Command7_Click()中去掉
    pr = my1.PrinterInfoGet
    my1.PrinterInfoSet pr
    这两句,那么工程编译后无论如何改动注册表,均能正常运行。
    如果有上述两句中的任何一句,注册表改动后,程序将不能正常运行,必须重新编译后才能正常运行。
    十分奇怪的是,这部分代码是在command7的事件中,程序运行应该不会发生,为什么会影响到整程序都不能正常运行呢?(程序的主窗体都不能出现)。它们又与注册表有什么关系呢?
      

  14.   

    经查实,问题不出在版,也不出在OCX注册,而与上面的代码有关,请指教。
      

  15.   

    问题我已找到,全是VB的错,因为他根本就不想我们发布用VB开发的程序!
    主要原因的我在控件中用了:
    public type printerinfos 
    ……
    end type
    并且在VB工程中用调用了它。
    要使用
    public type printerinfos 
    ……
    end type
    程序在编译时,将生成一个叫做vbc*.oca的文件,而且在注册表中注册,可悲的是,程序每一次编译时,生成的vbc*.ocx文件均不同(这全是VB的错,又要生成它,又不告诉我们,在csdn中也没有相关信息)
    软件发布,不会打包这个文件,更不知它的注册ID,所以别指望发布这样的程序了,只可在本机用。他妈的VB!更惨的是,VB会生成很多这样的OCA文件,不信你自己查一下,我们根本不知哪个程序对应哪个!
    盖次相本不想让我们在控件中使用
    public type printerinfos 
    ……
    end type
    (不使用这个,要不要OCA文件无所谓,注不注册无所谓!)
      

  16.   

    楼主啊,编译ocx的时候选择二进制兼容就不会每次编译产生不同的ID了
      

  17.   

    gcj123呀,我选的就是进制兼容,不是编译OCX时产生不同的ID,而地编译EXE程序时产生不同的ID,是EXE的ID。OCX的OCA文件与OCX文件同名,同在windwos\system\目录下,exe的oca文件在VB目录下文件名为vbc(一串数字).oca.
      

  18.   

    VB还有更怪的你们一定还没有见过:
    你见过一个工程改动后,而且重新保存了,但编译后运行,却是未改动前的效果。就算你把原来编译的EXE文件删了,重新编译后还是如此,就象代码没有改动过一样。把工程的属性的优化性质设成代码最小化,便会发生这种情况,而且是偶尔发生的。
    闻所未闻,见所未见吧!
      

  19.   

    选择二进制兼容,并保证这个键在就行了
    (4)HKEY_CLASSES_BOOT\TypeLib\{FF4B3869-D68C-11E0-8D08-9552CDFA083B}
      

  20.   

    引:问题我已找到,全是VB的错,因为他根本就不想我们发布用VB开发的程序!VB没有错.我做DLL和OCX都有一百几十个了,相同的问题我也曾经历过.改进的方法如下.1.问题可能在这里吧 
      TableHeadFont As StdFont  '表头字体
      改成:
      TableHeadFont As Variant 或 Object  '表头字体
      在OCX或DLL中,所有具体定义的控件(除标准EXE的控件以外),一律用Object 代替.所有其它对象用Variant代替.在自定义类型中不能出现具体的类型.只能用Object 或 Variant
    2.将
       PUBLIC TYPE ....
              ....................
       END TYPE 
       放在一个类模块中去定义.
      

  21.   

    啊,stdFont,呵呵,的确,用VB做类并且选择了2进制兼容之后,会经常告诉你stdfont对象发生变化,我也碰上过好几次,总结原因,感觉可能是因为ole版本的变化导致的,所以,一旦编译用的机子的office、ie、service pack等发生变化,就会导致ole版本的变化,也就有可能让stdfont发生变化,改成object可能是最好的解决办法了。
    真的很不明白,micrsoft为什么退出些什么东西都要去该ole对象的版本。