/// <summary> /// Run SQL command /// </summary> /// <param name="context">script context</param> /// <param name="cmdText">SQL statement text</param> /// <param name="parameters">list of parameters</param> /// <param name="timeout">Timeout, may be null</param> /// <param name="execCommand">callback</param> /// <param name="messagesTo">Where to output messages (for example, by PRINT SQL statement)</param> /// <param name="errorsTo">Where to output errors</param> /// <param name="ignoreDataErrors">If true, SQL errors below severity 17 do not throw exceptions and instead just write messages to the output</param> public static void RunCommand(ScriptContext context, string cmdText, List <SqlParam> parameters, TimeSpan?timeout, ExecCommand execCommand, string messagesTo, string errorsTo, bool ignoreDataErrors) { var connection = Database.CurrentConnection; if (connection == null) { throw new ScriptRuntimeException("There is no active database connection"); } { IDbCommand cmd = connection.CreateCommand(); if (timeout.HasValue) { cmd.CommandTimeout = (int)(timeout.Value.TotalSeconds + 0.999); } cmd.CommandType = CommandType.Text; cmd.CommandText = cmdText; context.WriteVerbose(Utils.PrefixEachLine("SQL> ", cmdText)); if (parameters != null && parameters.Count > 0) { context.WriteVerbose(String.Format("SQL> -- with {0} params: ", parameters.Count)); foreach (var parameter in parameters) { object val = context.Transform(parameter.Value, parameter.Transform); string type = context.TransformStr(parameter.SqlType, parameter.Transform); var param = cmd.CreateParameter(); if (String.IsNullOrEmpty(type)) { if (param is SqlParameter) { type = "nvarchar(4000)"; } else { type = "string(4000)"; } if (val != null) { if (val is DateTime || val is DateTime?) { type = "datetime"; } else if (val is DateTimeOffset || val is DateTimeOffset?) { type = "datetimeoffset"; } if (param is SqlParameter) { if (val is int || val is int?) { type = SqlDbType.Int.ToString(); } else if (val is short || val is short? || val is byte || val is byte?) { type = SqlDbType.SmallInt.ToString(); } else if (val is sbyte || val is sbyte?) { type = SqlDbType.TinyInt.ToString(); } else if (val is decimal || val is decimal?) { type = SqlDbType.Money.ToString(); } else if (val is byte[]) { type = SqlDbType.Binary.ToString(); } else if (val is double || val is double? || val is float || val is float?) { type = SqlDbType.Real.ToString(); } else if (val is uint || val is Nullable <uint> || val is ushort || val is Nullable <ushort> ) { type = SqlDbType.Int.ToString(); } else if (val is long || val is Nullable <long> || val is Nullable <ulong> || val is ulong) { type = SqlDbType.BigInt.ToString(); } } else { if (val is int || val is int?) { type = DbType.Int32.ToString(); } else if (val is short || val is short? || val is byte || val is byte?) { type = DbType.Int16.ToString(); } else if (val is sbyte || val is sbyte?) { type = DbType.SByte.ToString(); } else if (val is decimal || val is decimal?) { type = DbType.Decimal.ToString(); } else if (val is byte[]) { type = DbType.Binary.ToString(); } else if (val is double || val is double? || val is float || val is float?) { type = DbType.Double.ToString(); } else if (val is uint || val is Nullable <uint> || val is ushort || val is Nullable <ushort> ) { type = DbType.Int64.ToString(); } else if (val is long || val is Nullable <long> || val is Nullable <ulong> || val is ulong) { type = DbType.Int64.ToString(); } } } } int?size = null; int n = type.IndexOf('('); if (n != -1) { var sz = type.Substring(n + 1).TrimEnd().TrimEnd(new char[] { ')' }).Trim(); size = (string.Compare(sz, "max", StringComparison.OrdinalIgnoreCase) == 0)?-1:Utils.To <int>(sz); type = type.Substring(0, n).Trim(); } if (param is SqlParameter && Array.Exists(s_sqlDbTypeNames, x => StringComparer.OrdinalIgnoreCase.Compare(type, x) == 0)) { ((SqlParameter)param).SqlDbType = Utils.To <SqlDbType>(type); } else { param.DbType = Utils.To <DbType>(type); } param.ParameterName = parameter.Name; param.Direction = ParameterDirection.Input; if (size.HasValue) { param.Size = size.Value; } if (val == null || ((val is string && String.IsNullOrEmpty((string)val)) && parameter.EmptyAsNull)) { param.Value = DBNull.Value; val = null; } else { param.Value = val; } cmd.Parameters.Add(param); context.WriteVerbose(String.Format("SQL> -- {1} {0}=> {2}", param.ParameterName, param.DbType, Dump.ToDump(val))); } } SqlInfoMessageEventHandler handler = (sender, e) => { if (e.Errors.Count > 0) { foreach (SqlError s1 in e.Errors) { context.Debug.WriteLine(String.Format("SQL> (Error: {0}, Class:{1}, State:{2}, Proc: {3}, #: {4}): {5}", s1.Number, s1.Class, s1.State, s1.Procedure, s1.LineNumber, s1.Message)); if (s1.Class >= 11) { context.OutTo(errorsTo, s1.Message + Environment.NewLine); } else { context.OutTo(messagesTo, s1.Message + Environment.NewLine); } } } }; var sql = connection as SqlConnection; bool b = false; if (sql != null) { b = sql.FireInfoMessageEventOnUserErrors; sql.FireInfoMessageEventOnUserErrors = ignoreDataErrors; sql.InfoMessage += handler; } try { int nRows = execCommand(cmd); if (nRows != -1) { context.WriteVerbose(String.Format("SQL>-- {0} rows affected", nRows)); } } finally { if (sql != null) { sql.InfoMessage -= handler; sql.FireInfoMessageEventOnUserErrors = b; } } } }
/// <summary> /// Compile code /// </summary> /// <param name="outputtype">Type of the assembly to produce</param> /// <param name="code">C# code</param> /// <param name="moduleName">Name of the generated module</param> /// <param name="options">Compilation options</param> /// <returns></returns> public Assembly Compile(CompiledOutputType outputtype, string code, string moduleName, CompileOptions options) { string codeOutputDirectory = null; if (options != null && !string.IsNullOrEmpty(options.CodeOutputDirectory)) { Directory.CreateDirectory(options.CodeOutputDirectory); codeOutputDirectory = Path.GetFullPath(options.CodeOutputDirectory); } // Check that we have .NET if (MaxAvailableNETVersion < _neededVersion) { throw new ParsingException(string.Format( ".NET v{0}.{1} is required to compile this script. .NET v{2}.{3} is installed.", _neededVersion.Major, _neededVersion.Minor, MaxAvailableNETVersion.Major, MaxAvailableNETVersion.Minor)); } // .NET 3.0 missing method fix bool prov35 = (MaxAvailableNETVersion >= new Version(3, 5)); // Proceed with the gory details CompilerParameters param = new CompilerParameters(); if (outputtype == CompiledOutputType.InMemoryAssembly) { param.GenerateExecutable = false; // If codeoutput directory is set, generate DLLs with debug info for <code> debuggin param.GenerateInMemory = false; param.IncludeDebugInformation = (codeOutputDirectory != null); } else { param.GenerateExecutable = (outputtype == CompiledOutputType.ConsoleExe || outputtype == CompiledOutputType.WindowsExe); param.GenerateInMemory = false; param.IncludeDebugInformation = (codeOutputDirectory != null); param.OutputAssembly = moduleName; var dir = Path.GetDirectoryName(moduleName); if (!string.IsNullOrEmpty(dir) && (codeOutputDirectory != null) && !Directory.Exists(dir)) { Directory.CreateDirectory(dir); } } param.WarningLevel = 0; switch (outputtype) { case CompiledOutputType.Library: param.CompilerOptions += " /target:library"; break; case CompiledOutputType.ConsoleExe: param.CompilerOptions += " /target:exe"; break; case CompiledOutputType.WindowsExe: param.CompilerOptions += " /target:winexe"; break; } CompilerResults cr; List <string> toDelete = new List <string>(); Dictionary <string, bool> embedded = new Dictionary <string, bool>(); try { if (options != null && options.Manifest != null) { // Only C# 3.5 can do manifests & icons separately. If compiled with .NET 2.0 there will be no file version if (prov35) { string wm = getTempFilename(codeOutputDirectory, str_manifest); toDelete.Add(wm); File.WriteAllBytes(wm, options.Manifest); string wi = getTempFilename(codeOutputDirectory, str_icon); toDelete.Add(wi); File.WriteAllBytes(wi, options.Icon); param.CompilerOptions += " " + Utils.QuoteArg("/win32manifest:" + wm) + " " + Utils.QuoteArg("/win32icon:" + wi); } else { string w32 = getTempFilename(codeOutputDirectory, str_w32resources); toDelete.Add(w32); File.WriteAllBytes(w32, options.Compiled); param.Win32Resource = w32; } } if (options != null && options.EntryPoint != null) { param.MainClass = options.EntryPoint; } bool allStrong = true; Dictionary <string, string> resources = new Dictionary <string, string>(); foreach (Ref r in _references) { string location = r.From; string dllName = string.Empty; if (!string.IsNullOrEmpty(r.Name)) { dllName = new AssemblyName(r.Name).Name + ".dll"; } if (string.IsNullOrEmpty(location) && options != null && options.StreamProvider != null) { using (var v = options.StreamProvider(dllName)) if (v != null) { location = getTempFilename(codeOutputDirectory, str_references + Path.GetFileName(dllName)); toDelete.Add(location); using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.Read)) v.WriteTo(fs); } } if (string.IsNullOrEmpty(location)) { location = r.ForceLoad(_verboseWriter).Location; } if (string.IsNullOrEmpty(location)) { throw new FileNotFoundException(string.Format("Referenced assembly {0} could not be found", r)); } param.ReferencedAssemblies.Add(location); if (options != null && moduleName != null && r.Embed && (CompiledOutputType.WindowsExe == outputtype || CompiledOutputType.ConsoleExe == outputtype) && options.StreamProvider != null) { MemoryStream v = options.StreamProvider(dllName + ".gz"); if (!string.IsNullOrEmpty(r.Name)) { var n = new AssemblyName(r.Name); if (n.GetPublicKeyToken() == null || n.GetPublicKeyToken().Length == 0) { _verboseWriter.WriteVerbose("Compile> Embedded assembly " + r.Name + " does not have a strong name."); allStrong = false; } } if (!embedded.ContainsKey(dllName)) { string prefix = "XSharper.Embedded.Assemblies."; // Let's be nice here, and compress the dll a bit string complocation = createResource(resources, v, location, prefix + dllName, codeOutputDirectory, str_resources + prefix.Replace(".", "\\")); if (complocation != null) { toDelete.Add(complocation); } embedded[dllName] = true; } } } // If user wanted any files, add them too if (options != null && options.FilesToEmbed != null) { foreach (var pair in options.FilesToEmbed) { string name = (pair.IsAssembly) ? "XSharper.Embedded.Assemblies." : "XSharper.Embedded.Files."; if (pair.IsAssembly) { _verboseWriter.WriteVerbose("Compile> Getting assembly name of " + pair.Location); var pkt = AssemblyName.GetAssemblyName(pair.Location).GetPublicKeyToken(); if (pkt == null || pkt.Length == 0) { _verboseWriter.WriteVerbose("Compile> Embedded assembly " + pair.Location + " does not have a strong name."); allStrong = false; } } string complocation = createResource(resources, null, pair.Location, name + new FileInfo(pair.StreamName).Name, codeOutputDirectory, str_resources + name.Replace(".", "\\")); if (complocation != null) { toDelete.Add(complocation); } } if (allStrong) { string location = getTempFilename(codeOutputDirectory, str_resources + "XSharper\\Embedded\\Assemblies\\AllStrongName.flag"); toDelete.Add(location); using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.Read)) fs.WriteByte((byte)'1'); } } if (codeOutputDirectory != null) { param.TempFiles = new TempFileCollection(codeOutputDirectory, true); } foreach (var resource in resources) { param.CompilerOptions += " \"/res:" + resource.Key + "," + resource.Value + "\" "; } if (options != null && options.ExtraOptions != null) { param.CompilerOptions += " " + options.ExtraOptions; } CSharpCodeProvider prov; if (!prov35) { prov = new CSharpCodeProvider(); } else { Dictionary <string, string> providerOptions = new Dictionary <string, string>(); if (Environment.Version.Major >= 4) { providerOptions.Add("CompilerVersion", string.Format("v{0}", "4.0")); } else { providerOptions.Add("CompilerVersion", string.Format("v{0}", "3.5")); } // Must do it this way, to prevent loading errors on machines with .net 2.0 prov = (CSharpCodeProvider)Activator.CreateInstance(typeof(CSharpCodeProvider), new object[] { providerOptions }); } _verboseWriter.WriteVerbose("Compile> " + Dump.ToDump(param)); cr = prov.CompileAssemblyFromSource(param, code); // Do some beautification if (outputtype != CompiledOutputType.InMemoryAssembly && codeOutputDirectory != null) { beautifyOutput(prov35, outputtype, options, param, resources, moduleName, _neededVersion); } _verboseWriter.WriteVerbose("Compile> -- Completed --"); // Fire compilation if (cr.Errors != null && cr.Errors.Count != 0) { if (File.Exists(cr.PathToAssembly)) { File.Delete(cr.PathToAssembly); } StringBuilder sb = new StringBuilder(); sb.Append("C# code compilation error:\n"); string[] lines = code.Split('\n'); foreach (CompilerError error in cr.Errors) { if (error != null) { string line = (error.Line >= 1 && error.Line <= lines.Length) ? lines[error.Line - 1] : "???"; sb.AppendLine(string.Format("Line: {0}\nError: {1}", line.TrimEnd(), error.ErrorText)); } } _verboseWriter.WriteVerbose("Compile> Errors: " + sb.ToString()); throw new ParsingException(sb.ToString()); } if (outputtype == CompiledOutputType.InMemoryAssembly) { byte[] asmData = File.ReadAllBytes(cr.PathToAssembly); File.Delete(cr.PathToAssembly); Assembly a = Assembly.Load(asmData); return(a); } } finally { if (string.IsNullOrEmpty(codeOutputDirectory) || outputtype == CompiledOutputType.InMemoryAssembly) { foreach (string na in toDelete) { File.Delete(na); } } } return(outputtype == CompiledOutputType.InMemoryAssembly ? cr.CompiledAssembly : null); }