Skip to content

Instantly share code, notes, and snippets.

@akimboyko
Last active October 22, 2018 08:45
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save akimboyko/5754346 to your computer and use it in GitHub Desktop.
Save akimboyko/5754346 to your computer and use it in GitHub Desktop.
ScriptCs as embedded scripting engine for .Net application with NuGet support

ScriptCs as embedded scripting engine for .Net application with NuGet support

This gist contains:

  • ExecuteScriptCs.cs — class that are able to execute ScriptCs from another .Net application
  • ScriptModule.cs — AutoFac configuration for ScriptCs/NuGet dependencies
  • Program.cs — command-line example
  • Sample.csx — sample ScriptCs script
  • packages.config — NuGet packages configuration

Support: ScriptCs 0.5.0.0

// ScriptCs sample with Newtonsoft.Json — just for test
using Newtonsoft.Json;
var message = new { messaeg = "Hello, world!", timestamp = DateTime.Now };
Console.WriteLine(
JsonConvert.SerializeObject(
message,
Newtonsoft.Json.Formatting.Indented));
public class ExecuteScriptCs
{
// dependencies
private readonly ILog logger;
private readonly ScriptCs.IFileSystem fileSystem;
private readonly IPackageAssemblyResolver packageAssemblyResolver;
private readonly IPackageInstaller packageInstaller;
private readonly IScriptPackResolver scriptPackResolver;
private readonly IScriptExecutor scriptExecutor;
public ExecuteScriptCs(ILog logger, ScriptCs.IFileSystem fileSystem,
IPackageAssemblyResolver packageAssemblyResolver,
IPackageInstaller packageInstaller, IScriptPackResolver scriptPackResolver,
IScriptExecutor scriptExecutor)
{
this.logger = logger;
this.fileSystem = fileSystem;
this.packageAssemblyResolver = packageAssemblyResolver;
this.packageInstaller = packageInstaller;
this.scriptPackResolver = scriptPackResolver;
this.scriptExecutor = scriptExecutor;
}
// run script from file
public void Run(string scriptPath)
{
// preserve current directory
var previousCurrentDirectory = Environment.CurrentDirectory;
try
{
// set directory to where script is
// required to find NuGet dependencies
Environment.CurrentDirectory = Path.GetDirectoryName(scriptPath);
// prepare NuGet dependencies, download them if required
var nuGetReferences = PreparePackages(
scriptPath,
fileSystem, packageAssemblyResolver,
packageInstaller, logger.Info);
// get script packs: not fully tested yet
var scriptPacks = scriptPackResolver.GetPacks();
// execute script from file
scriptExecutor.Initialize(nuGetReferences, scriptPacks);
scriptExecutor.Execute(scriptPath);
}
finally
{
// restore current directory
Environment.CurrentDirectory = previousCurrentDirectory;
}
}
// prepare NuGet dependencies, download them if required
private static IEnumerable<string> PreparePackages(
string scriptPath,
ScriptCs.IFileSystem fileSystem, IPackageAssemblyResolver packageAssemblyResolver,
IPackageInstaller packageInstaller, Action<string> outputCallback = null)
{
var workingDirectory = Path.GetDirectoryName(scriptPath);
var binDirectory = Path.Combine(workingDirectory, ScriptCs.Constants.BinFolder);
var packages = packageAssemblyResolver.GetPackages(workingDirectory);
packageInstaller.InstallPackages(
packages,
allowPreRelease: true, packageInstalled: outputCallback);
// current implementeation of RoslynCTP required dependencies to be in 'bin' folder
if (!fileSystem.DirectoryExists(binDirectory))
{
fileSystem.CreateDirectory(binDirectory);
}
// copy dependencies one by one from 'packages' to 'bin'
foreach(var assemblyName
in packageAssemblyResolver.GetAssemblyNames(workingDirectory, outputCallback))
{
var assemblyFileName = Path.GetFileName(assemblyName);
var destFile = Path.Combine(binDirectory, assemblyFileName);
var sourceFileLastWriteTime = fileSystem.GetLastWriteTime(assemblyName);
var destFileLastWriteTime = fileSystem.GetLastWriteTime(destFile);
if (sourceFileLastWriteTime == destFileLastWriteTime)
{
outputCallback(string.Format("Skipped: '{0}' because it is already exists", assemblyName));
}
else
{
fileSystem.Copy(assemblyName, destFile, overwrite: true);
if(outputCallback != null)
{
outputCallback(string.Format("Copy: '{0}' to '{1}'", assemblyName, destFile));
}
}
yield return destFile;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FluentAutomation.SeleniumWebDriver" version="2.0.0.2" targetFramework="net45" />
<package id="Newtonsoft.Json" version="5.0.5" targetFramework="net45" />
<package id="ScriptCs.ClrDiagnostics" targetFramework="net45" />
</packages>
void Main()
{
const string scriptPath = @".\EmbededScriptCsWithNuGetSupport.csx";
// AutoFac container
var builder = new ContainerBuilder();
// register ScripotCs specific module
builder.RegisterModule(new ScriptModule());
using(var container = builder.Build())
{
using (var scope = container.BeginLifetimeScope())
{
var logger = scope.Resolve<ILog>();
var executeScriptCs = scope.Resolve<ExecuteScriptCs>();
try
{
executeScriptCs.Run(scriptPath);
}
catch(Exception ex)
{
logger.Error(ex);
throw;
}
}
}
}
// AutoFac configuration
public class ScriptModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder
.RegisterType<ScriptCs.FileSystem>()
.As<ScriptCs.IFileSystem>()
.SingleInstance();
builder
.RegisterType<ConsoleOutLogger>()
.As<ILog>()
.SingleInstance()
.WithParameter("logName", @"Custom ScriptCs from C#")
.WithParameter("logLevel", Common.Logging.LogLevel.All)
.WithParameter("showLevel", true)
.WithParameter("showDateTime", true)
.WithParameter("showLogName", true)
.WithParameter("dateTimeFormat", @"yyyy-mm-dd hh:mm:ss");
builder
.RegisterType<FilePreProcessor>()
.As<IFilePreProcessor>()
.SingleInstance();
builder
.RegisterType<ScriptHostFactory>()
.As<IScriptHostFactory>()
.SingleInstance();
builder
.RegisterType<RoslynScriptEngine>()
.As<IScriptEngine>();
builder
.RegisterType<ScriptExecutor>()
.As<IScriptExecutor>();
builder
.RegisterType<NugetInstallationProvider>()
.As<IInstallationProvider>()
.SingleInstance();
builder
.RegisterType<PackageAssemblyResolver>()
.As<IPackageAssemblyResolver>()
.SingleInstance();
builder
.RegisterType<PackageContainer>()
.As<IPackageContainer>()
.SingleInstance();
builder
.RegisterType<PackageInstaller>()
.As<IPackageInstaller>()
.SingleInstance();
builder
.RegisterType<PackageManager>()
.As<IPackageManager>()
.SingleInstance();
builder
.RegisterType<ScriptPackResolver>()
.As<IScriptPackResolver>()
.SingleInstance();
builder
.RegisterType<ExecuteScriptCs>();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment