Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

IMAPI2, COM Events problem

[es] :: .NET :: IMAPI2, COM Events problem

[ Pregleda: 2523 | Odgovora: 6 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Mikelly

Član broj: 16730
Poruke: 389
77.222.22.*



Profil

icon IMAPI2, COM Events problem25.04.2010. u 01:11 - pre 169 meseci
Samo za strpljive :)

Ovako, na codeproject-u sam nasao clanak, tj interop wrapper za IMAPI2 za narezivanje optickih medija. Trebalo mi je da narezujem crystalreports izvjestaje direktno, pa reko ajde da se latim posla. I evo zaglavih nekoliko dana.

Ono sto sam uspio, jeste da uspjesno narezem disk. Ono sto nikako ne uspijevam jeste da se nakacim na COM event koji mi daje informacije o procesu narezivanja, kako bih mogao korisniku napraviti kakav progress bar. Bez njega izgleda sve izgleda malo bzvz.

Evo kako izgleda delegat i COM funkcija update koja treba da se okida, definisani u interop wrapperu
Code:

[DispId(0x200)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Update([In, MarshalAs(UnmanagedType.IDispatch)] object sender, [In, MarshalAs(UnmanagedType.IDispatch)] object progress);

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void DiscFormat2Data_EventHandler([In, MarshalAs(UnmanagedType.IDispatch)] object sender, [In, MarshalAs(UnmanagedType.IDispatch)] object progress);


Mozda ovo sto pisem nema mnogo smisla, jer se u ovo previse ne razumijem, ali sam poceo i citati kako se u COM-u radi sa dogadjajima: connection point, advise, cookie i sl, ali bez prakticnog iskustva to mi nista ne znaci...

Naime, drugi argument f-je update sadrzi te podatke koji su mi potrebni, i ja se prijavim na dogadjaj na sledeci nacin:
Code:

discFormatData.Update += discFormatData_Update;
discFormatData.Write(stream);
discFormatData.Update -= discFormatData_Update;

void discFormatData_Update([In, MarshalAs(UnmanagedType.IDispatch)] object sender, [In, MarshalAs(UnmanagedType.IDispatch)] object progress) { ... }


... ali se kod koji se nalazi u funkciji discFormatData_Update nikada nece izvrsiti. Zakljucujem, nisam se dobro prijavio na COM dogadjaj. Ili interop nije dobar, ali kad izvrsim program sa codeproject-a prograssbar funkcionise, tako da tu mogucnost iskljucujem.

Valjda je moje pitanje: Da li je za prijavljivanje na COM dogadjaj dovoljno uraditi += ili je potrebno preduzeti neke korake prije ili poslije?

Ne znam, ako neko ima iskustva sa COM-om ili mozda konkretno sa ovim API-jem cijenio nih pomoc.

Pozdrav.
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6041



+4631 Profil

icon Re: IMAPI2, COM Events problem25.04.2010. u 10:24 - pre 169 meseci
Ne mogu da ti kazem za IMAPI32, ali ako je event nmapravljen koriscenjem COM sink eventa onda interop autoamtski to implementira kao multicast event u .NETu (direktno su kompatibilni), tako da se handleri zaista kace sa +=.
Mozda je versioning problem, nema potrebe da koristis tudji interop wrapper za "svoj" COM objekat na masini, ako je tlb registrovan (a pretposavljam da jeste) dodaj sam IMAPI32 i pusti VS da napravi wrapper.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Mikelly

Član broj: 16730
Poruke: 389
77.222.22.*



Profil

icon Re: IMAPI2, COM Events problem25.04.2010. u 13:17 - pre 169 meseci
Hvala :)

Nije u pitanju IMAPI32 vec IMAPI2 za dvd, bluray i ostale gluposti, mada pretpostavljam da nema neke velike razlike.

Kad kazes 'svoj' COM objekat, ne razumijem te bas skroz. Nijesam ja nista pravio u COM, to je MS biblioteka, valjda ce se isto ponasati i meni i njemu...

To je ipak dosta komplikovan interop, izlaze sve sto postoji iz tog API-ja za narezivanje, nemam ja znanja da pravim svoj. Mada, nijesam direktno koristio njegove dll-ove vec sam njegov kod ukljucio u projekat (takva je njegova instrukcija), ne znam da li ti to sto znaci.

Ako imas strpljenja pogledaj snippet koda koji definise taj dogadjaj. Meni je dosta toga odavde jasno, ali isto tako i ne znam da mrdem sa mjesta.

Code:

[ComImport]
    [Guid("2735413C-7F64-5B0F-8F00-5D77AFBE261E")]
    [TypeLibType(TypeLibTypeFlags.FNonExtensible|TypeLibTypeFlags.FOleAutomation|TypeLibTypeFlags.FDispatchable)]
    public interface DDiscFormat2DataEvents
    {
        // Update to current progress
        [DispId(0x200)]     // DISPID_DDISCFORMAT2DATAEVENTS_UPDATE
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void Update([In, MarshalAs(UnmanagedType.IDispatch)] object sender, [In, MarshalAs(UnmanagedType.IDispatch)] object progress);
    }

    [ComVisible(false)]
    [ComEventInterface(typeof(DDiscFormat2DataEvents),typeof(DiscFormat2Data_EventProvider))]
    [TypeLibType(TypeLibTypeFlags.FHidden)]
    public interface DiscFormat2Data_Event
    {
        // Events
        event DiscFormat2Data_EventHandler Update;
    }

    [ClassInterface(ClassInterfaceType.None)]
    internal sealed class DiscFormat2Data_EventProvider : DiscFormat2Data_Event, IDisposable
    {
        // Fields
        private Hashtable m_aEventSinkHelpers = new Hashtable();
        private IConnectionPoint m_connectionPoint = null;


        // Methods
        public DiscFormat2Data_EventProvider(object pointContainer)
        {
            lock (this)
            {
                Guid eventsGuid = typeof(DDiscFormat2DataEvents).GUID;
                IConnectionPointContainer connectionPointContainer = pointContainer as IConnectionPointContainer;

                connectionPointContainer.FindConnectionPoint(ref eventsGuid, out m_connectionPoint);
            }
        }

        public event DiscFormat2Data_EventHandler Update
        {
            add
            {
                lock (this)
                {
                    DiscFormat2Data_SinkHelper helper =
                        new DiscFormat2Data_SinkHelper(value);
                    int cookie;

                    m_connectionPoint.Advise(helper, out cookie);
                    helper.Cookie = cookie;
                    m_aEventSinkHelpers.Add(helper.UpdateDelegate, helper);
                }
            }

            remove
            {
                lock (this)
                {
                    DiscFormat2Data_SinkHelper helper =
                        m_aEventSinkHelpers[value] as DiscFormat2Data_SinkHelper;
                    if (helper != null)
                    {
                        m_connectionPoint.Unadvise(helper.Cookie);
                        m_aEventSinkHelpers.Remove(helper.UpdateDelegate);
                    }
                }
            }
        }

        ~DiscFormat2Data_EventProvider()
        {
            Cleanup();
        }

        public void Dispose()
        {
            Cleanup();
            GC.SuppressFinalize(this);
        }

        private void Cleanup()
        {
            Monitor.Enter(this);
            try
            {
                foreach (DiscFormat2Data_SinkHelper helper in m_aEventSinkHelpers.Values)
                {
                    m_connectionPoint.Unadvise(helper.Cookie);
                }

                m_aEventSinkHelpers.Clear();
                Marshal.ReleaseComObject(m_connectionPoint);
            }
            catch (SynchronizationLockException)
            {
                return;
            }
            finally
            {
                Monitor.Exit(this);
            }
        }
    }

    [ClassInterface(ClassInterfaceType.None)]
    [TypeLibType(TypeLibTypeFlags.FHidden)]
    public sealed class DiscFormat2Data_SinkHelper : DDiscFormat2DataEvents
    {
        // Fields
        private int m_dwCookie;
        private DiscFormat2Data_EventHandler m_UpdateDelegate;

        // Methods
        internal DiscFormat2Data_SinkHelper(DiscFormat2Data_EventHandler eventHandler)
        {
            if (eventHandler == null)
                throw new ArgumentNullException("Delegate (callback function) cannot be null");
            m_dwCookie = 0;
            m_UpdateDelegate = eventHandler;
        }

        public void Update(object sender, object args)
        {
            m_UpdateDelegate(sender, args);
        }

        public int Cookie
        {
            get
            {
                return m_dwCookie;
            }
            set
            {
                m_dwCookie = value;
            }
        }

        public DiscFormat2Data_EventHandler UpdateDelegate
        {
            get
            {
                return m_UpdateDelegate;
            }
            set
            {
                m_UpdateDelegate = value;
            }
        }
    }

    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void DiscFormat2Data_EventHandler([In, MarshalAs(UnmanagedType.IDispatch)] object sender, [In, MarshalAs(UnmanagedType.IDispatch)] object progress);
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6041



+4631 Profil

icon Re: IMAPI2, COM Events problem25.04.2010. u 17:48 - pre 169 meseci
Kad dodajes referencu u projekat jedan od tabova je spisak COM objekata, lociraj IMAPI2 i dodaj u projekat i VS ce sam napraviti wrapper na osnovu type library-a.

Sors koji si okacio lici na standardno implementiran .net multicast event <-> COM event sink wrapper i trebao bi da radi (kazem na prvi pogled, nemam VS pri ruci sada). JEsi ti siguran da treba da dobijes bilo kakav povratni poziv u tvom scenarioju sa rezanjem par izvestaja (lupam sad, kazem nisam koristio IMAPI2), mozda se zavrsi sve previse brzo a even je time based?
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Mikelly

Član broj: 16730
Poruke: 389
77.222.22.*



Profil

icon Re: IMAPI2, COM Events problem26.04.2010. u 07:33 - pre 169 meseci
Ok, dodao sam imapi2.dll i imapi2fs.dll u projekat, i sad mogu da ih koristim, ali nidje ne vidim wrapper. Dje da ga trazim?

Mada, u sustini, ja se moram koristiti njegovim wrapperom, jer postoji problem prilikom koverzije FSIStreamClass definisane u impapi2fs.dll (tu se kreira image za rezanje) u IStream koja je potrebna metodi Write() u imapi2.dll (rezanje) - Microsoft pogrijesio, a on je to valjda ispravio.

I evo sto on kaze u clanku, sto mi je zapalo za oko:

Citat:

Lastly, in order to receive notifications for all events, I had to go through the SDK and find all of the Dispatch IDs for all of the events. Without these values, the event handlers are unable to receive notifications.


Mada, taj dispach ID je naveden na jednom mjestu:
Code:

    public interface DDiscFormat2DataEvents
    {
        // Update to current progress
        [DispId(0x200)]     // DISPID_DDISCFORMAT2DATAEVENTS_UPDATE
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void Update([In, MarshalAs(UnmanagedType.IDispatch)] object sender, [In, MarshalAs(UnmanagedType.IDispatch)] object progress);
    }


Koliko ja shvatam, on se upravo koristio tim autogenerisanim wrapperom, pa ga mijenjao...

Ne znam vise sta, probacu sjutra ground up, pa cu vidjet. Mada mi nije ovo skodilo, naucih nesto o COM-u :)\

Ti ako imas jos kakvu ideju, slobodno...
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6041



+4631 Profil

icon Re: IMAPI2, COM Events problem26.04.2010. u 13:28 - pre 169 meseci
Kad dodas na ovaj nacin nema wrappera (sve je u vec generisanom asembliju)

Inace, sad sam pogledao IMAPI2, prilicno je lose uradjen type library, nije ni cudo da morate da se dovijate.

Code:
[
  odl,
  uuid(2735413C-7F64-5B0F-8F00-5D77AFBE261E),
  helpstring("Data Writer"),
  nonextensible,
  oleautomation
]
interface DDiscFormat2DataEvents : IDispatch {
    [helpstring("Update to current progress")]
    HRESULT _stdcall Update(
                    [in] IDispatch* object, 
                    [in] IDispatch* progress);
};


svi eventi su im ocigledno namesteni kao IDispatch sto ej supacki potupno jer ionako vec definisu tipove parametara i nema potrebe da se dinamicki zezas posle (IDiscFormat2DataEventArgs). Nista, sa ovakvim COM objektima nema mnogo zabave, mora custom interop. :(
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Mikelly

Član broj: 16730
Poruke: 389
77.222.25.*



Profil

icon Re: IMAPI2, COM Events problem26.04.2010. u 17:30 - pre 169 meseci
Uf, uf,

Treba da se postavi
Code:

[assembly: ComVisible(true)]


za citav sklop koji pristupa COM-u.

Mada, nije mi jasno zasto nije postavio taj atribut za klase u wrapper-u, jer tamo mu pored svake klase stoji:

Code:

[ComVisible(false)]


Mada, nije ni bitno, ne moram to znat, ovo sad radi :) Imam progres bar.

Hvala na pomoci :)
 
Odgovor na temu

[es] :: .NET :: IMAPI2, COM Events problem

[ Pregleda: 2523 | Odgovora: 6 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.