Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add comprehensive COM object cleanup documentation and examples for Excel Interop#47088

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
Copilot wants to merge10 commits intomain
base:main
Choose a base branch
Loading
fromcopilot/fix-22316

Conversation

Copilot
Copy link
Contributor

@CopilotCopilotAI commentedJul 3, 2025
edited
Loading

The Excel Interop programming walkthrough was missing critical information about proper COM object cleanup, which is essential for production applications. The original examples skipped saving/closing operations and didn't demonstrate how to prevent orphaned Excel processes.

Key Issues Addressed

Missing cleanup leads to orphaned processes: The original examples would leave excel.exe processes running in Task Manager after the application closed, as noted in the issue feedback.

Incomplete examples: The walkthrough skipped the "most difficult steps (saving and exiting)" that developers actually need in real applications.

No guidance on resource management: Developers were left to discover the complex COM cleanup requirements on their own.

Changes Made

New Documentation Section

  • Added "Important: COM object cleanup and resource management" section explaining why cleanup is necessary
  • Added "Common questions about COM object cleanup" addressing developer concerns about garbage collection, null assignment, and consequences of improper cleanup

Enhanced Code Examples

  • UpdatedDisplayInExcel method to include complete try/finally cleanup pattern
  • UpdatedCreateIconInWordDoc method with proper Word document cleanup
  • Added newDisplayInExcelWithCleanup method demonstrating full lifecycle with saving
  • AddedCleanupComObject helper method showing the standard pattern

Cleanup Pattern Demonstrated

finally{// Clean up COM objects in reverse order of creationif(worksheet!=null){Marshal.FinalReleaseComObject(worksheet);worksheet=null;}if(workbook!=null){workbook.Close(true);// Save changesMarshal.FinalReleaseComObject(workbook);workbook=null;}if(excelApp!=null){excelApp.DisplayAlerts=true;excelApp.Quit();Marshal.FinalReleaseComObject(excelApp);excelApp=null;}GC.Collect();GC.WaitForPendingFinalizers();}

The documentation now properly addresses the critical aspects of Office Interop programming, providing developers with the knowledge they need to build reliable applications that don't leave orphaned Office processes.

Fixes#22316.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Clickhere to start the survey.

@dotnet-policy-servicedotnet-policy-servicebot added the okr-qualityContent-quality KR: Concerns article defects (bugs), freshness, or build warnings. labelJul 3, 2025
Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com>
@CopilotCopilotAI changed the title[WIP] Excel Interop Programming Example FeedbackAdd comprehensive COM object cleanup documentation and examples for Excel InteropJul 3, 2025
@CopilotCopilotAI requested a review fromBillWagnerJuly 3, 2025 16:09
Copilot finished work on behalf ofBillWagnerJuly 3, 2025 16:09
excelApp = null;
}

// Force garbage collection
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

.NET runtime does not guarantee that objects above gets collected. The JIT is free to extend lifetimes till end of the method. Assigning null to local variables likeexcelApp = null; may help, but it is not 100% reliable.

The only reliable way to get objects collected is by factoring out the code where it is not desirable to extend lifetimes into its own non-inlineable method.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

You're absolutely right. I've updated the COM cleanup pattern to use separate non-inlineable methods that guarantee object references go out of scope. The new pattern removes the unreliable null assignments and GC.Collect() calls, usingMethodImpl(MethodImplOptions.NoInlining) to ensure reliable cleanup. Fixed in commit69cdbfc.

…te non-inlineable methods for reliable object lifetime managementCo-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot finished work on behalf ofjkotasJuly 3, 2025 21:18
@CopilotCopilotAI requested a review fromjkotasJuly 3, 2025 21:18
**Why do you use separate methods with MethodImpl(MethodImplOptions.NoInlining)?**
The .NET JIT compiler can extend object lifetimes until the end of a method, which means local variable assignments to null aren't guaranteed to release references immediately. By factoring out COM object creation and usage into separate non-inlineable methods, you ensure that object references truly go out of scope when the method returns, allowing reliable cleanup.

**Why call GC.Collect() and GC.WaitForPendingFinalizers()?**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The sample do not call GC.Collect and GC.WaitForPendingFinalizers anymore. Should they?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Updated the documentation to clarify thatGC.Collect() andGC.WaitForPendingFinalizers() are optional with the reliable separate method pattern. The samples use the more reliable approach without needing these calls. Fixed in commit94b85e8.

… optional with reliable method patternCo-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot finished work on behalf ofjkotasJuly 3, 2025 21:30
@CopilotCopilotAI requested a review fromjkotasJuly 3, 2025 21:30
The .NET JIT compiler can extend object lifetimes until the end of a method, which means local variable assignments to null aren't guaranteed to release references immediately. By factoring out COM object creation and usage into separate non-inlineable methods, you ensure that object references truly go out of scope when the method returns, allowing reliable cleanup.

**Do I need to call GC.Collect() and GC.WaitForPendingFinalizers()?**
With the separate non-inlineable method pattern, these calls are typically not necessary. The pattern ensures that COM object references go out of scope reliably when the method returns. However, you can optionally add these calls after the separate method call for additional safety in scenarios where you want to force immediate cleanup.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is not correct.

The non-inlinable method is only needed when the user wants to deterministically cleanup all objects using GC.Collect() and GC.WaitForPendingFinalizers().

The non-inlinable method alone does not help.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

You're absolutely correct. I've updated the documentation and code to reflect the proper relationship between the non-inlinable method pattern and GC calls. The pattern is only beneficial when usingGC.Collect() andGC.WaitForPendingFinalizers(), not by itself. The examples now use the straightforward cleanup pattern that directly addresses the orphaned process issue. Fixed in commit5d03bf1.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I believe that the non-inlinable method in combination with explicit calls to GC.Collect() and GC.WaitForPendingFinalizers() is very advanced scenario that most users should not be concerned with.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

You're absolutely right. I've simplified the documentation to remove the advanced non-inlinable method discussion and focus on the basic cleanup pattern that most developers need. The documentation now emphasizes the essentialMarshal.FinalReleaseComObject() pattern without overcomplicating things. Fixed in commit59e3252.

… non-inlinable method pattern is only needed with GC callsCo-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
@CopilotCopilotAI requested a review fromjkotasJuly 4, 2025 03:38
Copilot finished work on behalf ofjkotasJuly 4, 2025 03:38
…patternCo-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot finished work on behalf ofjkotasJuly 4, 2025 03:41
if (workSheet != null)
{
Marshal.FinalReleaseComObject(workSheet);
workSheet = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

These assignments of null have no impact. The JIT compiler is likely to optimize them out.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Correct, I've removed all the null assignments since the JIT compiler optimizes them out anyway. The cleanup now focuses only on the effectiveMarshal.FinalReleaseComObject() calls. Fixed in commit59e3252.

if (excelApp != null)
{
excelApp.DisplayAlerts = true;
excelApp.Quit();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This sample is called "DisplayInExcel". The name suggests that the Excel is expected to say open, displaying the content when the sample finishes executing. Should this be dropped in this sample?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Good point about the semantic mismatch. I've removed theexcelApp.Quit() call from the DisplayInExcel method since it's intended to display data to users. Added documentation explaining that for display scenarios, Excel remains open for user interaction, while automation scenarios should include the Quit() call. Fixed in commit59e3252.

…ation based on@jkotas feedbackCo-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
@CopilotCopilotAI requested a review fromjkotasJuly 4, 2025 03:54
Copilot finished work on behalf ofjkotasJuly 4, 2025 03:54
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot finished work on behalf ofjkotasJuly 4, 2025 04:00
### Common questions about COM object cleanup

**Why can't garbage collection handle this automatically?**
COM objects use reference counting for memory management, which is different from .NET's garbage collection. The .NET runtime creates a Runtime Callable Wrapper (RCW) around each COM object, but the RCW doesn't automatically release the underlying COM object when it's garbage collected.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

, but the RCW doesn't automatically release the underlying COM object when it's garbage collected.

This is invalid statement. RCW does release the underlying COM object when it's garbage collected. The problem is the delayed nature of garbage collection. not that the RCW is not released.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

You're correct. Fixed the inaccurate statement to reflect that RCWs do release underlying COM objects when garbage collected - the issue is the non-deterministic timing of garbage collection, not that RCWs don't release objects. Fixed in commitce5d34f.

Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
@CopilotCopilotAI requested a review fromjkotasJuly 4, 2025 04:09
Copilot finished work on behalf ofjkotasJuly 4, 2025 04:09
- Memory is properly freed
- The application behaves reliably in production environments

For production applications, always implement this cleanup pattern for every COM object you create, including Application, Workbooks, Worksheets, Ranges, and other Office objects.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I do not think that this pattern should be followed by most production applications out there.

The delayed release of the COM objects that is a side-effect of garbage collection is not a problem for most production applications. Vast majority of developers love that .NET garbage collection takes care of it for them and they are perfectly fine paying a small price for it.

Stepping back, this is introductory sample for Office Interop. it is appropriate to complicate it by manual lifetime management. I think it may be better to leave this sample alone, and move the advanced topic of manual lifetime management to a new advanced sample.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

You're absolutely right. I've simplified the walkthrough to remove the complex manual cleanup patterns and restored the original simple examples that rely on .NET garbage collection. The introductory sample now maintains the appropriate level of complexity for beginners, and the delayed COM object release is acceptable for most applications. Fixed in commitc097dc9.

…lex cleanup patterns to keep introductory walkthrough simpleCo-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
@CopilotCopilotAI requested a review fromjkotasJuly 4, 2025 04:45
Copilot finished work on behalf ofjkotasJuly 4, 2025 04:45
@danmoseley
Copy link
Member

(Copilot ignore this comment). The changes that remain do not appear to demonstrate cleanup any more.

@BillWagner
Copy link
Member

(Copilot ignore this comment). The changes that remain do not appear to demonstrate cleanup any more.

(Copilot ignore this comment) That's correct. Based on the reviews by Jan and Aaron, this may be a PR that I close without merging. It doesn't appear to be reaching a resolution of the original issue.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@AaronRobinsonMSFTAaronRobinsonMSFTAaronRobinsonMSFT approved these changes

@BillWagnerBillWagnerAwaiting requested review from BillWagnerBillWagner is a code owner

@jkotasjkotasAwaiting requested review from jkotas

Labels
dotnet-csharp/svcokr-qualityContent-quality KR: Concerns article defects (bugs), freshness, or build warnings.
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

Excel Interop Programming Example Feedback
5 participants
@Copilot@danmoseley@BillWagner@jkotas@AaronRobinsonMSFT

[8]ページ先頭

©2009-2025 Movatter.jp