-
Notifications
You must be signed in to change notification settings - Fork 0
/
Settings.cs
513 lines (454 loc) · 24.8 KB
/
Settings.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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
#region Licence...
//-----------------------------------------------------------------------------
// Date: 25/10/10 Time: 2:33p
// Module: settings.cs
// Classes: Settings
// ExecuteOptions
//
// This module contains the definition of the CSExecutor class. Which implements
// compiling C# code and executing 'Main' method of compiled assembly
//
// Written by Oleg Shilo ([email protected])
//----------------------------------------------
// The MIT License (MIT)
// Copyright (c) 2014 Oleg Shilo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
// and associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//----------------------------------------------
#endregion Licence...
using System;
using System.IO;
#if net1
using System.Collections;
#else
#endif
using System.Threading;
using System.Xml;
#if !InterfaceAssembly
using System.Drawing.Design;
#endif
using System.ComponentModel;
namespace csscript
{
/// <summary>
/// Settings is an class that holds CS-Script application settings.
/// </summary>
public class Settings
{
/// <summary>
/// Command to be executed to perform custom cleanup.
/// If this value is empty automatic cleanup of all
/// temporary files will occurs after the script execution.
/// This implies that the script has to be executed in the
/// separate AppDomain and some performance penalty will be incurred.
///
/// Setting this value to the command for custom cleanup application
/// (e.g. csc.exe cleanTemp.cs) will force the script engine to execute
/// script in the 'current' AppDomain what will improve performance.
/// </summary>
[Category("CustomCleanup"), Description("Command to be executed to perform custom cleanup.")]
public string CleanupShellCommand
{
get { return cleanupShellCommand; }
set { cleanupShellCommand = value; }
}
/// <summary>
/// Returns value of the CleanupShellCommand (with expanding environment variables).
/// </summary>
/// <returns>shell command string</returns>
public string ExpandCleanupShellCommand() { return Environment.ExpandEnvironmentVariables(cleanupShellCommand); }
private string cleanupShellCommand = "";
/// <summary>
/// This value indicates frequency of the custom cleanup
/// operation. It has affect only if CleanupShellCommand is not empty.
/// </summary>
[Category("CustomCleanup"), Description("This value indicates frequency of the custom cleanup operation.")]
public uint DoCleanupAfterNumberOfRuns
{
get { return doCleanupAfterNumberOfRuns; }
set { doCleanupAfterNumberOfRuns = value; }
}
private uint doCleanupAfterNumberOfRuns = 30;
/// <summary>
/// Location of alternative code provider assembly. If set it forces script engine to use an alternative code compiler.
/// </summary>
[Category("Extensibility"), Description("Location of alternative code provider assembly. If set it forces script engine to use an alternative code compiler.")]
#if !InterfaceAssembly
[Editor(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(UITypeEditor))]
#endif
public string UseAlternativeCompiler
{
get { return useAlternativeCompiler; }
set { useAlternativeCompiler = value; }
}
/// <summary>
/// Returns value of the UseAlternativeCompiler (with expanding environment variables).
/// </summary>
/// <returns>Path string</returns>
public string ExpandUseAlternativeCompiler() { return Environment.ExpandEnvironmentVariables(useAlternativeCompiler); }
private string useAlternativeCompiler = "";
/// <summary>
/// Location of PostProcessor assembly. If set it forces script engine to pass compiled script through PostProcessor before the execution.
/// </summary>
[Category("Extensibility"), Description("Location of PostProcessor assembly. If set it forces script engine to pass compiled script through PostProcessor before the execution.")]
#if !InterfaceAssembly
[Editor(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(UITypeEditor))]
#endif
public string UsePostProcessor
{
get { return usePostProcessor; }
set { usePostProcessor = value; }
}
/// <summary>
/// Returns value of the UsePostProcessor (with expanding environment variables).
/// </summary>
/// <returns>Path string</returns>
public string ExpandUsePostProcessor() { return Environment.ExpandEnvironmentVariables(usePostProcessor); }
private string usePostProcessor = "";
/// <summary>
/// DefaultApartmentState is an ApartmemntState, which will be used
/// at run-time if none specified in the code with COM threading model attributes.
/// </summary>
[Category("RuntimeSettings"), Description("DefaultApartmentState is an ApartmemntState, which will be used at run-time if none specified in the code with COM threading model attributes.")]
public ApartmentState DefaultApartmentState
{
get { return defaultApartmentState; }
set { defaultApartmentState = value; }
}
private ApartmentState defaultApartmentState = ApartmentState.STA;
/// <summary>
/// Default command-line arguments. For example if "/dbg" is specified all scripts will be compiled in debug mode
/// regardless if the user specified "/dbg" when a particular script is launched.
/// </summary>
[Category("RuntimeSettings"), Description("Default command-line arguments (e.g./dbg) for all scripts.")]
public string DefaultArguments
{
get { return defaultArguments; }
set { defaultArguments = value; }
}
private string defaultArguments = CSSUtils.cmdFlagPrefix + "c " + CSSUtils.cmdFlagPrefix + "sconfig " + CSSUtils.cmdFlagPrefix + "co:" + CSSUtils.cmdFlagPrefix + "warn:0";
///// <summary>
///// Enables using a surrogate process to host the script engine at runtime. This may be a useful option for fine control over the hosting process
///// (e.g. ensuring "CPU type" of the process, CLR version to be loaded).
///// </summary>
//[Category("RuntimeSettings")]
//internal bool UseSurrogateHostingProcess //do not expose it to the user just yet
//{
// get { return useSurrogatepHostingProcess; }
// set { useSurrogatepHostingProcess = value; }
//}
private bool useSurrogatepHostingProcess = false;
bool openEndDirectiveSyntax = true;
/// <summary>
/// Enables omitting closing character (";") for CS-Script directives (e.g. "//css_ref System.Xml.dll" instead of "//css_ref System.Xml.dll;").
/// </summary>
[Browsable(false)]
public bool OpenEndDirectiveSyntax
{
get { return openEndDirectiveSyntax; }
set { openEndDirectiveSyntax = value; }
}
/// <summary>
/// Specifies the .NET Framework version that the script is compiled against. This option can have the following values:
/// v2.0
/// v3.0
/// v3.5
/// v4.0
/// </summary>
[Browsable(false)]
public string TargetFramework
{
get { return targetFramework; }
set { targetFramework = value; }
}
#if net35
private string targetFramework = "v3.5";
#else
private string targetFramework = "v4.0";
#endif
/// <summary>
/// Specifies the .NET Framework version that the script is compiled against. This option can have the following values:
/// v2.0
/// v3.0
/// v3.5
/// v4.0
/// </summary>
[Category("RuntimeSettings")]
[Description("Specifies the .NET Framework version that the script is compiled against (used by CSharpCodeProvider.CreateCompiler as the 'CompilerVersion' parameter).\nThis option is for the script compilation only.\nFor changing the script execution CLR use //css_host directive from the script.\nYou are discouraged from modifying this value thus if the change is required you need to edit css_config.xml file directly.")]
public string CompilerFramework
{
get { return targetFramework; }
}
/// <summary>
/// List of assembly names to be automatically referenced by the script. The items must be separated by coma or semicolon. Specifying .dll extension (e.g. System.Core.dll) is optional.
/// Assembly can contain expandable environment variables.
/// </summary>
[Category("Extensibility"), Description("List of assembly names to be automatically referenced by the scripts (e.g. System.dll, System.Core.dll). Assembly extension is optional.")]
public string DefaultRefAssemblies
{
get { return defaultRefAssemblies; }
set { defaultRefAssemblies = value; }
}
private string defaultRefAssemblies = "System.Core; System.Linq;";
/// <summary>
/// Returns value of the DefaultRefAssemblies (with expanding environment variables).
/// </summary>
/// <returns>List of assembly names</returns>
public string ExpandDefaultRefAssemblies() { return Environment.ExpandEnvironmentVariables(DefaultRefAssemblies); }
/// <summary>
/// List of directories to be used to search (probing) for referenced assemblies and script files.
/// This setting is similar to the system environment variable PATH.
/// </summary>
[Category("Extensibility"), Description("List of directories to be used to search (probing) for referenced assemblies and script files.\nThis setting is similar to the system environment variable PATH.")]
public string SearchDirs
{
get { return searchDirs; }
set { searchDirs = value; }
}
private string searchDirs = "%CSSCRIPT_DIR%" + Path.DirectorySeparatorChar + "Lib";
/// <summary>
/// Add search directory to the search (probing) path Settings.SearchDirs.
/// For example if Settings.SearchDirs = "c:\scripts" then after call Settings.AddSearchDir("c:\temp") Settings.SearchDirs is "c:\scripts;c:\temp"
/// </summary>
/// <param name="dir">Directory path.</param>
public void AddSearchDir(string dir)
{
if (dir != "")
{
foreach (string searchDir in searchDirs.Split(';'))
if (searchDir != "" && Utils.IsSamePath(Path.GetFullPath(searchDir), Path.GetFullPath(dir)))
return; //already there
searchDirs += ";" + dir;
}
}
/// <summary>
/// The value, which indicates if auto-generated files (if any) should should be hidden in the temporary directory.
/// </summary>
[Category("RuntimeSettings"), Description("The value, which indicates if auto-generated files (if any) should should be hidden in the temporary directory.")]
public HideOptions HideAutoGeneratedFiles
{
get { return hideOptions; }
set { hideOptions = value; }
}
private string precompiler = "";
/// <summary>
/// Path to the precompiller script/assembly (see documentation for details). You can specify multiple recompiles separating them by semicolon.
/// </summary>
[Category("RuntimeSettings"), Description("Path to the precompiller script/assembly (see documentation for details). You can specify multiple recompiles separating them by semicolon.")]
public string Precompiler
{
get { return precompiler; }
set { precompiler = value; }
}
bool customHashing = true;
/// <summary>
/// Gets or sets a value indicating whether custom string hashing algorithm should be used.
/// <para>
/// String hashing is used by the script engine for allocating temporary and cached paths.
/// However default string hashing is platform dependant (x32 vs. x64) what makes impossible
/// truly deterministic string hashing. This in turns complicates the integration of the
/// CS-Script infrastructure with the third-party applications (e.g. Notepad++ CS-Script plugin).
/// </para>
/// <para>
/// To overcome this problem CS-Script uses custom string hashing algorithm (default setting).
/// Though the native .NET hashing can be enabled if desired by setting <c>CustomHashing</c>
/// to <c>false</c>.</para>
/// </summary>
/// <value>
/// <c>true</c> if custom hashing is in use; otherwise, <c>false</c>.
/// </value>
[Browsable(false)]
public bool CustomHashing
{
get { return customHashing; }
set { customHashing = value; }
}
private HideOptions hideOptions = HideOptions.HideMostFiles;
///// <summary>
///// The value, which indicates which version of CLR compiler should be used to compile script.
///// For example CLR 2.0 can use the following compiler versions:
///// default - .NET 2.0
///// 3.5 - .NET 3.5
///// Use empty string for default compiler.
///// </summary>private string compilerVersion = "";
//[Category("RuntimeSettings")]
//public string CompilerVersion
//{
// get { return compilerVersion; }
// set { compilerVersion = value; }
//}
//private string compilerVersion = "";
/// <summary>
/// Enum for possible hide auto-generated files scenarios
/// Note: when HideAll is used it is responsibility of the pre/post script to implement actual hiding.
/// </summary>
public enum HideOptions
{
/// <summary>
/// Do not hide auto-generated files.
/// </summary>
DoNotHide,
/// <summary>
/// Hide the most of the auto-generated (cache and "imported") files.
/// </summary>
HideMostFiles,
/// <summary>
/// Hide all auto-generated files including the files generated by pre/post scripts.
/// </summary>
HideAll
}
/// <summary>
/// Boolean flag that indicates how much error details to be reported should error occur.
/// false - Top level exception will be reported
/// true - Whole exception stack will be reported
/// </summary>
[Category("RuntimeSettings"), Description("Indicates how much error details to be reported should error occur.")]
public bool ReportDetailedErrorInfo
{
get { return reportDetailedErrorInfo; }
set { reportDetailedErrorInfo = value; }
}
bool reportDetailedErrorInfo = true;
/// <summary>
/// Gets or sets a value indicating whether Optimistic Concurrency model should be used when executing scripts from the host application.
/// If set to <c>false</c> the script loading (not the execution) is globally thread-safe. If set to <c>true</c> the script loading is
/// thread-safe only among loading operations for the same script file.
/// <para>The default value is <c>true</c>.</para>
/// </summary>
/// <value>
/// <c>true</c> if Optimistic Concurrency model otherwise, <c>false</c>.
/// </value>
[Browsable(false)]
public bool OptimisticConcurrencyModel
{
get { return optimisticConcurrencyModel; }
set { optimisticConcurrencyModel = value; }
}
private bool optimisticConcurrencyModel = true;
/// <summary>
/// Boolean flag that indicates if compiler warnings should be included in script compilation output.
/// false - warnings will be displayed
/// true - warnings will not be displayed
/// </summary>
[Category("RuntimeSettings"), Description("Indicates if compiler warnings should be included in script compilation output.")]
public bool HideCompilerWarnings
{
get { return hideCompilerWarnings; }
set { hideCompilerWarnings = value; }
}
private bool hideCompilerWarnings = false;
/// <summary>
/// Boolean flag that indicates the script assembly is to be loaded by CLR as an in-memory byte stream instead of the file.
/// This setting can be useful when you need to prevent script assembly (compiled script) from locking by CLR during the execution.
/// false - script assembly will be loaded as a file. It is an equivalent of Assembly.LoadFrom(string assemblyFile).
/// true - script assembly will be loaded as a file. It is an equivalent of Assembly.Load(byte[] rawAssembly)
/// </summary>
[Category("RuntimeSettings"), Description("Indicates the script assembly is to be loaded by CLR as an in-memory byte stream instead of the file.")]
public bool InMemoryAsssembly
{
get { return inMemoryAsm; }
set { inMemoryAsm = value; }
}
private bool inMemoryAsm = false;
/// <summary>
/// Saves CS-Script application settings to a file (.dat).
/// </summary>
/// <param name="fileName">File name of the .dat file</param>
public void Save(string fileName)
{
//It is very tempting to use XmlSerializer but it adds 200 ms to the
//application startup time. Whereas current startup delay for cscs.exe is just a 100 ms.
try
{
XmlDocument doc = new XmlDocument();
doc.LoadXml("<CSSConfig/>");
doc.DocumentElement.AppendChild(doc.CreateElement("defaultArguments")).AppendChild(doc.CreateTextNode(defaultArguments));
doc.DocumentElement.AppendChild(doc.CreateElement("defaultApartmentState")).AppendChild(doc.CreateTextNode(defaultApartmentState.ToString()));
doc.DocumentElement.AppendChild(doc.CreateElement("reportDetailedErrorInfo")).AppendChild(doc.CreateTextNode(reportDetailedErrorInfo.ToString()));
doc.DocumentElement.AppendChild(doc.CreateElement("useAlternativeCompiler")).AppendChild(doc.CreateTextNode(useAlternativeCompiler));
doc.DocumentElement.AppendChild(doc.CreateElement("usePostProcessor")).AppendChild(doc.CreateTextNode(usePostProcessor));
doc.DocumentElement.AppendChild(doc.CreateElement("searchDirs")).AppendChild(doc.CreateTextNode(searchDirs));
doc.DocumentElement.AppendChild(doc.CreateElement("cleanupShellCommand")).AppendChild(doc.CreateTextNode(cleanupShellCommand));
doc.DocumentElement.AppendChild(doc.CreateElement("doCleanupAfterNumberOfRuns")).AppendChild(doc.CreateTextNode(doCleanupAfterNumberOfRuns.ToString()));
doc.DocumentElement.AppendChild(doc.CreateElement("hideOptions")).AppendChild(doc.CreateTextNode(hideOptions.ToString()));
doc.DocumentElement.AppendChild(doc.CreateElement("hideCompilerWarnings")).AppendChild(doc.CreateTextNode(hideCompilerWarnings.ToString()));
doc.DocumentElement.AppendChild(doc.CreateElement("inMemoryAsm")).AppendChild(doc.CreateTextNode(inMemoryAsm.ToString()));
doc.DocumentElement.AppendChild(doc.CreateElement("TragetFramework")).AppendChild(doc.CreateTextNode(TargetFramework));
doc.DocumentElement.AppendChild(doc.CreateElement("defaultRefAssemblies")).AppendChild(doc.CreateTextNode(defaultRefAssemblies));
doc.DocumentElement.AppendChild(doc.CreateElement("useSurrogatepHostingProcess")).AppendChild(doc.CreateTextNode(useSurrogatepHostingProcess.ToString()));
doc.DocumentElement.AppendChild(doc.CreateElement("openEndDirectiveSyntax")).AppendChild(doc.CreateTextNode(openEndDirectiveSyntax.ToString()));
doc.DocumentElement.AppendChild(doc.CreateElement("Precompiler")).AppendChild(doc.CreateTextNode(Precompiler));
doc.DocumentElement.AppendChild(doc.CreateElement("CustomHashing")).AppendChild(doc.CreateTextNode(CustomHashing.ToString()));
doc.Save(fileName);
}
catch { }
}
/// <summary>
/// Loads CS-Script application settings from a file. Default settings object is returned if it cannot be loaded from the file.
/// </summary>
/// <param name="fileName">File name of the XML file</param>
/// <returns>Setting object desterilized from the XML file</returns>
public static Settings Load(string fileName)
{
return Load(fileName, true);
}
/// <summary>
/// Loads CS-Script application settings from a file.
/// </summary>
/// <param name="fileName">File name of the XML file</param>
/// <param name="createAlways">Create and return default settings object if it cannot be loaded from the file.</param>
/// <returns>Setting object desterilized from the XML file</returns>
public static Settings Load(string fileName, bool createAlways)
{
Settings settings = new Settings();
if (File.Exists(fileName))
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
XmlNode data = doc.FirstChild;
settings.defaultArguments = data.SelectSingleNode("defaultArguments").InnerText;
settings.defaultApartmentState = (ApartmentState)Enum.Parse(typeof(ApartmentState), data.SelectSingleNode("defaultApartmentState").InnerText, false);
settings.reportDetailedErrorInfo = data.SelectSingleNode("reportDetailedErrorInfo").InnerText.ToLower() == "true";
settings.UseAlternativeCompiler = data.SelectSingleNode("useAlternativeCompiler").InnerText;
settings.UsePostProcessor = data.SelectSingleNode("usePostProcessor").InnerText;
settings.SearchDirs = data.SelectSingleNode("searchDirs").InnerText;
settings.cleanupShellCommand = data.SelectSingleNode("cleanupShellCommand").InnerText;
settings.doCleanupAfterNumberOfRuns = uint.Parse(data.SelectSingleNode("doCleanupAfterNumberOfRuns").InnerText);
settings.hideOptions = (HideOptions)Enum.Parse(typeof(HideOptions), data.SelectSingleNode("hideOptions").InnerText, true);
settings.hideCompilerWarnings = data.SelectSingleNode("hideCompilerWarnings").InnerText.ToLower() == "true";
settings.inMemoryAsm = data.SelectSingleNode("inMemoryAsm").InnerText.ToLower() == "true";
settings.TargetFramework = data.SelectSingleNode("TragetFramework").InnerText;
settings.defaultRefAssemblies = data.SelectSingleNode("defaultRefAssemblies").InnerText;
settings.useSurrogatepHostingProcess = data.SelectSingleNode("useSurrogatepHostingProcess").InnerText.ToLower() == "true";
settings.OpenEndDirectiveSyntax = data.SelectSingleNode("openEndDirectiveSyntax").InnerText.ToLower() == "true";
settings.Precompiler = data.SelectSingleNode("Precompiler").InnerText;
settings.CustomHashing = data.SelectSingleNode("CustomHashing").InnerText.ToLower() == "true";
}
catch
{
if (!createAlways)
settings = null;
else
settings.Save(fileName);
}
CSharpParser.OpenEndDirectiveSyntax = settings.OpenEndDirectiveSyntax;
}
return settings;
}
}
}