Пример #1
0
        /// <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;
                    }
                }
            }
        }
Пример #2
0
        /// <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);
        }