-
Notifications
You must be signed in to change notification settings - Fork 299
/
TypeInfoVBEExtensions.cs
163 lines (149 loc) · 6.1 KB
/
TypeInfoVBEExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Rubberduck.VBEditor.ComManagement.TypeLibs.Abstract;
using Rubberduck.VBEditor.ComManagement.TypeLibs.Unmanaged;
namespace Rubberduck.VBEditor.ComManagement.TypeLibs
{
/// <summary>
/// An internal interface exposed by VBA for all components (modules, class modules, etc)
/// </summary>
/// <remarks>This internal interface is known to be supported since the very earliest version of VBA6</remarks>
[ComImport(), Guid("DDD557E1-D96F-11CD-9570-00AA0051E5D4")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IVBEComponent
{
void Placeholder1();
void Placeholder2();
void Placeholder3();
void Placeholder4();
void Placeholder5();
void Placeholder6();
void Placeholder7();
void Placeholder8();
void Placeholder9();
void Placeholder10();
void Placeholder11();
void Placeholder12();
void CompileComponent();
void Placeholder14();
IDispatch GetStdModAccessor();
void Placeholder16();
void Placeholder17();
void Placeholder18();
void Placeholder19();
void Placeholder20();
void Placeholder21();
void Placeholder22();
void Placeholder23();
void Placeholder24();
void Placeholder25();
void Placeholder26();
void Placeholder27();
void Placeholder28();
void Placeholder29();
void Placeholder30();
void Placeholder31();
void Placeholder32();
void Placeholder33();
void GetSomeRelatedTypeInfoPtrs(out IntPtr a, out IntPtr b); // returns 2 TypeInfos, seemingly related to this ITypeInfo, but slightly different.
}
/// <summary>
/// Exposes the VBE specific extensions provided by an ITypeInfo
/// </summary>
internal class TypeInfoVBEExtensions : ITypeInfoVBEExtensions, IDisposable
{
private readonly ITypeInfoWrapper _parent;
//private readonly IVBEComponent _target_IVBEComponent;
private readonly ComPointer<IVBEComponent> _vbeComponentPointer;
private IVBEComponent _vbeComponent => _vbeComponentPointer.Interface;
public TypeInfoVBEExtensions(ITypeInfoWrapper parent, IntPtr tiPtr)
{
_parent = parent;
//_target_IVBEComponent = ComHelper.ComCastViaAggregation<IVBEComponent>(tiPtr);
_vbeComponentPointer = ComPointer<IVBEComponent>.GetObjectViaAggregation(tiPtr, false, true);
}
private bool _isDisposed;
public void Dispose()
{
if (_isDisposed)
{
return;
}
_isDisposed = true;
// We shouldn't dispose the containing ITypeInfoWrapper, since it is required
// to create the class with it as a parameter and ITypeInfoWrapper should be
// the one to dispose of this class. However, we did create the IVBEComponent,
// so we'll dispose of it here.
_vbeComponentPointer?.Dispose();
/*if (_target_IVBEComponent != null)
{
RdMarshal.ReleaseComObject(_target_IVBEComponent);
}*/
}
/// <summary>
/// Silently compiles the individual VBE component (class/module etc)
/// </summary>
/// <returns>true if this module, plus any direct dependent modules compile successfully</returns>
public bool CompileComponent()
{
try
{
//_target_IVBEComponent.CompileComponent();
_vbeComponent.CompileComponent();
return true;
}
catch (Exception e)
{
ThrowOnUnrecongizedCompileError(e);
return false;
}
}
[Conditional("DEBUG")]
private static void ThrowOnUnrecongizedCompileError(Exception e)
{
if (e.HResult != (int) KnownComHResults.E_VBA_COMPILEERROR)
{
// When debugging we want to know if there are any other errors returned by the compiler as
// the error code might be useful.
throw new ArgumentException("Unrecognized VBE compiler error: \n" + e.ToString());
}
}
/// <summary>
/// Provides an accessor object for invoking methods on a standard module in a VBA project
/// </summary>
/// <remarks>caller is responsible for calling ReleaseComObject</remarks>
/// <returns>the accessor object</returns>
public IDispatch GetStdModAccessor()
{
//return _target_IVBEComponent.GetStdModAccessor();
return _vbeComponent.GetStdModAccessor();
}
/// <summary>
/// Executes a procedure inside a standard module in a VBA project
/// </summary>
/// <param name="name">the name of the procedure to invoke</param>
/// <param name="args">arguments to pass to the procedure</param>
/// <remarks>the returned object can be a COM object, and the callee is responsible for releasing it appropriately</remarks>
/// <returns>an object representing the return value from the procedure, or null if none.</returns>
public object StdModExecute(string name, object[] args = null)
{
// We search for the dispId using the real type info rather than using staticModule.GetIdsOfNames,
// as we can then also include PRIVATE scoped procedures.
var func = _parent.Funcs.Find(name, PROCKIND.PROCKIND_PROC);
if (func == null)
{
throw new ArgumentException($"StdModExecute failed. Couldn't find procedure named '{name}'");
}
var staticModule = GetStdModAccessor();
try
{
return IDispatchHelper.Invoke(staticModule, func.FuncDesc.memid, IDispatchHelper.InvokeKind.DISPATCH_METHOD, args);
}
finally
{
RdMarshal.ReleaseComObject(staticModule);
}
}
}
}