C# Academy · Oppitunti

COM-yhteentoimivuus ja ajonaikaiset kutsukääreet

Käyttäkää COM-komponentteja C#:sta RCW:n avulla, tuokaa tyyppikirjastoja ja käsitelkää HRESULT-poikkeuksia.

Oppitunti 4/412 vaihetta

COM-yhteentoimivuus ja ajonaikaiset kutsukääreet on ilmainen C# Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C# Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C# Academy-kurssilla on yhteensä 4 oppituntia.

Mitä COM-yhteentoimivuus on

COM (Component Object Model) on Microsoftin perinteinen binäärirajapintastandardi, jota käytetään edelleen Officessa, Windows Shellissä, DirectX:n vanhoissa rajapinnoissa ja monissa yritystyökaluissa. .NET voi käyttää COM-komponentteja yhteentoimivuuskääreiden kautta, jotka muuntavat hallittujen olioiden ja COM-rajapintojen välillä.

Runtime Callable Wrapperit (RCW)

Kun käytät COM-oliota .NETistä, CLR luo Runtime Callable Wrapperin (RCW) eli COM-olion ympärille hallitun välityspalvelimen. RCW huolehtii automaattisesti viitelaskennasta (AddRef/Release), COM-apartmentien säikeistyksestä ja COM- sekä .NET-tyyppien välisestä marshalaamisesta.

// The RCW is created automatically when you instantiate a COM class
// via a registered ProgID or CLSID

// Example: create an Excel Application COM object
Type excelType = Type.GetTypeFromProgID("Excel.Application")!;
object excelApp = Activator.CreateInstance(excelType)!;

// excelApp is an RCW — the CLR wraps the underlying IDispatch COM object
// COM AddRef is called; CLR tracks references
Console.WriteLine(excelApp.GetType().Name); // ApplicationClass

Tyyppikirjastojen tuominen (TLB)

tlbimp.exe-työkalu (Type Library Importer) lukee COM-tyyppikirjaston (.tlb-tiedoston tai .dll-tiedostoon upotetun kirjaston) ja tuottaa .NET-yhteentoimivuuskokoonpanon, joka sisältää vahvasti tyypitetyt RCW-luokat ja rajapintamäärittelyt.

// From a Developer Command Prompt:
// tlbimp MyComLib.dll /out:MyComLib.Interop.dll

// Or reference via Visual Studio:
// Add Reference → COM → Microsoft Excel 16.0 Object Library
// → Generates Microsoft.Office.Interop.Excel.dll automatically

// The generated Interop assembly contains:
// - Interface types (matching COM vtable layout)
// - Co-class wrappers (implement the interfaces)
// - Enum types (from the type library)
// - Delegate types for COM event sinks

COM-olion käyttäminen interop-kokoonpanon kautta

Kun olet lisännyt viittauksen interop-kokoonpanoon, COM-tyypit näyttävät tavallisilta .NET-tyypeiltä. Metodikutsu välittyy RCW:n kautta COM:n vtable-dispatchiksi. Vapauta COM-oliot aina asianmukaisesti resurssivuotojen välttämiseksi.

using Microsoft.Office.Interop.Excel;

Application excel = new Application();
excel.Visible = false;

Workbooks books = excel.Workbooks;
Workbook wb = books.Add();
Worksheet ws = (Worksheet)wb.Sheets[1];

((Range)ws.Cells[1, 1]).Value = "Hello, COM!";
wb.SaveAs(@"C:\Temp\test.xlsx");
wb.Close();

// Release COM RCW explicitly
Marshal.ReleaseComObject(ws);
Marshal.ReleaseComObject(wb);
Marshal.ReleaseComObject(books);
excel.Quit();
Marshal.ReleaseComObject(excel);

Marshal.ReleaseComObject

COM käyttää viitelaskentaa: AddRef/Release. RCW kutsuu Release-metodia vasta, kun GC kerää sen, mikä voi tapahtua paljon myöhemmin. Kutsu Marshal.ReleaseComObject()-metodia pienentääksesi RCW:n viitelaskuria välittömästi ja vapauttaaksesi COM-olion odottamatta GC:tä.

// Pattern: release COM objects in finally block
Application? excel = null;
Workbook? wb = null;
try
{
    excel = new Application();
    wb = excel.Workbooks.Add();
    // ... do work ...
}
finally
{
    if (wb   != null) Marshal.ReleaseComObject(wb);
    if (excel != null)
    {
        excel.Quit();
        Marshal.ReleaseComObject(excel);
    }
    // Force GC to clean up any remaining RCWs
    GC.Collect();
    GC.WaitForPendingFinalizers();
}

HRESULT ja COM-poikkeukset

COM-metodit palauttavat HRESULT-arvoja ilmoittaakseen onnistumisesta tai epäonnistumisesta. RCW tarkistaa HRESULT-arvon automaattisesti ja heittää COMException-poikkeuksen tai tarkemman poikkeuksen, kun arvo ilmaisee epäonnistumista. Käsittele niitä tavallisella try/catch-rakenteella.

try
{
    // COM method that might fail
    Workbook wb = excel.Workbooks.Open(@"C:\missing.xlsx");
}
catch (COMException ex) when (ex.HResult == unchecked((int)0x800A03EC))
{
    // Excel-specific HRESULT for file not found
    Console.WriteLine($"Excel error: {ex.Message}");
}
catch (COMException ex)
{
    // General COM failure
    Console.WriteLine($"COM error 0x{ex.HResult:X8}: {ex.Message}");
}

Myöhäinen sidonta dynamic-avainsanalla

Jos käytettävissä ei ole tyyppikirjastoa tai interop-kokoonpanoa, voit käyttää C#:n dynamic-avainsanaa myöhäissidottuun COM-dispatchiin (IDispatch). Tämä on hitaampaa, koska dispatch-tunnisteet ratkaistaan ajonaikana, mutta generoitua käärettä ei tarvita.

// Late-bound COM via dynamic — no interop DLL needed
Type type = Type.GetTypeFromProgID("Word.Application")!;
dynamic word = Activator.CreateInstance(type)!;

word.Visible = false;
dynamic docs = word.Documents;
dynamic doc = docs.Add();

doc.Content.Text = "Late-bound COM example";
doc.SaveAs2(@"C:\Temp\test.docx");
doc.Close();
word.Quit();

Marshal.ReleaseComObject(doc);
Marshal.ReleaseComObject(docs);
Marshal.ReleaseComObject(word);

COM-tapahtumavastaanottimet

COM-oliot lähettävät tapahtumia yhteyspisteiden kautta. Interop-kokoonpano generoi tapahtumavastaanotinrajapinnat. Tapahtumiin liitytään tavallisten .NET-delegaattien ja -tapahtumien avulla, ja RCW huolehtii COM:n IConnectionPoint-kytkennästä.

using Microsoft.Office.Interop.Excel;

Application excel = new Application();
excel.Visible = true;

// Subscribe to COM event via generated event wrapper
excel.WorkbookBeforeClose += (wb, ref cancel) =>
{
    Console.WriteLine($"Closing: {wb.Name}");
    // Set cancel = true to prevent close
};

excel.WorkbookOpen += (wb) =>
{
    Console.WriteLine($"Opened: {wb.Name}");
};

// Open a workbook to trigger events
excel.Workbooks.Open(@"C:\Temp\test.xlsx");

COM-apartmentit: STA vs. MTA

Monet COM-komponentit, erityisesti käyttöliittymiin liittyvät komponentit, kuten Office, edellyttävät yksisäikeistä apartmentia (STA). Merkitse STA-COM-olioita luovat säikeet aina attribuutilla [STAThread] (Main) tai määritä säikeen apartment-tila ennen säikeen käynnistämistä.

// Console apps default to MTA — COM Office automation requires STA
// Option 1: Mark Main with [STAThread]
[STAThread]
static void Main()
{
    var excel = new Microsoft.Office.Interop.Excel.Application();
    // ...
}

// Option 2: Run on an STA thread manually
Thread staThread = new Thread(() =>
{
    var excel = new Microsoft.Office.Interop.Excel.Application();
    // ...
    excel.Quit();
    Marshal.ReleaseComObject(excel);
});
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
staThread.Join();

ComImport ja COM-rajapintojen manuaaliset määrittelyt

Voit määrittää COM-rajapinnat manuaalisesti käyttämällä attribuutteja [ComImport], [Guid] ja [InterfaceType]. Tämä on hyödyllistä, kun tyyppikirjastoa ei ole tai tarvitset vain osan suuresta COM-rajapinnasta.

[ComImport]
[Guid("00000000-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IUnknown
{
    void QueryInterface(ref Guid riid, out IntPtr ppvObject);
    int  AddRef();
    int  Release();
}

// Declare a specific COM interface you want to consume:
[ComImport]
[Guid("0000010C-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IPersist
{
    void GetClassID(out Guid pClassID);
}

Pikatarkistus

Mikä on Runtime Callable Wrapperin (RCW) tehtävä .NETin COM-yhteentoimivuudessa?

Kertaus: COM-yhteentoimivuus ja Runtime Callable Wrapperit

Keskeiset opit:

  • RCW on COM-olion ympärille muodostettu hallittu välityspalvelin; CLR luo sen automaattisesti jokaiselle COM-oliolle
  • Luo vahvasti tyypitettyjä interop-kokoonpanoja käyttämällä tlbimp.exe-työkalua tai Visual Studion References-toimintoa
  • Vapauta COM-oliot heti kutsumalla Marshal.ReleaseComObject()-metodia – älä odota GC:n suorittamaa keräystä
  • COM-virheet näkyvät COMException-poikkeuksina, jotka sisältävät alkuperäisen HRESULT-arvon
  • dynamic mahdollistaa myöhäissidotun COM-dispatchin ilman interop-kokoonpanoa
  • Office- ja käyttöliittymäkomponentit edellyttävät STA-säiettä – käytä [STAThread]-attribuuttia tai määritä apartment-tila
Aloita maksutta

Opi C# tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
93
Oppitunnit
346

Usein kysytyt kysymykset

Onko oppitunti ”COM-yhteentoimivuus ja ajonaikaiset kutsukääreet” ilmainen?

Kyllä – oppitunnin ”COM-yhteentoimivuus ja ajonaikaiset kutsukääreet” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C# Academy-kurssin, päivitä CoddyKit PROhon. C# Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”COM-yhteentoimivuus ja ajonaikaiset kutsukääreet”?

Käyttäkää COM-komponentteja C#:sta RCW:n avulla, tuokaa tyyppikirjastoja ja käsitelkää HRESULT-poikkeuksia. Harjoittelet C# Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni C# Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin C# Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”COM-yhteentoimivuus ja ajonaikaiset kutsukääreet”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä C# Academy-oppitunnilla?

Kyllä. Jokainen C# Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. P/Invoken perusteet
  2. LibraryImport ja lähdekoodin generoima P/Invoke
  3. Turvaton koodi, osoittimet ja kiinteät puskurit
  4. COM-yhteentoimivuus ja ajonaikaiset kutsukääreet
← Takaisin: C# Academy