How to run cs-script (c# script) with StringTemplate? - c#

I copied Antlr3.StringTemplate.dll and Antlr3.Runtime.dll from http://www.stringtemplate.org/ to cs-script/lib directory ( http://www.csscript.net/ ) and execute the code below but it says it cannot find the assemblies of Antlr why ? My prog below
//css_reference Antlr3.Runtime.dll;
//css_reference Antlr3.StringTemplate.dll;
using System;
using Antlr.StringTemplate;
using Antlr.StringTemplate.Language;
using System.Windows.Forms;
class Script
{
static public void Main(string[] args)
{
StringTemplateGroup group = new StringTemplateGroup("myGroup", #"C:\Tutorials\stringtemplate", typeof(DefaultTemplateLexer));
StringTemplate helloAgain = group.GetInstanceOf("homepage");
helloAgain.SetAttribute("title", "Welcome To StringTemplate");
helloAgain.SetAttribute("name", "World");
helloAgain.SetAttribute("friends", "Terence");
helloAgain.SetAttribute("friends", "Kunle");
helloAgain.SetAttribute("friends", "Micheal");
helloAgain.SetAttribute("friends", "Marq");
Console.Out.WriteLine(helloAgain.ToString());
}
}

The error means that CS-Script cannot resolve Antlr3.*.dll assemblies.
You need to instruct the script engine where these assemblies may be located and if you do not do this CS-Script will look only in the GAC, your local directory (where the script is) and in the [cs-script]\Lib.
You have a few options to solve the problem:
You can specify assemblies with the absolute path
Add probing directories to the CS-Script global settings or directly to your script.
Register Antrl in GAC.
Have a look at AddingSearchDirs and www.csscript.net/help/Using_.NET_assemblies.html, this will help you to start.

Related

Is it possible to add a new dependency to a .dll without changing the source code?

I have two dotnetcore2.1 projects. First project calls a method of the second project via reflection.
using System;
using System.Reflection;
namespace experiment1
{
class Program
{
static void Main(string[] args)
{
Type _type = Type.GetType("experiment2.Program");
object _object = Activator.CreateInstance(_type);
MethodInfo info = _type.GetMethod("SecondProjectsMethod");
info.Invoke(_object, new object[]{});
}
}
}
I can't give any reference to the Second Project nor changes its code. How can I make this call successfully without adding a Reference to the First Project? I tried to add records to the first project's deps-file and execute the first program like this:
dotnet exec --depsfile experiment1.deps.json experiment1.dll
It didn't work. Is it even possible to do this by changing deps-file or any other config? Or should I manipulate .dll file somehow? Which direction I should go?
You can manually load the assembly by calling:
Assembly.Load("experiment2");
It should look for the assembly in the current folder, or use the deps file to locate it. After that, you should be able to use Type.GetType just fine.
If you want to specify the full path to the assembly, use AssemblyLoadContext.Default.LoadFromAssemblyPath instead.
You can refer to this page for more information on the different ways of loading an assembly in .net core.

Unity command-line build requires UnityEditor.BuildPipeline, but builds fail for missing 'UnityEditor' reference

I am presently trying to create a batch file for a command-line build of a simple Unity project.
Current environment is:
* Windows 10
* Unity 2017.4.19f1 (Personal)
* Offline network
The project consists of just a simple scene that works fine in the UnityEditor. After failing to get a good build, I've stripped down my build script and batch file to the following:
BareBoneBuild.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
namespace Assets.BuildScripts
{
class BareBoneBuild
{
private static string windowsBuildFolderPath = "G:/dev/projects/SimpleProject";
static void PerformBuild()
{
string[] scenes = { "Assets/Scenes/DetectionTest.cs" };
BuildPipeline.BuildPlayer(scenes, windowsBuildFolderPath + "/junk.exe", BuildTarget.StandaloneWindows, BuildOptions.None);
}
}
}
BareBoneBuild.bat
title Unity Build
echo Launching Unity Build...
"C:\Program Files\Unity\Editor\Unity.exe" ^
-batchmode ^
-projectPath G:\dev\projects\SimpleProject ^
-executeMethod Assets.BuildScripts.BareBoneBuild.PerformBuild ^
-quit ^
-logFile G:\dev\projects\SimpleProject\logs\BareBoneBuild.log
echo Build Finished!
PAUSE
BareBoneBuild.log (snippet)
...
-----CompilerOutput:-stdout--exitcode: 1--compilationhadfailure: True--outfile: Temp/Assembly-CSharp.dll
Compilation failed: 1 error(s), 0 warnings
-----CompilerOutput:-stderr----------
Assets/BuildScripts/BareBoneBuild.cs(6,7): error CS0246: The type or namespace name `UnityEditor' could not be found. Are you missing an assembly reference?
-----EndCompilerOutput---------------
- Finished compile Library/ScriptAssemblies/Assembly-CSharp.dll
Assets/BuildScripts/BareBoneBuild.cs(6,7): error CS0246: The type or namespace name `UnityEditor' could not be found. Are you missing an assembly reference?**
(Filename: Assets/BuildScripts/BareBoneBuild.cs Line: 6)
DisplayProgressNotification: Build Failed
Error building Player because scripts had compiler errors
(Filename: Line: -1)
...
EVERY tutorial, blog, youtube video, forum
* https://docs.unity3d.com/2017.4/Documentation/Manual/CommandLineArguments.html
* http://jonathanpeppers.com/Blog/automating-unity3d-builds-with-fake
* https://www.youtube.com/watch?v=4J3SmhGxO1Y
* others...that I don't have the links to
I've viewed states that BuildPipeline.BuildPlayer is the way to build a project from the command-line. BuildPipeline is inside the UnityEditor library.
What am I doing wrong? I'm still new to Unity, so any obvious solution is probably correct.
Thanks in advance for any guidance!
You can't have using UnityEditor; in a build. It is stripped of.
You only need this available in an editor script and not in a build so:
Either use #if pre-processors wrapping everything using it like
#if UNITY_EDITOR
using UnityEditor;
#endif
...
#if UNITY_EDITOR
// anything using UnityEidtor e.g. the method or entire class
#endif
or in your case simply move the entire script into a folder called Editor which strippes of the entire script for a build (see Special folder names).
This is actually also mentioned - though not well explained - by your link:
Then you would need a class in your Unity project in an Editor folder such as this Android example:
or in newer Unity versions you can put it in a separate folder (with any name) and create an AssemblyDefinition and configure it so it is only compiled for the UnityEditor (see in particular Creating an assembly for Editor code)

Cake (C# make) use .Net Framework methods in build.cake

Maybe a dump question. Cake states that its a build automation system that can be written in C#. I'm actually playing around a bit and now want to know if it is possible to call .Net methods in build.cake. At the time I've the following build.cake:
var target = Argument("target", "Default");
Task("NuGet")
.Does(() =>
{
// Get local directory
// Get all packages.config files in local directory
// Call nuget restore for every file
var currentDir = System.IO.GetCurrentDirectory(); // This doesn't work
var allPgkConfigs = System.IO.Directory.GetFiles(currentDir, "packages.config", System.IO.SearchOption.AllDirectories); // This doesn't work
foreach (var pgk in allPgkConfigs)
{
// GetNuGetPackageId(pkg);
}
});
Task("Build")
.Does(() =>
{
MSBuild("MySolution.sln");
});
RunTarget(target);
When calling build.ps1 -target nuget I get the following error:
PS C:\> .\build.ps1 -Target nuget
Preparing to run build script...
Running build script...
Analyzing build script...
Processing build script...
Compiling build script...
Error: C:/Users/Mewald-T550/XAP_Playground/build.cake(6,26): error CS0234: The type or namespace name 'GetCurrentDirectory' does not exist in the namespace 'System.IO' (are you missing an assembly reference?)
As cake already states it can't find System.IO how can I add this reference to cake?
I know that cake offers some build-in file operations, but I want to know how to add .Net Framework methods to the cake script.
Thx
You're calling a method on a namespace
Change
System.IO.GetCurrentDirectory()
to
System.IO.Directory.GetCurrentDirectory()
Tried this script and it worked just fine
var directory = System.IO.Directory.GetCurrentDirectory();
Information(directory);
That said, Cake has several IO abstractions built in
I.e. this will achieve the same:
var allPgkConfigs = GetFiles("./**/packages.config");
foreach (var pgk in allPgkConfigs)
{
// GetNuGetPackageId(pkg);
}
If you just want the current directory you can use
Context.Environment.WorkingDirectory
or just
var curDir = MakeAbsolute(Directory("./"));
Information("Current directory is: {0}", curDir);
You can use a reference directive:
#r "bin/myassembly.dll"
or
#reference "bin/myassembly.dll"
See http://cakebuild.net/docs/fundamentals/preprocessor-directives
Reference directive
The reference directive is used to reference external assemblies for use in your scripts.
Usage
The directive has one parameter which is the path to the dll to load.
#r "bin/myassembly.dll"
or
#reference "bin/myassembly.dll"
Try make it point to C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.IO.dll

c# How does Process.Start() method automatically know where files are located?

If I feed Process.Start(); the parameters "Firefox", Notepad or "cmd" it runs those programs like their location is built in, but with other programs I have to specify the program's directory for it to work.
How does it automatically know where some programs located, and why only those programs and not others?
My code:
using System;
using System.Diagnostics;
namespace Testing
{
public class MainClass
{
static void Main()
{
Process.Start("Firefox"); // Works
Process.Start("Notepad"); // Works
Process.Start(#"C:\Users\user\Desktop\Steam"); // Works too
Process.Start("Steam"); // This line gives me "The System cannot find the file specified"(run-time error)
}
}
}
I think it depends on Environment variables in Windows.
or type PATH in cmd and observe paths, where *.exe files can be found automatically.

c# Class Library Project - Load DLL from same folder?

I'm working on a plugin for a existing C# .NET Program. It's structured in a manner where you put your custom .dll file in Program Root/Plugins/your plugin name/your plugin name.dll
This is all working well, but now I'm trying to use NAudio in my project.
I've downloaded NAudio via Nuget, and that part works fine, but the problem is that it looks for the NAudio.dll in Program Root, and not in the folder of my plugin.
This makes it hard to distribute my plugin, because it would rely on users dropping the NAudio.dll in their Program Root in addition to putting the plugin into the "Plugins" folder.
Source:
SettingsView.xaml:
<Button HorizontalAlignment="Center"
Margin="0 5"
Width="120"
Command="{Binding SoundTestCommand,
Source={StaticResource SettingsViewModel}}"
Content="Sound Test" />
SettingsViewModel.cs:
using NAudio.Wave;
.
.
.
public void SoundTest()
{
IWavePlayer waveOutDevice;
WaveStream mainOutputStream;
WaveChannel32 inputStream;
waveOutDevice = new WaveOut();
mainOutputStream = new Mp3FileReader(#"E:\1.mp3");
inputStream = new WaveChannel32(mainOutputStream);
inputStream.Volume = 0.2F;
waveOutDevice.Init(mainOutputStream);
waveOutDevice.Play();
}
How can I get C# to look for NAudio in Program Root/Plugins/my plugin name/NAudio.dll instead of looking for it in Program Root/NAudio.dll ?
I'm using VS Express 2013, Target Framework is 4.5 and Output type is Class Library.
Edit:
I found 2 ways to make this work ( I'm not sure what the pros and cons of both methods are - if anyone knows I would appreciate additional information ).
Using the NuGet Package Costura.Fody.
After installing the NuGet package, I simply had to set all other References "Copy Local" to "False" and then set "Copy Local" for NAudio to "True".
Now when I build, the NAudio.dll is compressed and added to my own DLL.
Using the AssemblyResolver outlined below.
It didn't work right away though, so here is some additional information that may help anyone facing the same issue:
I put Corey's code as he posted it into the Helpers folder.
My entry point is Plugin.cs, the class is public class Plugin : IPlugin, INotifyPropertyChanged
In there, the entry method is public void Initialize(IPluginHost pluginHost), but simply putting PluginResolver.Init(path) did not work.
The host program uses WPF and is threaded and I had to use a dispatcher helper function of the host program to get it to work: DispatcherHelper.Invoke(() => Resolver.Init(path));
As mentioned, I'm currently unsure which method to use, but I'm glad I got it to work. Thanks Corey!
You can use the PATH environment variable to add additional folders to the search path. This works for native DLLs, but I haven't tried to use it for .NET assemblies.
Another option is to add a hook to the AssemblyResolve event on the current application domain and use a custom resolver to load the appropriate assembly from wherever you find it. This can be done at the assembly level - I use it in NAudio.Lame to load an assembly from a resource.
Something along these lines:
public static class PluginResolver
{
private static bool hooked = false;
public static string PluginBasePath { get; private set; }
public static void Init(string BasePath)
{
PluginBasePath = BasePath;
if (!hooked)
{
AppDomain.CurrentDomain.AssemblyResolve += ResolvePluginAssembly;
hooked = true;
}
}
static Assembly ResolvePluginAssembly(object sender, ResolveEventArgs args)
{
var asmName = new AssemblyName(args.Name).Name + ".dll";
var assemblyFiles = Directory.EnumerateFiles(PluginBasePath, "*.dll", SearchOption.AllDirectories);
var asmFile = assemblyFiles.FirstOrDefault(fn => string.Compare(Path.GetFileName(fn), asmName, true) == 0);
if (string.IsNullOrEmpty(asmFile))
return null;
return Assembly.LoadFile(asmFile);
}
}
(Usings for the above: System.IO, System.Reflection, System.Linq)
Call Init with the base path to your plugins folder. When you try to reference an assembly that isn't loaded yet it will search for the first file that matches the base name of the assembly with dll appended. For instance, the NAudio assembly will match the first file named NAudio.dll. It will then load and return the assembly.
No checking is done in the above code on the version, etc. and no preference is given to the current plugin's folder.

Categories