/// <summary> /// Access to shell for event data. /// </summary> /// <param name="evt">Configured event.</param> /// <param name="cmd">Formatted command to shell.</param> public virtual void shell(ISolutionEvent evt, string cmd) { Log.Info("Prepared command: '{0}'", cmd); HProcess p = new HProcess(Settings.WPath); p.useShell(cmd, evt.Process.Waiting, evt.Process.Hidden, evt.Process.TimeLimit); }
/// <summary> /// Runs user code. /// </summary> /// <param name="type">The Type for work with user code.</param> /// <param name="cmd">Push net.r_eg.vsCE.Actions.ICommand into user code.</param> /// <param name="evt">Push net.r_eg.vsCE.Events.ISolutionEvent into user code.</param> /// <returns>Result from user code.</returns> protected int run(Type type, ICommand cmd, ISolutionEvent evt) { MethodInfo method = type.GetMethod(ENTRY_POINT); var exec = (Func <ICommand, ISolutionEvent, int>)Delegate.CreateDelegate(typeof(Func <ICommand, ISolutionEvent, int>), method); return(exec(cmd, evt)); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { if(((IModeInterpreter)evt.Mode).Handler.Trim().Length < 1) { throw new NotFoundException("Interpreter: Handler is empty or not selected."); } string script = ((IModeInterpreter)evt.Mode).Command; string wrapper = ((IModeInterpreter)evt.Mode).Wrapper; script = parse(evt, script); script = treatNewlineAs(((IModeInterpreter)evt.Mode).Newline, script); switch(wrapper.Length) { case 1: { script = string.Format("{0}{1}{0}", wrapper, script.Replace(wrapper, "\\" + wrapper)); break; } case 2: { //pair as: (), {}, [] ... //e.g.: (echo str&echo.&echo str) >> out string wL = wrapper[0].ToString(); string wR = wrapper[1].ToString(); script = string.Format("{0}{1}{2}", wL, script.Replace(wL, "\\" + wL).Replace(wR, "\\" + wR), wR); break; } } string handler = ((IModeInterpreter)evt.Mode).Handler; if(evt.SupportMSBuild) { handler = cmd.MSBuild.parse(handler); } shell(evt, string.Format("{0} {1}", handler, script)); return true; }
/// <summary> /// Supports the user interaction. /// Waiting until user presses yes/no or cancel /// </summary> /// <param name="evt"></param> /// <returns>true value if need to execute</returns> protected bool confirm(ISolutionEvent evt) { if (!evt.Confirmation) { return(true); } Log.Debug("Ask user about action [{0}]:{1} '{2}'", EventType, evt.Name, evt.Caption); string msg = String.Format("Execute the next action ?\n [{0}]:{1} '{2}'\n\n* Cancel - to disable current action", EventType, evt.Name, evt.Caption); System.Windows.Forms.DialogResult ret = System.Windows.Forms.MessageBox.Show(msg, "Confirm the action", System.Windows.Forms.MessageBoxButtons.YesNoCancel, System.Windows.Forms.MessageBoxIcon.Question); switch (ret) { case System.Windows.Forms.DialogResult.Yes: { return(true); } case System.Windows.Forms.DialogResult.Cancel: { evt.Enabled = false; Settings.CfgManager.Config.save(); throw new SBEException("Aborted by user"); } } return(false); }
protected bool isContext(ISolutionEvent evt, SolutionEventType type) { var cfgContext = evt.BuildType; // /LC: #799 if (type == SolutionEventType.SlnOpened) { if (cfgContext == BuildType.Common) { cfgContext = BuildType.Before; // consider it as default type } if (cfgContext != BuildType.Before && cfgContext != BuildType.After && cfgContext != BuildType.BeforeAndAfter) { return(false); } if (CurrentContext == BuildType.Common || // Before & After are not possible at all, e.g. Isolated env etc., thus consider it as any possible cfgContext == BuildType.BeforeAndAfter) { return(true); } if (cfgContext == BuildType.Before || cfgContext == BuildType.After) { return(cfgContext == CurrentContext); } } return(cfgContext == BuildType.Common || cfgContext == CurrentContext); }
protected bool actionBy(ModeType type, ISolutionEvent evt) { if (evt.Process.Waiting) { return(actions[type].process(evt)); } string marker = null; if (Thread.CurrentThread.Name == LoggingEvent.IDENT_TH) { marker = LoggingEvent.IDENT_TH; } (new Task(() => { if (Thread.CurrentThread.Name == null && marker != null) { Thread.CurrentThread.Name = marker; } Log.Trace($"Task ({type}) for another thread is started for '{evt.Name}'"); try { actions[type].process(evt); } catch (Exception ex) { Log.Error($"Task ({type}) for another thread is failed. '{evt.Name}' Error: `{ex.Message}`"); } })).Start(); return(true); }
protected bool actionBy(ISolutionEvent evt) { switch (evt.Mode.Type) { case ModeType.Operation: { Log.Info("Use Operation Mode"); return(actionBy(ModeType.Operation, evt)); } case ModeType.Interpreter: { Log.Info("Use Interpreter Mode"); return(actionBy(ModeType.Interpreter, evt)); } case ModeType.Script: { Log.Info("Use Script Mode"); return(actionBy(ModeType.Script, evt)); } case ModeType.Targets: { Log.Info("Use Targets Mode"); return(actionBy(ModeType.Targets, evt)); } case ModeType.CSharp: { Log.Info("Use C# Mode"); return(actionBy(ModeType.CSharp, evt)); } } Log.Info("Use Files Mode"); return(actionBy(ModeType.File, evt)); }
/// <summary> /// Execution by user. /// </summary> public void execAction() { if (SBEItem == null) { Log.Info("No actions to execution. Add new, then try again."); return; } Actions.ICommand cmd = new Actions.Command ( Loader.Env, Loader.Soba, Loader.Soba.EvMSBuild ); ISolutionEvent evt = SBEItem; SolutionEventType type = SBE.type; Log.Info("Action: execute action '{0}':'{1}' manually :: emulate '{2}' event", evt.Name, evt.Caption, type); cmd.Env.BuildType = BuildType.Common; //TODO: IBuild.updateBuildType try { bool res = cmd.exec(evt, type); Log.Info("Action: '{0}':'{1}' completed as - '{2}'", evt.Name, evt.Caption, res.ToString()); } catch (Exception ex) { Log.Error("Action: '{0}':'{1}' is failed. Error: '{2}'", evt.Name, evt.Caption, ex.Message); } }
/// <summary> /// Find and execute action by specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <param name="type">The type of event.</param> /// <returns>true value if it was handled.</returns> public bool exec(ISolutionEvent evt, SolutionEventType type) { if (!evt.Enabled) { return(false); } EventType = type; if (!isContext(evt, type)) { Log.Debug($"Ignored Context '{CurrentContext}'. Expected '{evt.BuildType}'"); return(false); } string cfg = Env.SolutionActiveCfgString; if (evt.ToConfiguration != null && evt.ToConfiguration.Length > 0 && !evt.ToConfiguration.Any(s => cmpConfig(s, cfg))) { Log.Info("Action '{0}' is ignored for current configuration - '{1}'", evt.Caption, cfg); return(false); } if (!confirm(evt)) { Log.Debug("Skipped action by user"); return(false); } Log.Info("Launching action '{0}' :: Configuration - '{1}'", evt.Caption, cfg); return(actionBy(evt)); }
/// <summary> /// Only compiling user code. /// Use the safe compileAndGetType for work with the end-type. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Compiled user code.</returns> protected CompilerResults onlyCompile(ISolutionEvent evt) { Log.Trace("[Compiler] start new compilation."); IModeCSharp cfg = (IModeCSharp)evt.Mode; string command = cfg.Command; if (String.IsNullOrWhiteSpace(command)) { throw new InvalidArgumentException("[Compiler] code is not found. abort;"); } command = parse(evt, command); string output = outputCacheFile(evt); Log.Debug("[Compiler] output: '{0}' /GenerateInMemory: {1}", output, cfg.GenerateInMemory); if (File.Exists(output)) { Log.Trace("[Compiler] clear cache."); File.Delete(output); } CompilerParameters parameters = new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = cfg.GenerateInMemory, CompilerOptions = cfg.CompilerOptions, TreatWarningsAsErrors = cfg.TreatWarningsAsErrors, WarningLevel = cfg.WarningLevel, // use prefix from fileName() to avoid random names if used GenerateInMemory OutputAssembly = (!cfg.GenerateInMemory)? output : Path.Combine(Path.GetTempPath(), fileName(evt)) }; // Assembly references string[] references = constructReferences(cfg, evt.SupportMSBuild); Log.Trace("[Compiler] final references: '{0}'", String.Join("; ", references)); parameters.ReferencedAssemblies.AddRange(references); parameters.ReferencedAssemblies.Add(typeof(ISolutionEvent).Assembly.Location); // to support ICommand & ISolutionEvent parameters.ReferencedAssemblies.Add(typeof(Bridge.IEvent).Assembly.Location); // to support Bridge // ready to work with provider CompilerResults compiled = toBinary(command, parameters, cfg); // messages about errors & warnings foreach (CompilerError msg in compiled.Errors) { Log._.NLog.Log((msg.IsWarning)? LogLevel.Warn : LogLevel.Error, "[Compiler] '{0}'", msg.ToString()); } if (compiled.Errors.HasErrors) { throw new CompilerException("[Compiler] found errors. abort;"); } return(compiled); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { IModeOperation operation = (IModeOperation)evt.Mode; if(operation.Command == null || operation.Command.Length < 1) { return true; } DTEOperation dteo = new DTEOperation(cmd.Env, cmd.EventType); if(!evt.SupportMSBuild && !evt.SupportSBEScripts) { dteo.exec(operation.Command, operation.AbortOnFirstError); return true; } // need evaluation for data ECommand[] parsed = new ECommand[operation.Command.Length]; for(int i = 0; i < operation.Command.Length; ++i) { parsed[i].name = parse(evt, operation.Command[i].name); parsed[i].args = parse(evt, operation.Command[i].args); } dteo.exec(parsed, operation.AbortOnFirstError); return true; }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { string command = ((IModeTargets)evt.Mode).Command; ProjectRootElement root = getXml(parse(evt, command)); BuildRequestData request = new BuildRequestData( new ProjectInstance(root, propertiesByDefault(evt), root.ToolsVersion, ProjectCollection.GlobalProjectCollection), new string[] { ENTRY_POINT }, new HostServices() ); // holy hedgehogs... #if !NET_40 // Using of BuildManager from Microsoft.Build.dll, v4.0.0.0 - .NETFramework\v4.5\Microsoft.Build.dll // you should see IDisposable, and of course you can see CA1001 for block as in #else section below. using (BuildManager manager = new BuildManager(Settings.APP_NAME_SHORT)) { return(build(manager, request, evt.Process.Hidden)); } #else // Using of BuildManager from Microsoft.Build.dll, v4.0.30319 - .NETFramework\v4.0\Microsoft.Build.dll // It doesn't implement IDisposable, and voila: // https://ci.appveyor.com/project/3Fs/vssolutionbuildevent/build/build-103 return(build(new BuildManager(Settings.APP_NAME_SHORT), request, evt.Process.Hidden)); #endif }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { string command = ((IModeTargets)evt.Mode).Command; ProjectRootElement root = getXml(parse(evt, command)); BuildRequestData request = new BuildRequestData( new ProjectInstance(root, propertiesByDefault(evt), root.ToolsVersion, ProjectCollection.GlobalProjectCollection), new string[] { ENTRY_POINT }, new HostServices() ); // holy hedgehogs... #if !NET_40 // Using of BuildManager from Microsoft.Build.dll, v4.0.0.0 - .NETFramework\v4.5\Microsoft.Build.dll // you should see IDisposable, and of course you can see CA1001 for block as in #else section below. using(BuildManager manager = new BuildManager(Settings.APP_NAME_SHORT)) { return build(manager, request, evt.Process.Hidden); } #else // Using of BuildManager from Microsoft.Build.dll, v4.0.30319 - .NETFramework\v4.0\Microsoft.Build.dll // It doesn't implement IDisposable, and voila: // https://ci.appveyor.com/project/3Fs/vssolutionbuildevent/build/build-103 return build(new BuildManager(Settings.APP_NAME_SHORT), request, evt.Process.Hidden); #endif }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { IModeEnvCommand mode = (IModeEnvCommand)evt.Mode; if(mode.Command == null || mode.Command.Length < 1) { return true; } if(!evt.SupportMSBuild && !evt.SupportSBEScripts) { return raise(mode.Command, mode.AbortOnFirstError); } var parsed = new CommandDte[mode.Command.Length]; for(int i = 0; i < mode.Command.Length; ++i) { parsed[i] = new CommandDte() { Guid = parse(evt, mode.Command[i].Guid), Id = mode.Command[i].Id, CustomIn = parse(mode.Command[i].CustomIn, evt), CustomOut = parse(mode.Command[i].CustomOut, evt) }; } return raise(parsed, mode.AbortOnFirstError); }
/// <summary> /// Checks requirement of compiling source code. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>true value if needed compilation, otherwise we can use compiled version from cache.</returns> protected bool isRequiresCompilation(ISolutionEvent evt) { IModeCSharp cfg = ((IModeCSharp)evt.Mode); string cache = fileName(evt); Log.Trace("[Cache] Checks: '{0}','{1}','{2}','{3}'", cfg.GenerateInMemory, cfg.CachingBytecode, evt.Name, cache); if (cfg.GenerateInMemory || !cfg.CachingBytecode || String.IsNullOrEmpty(cache)) { return(true); } if (cfg.CacheData == null) { Log.Trace("[Cache] hash data is empty."); return(true); } FileInfo f = new FileInfo(outputCacheFile(evt)); if (!f.Exists) { Log.Info("[Cache] Binary '{0}' is not found in '{1}'. Compile new.", cache, f.FullName); return(true); } string actual = cfg.CacheData.Manager.CacheHeader.Hash; if (!hashEquals(f.FullName, actual)) { Log.Info("[Cache] hash code '{0}' is invalid. Compile new.", actual); return(true); } return(false); }
protected bool hasExecutionOrder(ISolutionEvent evt) { if (evt.ExecutionOrder == null || evt.ExecutionOrder.Length < 1) { return(false); } return(true); }
/// <summary> /// Access to shell for event data. /// </summary> /// <param name="evt">Configured event.</param> /// <param name="cmd">Formatted command to shell.</param> public virtual void shell(ISolutionEvent evt, string cmd) { Log.Info("Prepared command: '{0}'", cmd); HProcess p = new HProcess(Settings.WPath); p.useShell(cmd, evt.Id, evt.Process.Waiting, evt.Process.Hidden, evt.Process.TimeLimit); }
protected string pStdout(ISolutionEvent evt, IPM pm) { if (pm.FinalEmptyIs(LevelType.RightOperandEmpty)) { return(Value.from(HProcess.Stdout(evt.Id))); } throw new IncorrectNodeException(pm); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { string cFiles = ((IModeFile)evt.Mode).Command; cFiles = parse(evt, cFiles); shell(evt, treatNewlineAs(" & ", cFiles)); return true; }
protected string pStderr(ISolutionEvent evt, IPM pm) { if (pm.FinalEmptyIs(LevelType.RightOperandEmpty)) { return(Value.From(Exer?.PullStdErr(evt.Id))); } throw new IncorrectNodeException(pm); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { string cFiles = ((IModeFile)evt.Mode).Command; cFiles = parse(evt, cFiles); shell(evt, treatNewlineAs(" & ", cFiles)); return(true); }
protected Dictionary <string, string> propertiesByDefault(ISolutionEvent evt) => new Dictionary <string, string>(cmd.Env.getProject(null).GlobalProperties) { { PropertyNames.PRJ_NAME, $"_{evt.Name}" }, { "ActionName", evt.Name }, { "BuildType", cmd.Env.BuildType.ToString() }, { "EventType", cmd.EventType.ToString() }, { "SupportMSBuild", evt.SupportMSBuild.ToString() }, { "SupportSBEScripts", evt.SupportSBEScripts.ToString() }, { "SolutionActiveCfg", cmd.Env.SolutionActiveCfgString }, { "StartupProject", cmd.Env.StartupProjectString } };
protected string pEnabled(ISolutionEvent evt, IPM pm) { if (pm.FinalEmptyIs(LevelType.RightOperandEmpty)) { return(Value.From(evt.Enabled)); } evt.Enabled = Value.ToBoolean(pm.FirstLevel.Data); Log.Trace($"pEnabled: updated status '{evt.Enabled}' for '{evt.Name}'"); return(Value.Empty); }
/// <summary> /// Access to shell for event data. /// </summary> /// <param name="evt">Configured event.</param> /// <param name="cmd">Formatted command to shell.</param> public virtual void shell(ISolutionEvent evt, string cmd) { Log.Info($"Prepared command: '{cmd}'"); exer.UseShell ( cmd, evt.Id, evt.Process.Waiting, evt.Process.Hidden, evt.Process.TimeLimit ); }
/// <summary> /// Access to parsers for event data. /// </summary> /// <param name="evt">Configured event.</param> /// <param name="data">Data to analysing.</param> /// <returns>Parsed data.</returns> public virtual string parse(ISolutionEvent evt, string data) { if(evt.SupportSBEScripts) { data = cmd.SBEScript.parse(data, evt.SupportMSBuild); } if(evt.SupportMSBuild) { data = cmd.MSBuild.parse(data); } return data; }
/// <summary> /// Checking state from incoming projects /// In general, this checking for single the event-action like a POST/Cacnel /// note: /// * The 'POST' - exists as successfully completed event, therefore we should getting only the 'After' state. /// * The 'Cancel' - works differently and contains realy the reached state: 'Before' or 'After'. /// </summary> protected bool isReached(ISolutionEvent evt) { if (!hasExecutionOrder(evt)) { return(true); } Log.Debug("hasExecutionOrder(->isReached) for '{0}' is true", evt.Caption); return(evt.ExecutionOrder.Any(e => projects.ContainsKey(e.Project) && projects[e.Project].Order == e.Order )); }
private string outputCacheFile(ISolutionEvent evt) { IModeCSharp cfg = (IModeCSharp)evt.Mode; string path = (cfg.OutputPath) ?? String.Empty; if (evt.SupportMSBuild) { path = cmd.MSBuild.parse(path); } return(Path.Combine(BasePathToCache, path, fileName(evt))); }
/// <summary> /// Access to parsers for event data. /// </summary> /// <param name="evt">Configured event.</param> /// <param name="data">Data to analysing.</param> /// <returns>Parsed data.</returns> public virtual string parse(ISolutionEvent evt, string data) { if (evt.SupportSBEScripts) { data = cmd.SBEScript.parse(data, evt.SupportMSBuild); } if (evt.SupportMSBuild) { data = cmd.MSBuild.parse(data); } return(data); }
protected Dictionary <string, string> propertiesByDefault(ISolutionEvent evt) { Dictionary <string, string> prop = new Dictionary <string, string>(cmd.Env.getProject(null).GlobalProperties); prop.Add("ProjectName", String.Format("_{0}", evt.Name)); prop.Add("ActionName", evt.Name); prop.Add("BuildType", cmd.Env.BuildType.ToString()); prop.Add("EventType", cmd.EventType.ToString()); prop.Add("SupportMSBuild", evt.SupportMSBuild.ToString()); prop.Add("SupportSBEScripts", evt.SupportSBEScripts.ToString()); prop.Add("SolutionActiveCfg", cmd.Env.SolutionActiveCfgString); prop.Add("StartupProject", cmd.Env.StartupProjectString); return(prop); }
/// <summary> /// Compiling user code with getting the result type for next step. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>The Type for work with user code.</returns> protected Type compileAndGetType(ISolutionEvent evt) { IModeCSharp cfg = (IModeCSharp)evt.Mode; if (!cfg.GenerateInMemory) { CompilerResults compiled = onlyCompile(evt); return(load(compiled.PathToAssembly, null)); } Log.Trace("Uses memory for getting type."); // be careful, this should automatically load assembly with blocking file if not used GenerateInMemory // therefore, use this only with GenerateInMemory == true return(onlyCompile(evt).CompiledAssembly.GetType(MAIN_CLASS)); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { IModeOperation operation = (IModeOperation)evt.Mode; if(operation.Command == null || operation.Command.Length < 1) { return true; } string[] parsed = new string[operation.Command.Length]; for(int i = 0; i < operation.Command.Length; ++i) { parsed[i] = parse(evt, operation.Command[i]); } (new DTEOperation(cmd.Env, cmd.EventType)).exec(parsed, operation.AbortOnFirstError); return true; }
protected void status(ISolutionEvent evt) { Console.WriteLine(String.Format("Name: '{0}'", evt.Name)); Console.WriteLine(String.Format("Mode: '{0}'", evt.Mode.Type)); if(evt.Mode.Type == ModeType.File) { Console.WriteLine(String.Format("Command in File mode: '{0}'", ((IModeFile)evt.Mode).Command)); return; } if(evt.Mode.Type == ModeType.Script) { Console.WriteLine(String.Format("Command in Script mode: '{0}'", ((IModeScript)evt.Mode).Command)); return; } throw new Exception("Unsupported mode"); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { IModeOperation operation = (IModeOperation)evt.Mode; if (operation.Command == null || operation.Command.Length < 1) { return(true); } string[] parsed = new string[operation.Command.Length]; for (int i = 0; i < operation.Command.Length; ++i) { parsed[i] = parse(evt, operation.Command[i]); } (new DTEOperation(cmd.Env, cmd.EventType)).exec(parsed, operation.AbortOnFirstError); return(true); }
protected void status(ISolutionEvent evt) { Console.WriteLine(String.Format("Name: '{0}'", evt.Name)); Console.WriteLine(String.Format("Mode: '{0}'", evt.Mode.Type)); if (evt.Mode.Type == ModeType.File) { Console.WriteLine(String.Format("Command in File mode: '{0}'", ((IModeFile)evt.Mode).Command)); return; } if (evt.Mode.Type == ModeType.Script) { Console.WriteLine(String.Format("Command in Script mode: '{0}'", ((IModeScript)evt.Mode).Command)); return; } throw new Exception("Unsupported mode"); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { if (((IModeInterpreter)evt.Mode).Handler.Trim().Length < 1) { throw new NotFoundException("Interpreter: Handler is empty or not selected."); } string script = ((IModeInterpreter)evt.Mode).Command; string wrapper = ((IModeInterpreter)evt.Mode).Wrapper; script = parse(evt, script); script = treatNewlineAs(((IModeInterpreter)evt.Mode).Newline, script); switch (wrapper.Length) { case 1: { script = string.Format("{0}{1}{0}", wrapper, script.Replace(wrapper, "\\" + wrapper)); break; } case 2: { //pair as: (), {}, [] ... //e.g.: (echo str&echo.&echo str) >> out string wL = wrapper[0].ToString(); string wR = wrapper[1].ToString(); script = string.Format("{0}{1}{2}", wL, script.Replace(wL, "\\" + wL).Replace(wR, "\\" + wR), wR); break; } } string handler = ((IModeInterpreter)evt.Mode).Handler; if (evt.SupportMSBuild) { handler = cmd.MSBuild.parse(handler); } shell(evt, string.Format("{0} {1}", handler, script)); return(true); }
/// <summary> /// Parse object data. /// </summary> /// <param name="oin">Object for parsing inc. arrays.</param> /// <param name="evt"></param> /// <returns></returns> protected object parse(object oin, ISolutionEvent evt) { if(oin == null) { return null; } if(oin is string) { return parse(evt, (string)oin); } if(!oin.GetType().IsArray) { return oin; } object[] oinArr = (object[])oin; object[] ret = new object[oinArr.Length]; for(int i = 0; i < oinArr.Length; ++i) { ret[i] = parse(oinArr[i], evt); } return ret; }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { Type type; if (isRequiresCompilation(evt)) { type = compileAndGetType(evt); } else { type = load(outputCacheFile(evt), assemblyName(evt)); } int ret = run(type, cmd, evt); if (ret != 0) { Log.Warn("Return code '{0}'", ret); return(false); } return(true); }
protected bool actionBy(ModeType type, ISolutionEvent evt) { if (!actions.ContainsKey(type)) { Log.Warn($"{type} is not found as a registered action type"); actions[type] = new ActionScript(this); } if (evt.Process.Waiting) { return(actions[type].process(evt)); } string marker = null; if (Thread.CurrentThread.Name == LoggingEvent.IDENT_TH) { marker = LoggingEvent.IDENT_TH; } (new Task(() => { if (Thread.CurrentThread.Name == null && marker != null) { Thread.CurrentThread.Name = marker; } Log.Trace($"Task for '{evt.Name}' due to '{type}' ..."); try { actions[type].process(evt); } catch (Exception ex) { Log.Error($"Failed task for '{evt.Name}': {ex.Message}"); Log.Debug(ex.StackTrace); } })).Start(); return(true); }
/// <summary> /// Find and execute action by specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <param name="type">The type of event.</param> /// <returns>true value if it was handled.</returns> public bool exec(ISolutionEvent evt, SolutionEventType type) { if (!evt.Enabled) { return(false); } EventType = type; if (!isContext(evt, type)) { Log.Debug($"Ignored Context '{CurrentContext}'. Expected '{evt.BuildType}'"); return(false); } if (!confirm(evt)) { Log.Debug("Skipped action by user"); return(false); } Log.Info("Launching action '{0}' :: Configuration - '{1}'", evt.Caption, (Env != null)? Env.SolutionActiveCfgString : ""); return(actionBy(evt)); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { Type type; if (isRequiresCompilation(evt)) { type = compileAndGetType(evt); } else { type = load(outputCacheFile(evt), assemblyName(evt)); } if (type == null) { Log.Error($"Compiled type is null. Something went wrong for C# Action '{evt.Name}'"); } int ret = run(type, cmd, evt); if (ret == 0) { return(true); } string retmsg = $"Return code '{ret}'"; if (((IModeCSharp)evt.Mode).TreatWarningsAsErrors) { Log.Error(retmsg); } else { Log.Warn(retmsg); } return(false); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { parse(evt, ((IModeScript)evt.Mode).Command); return true; }
/// <summary> /// Entry point for execution /// </summary> /// <param name="evt">Configured event</param> /// <param name="type">Type of event</param> /// <returns>true value if has been processed</returns> public bool exec(ISolutionEvent evt, SolutionEventType type) { if(!evt.Enabled){ return false; } if(evt.BuildType != BuildType.Common && evt.BuildType != Env.BuildType) { Log.Debug("Ignored context. Build type '{0}' should be '{1}'", Env.BuildType, evt.BuildType); return false; } this.type = type; if(!confirm(evt)) { Log.Debug("Skipped action by user"); return false; } Log.Info("Launching action '{0}' :: Configuration - '{1}'", evt.Caption, (Env != null)? Env.SolutionActiveCfgString : ""); return actionBy(evt); }
protected void renderData(ISolutionEvent evt) { enabledStatus = evt.Enabled; checkBoxMSBuildSupport.Checked = evt.SupportMSBuild; checkBoxSBEScriptSupport.Checked = evt.SupportSBEScripts; checkBoxWaitForExit.Checked = evt.Process.Waiting; numericTimeLimit.Value = evt.Process.TimeLimit; checkBoxProcessHide.Checked = evt.Process.Hidden; chkConfirmation.Checked = evt.Confirmation; buildTypeSelect(evt.BuildType); if(evt.Mode == null) { Log.Warn("Mode is corrupt, reinitialized with default type - '{0}'", logic.DefaultMode.Type); evt.Mode = logic.DefaultMode; } pGridCompilerCfg.SelectedObject = (evt.Mode.Type == ModeType.CSharp)? (IModeCSharp)evt.Mode : new ModeCSharp(); // update settings for editor if(!isChangingMode(evt.Mode.Type)) { textEditor.config(logic.getCommonCfg(evt.Mode.Type)); } switch(evt.Mode.Type) { case ModeType.Interpreter: { radioModeInterpreter.Checked = true; textEditor.Text = ((IModeInterpreter)evt.Mode).Command; comboBoxInterpreter.Text = ((IModeInterpreter)evt.Mode).Handler; comboBoxNewline.Text = ((IModeInterpreter)evt.Mode).Newline; comboBoxWrapper.Text = ((IModeInterpreter)evt.Mode).Wrapper; return; } case ModeType.File: { radioModeFiles.Checked = true; textEditor.Text = ((IModeFile)evt.Mode).Command; return; } case ModeType.Script: { radioModeScript.Checked = true; textEditor.Text = ((IModeScript)evt.Mode).Command; return; } case ModeType.Targets: { radioModeTargets.Checked = true; textEditor.Text = ((IModeTargets)evt.Mode).Command; return; } case ModeType.CSharp: { radioModeCSharp.Checked = true; textEditor.Text = ((IModeCSharp)evt.Mode).Command; return; } case ModeType.Operation: { radioModeOperation.Checked = true; IModeOperation mode = (IModeOperation)evt.Mode; setCommandOperation(mode.Command); checkBoxOperationsAbort.Checked = mode.AbortOnFirstError; return; } case ModeType.EnvCommand: { radioModeEnvCmd.Checked = true; IModeEnvCommand mode = (IModeEnvCommand)evt.Mode; setCommandDte(mode.Command); checkBoxCommandsAbort.Checked = mode.AbortOnFirstError; return; } } }
/// <summary> /// Entry point for execution /// </summary> /// <param name="evt">Configured event</param> /// <returns>true value if has been processed</returns> public bool exec(ISolutionEvent evt) { return exec(evt, SolutionEventType.General); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public abstract bool process(ISolutionEvent evt);
/// <summary> /// Gets assembly name of compiled user code for event. /// </summary> /// <param name="evt">Specific event.</param> /// <returns></returns> protected virtual string assemblyName(ISolutionEvent evt) { return String.Format("{0}{1}.{2}", PREFIX_CACHE, cmd.EventType, evt.Name); }
protected bool actionBy(ISolutionEvent evt) { switch(evt.Mode.Type) { case ModeType.Operation: { Log.Info("Use Operation Mode"); return actionBy(ModeType.Operation, evt); } case ModeType.Interpreter: { Log.Info("Use Interpreter Mode"); return actionBy(ModeType.Interpreter, evt); } case ModeType.Script: { Log.Info("Use Script Mode"); return actionBy(ModeType.Script, evt); } case ModeType.Targets: { Log.Info("Use Targets Mode"); return actionBy(ModeType.Targets, evt); } case ModeType.CSharp: { Log.Info("Use C# Mode"); return actionBy(ModeType.CSharp, evt); } case ModeType.EnvCommand: { Log.Info("Use EnvCommand Mode"); return actionBy(ModeType.EnvCommand, evt); } } Log.Info("Use Files Mode"); return actionBy(ModeType.File, evt); }
private string outputCacheFile(ISolutionEvent evt) { IModeCSharp cfg = (IModeCSharp)evt.Mode; string path = (cfg.OutputPath)?? String.Empty; if(evt.SupportMSBuild) { path = cmd.MSBuild.parse(path); } return Path.Combine(BasePathToCache, path, fileName(evt)); }
protected bool actionBy(ModeType type, ISolutionEvent evt) { if(evt.Process.Waiting) { return actions[type].process(evt); } string marker = null; //if(Thread.CurrentThread.Name == Events.LoggingEvent.IDENT_TH) { // marker = Events.LoggingEvent.IDENT_TH; //} (new Task(() => { if(marker != null && Thread.CurrentThread.Name != marker) { Thread.CurrentThread.Name = marker; } Log.Trace("Task for another thread is started for '{0}' /{1}", evt.Name, type); actions[type].process(evt); })).Start(); return true; }
/// <summary> /// Only compiling user code. /// Use the safe compileAndGetType for work with the end-type. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Compiled user code.</returns> protected CompilerResults onlyCompile(ISolutionEvent evt) { Log.Trace("[Compiler] start new compilation."); IModeCSharp cfg = (IModeCSharp)evt.Mode; string command = cfg.Command; if(String.IsNullOrWhiteSpace(command)) { throw new InvalidArgumentException("[Compiler] code is not found. abort;"); } command = parse(evt, command); string output = outputCacheFile(evt); Log.Debug("[Compiler] output: '{0}' /GenerateInMemory: {1}", output, cfg.GenerateInMemory); if(File.Exists(output)) { Log.Trace("[Compiler] clear cache."); File.Delete(output); } CompilerParameters parameters = new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = cfg.GenerateInMemory, CompilerOptions = cfg.CompilerOptions, TreatWarningsAsErrors = cfg.TreatWarningsAsErrors, WarningLevel = cfg.WarningLevel, // use prefix from fileName() to avoid random names if used GenerateInMemory OutputAssembly = (!cfg.GenerateInMemory)? output : Path.Combine(Path.GetTempPath(), fileName(evt)) }; // Assembly references string[] references = constructReferences(cfg, evt.SupportMSBuild); Log.Trace("[Compiler] final references: '{0}'", String.Join("; ", references)); parameters.ReferencedAssemblies.AddRange(references); parameters.ReferencedAssemblies.Add(typeof(ISolutionEvent).Assembly.Location); // to support ICommand & ISolutionEvent parameters.ReferencedAssemblies.Add(typeof(Bridge.BuildType).Assembly.Location); // to support Bridge // ready to work with provider CompilerResults compiled = toBinary(command, parameters, cfg); // messages about errors & warnings foreach(CompilerError msg in compiled.Errors) { Log._.NLog.Log((msg.IsWarning)? LogLevel.Warn : LogLevel.Error, "[Compiler] '{0}'", msg.ToString()); } if(compiled.Errors.HasErrors) { throw new CompilerException("[Compiler] found errors. abort;"); } return compiled; }
/// <summary> /// Runs user code. /// </summary> /// <param name="type">The Type for work with user code.</param> /// <param name="cmd">Push net.r_eg.vsCE.Actions.ICommand into user code.</param> /// <param name="evt">Push net.r_eg.vsCE.Events.ISolutionEvent into user code.</param> /// <returns>Result from user code.</returns> protected int run(Type type, ICommand cmd, ISolutionEvent evt) { MethodInfo method = type.GetMethod(ENTRY_POINT); var exec = (Func<ICommand, ISolutionEvent, int>)Delegate.CreateDelegate(typeof(Func<ICommand, ISolutionEvent, int>), method); return exec(cmd, evt); }
/// <summary> /// Checks requirement of compiling source code. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>true value if needed compilation, otherwise we can use compiled version from cache.</returns> protected bool isRequiresCompilation(ISolutionEvent evt) { IModeCSharp cfg = ((IModeCSharp)evt.Mode); string cache = fileName(evt); Log.Trace("[Cache] Checks: '{0}','{1}','{2}','{3}'", cfg.GenerateInMemory, cfg.CachingBytecode, evt.Name, cache); if(cfg.GenerateInMemory || !cfg.CachingBytecode || String.IsNullOrEmpty(cache)) { return true; } if(cfg.CacheData == null) { Log.Trace("[Cache] hash data is empty."); return true; } FileInfo f = new FileInfo(outputCacheFile(evt)); if(!f.Exists) { Log.Info("[Cache] Binary '{0}' is not found in '{1}'. Compile new.", cache, f.FullName); return true; } string actual = cfg.CacheData.Manager.CacheHeader.Hash; if(!hashEquals(f.FullName, actual)) { Log.Info("[Cache] hash code '{0}' is invalid. Compile new.", actual); return true; } return false; }
/// <summary> /// Implements transport for new action by event type. /// </summary> /// <param name="type">The type of event.</param> /// <param name="cfg">The event configuration for action.</param> public void action(SolutionEventType type, ISolutionEvent cfg) { ISolutionEvent evt = addAction(-1); if(evt == null || cfg == null) { Log.Debug("UI.action for `{0}` - cfg or evt is null /skip", type); return; } cfg.CloneByReflectionInto(evt, true); refreshActions(true); refreshSettings(); notice(true); MessageBox.Show(String.Format("The new action `{0}`:\n`{1}` has been added.", evt.Name, evt.Caption), "New action"); }
/// <summary> /// Supports the user interaction. /// Waiting until user presses yes/no or cancel /// </summary> /// <param name="evt"></param> /// <returns>true value if need to execute</returns> protected bool confirm(ISolutionEvent evt) { if(!evt.Confirmation) { return true; } Log.Debug("Ask user about action [{0}]:{1} '{2}'", type, evt.Name, evt.Caption); string msg = String.Format("Execute the next action ?\n [{0}]:{1} '{2}'\n\n* Cancel - to disable current action", type, evt.Name, evt.Caption); System.Windows.Forms.DialogResult ret = System.Windows.Forms.MessageBox.Show(msg, "Confirm the action", System.Windows.Forms.MessageBoxButtons.YesNoCancel, System.Windows.Forms.MessageBoxIcon.Question); switch(ret) { case System.Windows.Forms.DialogResult.Yes: { return true; } case System.Windows.Forms.DialogResult.Cancel: { evt.Enabled = false; Settings.CfgManager.Config.save(); throw new SBEException("Aborted by user"); } } return false; }
/// <param name="evt">Array of handling events</param> /// <returns>true value if all event are disabled for present array</returns> protected bool isDisabledAll(ISolutionEvent[] evt) { foreach(ISolutionEvent item in evt) { if(item.Enabled) { return false; } } return true; }
/// <summary> /// Checking state from incoming projects /// In general, this checking for single the event-action like a POST/Cacnel /// note: /// * The 'POST' - exists as successfully completed event, therefore we should getting only the 'After' state. /// * The 'Cancel' - works differently and contains realy the reached state: 'Before' or 'After'. /// </summary> protected bool isReached(ISolutionEvent evt) { if(!hasExecutionOrder(evt)) { return true; } Log.Debug("hasExecutionOrder(->isReached) for '{0}' is true", evt.Caption); return evt.ExecutionOrder.Any(e => projects.ContainsKey(e.Project) && projects[e.Project] == e.Order ); }
/// <summary> /// Compiling user code with getting the result type for next step. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>The Type for work with user code.</returns> protected Type compileAndGetType(ISolutionEvent evt) { IModeCSharp cfg = (IModeCSharp)evt.Mode; if(!cfg.GenerateInMemory) { CompilerResults compiled = onlyCompile(evt); return load(compiled.PathToAssembly, null); } Log.Trace("Uses memory for getting type."); // be careful, this should automatically load assembly with blocking file if not used GenerateInMemory // therefore, use this only with GenerateInMemory == true return onlyCompile(evt).CompiledAssembly.GetType(MAIN_CLASS); }
/// <summary> /// Process for specified event. /// </summary> /// <param name="evt">Configured event.</param> /// <returns>Result of handling.</returns> public override bool process(ISolutionEvent evt) { Type type; if(isRequiresCompilation(evt)) { type = compileAndGetType(evt); } else { type = load(outputCacheFile(evt), assemblyName(evt)); } int ret = run(type, cmd, evt); if(ret != 0) { Log.Warn("Return code '{0}'", ret); return false; } return true; }
protected void saveData(ISolutionEvent evt) { evt.Enabled = enabledStatus; evt.Name = (String.IsNullOrWhiteSpace(evt.Name))? logic.UniqueNameForAction : evt.Name; evt.SupportMSBuild = checkBoxMSBuildSupport.Checked; evt.SupportSBEScripts = checkBoxSBEScriptSupport.Checked; evt.Process.Waiting = checkBoxWaitForExit.Checked; evt.Process.Hidden = checkBoxProcessHide.Checked; evt.Process.TimeLimit = (int)numericTimeLimit.Value; evt.Confirmation = chkConfirmation.Checked; evt.BuildType = (chkBuildContext.Checked)? logic.getBuildTypeBy(comboBoxBuildContext.SelectedIndex) : BuildType.Common; if(evt.Mode.Type == ModeType.CSharp && !radioModeCSharp.Checked) { logic.cacheToRemove(evt.Mode); } if(radioModeInterpreter.Checked) { evt.Mode = new ModeInterpreter() { Command = textEditor.Text, Handler = comboBoxInterpreter.Text, Newline = comboBoxNewline.Text, Wrapper = comboBoxWrapper.Text.Trim() }; } else if(radioModeFiles.Checked) { evt.Mode = new ModeFile() { Command = textEditor.Text }; } else if(radioModeScript.Checked) { evt.Mode = new ModeScript() { Command = textEditor.Text }; } else if(radioModeTargets.Checked) { evt.Mode = new ModeTargets() { Command = textEditor.Text }; } else if(radioModeCSharp.Checked) { evt.Mode = (IMode)pGridCompilerCfg.SelectedObject; IModeCSharp cfg = (IModeCSharp)evt.Mode; cfg.Command = textEditor.Text; if(!cfg.CachingBytecode) { logic.cacheToRemove(evt.Mode); } else { // probably a new data - reset for recalculation later. logic.cacheReset(evt.Mode); } } else if(radioModeOperation.Checked) { evt.Mode = new ModeOperation() { Command = getCommandOperation(), AbortOnFirstError = checkBoxOperationsAbort.Checked }; } else if(radioModeEnvCmd.Checked) { evt.Mode = new ModeEnvCommand() { Command = getCommandDte(), AbortOnFirstError = checkBoxCommandsAbort.Checked }; } }
/// <summary> /// Gets unique file name of compiled user code for event. /// </summary> /// <param name="evt">Specific event.</param> /// <returns></returns> protected virtual string fileName(ISolutionEvent evt) { return String.Format("{0}.dll", assemblyName(evt)); }