Ki Frost
Sorceror
Im making a compiler that sits on-top of the distro compiler, it compiles a defined 'list' of folders.
I have it semi-working, but I have an issue im not entirely sure how to resolve.
Script:
Result:
I changed the reference collection to include the MultiCompiler additions, and it gives that, but without the MultiCompiler additions, it doesnt include any of the lower-level scripts\folders.
Any help is appreciated. Ty
I have it semi-working, but I have an issue im not entirely sure how to resolve.
Script:
Code:
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Reflection;
using System.Security.Cryptography;
using Microsoft.CSharp;
using Microsoft.VisualBasic;
using System.Diagnostics;
namespace Server
{
public static class MultiCompiler
{
public static string[] ScriptPath = new string[]
{
"Scripts\\Distros\\",
"Scripts\\Modified\\",
"Scripts\\Customs\\",
};
private static List<string> m_AdditionalReferences = new List<string>();
private delegate CompilerResults Compiler(bool debug);
public static bool Compile()
{
return Compile(false);
}
public static bool Compile(bool debug)
{
return Compile(debug, true);
}
public static bool Compile(bool debug, bool cache)
{
if (ScriptPath.Length <= 0)
{
Console.WriteLine("Scripts: Compiling C# scripts... no directories defined.");
return false;
}
for (int i = 0; i < ScriptPath.Length; i++)
{
ScriptCompiler.EnsureDirectory(ScriptPath[i]);
ScriptCompiler.EnsureDirectory((ScriptPath[i] + "Output\\"));
}
if (m_AdditionalReferences.Count > 0)
m_AdditionalReferences.Clear();
List<Assembly> assemblies = new List<Assembly>();
for (int i = 0; i < ScriptPath.Length; i++)
{
string dir = ScriptPath[i].Remove(0, (ScriptPath[i].IndexOf("\\") + 1));
dir = dir.Remove(dir.Length - 1);
Console.Write("Scripts: Compiling C# scripts... [{0}] ", dir);
List<string> files = new List<string>();
ScriptCompiler.GetScripts(files, ScriptPath[i], "*.cs");
if (files.Count == 0)
{
if (i == 0)
{
Console.WriteLine("no files found.");
return false;
}
else
{
Console.WriteLine("-skipped (empty)");
continue;
}
}
Assembly assembly;
if (CompileCSScripts(ScriptPath[i], files, debug, cache, out assembly))
{
if (assembly != null)
{
assemblies.Add(assembly);
}
}
else
{
return false;
}
files = new List<string>();
}
if (assemblies.Count == 0)
{
return false;
}
ScriptCompiler.Assemblies = assemblies.ToArray();
Console.Write("Scripts: Verifying...");
Stopwatch watch = Stopwatch.StartNew();
Core.VerifySerialization();
watch.Stop();
Console.WriteLine("done ({0} items, {1} mobiles) ({2:F2} seconds)", Core.ScriptItems, Core.ScriptMobiles, watch.Elapsed.TotalSeconds);
return true;
}
public static bool CompileCSScripts(string dir, List<string> files, bool debug, bool cache, out Assembly assembly)
{
if (File.Exists((dir + "Output\\Scripts.CS.dll")))
{
if (cache && File.Exists((dir + "Output\\Scripts.CS.hash")))
{
try
{
byte[] hashCode = GetHashCode((dir + "Output\\Scripts.CS.dll"), files.ToArray(), debug);
using (FileStream fs = new FileStream((dir + "Output\\Scripts.CS.hash"), FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (BinaryReader bin = new BinaryReader(fs))
{
byte[] bytes = bin.ReadBytes(hashCode.Length);
if (bytes.Length == hashCode.Length)
{
bool valid = true;
for (int i = 0; i < bytes.Length; ++i)
{
if (bytes[i] != hashCode[i])
{
valid = false;
break;
}
}
if (valid)
{
assembly = Assembly.LoadFrom((dir + "Output\\Scripts.CS.dll"));
if (!m_AdditionalReferences.Contains(assembly.Location))
{
m_AdditionalReferences.Add(assembly.Location);
}
Console.WriteLine("done (cached)");
return true;
}
}
}
}
}
catch
{
}
}
}
DeleteFiles(dir, "Scripts.CS*.dll");
using (CSharpCodeProvider provider = new CSharpCodeProvider())
{
string path = GetUnusedPath(dir, "Scripts.CS");
List<string> getRefAssemblies = new List<string>(ScriptCompiler.GetReferenceAssemblies());
getRefAssemblies.AddRange(m_AdditionalReferences); //MultiCompiler references...
string[] refAssemblies = getRefAssemblies.ToArray();
CompilerParameters parms = new CompilerParameters(refAssemblies, path, debug);
string defines = ScriptCompiler.GetDefines();
if (defines != null)
parms.CompilerOptions = defines;
if (Core.HaltOnWarning)
parms.WarningLevel = 4;
#if !MONO
CompilerResults results = provider.CompileAssemblyFromFile(parms, files.ToArray());
#else
parms.CompilerOptions = String.Format( "{0} /nowarn:169,219,414 /recurse:Scripts/*.cs", parms.CompilerOptions );
CompilerResults results = provider.CompileAssemblyFromFile( parms, "" );
#endif
m_AdditionalReferences.Add(path);
ScriptCompiler.Display(results);
#if !MONO
if (results.Errors.Count > 0)
{
assembly = null;
return false;
}
#else
if( results.Errors.Count > 0 ) {
foreach( CompilerError err in results.Errors ) {
if ( !err.IsWarning ) {
assembly = null;
return false;
}
}
}
#endif
if (cache && Path.GetFileName(path) == "Scripts.CS.dll")
{
try
{
byte[] hashCode = GetHashCode(path, files.ToArray(), debug);
using (FileStream fs = new FileStream((dir + "Output\\Scripts.CS.hash"), FileMode.Create, FileAccess.Write, FileShare.None))
{
using (BinaryWriter bin = new BinaryWriter(fs))
{
bin.Write(hashCode, 0, hashCode.Length);
}
}
}
catch
{
}
}
assembly = results.CompiledAssembly;
return true;
}
}
public static string GetUnusedPath(string dir, string name)
{
string path = Path.Combine(Core.BaseDirectory, String.Format((dir + "Output\\{0}.dll"), name));
for (int i = 2; File.Exists(path) && i <= 1000; ++i)
path = Path.Combine(Core.BaseDirectory, String.Format((dir + "Output\\{0}.{1}.dll"), name, i));
return path;
}
public static void DeleteFiles(string path, string mask)
{
try
{
string[] files = Directory.GetFiles(Path.Combine(Core.BaseDirectory, (path + "Output")), mask);
foreach (string file in files)
{
try { File.Delete(file); }
catch { }
}
}
catch
{
}
}
private static byte[] GetHashCode(string compiledFile, string[] scriptFiles, bool debug)
{
using (MemoryStream ms = new MemoryStream())
{
using (BinaryWriter bin = new BinaryWriter(ms))
{
FileInfo fileInfo = new FileInfo(compiledFile);
bin.Write(fileInfo.LastWriteTimeUtc.Ticks);
foreach (string scriptFile in scriptFiles)
{
fileInfo = new FileInfo(scriptFile);
bin.Write(fileInfo.LastWriteTimeUtc.Ticks);
}
bin.Write(debug);
bin.Write(Core.Version.ToString());
ms.Position = 0;
using (SHA1 sha1 = SHA1.Create())
{
return sha1.ComputeHash(ms);
}
}
}
}
}
}
Result:
RunUO - [www.runuo.com] Version 2.1, Build 4151.28729
Core: Running on .NET Framework Version 4.0.30319
Core: Running with arguments: -debug
Core: Optimizing for 2 64-bit processors
Scripts: Compiling C# scripts... [Distros] done (0 errors, 0 warnings)
Scripts: Compiling C# scripts... [Modified] -skipped (empty)
Scripts: Compiling C# scripts... [Customs] done (0 errors, 0 warnings)
Scripts: Verifying...done (4582 items, 1060 mobiles) (1.21 seconds)
Error:
System.Reflection.TargetInvocationException: Exception has been thrown by the ta
rget of an invocation. ---> System.Exception: A poison with that level already e
xists.
at Server.Poison.Register(Poison reg)
at Server.PoisonImpl.Configure() in c:\Dropbox\Nagashizar 3.0\Server\Scripts\
Distros\Misc\Poison.cs:line 19
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Ob
ject target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAt
tributes, RuntimeType typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Obj
ect target, Object[] arguments, Signature sig, MethodAttributes methodAttributes
, RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisib
ilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture)
at Server.ScriptCompiler.Invoke(String method)
at Server.Core.Main(String[] args)
This exception is fatal, press return to exit
I changed the reference collection to include the MultiCompiler additions, and it gives that, but without the MultiCompiler additions, it doesnt include any of the lower-level scripts\folders.
Any help is appreciated. Ty