5
votes

I have a DLL written in C#.NET which exposes a COM interface, so a vb6 application can call my DLL. This interface looks like:

   [System.Runtime.InteropServices.Guid("3D2C106C-097F-4ED7-9E4F-CDBC6A43BDC4")]
    public interface IZDPharmaManager {
        [System.Runtime.InteropServices.DispId(2)]
        SearchPatientEventArgs FoundPatient { get; set; }
        [System.Runtime.InteropServices.DispId(3)]
        IntPtr Start(string server, string database, string user, string password, bool integrated, int praktijkID, string userGUID, int userID, string userName, bool hasRightToSearchPatient);
        [System.Runtime.InteropServices.DispId(4)]
        void Stop();
        [System.Runtime.InteropServices.DispId(5)]
        void InitializeSkinner(System.Object skinnerFramework);
    }

[System.Runtime.InteropServices.Guid("4438852E-CF2D-4DB0-8E6E-428F65A6B16C")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IZDPharmaManagerEvents {
    [DispId(1)]
    void SearchPatient(ZDPharmaManager sender, SearchPatientEventArgs e);
}

   [System.Runtime.InteropServices.Guid("9297D43F-C581-3F0F-AA60-9506C6B77B5F")]
    [ClassInterface(ClassInterfaceType.None)]
    public class SearchPatientEventArgs : WebHIS.ZDPharmaceutisch.ISearchPatientEventArgs {

        public SearchPatientEventArgs() {
            //Nodig voor COM.
        }

        public int ID { get; set; }
        public string FullName { get; set; }
        public string OwnName { get; set; }
        public string PartnerName { get; set; }
        public string DateOfBirth { get; set; }
        public string ZipCode { get; set; }
        public string HouseNumber { get; set; }
        public string BSN { get; set; }
    }

    public delegate void SearchPatientEventHandler(ZDPharmaManager sender, SearchPatientEventArgs e);

    [System.Runtime.InteropServices.Guid("465AC7EC-27EF-3D95-AAA6-29D01FCF15A1")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(IZDPharmaManagerEvents))]
    public class ZDPharmaManager : WebHIS.ZDPharmaceutisch.IZDPharmaManager {

        public event SearchPatientEventHandler SearchPatient = null;

        public SearchPatientEventArgs FoundPatient { get; set; }

        //private MainForm GraphicalInterface { get; set; }
        private ChoosePatient GraphicalInterface { get; set; }

        public ZDPharmaManager() {
            //Nodig voor COM.
        }

        #region IZDPharmaManager Members

        public IntPtr Start(string server,
            string database,
            string user,
            string password,
            bool integrated,
            int praktijkID,
            string userGUID,
            int userID,
            string userName,
            bool hasRightToSearchPatient) {

            //Zet connectiestring.
            DAL.DAC.CnnInfo = new System.Data.SqlClient.SqlConnectionStringBuilder() {
                DataSource = server,
                InitialCatalog = database,
                UserID = user,
                Password = password,
                IntegratedSecurity = integrated
            };

            DAL.DAC.PracticeID = praktijkID;
            DAL.DAC.UserGUID = userGUID;
            DAL.DAC.UserID = userID;
            DAL.DAC.UserName = userName;
            DAL.DAC.HasRightToSearchPatient = hasRightToSearchPatient;

            //Apotheek IDs ophalen en bewaren.
            DAL.DAC.PharmacyIDs = DAL.PracticeDAO.GetPharmacyByPracticeID(praktijkID);

            //Initialiseer grafische interface.
            //this.GraphicalInterface = new MainForm();
            this.GraphicalInterface = new ChoosePatient();

            //Haal ongekoppelde afhaalberichten op.
            this.GraphicalInterface.Patients = new VML.PatientsVM(this);

            //Toon grafische interface.
            this.GraphicalInterface.Show();

            return this.GraphicalInterface.Handle;

        }

        public void Stop() {
            foreach (var item in this.SearchPatient.GetInvocationList()) {
                this.SearchPatient -= (SearchPatientEventHandler)item;

            }
            this.GraphicalInterface.Close();
            this.GraphicalInterface = null;
            this.FoundPatient = null;
        }

        public void InitializeSkinner(System.Object skinnerFramework) {

            WebHIS.ZDPharmaceutisch.SkinnerModule.SkinFramework = (XtremeSkinFramework.SkinFramework)skinnerFramework;

        }
        #endregion

        internal virtual void OnSearchPatient(SearchPatientEventArgs e) {
            if (this.SearchPatient != null) {
                this.SearchPatient(this, e);
            }
        }


    }

This works fine. But each time I build this DLL without changing the interface (because I had to fix something somewhere in the logic) the reference with the vb6 application is broken and we need to recompile the vb6 application.

Does anyone know what I am doing wrong? 'Cause we had vb.net DLL's which didn't break the reference after recompile due to fixed GUIDs. Any help would be much appreciated.

Update Both vb6 app and DLL are operational. But when I recompile the DLL and test it on our testserver via the vb6 application I get an automation error (which usually means the reference is broken and you need to recompile the vb6 app aswell)

1
im not quite sure what you mean but if you have attached the references and now you are making changes to your dll you need to at least close the VB6 or free references to you dll after each compilation of your dll.user2140173
That is indeed not what I mean. Both vb6 app and DLL are operational. But when I recompile the DLL and test it on our testserver via the vb6 application I get an automation error (which usually means the reference is broken and you need to recompile the vb6 app aswell)Danny van der Kraan
Other public classes in your DLL may be getting automatic UUIDs / GUIDs which change when you recompile. Seems like that was happening in an example I saw recently.StayOnTarget

1 Answers

11
votes

I don't see any strong leads that could explain this problem. The [Guid] attribute for the assembly matters, that sets the type library ID. And the [AssemblyVersion] matters, that sets the type library version number. The attributes are declared in the project's AssemblyInfo.cs file. Make sure your build system doesn't monkey with these attributes.

Best way to go about it is to find out what exactly changes. Run the OleView.exe utility from the Visual Studio Command Prompt. File + View Typelib and select the .tlb file. Copy/paste the content of the right panel into a text file.

Rebuild the project and repeat the OleView exercise. You can now simply use a diffing tool to see what exactly changed. Update your question with what you found out if you need more help.