Skip to content

Commit fe395a9

Browse files
committed
Convert registration logging to use System.Disgnostics.TraceSource etc.
Move registration TraceSource to ExcelDna.Integration, and share back to ExcelDna.Loader.
1 parent 7296adb commit fe395a9

File tree

13 files changed

+219
-108
lines changed

13 files changed

+219
-108
lines changed

Source/ExcelDna.Integration/AssemblyLoader.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ namespace ExcelDna.Integration
3737
// DOCUMENT: There is a lot of magic here, and many arbitrary decisions about what to register, and how.
3838
internal class AssemblyLoader
3939
{
40+
// We consolidate the TraceSources for both ExcelDna.Integration and ExcelDna.Loader under the Excel.Integration name
41+
// (since it is the public contract for ExcelDna).
42+
// For the first version we don't make separate TraceSources for each class, though in future we might specialize under
43+
// the ExcelDna.Integration namespace, so listening to ExcelDna.Integration* will be the forward-compatible pattern.
44+
4045
// Consolidated processing so we only have a single pass through the types.
4146
// CONSIDER: This is pretty ugly right now (both the flow and the names.)
4247
// Try some fancy visitor pattern?
@@ -155,7 +160,7 @@ static bool IsMethodSupported(MethodInfo mi, bool explicitExports)
155160
// We want to log methods that are marked for export, but have unsupported types.
156161
if (!isSupported && IsMethodMarkedForExport(mi))
157162
{
158-
Debug.Print("Excel-DNA -> Unsupported Method: " + mi.Name);
163+
RegistrationLogging.Error("Method not registered due to unsupported signature: " + mi.Name);
159164
}
160165

161166
return isSupported;

Source/ExcelDna.Integration/DnaLibrary.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ internal List<ExportedAssembly> GetAssemblies(string pathResolveRoot)
222222
}
223223
catch (Exception e)
224224
{
225-
Logging.LogDisplay.WriteLine("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):");
225+
Logging.LogDisplay.WriteLine("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):");
226226
Logging.LogDisplay.WriteLine("Error in loading assemblies. Exception: " + e.ToString());
227227
}
228228
return assemblies;

Source/ExcelDna.Integration/ExcelDna.Integration.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
<Compile Include="LogDisplay.designer.cs">
8383
<DependentUpon>LogDisplay.cs</DependentUpon>
8484
</Compile>
85+
<Compile Include="TraceLogging.cs" />
8586
<Compile Include="MenuManager.cs" />
8687
<Compile Include="Project.cs" />
8788
<Compile Include="Properties\AssemblyInfo.cs" />

Source/ExcelDna.Integration/ExcelIntegration.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ namespace ExcelDna.Integration
4848
public static class ExcelIntegration
4949
{
5050
// This version must match the version declared in ExcelDna.Loader.XlAddIn.
51-
const int ExcelIntegrationVersion = 7;
51+
const int ExcelIntegrationVersion = 8;
5252

5353
private static TryExcelImplDelegate tryExcelImpl;
5454
internal static void SetTryExcelImpl(TryExcelImplDelegate d)
@@ -217,12 +217,15 @@ internal static byte[] GetSourceBytes(string sourceName)
217217
return getResourceBytesDelegate(sourceName, 3);
218218
}
219219

220+
// Called via Reflection from Loader
220221
internal static void Initialize(string xllPath)
221222
{
222223
ExcelDnaUtil.Initialize(); // Set up window handle
224+
TraceLogging.Initialize();
223225
DnaLibrary.InitializeRootLibrary(xllPath);
224226
}
225227

228+
// Called via Reflection from Loader
226229
internal static void DeInitialize()
227230
{
228231
DnaLibrary.DeInitialize();
@@ -319,6 +322,12 @@ internal static void CalculationEnded()
319322
ExcelAsyncUtil.OnCalculationEnded();
320323
}
321324

325+
// Called via Reflection from Loader after Initialization
326+
internal static TraceSource GetIntegrationTraceSource()
327+
{
328+
return TraceLogging.IntegrationTraceSource;
329+
}
330+
322331
// This version check is made by the ExceDna.Loader to make sure we have matching versions.
323332
internal static int GetExcelIntegrationVersion()
324333
{

Source/ExcelDna.Integration/ExcelRtd.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public static bool TryRTD(out object result, string progId, string server, param
166166
}
167167
catch (UnauthorizedAccessException secex)
168168
{
169-
Logging.LogDisplay.WriteLine("The RTD server of type {0} required by add-in {1} could not be registered.\r\nThis may be due to restricted permissions on the user's HKCU\\Software\\Classes key.\r\nError message: {2}", rtdServerType.FullName, DnaLibrary.CurrentLibrary.Name, secex.Message );
169+
Logging.LogDisplay.WriteLine("The RTD server of type {0} required by add-in {1} could not be registered.\r\nThis may be due to restricted permissions on the user's HKCU\\Software\\Classes key.\r\nError message: {2}", rtdServerType.FullName, DnaLibrary.CurrentLibrary.Name, secex.Message);
170170
result = ExcelErrorUtil.ToComError(ExcelError.ExcelErrorValue);
171171
// Return true to have the #VALUE stick, just as it was before the array-call refactoring
172172
return true;

Source/ExcelDna.Integration/ExternalLibrary.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ internal List<ExportedAssembly> GetAssemblies(string pathResolveRoot, DnaLibrary
170170
DnaLibrary lib = DnaLibrary.LoadFrom(uri);
171171
if (lib == null)
172172
{
173-
LogDisplay.WriteLine("External library could not be registered - Path: " + Path);
174-
LogDisplay.WriteLine(" Error: DnaLibrary could not be loaded.");
173+
Logging.LogDisplay.WriteLine("External library could not be registered - Path: " + Path);
174+
Logging.LogDisplay.WriteLine(" Error: DnaLibrary could not be loaded.");
175175
return list;
176176
}
177177
// CONSIDER: Should we add a resolve story for .dna files at Uris?

Source/ExcelDna.Integration/Project.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ private CodeDomProvider GetProvider()
468468
}
469469
else
470470
{
471-
Logging.LogDisplay.WriteLine("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):");
471+
Logging.LogDisplay.WriteLine("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):");
472472
Logging.LogDisplay.WriteLine(" The F# CodeDom provider (FSharp.Compiler.CodeDom.dll) could not be loaded.");
473473
Logging.LogDisplay.WriteLine(" Please ensure that the F# Compiler is installed and that the");
474474
Logging.LogDisplay.WriteLine(" FSharp.Compiler.CodeDom.dll assembly (part of the F# PowerPack) can be loaded by the add-in.");
@@ -478,7 +478,7 @@ private CodeDomProvider GetProvider()
478478
}
479479
catch (Exception ex)
480480
{
481-
Logging.LogDisplay.WriteLine("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):");
481+
Logging.LogDisplay.WriteLine("There was an error in loading the add-in " + DnaLibrary.CurrentLibraryName + " (" + DnaLibrary.XllPath + "):");
482482
Logging.LogDisplay.WriteLine("Error in loading the F# CodeDom provider.");
483483
Logging.LogDisplay.WriteLine(" Exception: " + ex.Message);
484484
return null;
@@ -502,7 +502,7 @@ private CodeDomProvider GetProvider()
502502
catch (Exception e)
503503
{
504504
Debug.Fail("Unknown Project Language: " + Language);
505-
Logging.LogDisplay.WriteLine("Unknown Project Language: " + Language);
505+
Logging.LogDisplay.WriteLine("Unknown Project Language: " + Language);
506506
Logging.LogDisplay.WriteLine(" Exception: " + e.Message);
507507
}
508508
return null;
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Security;
5+
using System.Text;
6+
7+
namespace ExcelDna.Integration
8+
{
9+
// This class supports intenal logging.
10+
// Internal logging is implemented with the System.Diagnostics tracing implementation.
11+
12+
// Add a trace listener for the ExcelDna.Integration source which logs warnings and errors to the LogDisplay
13+
// (only popping up the window for errors).
14+
// Verbose logging can be configured via the .config file
15+
16+
// We define a TraceSource called ExcelDna.Integration (that is also exported to ExcelDna.Loader and called from there)
17+
// We consolidate the two assemblies against a single TraceSource, since ExcelDna.Integration is the only public contract,
18+
// and we expect to move more of the registration into the ExcelDna.Integration assembly in future.
19+
20+
#region Microsoft License
21+
// The logging helper implementation here is adapted from the Logging.cs file for System.Net
22+
// Taken from https://github.com/Microsoft/referencesource/blob/c697a4b9782dc8c85c02344a847cb68163702aa7/System/net/System/Net/Logging.cs
23+
// Under the following license:
24+
//
25+
// The MIT License (MIT)
26+
27+
// Copyright (c) Microsoft Corporation
28+
29+
// Permission is hereby granted, free of charge, to any person obtaining a copy
30+
// of this software and associated documentation files (the "Software"), to deal
31+
// in the Software without restriction, including without limitation the rights
32+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33+
// copies of the Software, and to permit persons to whom the Software is
34+
// furnished to do so, subject to the following conditions:
35+
36+
// The above copyright notice and this permission notice shall be included in all
37+
// copies or substantial portions of the Software.
38+
39+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
45+
// SOFTWARE.
46+
#endregion
47+
48+
enum IntegrationTraceEventId
49+
{
50+
RegistrationInitialize = 1025,
51+
RegistrationEvent = 1026 // Everything is miscellaneous
52+
}
53+
54+
class TraceLogging
55+
{
56+
static volatile bool s_LoggingEnabled = true;
57+
static volatile bool s_LoggingInitialized;
58+
static volatile bool s_AppDomainShutdown;
59+
const string TraceSourceName = "ExcelDna.Integration";
60+
internal static TraceSource IntegrationTraceSource; // Retrieved from ExcelDna.Loader through ExcelIntegration
61+
62+
public static void Initialize()
63+
{
64+
if (!s_LoggingInitialized)
65+
{
66+
bool loggingEnabled = false;
67+
IntegrationTraceSource = new TraceSource(TraceSourceName, SourceLevels.All);
68+
//GlobalLog.Print("Initalizating tracing");
69+
70+
try
71+
{
72+
loggingEnabled = (IntegrationTraceSource.Switch.ShouldTrace(TraceEventType.Critical));
73+
}
74+
catch (SecurityException)
75+
{
76+
// These may throw if the caller does not have permission to hook up trace listeners.
77+
// We treat this case as though logging were disabled.
78+
Close();
79+
loggingEnabled = false;
80+
}
81+
if (loggingEnabled)
82+
{
83+
AppDomain currentDomain = AppDomain.CurrentDomain;
84+
//currentDomain.UnhandledException += UnhandledExceptionHandler;
85+
currentDomain.DomainUnload += AppDomainUnloadEvent;
86+
currentDomain.ProcessExit += ProcessExitEvent;
87+
}
88+
s_LoggingEnabled = loggingEnabled;
89+
s_LoggingInitialized = true;
90+
}
91+
}
92+
93+
static bool ValidateSettings(TraceSource traceSource, TraceEventType traceLevel)
94+
{
95+
if (!s_LoggingEnabled)
96+
{
97+
return false;
98+
}
99+
if (!s_LoggingInitialized)
100+
{
101+
Initialize();
102+
}
103+
if (traceSource == null || !traceSource.Switch.ShouldTrace(traceLevel))
104+
{
105+
return false;
106+
}
107+
if (s_AppDomainShutdown)
108+
{
109+
return false;
110+
}
111+
return true;
112+
}
113+
114+
static void ProcessExitEvent(object sender, EventArgs e)
115+
{
116+
Close();
117+
s_AppDomainShutdown = true;
118+
}
119+
120+
private static void AppDomainUnloadEvent(object sender, EventArgs e)
121+
{
122+
Close();
123+
s_AppDomainShutdown = true;
124+
}
125+
126+
static void Close()
127+
{
128+
if (IntegrationTraceSource != null)
129+
IntegrationTraceSource.Close();
130+
}
131+
132+
}
133+
134+
class RegistrationLogging
135+
{
136+
public static void Log(TraceEventType eventType, string message, params object[] args)
137+
{
138+
Debug.Write(string.Format("RegistrationLogging: {0:yyyy-MM-dd HH:mm:ss} {1} {2}\r\n", DateTime.Now, eventType, string.Format(message, args)));
139+
140+
TraceLogging.IntegrationTraceSource.TraceEvent(eventType, (int)IntegrationTraceEventId.RegistrationEvent, message, args);
141+
}
142+
143+
public static void Info(string message, params object[] args)
144+
{
145+
Log(TraceEventType.Information, message, args);
146+
}
147+
148+
public static void Warn(string message, params object[] args)
149+
{
150+
Log(TraceEventType.Warning, message, args);
151+
}
152+
153+
public static void Error(string message, params object[] args)
154+
{
155+
Log(TraceEventType.Error, message, args);
156+
}
157+
158+
public static void ErrorException(string message, Exception ex)
159+
{
160+
Log(TraceEventType.Error, "{0} : {1} - {2}", message, ex.GetType().Name.ToString(), ex.Message);
161+
}
162+
163+
}
164+
}

Source/ExcelDna.Loader/IntegrationHelpers.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,5 +127,10 @@ internal static void CalculationEnded()
127127
{
128128
integrationType.InvokeMember("CalculationEnded", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, null);
129129
}
130+
131+
internal static System.Diagnostics.TraceSource GetIntegrationTraceSource()
132+
{
133+
return (System.Diagnostics.TraceSource)integrationType.InvokeMember("GetIntegrationTraceSource", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, null);
134+
}
130135
}
131136
}

0 commit comments

Comments
 (0)