微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C#制作ActiveX控件中如何调用海康SDK的问题解决

  这个事情就是一个坑,耽误了两周时间,之前并没有做过ActiveX这玩意,现在客户需求如此,只能说是在网上看着教程做了。

  事情是这样的,有一台海康威视的摄像头,客户需要一个ActiveX控件嵌入到网页中,通过点击按钮开始录制和结束录制来进行视频的录制和保存,关于海康摄像头的二次开发在此就不多说了,可以参考SDK中的说明。

  直接上流程:

  1.开发环境:

    VS2010,这个打包方便,之前用VS2013打包的,总是调用不了,不知道原因是什么;SDK是32位的,用64位的在Winform中可以正常使用,在网页中使用控件时会报错。

  2.新建项目:

    新建一个类库项目,如下:

    右键点击项目,添加用户控件”,如下:

    界面拖控件,如下:

    控件代码如下,其中Guid是“工具”->“创建GUID”自动生成的,#region->#endregion折叠部分是实现的IObjectSafety接口

using System;

namespace VideoHelper
{
    [System.Security.SecuritySafeCritical]
    public class Videos
    {
        private bool m_initSDK = false;
        /// <summary>
        /// 正在录制
        /// </summary>
        private bool m_Record = false;
        private uint LastErr = 0;
        private Int32 m_RealHandle = -1;
        private Int32 m_lUserID = -1;
        public IntPtr handle { get; set; }
        public bool Initialize(string ip = 192.168.1.64, int port = 8000, string username = admin, string password = 8910jqk#)
        {
            try
            {
                m_initSDK = CHCNetSDK.NET_DVR_Init();
                if (m_initSDK)
                {
                    CHCNetSDK.NET_DVR_SetLogToFile(3, C:\\SdkLog\\, true);
                    //设备参数结构体
                    CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V30();
                    //注册设备
                    m_lUserID = CHCNetSDK.NET_DVR_Login_V30(ip, port, username, password, ref DeviceInfo);
                    return m_lUserID >= 0;
                }
                return false;
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(Initialize: + ex.Message);
                return false;
            }
        }

        public bool Start(IntPtr handle, string filename)
        {
            try
            {
                CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO();
                lpPreviewInfo.lChannel = 1;
                lpPreviewInfo.dwLinkMode = 0;
                lpPreviewInfo.dwStreamType = 0;
                lpPreviewInfo.bBlocked = true;
                lpPreviewInfo.dwdisplayBufNum = 15;
                lpPreviewInfo.hPlayWnd = handle;
                IntPtr pUser = IntPtr.Zero;//new IntPtr();         
                //获取实时视频流
                m_RealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, null, pUser);
                if (m_Record == false)
                {
                    CHCNetSDK.NET_DVR_MakeKeyFrame(m_lUserID, 1);
                    if (!CHCNetSDK.NET_DVR_SaveRealData(m_RealHandle, filename))
                    {
                        LastErr = CHCNetSDK.NET_DVR_GetLastError();
                        return false;
                    }
                    else
                    {
                        m_Record = true;
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

        public bool End()
        {
            if (m_Record)
            {
                if (!CHCNetSDK.NET_DVR_StopSaveRealData(m_RealHandle))
                {
                    LastErr = CHCNetSDK.NET_DVR_GetLastError();
                    return false;
                }
                m_Record = false;
                m_RealHandle = -1;
                return true;
            }
            else
            {
                return false;
            }
        }

        public void dispose()
        {
            try
            {
                if (m_lUserID >= 0)
                {
                    CHCNetSDK.NET_DVR_logout_V30(m_lUserID);
                    m_lUserID = -1;
                }

                if (m_RealHandle >= 0)
                {
                    CHCNetSDK.NET_DVR_StopRealPlay(m_RealHandle);
                    m_RealHandle = -1;
                }

                CHCNetSDK.NET_DVR_Cleanup();
            }
            catch
            { }
        }
    }
}

录制视频操作类

录制视频操作类

using System;
using System.Runtime.InteropServices;

namespace VideoHelper
{
    [ComImport, GuidAttribute(CB5BDC81-93C1-11CF-8F20-00805F2CD064)]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnkNown)]
    public interface IObjectSafety
    {
        [PreserveSig]
        int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);

        [PreserveSig()]
        int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
    }
}

接口代码
using System;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
namespace VideoHelper
{
    [System.Security.SecuritySafeCritical]
    [Guid(79629620-3C0C-4D47-B93B-2D36AEF8EF31)]
    public partial class VideoControl : UserControl,IObjectSafety
    {
        public VideoControl()
        {
            InitializeComponent();
        }
        string videopath = Environment.CurrentDirectory;
        Videos video;
        IntPtr handle;
        private void btnLogin_Click(object sender, EventArgs e)
        {
            if (btnLogin.Text == 登录)
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(this.txtIP.Text))
                    {
                        MessageBox.Show(IP地址不能为空!);
                        return;
                    }
                    if (string.IsNullOrWhiteSpace(this.txtUserID.Text))
                    {
                        MessageBox.Show(用户名不能为空!);
                        return;
                    }
                    if (string.IsNullOrWhiteSpace(this.txtPwd.Text))
                    {
                        MessageBox.Show(密码不能为空!);
                        return;
                    }
                    video = new Videos();
                    if (video.Initialize(this.txtIP.Text, Convert.ToInt32(this.numericupdown1.Value), this.txtUserID.Text, this.txtPwd.Text))
                    {
                        this.btnLogin.Text = 注销;
                        MessageBox.Show(登录成功!);
                        this.btnStart.Enabled = true;
                        this.btnSave.Enabled = true;
                    }
                    else
                    {
                        MessageBox.Show(登录失败!);
                    }
                }
                catch (Exception ee)
                {
                    MessageBox.Show(登录异常: + ee.Message);
                }
            }
            else if (btnLogin.Text == 注销)
            {
                try
                {
                    video.dispose();
                    this.btnLogin.Text = 登录;
                    this.btnStart.Enabled = false;
                    this.btnSave.Enabled = false;
                }
                catch (Exception ee)
                {
                    MessageBox.Show(注销异常: + ee.Message);
                }
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                string filename = txtFile.Text.Trim();
                if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0 || string.IsNullOrWhiteSpace(filename))
                {
                    MessageBox.Show(文件名含有非法字符或空格,请重新输入);
                    txtFile.Focus();
                    return;
                }
                video.Start(handle, filename + comboBox1.SelectedItem.ToString());
                this.btnStart.Enabled = false;
                this.btnSave.Enabled = true;
            }
            catch (Exception ee)
            {
                MessageBox.Show(异常: + ee.Message);
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                if (video.End())
                {
                    MessageBox.Show(视频已保存!);
                    this.btnStart.Enabled = true;
                    this.btnSave.Enabled = false;
                }
                else
                {
                    MessageBox.Show(保存失败!);
                    this.btnStart.Enabled = true;
                    this.btnSave.Enabled = true;
                }
            }
            catch (Exception ee)
            { MessageBox.Show(异常: + ee.Message); }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start(videopath);

            }
            catch
            { }
        }

        private void VideoControl_Load(object sender, EventArgs e)
        {
            this.comboBox1.SelectedItem = .mp4;
            this.handle = pictureBox1.Handle;
            this.btnStart.Enabled = false;
            this.btnSave.Enabled = false;
        }

        #region IObjectSafety 成员
        private const string _IID_Idispatch = {00020400-0000-0000-C000-000000000046};
        private const string _IID_IdispatchEx = {a6ef9860-c720-11d0-9337-00a0c90dcaa9};
        private const string _IID_IPersistStorage = {0000010A-0000-0000-C000-000000000046};
        private const string _IID_IPersistStream = {00000109-0000-0000-C000-000000000046};
        private const string _IID_IPersistpropertybag = {37D84F60-42CB-11CE-8135-00AA004BB851};

        private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
        private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
        private const int S_OK = 0;
        private const int E_FAIL = unchecked((int)0x80004005);
        private const int E_NOINTERFACE = unchecked((int)0x80004002);

        private bool _fSafeForScripting = true;
        private bool _fSafeForInitializing = true;

        public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
        {
            int Rslt = E_FAIL;

            string strGUID = riid.ToString(B);
            pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
            switch (strGUID)
            {
                case _IID_Idispatch:
                case _IID_IdispatchEx:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForScripting == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistpropertybag:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForInitializing == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }

            return Rslt;
        }

        public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
        {
            int Rslt = E_FAIL;
            string strGUID = riid.ToString(B);
            switch (strGUID)
            {
                case _IID_Idispatch:
                case _IID_IdispatchEx:
                    if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
                        Rslt = S_OK;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistpropertybag:
                    if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
                        Rslt = S_OK;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }

            return Rslt;
        }

        #endregion
    }
}

控件代码
namespace VideoHelper
{
    partial class VideoControl
    {
        /// <summary> 
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name=disposing>如果应释放托管资源,为 true;否则为 false。</param>
        protected override void dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.dispose();
            }
            base.dispose(disposing);
        }

        #region 组件设计器生成代码

        /// <summary> 
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改方法内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.label4 = new System.Windows.Forms.Label();
            this.txtFile = new System.Windows.Forms.TextBox();
            this.btnSave = new System.Windows.Forms.Button();
            this.btnStart = new System.Windows.Forms.Button();
            this.btnLogin = new System.Windows.Forms.Button();
            this.label3 = new System.Windows.Forms.Label();
            this.txtPwd = new System.Windows.Forms.TextBox();
            this.label2 = new System.Windows.Forms.Label();
            this.txtUserID = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.numericupdown1 = new System.Windows.Forms.Numericupdown();
            this.IP = new System.Windows.Forms.Label();
            this.txtIP = new System.Windows.Forms.TextBox();
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportinitialize)(this.numericupdown1)).BeginInit();
            ((System.ComponentModel.ISupportinitialize)(this.pictureBox1)).BeginInit();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Cursor = System.Windows.Forms.Cursors.Hand;
            this.button1.Font = new System.Drawing.Font(微软雅黑, 9F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.button1.Location = new System.Drawing.Point(377, 360);
            this.button1.Name = button1;
            this.button1.Size = new System.Drawing.Size(138, 22);
            this.button1.TabIndex = 58;
            this.button1.Text = 打开视频存放位置;
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // comboBox1
            // 
            this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.comboBox1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.comboBox1.Font = new System.Drawing.Font(微软雅黑, 9F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.comboBox1.FormattingEnabled = true;
            this.comboBox1.Items.AddRange(new object[] {
            .mp4,
            .avi,
            .wmv,
            .3gp,
            .flv});
            this.comboBox1.Location = new System.Drawing.Point(303, 361);
            this.comboBox1.Name = comboBox1;
            this.comboBox1.Size = new System.Drawing.Size(55, 25);
            this.comboBox1.TabIndex = 57;
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Font = new System.Drawing.Font(微软雅黑, 9F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.label4.Location = new System.Drawing.Point(14, 360);
            this.label4.Name = label4;
            this.label4.Size = new System.Drawing.Size(116, 17);
            this.label4.TabIndex = 56;
            this.label4.Text = 请输入视频文件名:;
            // 
            // txtFile
            // 
            this.txtFile.Location = new System.Drawing.Point(136, 360);
            this.txtFile.Name = txtFile;
            this.txtFile.Size = new System.Drawing.Size(161, 21);
            this.txtFile.TabIndex = 55;
            // 
            // btnSave
            // 
            this.btnSave.Cursor = System.Windows.Forms.Cursors.Hand;
            this.btnSave.Font = new System.Drawing.Font(微软雅黑, 10.5F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.btnSave.Location = new System.Drawing.Point(490, 298);
            this.btnSave.Name = btnSave;
            this.btnSave.Size = new System.Drawing.Size(57, 45);
            this.btnSave.TabIndex = 54;
            this.btnSave.Text = 保存;
            this.btnSave.UseVisualStyleBackColor = true;
            this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
            // 
            // btnStart
            // 
            this.btnStart.Cursor = System.Windows.Forms.Cursors.Hand;
            this.btnStart.Font = new System.Drawing.Font(微软雅黑, 10.5F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.btnStart.Location = new System.Drawing.Point(421, 298);
            this.btnStart.Name = btnStart;
            this.btnStart.Size = new System.Drawing.Size(57, 45);
            this.btnStart.TabIndex = 53;
            this.btnStart.Text = 录制;
            this.btnStart.UseVisualStyleBackColor = true;
            this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
            // 
            // btnLogin
            // 
            this.btnLogin.Cursor = System.Windows.Forms.Cursors.Hand;
            this.btnLogin.Font = new System.Drawing.Font(微软雅黑, 10.5F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.btnLogin.Location = new System.Drawing.Point(352, 298);
            this.btnLogin.Name = btnLogin;
            this.btnLogin.Size = new System.Drawing.Size(57, 45);
            this.btnLogin.TabIndex = 52;
            this.btnLogin.Text = 登录;
            this.btnLogin.UseVisualStyleBackColor = true;
            this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Font = new System.Drawing.Font(微软雅黑, 9F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.label3.Location = new System.Drawing.Point(172, 325);
            this.label3.Name = label3;
            this.label3.Size = new System.Drawing.Size(44, 17);
            this.label3.TabIndex = 51;
            this.label3.Text = 密码:;
            // 
            // txtPwd
            // 
            this.txtPwd.Location = new System.Drawing.Point(221, 322);
            this.txtPwd.Name = txtPwd;
            this.txtPwd.PasswordChar = '*';
            this.txtPwd.Size = new System.Drawing.Size(115, 21);
            this.txtPwd.TabIndex = 50;
            this.txtPwd.Text = 8910jqk#;
            this.txtPwd.UseSystemPasswordChar = true;
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Font = new System.Drawing.Font(微软雅黑, 9F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.label2.Location = new System.Drawing.Point(8, 322);
            this.label2.Name = label2;
            this.label2.Size = new System.Drawing.Size(44, 17);
            this.label2.TabIndex = 49;
            this.label2.Text = 用户名;
            // 
            // txtUserID
            // 
            this.txtUserID.Location = new System.Drawing.Point(66, 322);
            this.txtUserID.Name = txtUserID;
            this.txtUserID.Size = new System.Drawing.Size(100, 21);
            this.txtUserID.TabIndex = 48;
            this.txtUserID.Text = admin;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Font = new System.Drawing.Font(微软雅黑, 9F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.label1.Location = new System.Drawing.Point(172, 295);
            this.label1.Name = label1;
            this.label1.Size = new System.Drawing.Size(44, 17);
            this.label1.TabIndex = 47;
            this.label1.Text = 端口:;
            // 
            // numericupdown1
            // 
            this.numericupdown1.Location = new System.Drawing.Point(222, 295);
            this.numericupdown1.Maximum = new decimal(new int[] {
            65535,
            0,
            0,
            0});
            this.numericupdown1.Minimum = new decimal(new int[] {
            1,
            0,
            0,
            0});
            this.numericupdown1.Name = numericupdown1;
            this.numericupdown1.Size = new System.Drawing.Size(114, 21);
            this.numericupdown1.TabIndex = 46;
            this.numericupdown1.Value = new decimal(new int[] {
            8000,
            0,
            0,
            0});
            // 
            // IP
            // 
            this.IP.AutoSize = true;
            this.IP.Font = new System.Drawing.Font(微软雅黑, 9F, System.Drawing.FontStyle.Regular, system.drawing.graphicsUnit.Point, ((byte)(134)));
            this.IP.Location = new System.Drawing.Point(20, 295);
            this.IP.Name = IP;
            this.IP.Size = new System.Drawing.Size(19, 17);
            this.IP.TabIndex = 45;
            this.IP.Text = IP;
            // 
            // txtIP
            // 
            this.txtIP.Location = new System.Drawing.Point(66, 295);
            this.txtIP.Name = txtIP;
            this.txtIP.Size = new System.Drawing.Size(100, 21);
            this.txtIP.TabIndex = 44;
            this.txtIP.Text = 192.168.1.64;
            // 
            // pictureBox1
            // 
            this.pictureBox1.Location = new System.Drawing.Point(5, 5);
            this.pictureBox1.Name = pictureBox1;
            this.pictureBox1.Size = new System.Drawing.Size(542, 269);
            this.pictureBox1.TabIndex = 43;
            this.pictureBox1.TabStop = false;
            // 
            // VideoControl
            // 
            this.AutoScaleDimensions = new System.Drawing.Sizef(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Controls.Add(this.button1);
            this.Controls.Add(this.comboBox1);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.txtFile);
            this.Controls.Add(this.btnSave);
            this.Controls.Add(this.btnStart);
            this.Controls.Add(this.btnLogin);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.txtPwd);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.txtUserID);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.numericupdown1);
            this.Controls.Add(this.IP);
            this.Controls.Add(this.txtIP);
            this.Controls.Add(this.pictureBox1);
            this.Name = VideoControl;
            this.Size = new System.Drawing.Size(556, 398);
            this.Load += new System.EventHandler(this.VideoControl_Load);
            ((System.ComponentModel.ISupportinitialize)(this.numericupdown1)).EndInit();
            ((System.ComponentModel.ISupportinitialize)(this.pictureBox1)).EndInit();
            this.ResumeLayout(false);
            this.Performlayout();

        }

        #endregion

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.ComboBox comboBox1;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.TextBox txtFile;
        private System.Windows.Forms.Button btnSave;
        private System.Windows.Forms.Button btnStart;
        private System.Windows.Forms.Button btnLogin;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.TextBox txtPwd;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.TextBox txtUserID;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Numericupdown numericupdown1;
        private System.Windows.Forms.Label IP;
        private System.Windows.Forms.TextBox txtIP;
        private System.Windows.Forms.PictureBox pictureBox1;
    }
}

控件设计器代码

控件设计器代码

    至此,此项目结束。

    右键点击解决方案,添加新项目,如下,至于为什么建立两个项目,我一会儿在下面解释,

    在HkHelper项目中添加类CHCNetSDK.cs,此类是海康提供的,可以在官网找到

    接下来,最重要的,项目属性设置如下,两个项目都要设置:

    至此,自定义控件已经完成,接下来就是打包,新建一个安装项目:

    右键点击安装项目,“添加”->“项目输出”,并选择自定义控件的项目,然后确定

    然后添加海康提供的SDK的库文件文件夹下的所有文件文件夹到项目中,如下:

    然后生成项目,会生成setup.exe和SetupVideo.msi两个文件,然后用打包文件,把这两个文件打包称cab文件就OK了

打包文件一共三个cabarc.exe、build.bat、install.inf

build.bat文件


cabarc.exe  n VideoSetup.cab SetupVideo.msi install.inf

install.inf文件


[version]
signature=$CHICAGO$AdvancedINF=2.0[Setup Hooks]
hook1=hook1

[hook1]
run=msiexec.exe /i %EXTRACT_DIR%\SetupVideo.msi /qn

cabarc.exe是微软提供的工具

最后说一下为什么要分为两个项目去实现控件,那是因为如果在一个项目中的话,调用海康动态库的类CHCNetSDK.cs不能进行COM注册

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐