PRB: Visual Basic .NET Error Using GetObject or GetActiveObject for Running Instance of Office Application (308409)
The information in this article applies to:
- Microsoft Visual Basic .NET (2003)
- Microsoft Visual Basic .NET (2002)
- Microsoft Office Access 2003
- Microsoft Access 2002
- Microsoft Office Excel 2003
- Microsoft Excel 2002
- Microsoft Office PowerPoint 2003
- Microsoft PowerPoint 2002
- Microsoft Office Word 2003
- Microsoft Word 2002
This article was previously published under Q308409 For a Microsoft Visual Basic 6.0 version of this
article, see
238610. For a Microsoft Visual C#
.NET version of this article, see
316125. SYMPTOMS When you try to use GetObject or System.Runtime.InteropServices.Marshal.GetActiveObject from Microsoft Visual Basic .NET to automate a running Microsoft Office
application, you may receive one of the following error messages:
With GetObject: Cannot create ActiveX component.
With System.Runtime.InteropServices.Marshal.GetActiveObject: An unhandled exception of type
'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll
Additional information: Operation unavailable
CAUSE Although the Office application is running, it may not be
registered in the Running Object Table (ROT). A running instance of an Office
application must be registered in the ROT before before it can be
automated.
When an Office application starts, it does not immediately
register its running objects. This optimizes the application startup process.
Instead of registering at startup, an Office application registers its running
objects in the ROT after it loses focus. Therefore, if you attempt to attach to
a running instance of an Office application before the application has lost
focus, you may receive an error message. RESOLUTION Using code, you can change focus from the Office
application to your own application (or to some other application) to allow it
to register itself in the ROT. Additionally, if your code is starting the
executable (.exe) file for the Office application, you may need to wait for the
Office application to finish loading before you attempt to attach to the
running instance. A code sample is provided as a workaround in the "More
Information" section.
STATUS This behavior is by design.WORKAROUNDTo work around the problem, follow these steps:
- Give focus to the Office application by changing the
second argument of the Shell function to AppWinStyle.MinimizedFocus, AppWinStyle.MaximizedFocus, or AppWinStyle.NormalFocus.
- Give your Visual Basic form the focus.
- Try to use GetObject while accounting for the load time of the Office
application.
The following revised code illustrates this workaround:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim iSection As Integer
Dim iTries As Integer
Dim oExcel As Object
' Enable an error handler for this procedure.
On Error GoTo ErrorHandler
' Start Excel, giving it focus.
Shell("C:\Program Files\Microsoft Office\Office10\Excel.exe", _
AppWinStyle.MinimizedFocus)
' Move focus back to this form. (This ensures the Office
' application registers itself in the ROT, allowing
' GetObject to find it.)
AppActivate(Title:=Me.Text)
' Attempt to use GetObject to reference the running
' Office application.
iSection = 1 'attempting GetObject...
oExcel = GetObject(, "Excel.Application")
iSection = 0 'resume normal error handling
' Automate Excel.
oExcel.ActiveCell.Value = "Hi"
MsgBox(oExcel.Name & ": able to GetObject after " & _
iTries + 1 & " tries.", MsgBoxStyle.MsgBoxSetForeground)
' You are finished with automation, so release your reference.
oExcel = Nothing
' Exit procedure.
Exit Sub
ErrorHandler:
If iSection = 1 Then 'GetObject may have failed because the
'Shell function is asynchronous; enough time has not elapsed
'for GetObject to find the running Office application. Wait
'1/2 seconds and retry the GetObject. If you try 20 times
'and GetObject still fails, assume some other reason
'for GetObject failing and exit the procedure.
iTries = iTries + 1
If iTries < 20 Then
System.Threading.Thread.Sleep(500) ' wait 1/2 seconds
AppActivate(Title:=Me.Text)
Resume 'resume code at the GetObject line
Else
MsgBox("GetObject still failing. Process ended.", _
MsgBoxStyle.MsgBoxSetForeground)
End If
Else 'iSection = 0 so use normal error handling:
MsgBox(Err.Description, _
MsgBoxStyle.MsgBoxSetForeground)
End If
End Sub
REFERENCES For more information, visit the following Microsoft Developer
Network (MSDN) Web site:
Modification Type: | Major | Last Reviewed: | 1/19/2006 |
---|
Keywords: | kbAutomation kbprb KB308409 kbAudDeveloper |
---|
|