How can I reference external project DLL with ScriptOptions? - c#

I have a project A in which I am writing code to be compiled internally using C# Script objects.
I have created another project in a different solution (external project), project B. I have already added a reference to the ProjectB.DLL inside Project A in the "references" list. What I want is to add Project B's reference on the internal Script code that I want to compile. To better explain, my code is as follows:
My "using statements" are:
APPROVED_USING_STATEMENTS = new HashSet<string>();
APPROVED_USING_STATEMENTS.Add("System.Text");
APPROVED_USING_STATEMENTS.Add("System.Data");
APPROVED_USING_STATEMENTS.Add("System.Text.RegularExpressions");
APPROVED_USING_STATEMENTS.Add("System");
APPROVED_USING_STATEMENTS.Add("System.Linq");
APPROVED_USING_STATEMENTS.Add("System.Collections");
APPROVED_USING_STATEMENTS.Add("System.Security.Cryptography");
APPROVED_USING_STATEMENTS.Add("Project.ProjectB");
The compiler code is as follows:
foreach (var apprvUsingStatements in DataTransformationScript.GetApprovedUsingStatements())
{
usingStatements.Append("using " + apprvUsingStatements + "; \n");
}
string transformCode = usingStatements.ToString();
transformCode += "object returnObject = currentData;";
transformCode += schemaMap.transform_script;
transformCode += ";returnObject";
ScriptOptions references = ScriptOptions.Default.AddReferences(DataTransformationScript.GetApprovedUsingStatements());
//Adding my own personal references from Connector
var asm = typeof(Project.ProjectB.TestTransformation).Assembly;
references.AddReferences(asm);
//HTMLEncodeLogMessage.Info(Logger, "Assmebly added: " + asm.FullName + " Location " + asm.Location + " Given Name " + asm.GetName().Name);
//===============================================//
var transformScript = CSharpScript.Create(transformCode, references, globalsType: typeof(DataTransformationScript.Globals));
transformScript.Compile();
As you can see, I add the reference to Project B using the following code extract:
var asm = typeof(Project.ProjectB.TestTransformation).Assembly;
references.AddReferences(asm);
And I already have the using statement above for project as "using Project.ProjectB". (TestTransformation is just a method inside ProjectB. It seems I had to use the method name as well to get the reference dll.
I am still getting an error: The type or namespace name 'Project' could not be found (are you missing a using directive or an assembly reference?).
Am I missing any other kind of reference that I need to add? I noticed I am not getting this error for all the "System" references that I have. Is it possible that C# Script objects only get data from the folders inside C:\Windows\assembly?
I have looked at the following stackoverflow question and it DID NOT solve my problem:
Link
I would really appreciate any kind of guidance and assistance. I am still learning.

Try using costura fody/ fody library

Related

The name 'zipfile' does not exist in the current context

I have an SSIS project that I can run as is, but when I try to edit it, I get an error:
The name 'zipfile' does not exist in the current context
Without editing, it works fine.
The code that's producing the error:
public void Main()
{
// TODO: Add your code here
string moduleName = Dts.Variables["User::ModuleName"].Value.ToString();
string s = Dts.Variables["User::ZipFileLocation"].Value.ToString().TrimEnd('\\') + "\\" + moduleName + "\\" + moduleName + "_" + DateTime.Now.ToString("ddMMyyyy");
// TODO: Add your code here
string startPath = s;
string zipPath = s + ".zip";
try
{
File.Delete(zipPath);
ZipFile.CreateFromDirectory(startPath, zipPath);
}
catch (Exception e)
{
}
Dts.TaskResult = (int)ScriptResults.Success;
}
How can I solve this?
Make sure you are using .NET version 4.5. Reference the Compression DLL - here is the path:
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.IO.Compression.FileSystem.dll
Reference it in the class by adding using System.IO.Compression.FileSystem. If the class is inherited from another class, make sure to reference it in the parent class too. (This is what I have to do to make it compile)
To use the ZipFile class, you must add a reference to the System.IO.Compression.FileSystem assembly in your project; otherwise, you'll get the following error message when trying to compile:
The name 'ZipFile' does not exist in the current context.
For more information on how to add a reference to your project in Visual Studio, see How to: Add or remove references by using the Reference Manager.
I found that the ZipFile class would not cooperate only using System.IO.Compression, it asked to see a Reference to System.IO.Compression.FileSystem.
If you're using Visual Basic, adding a reference is fairly easy. In the solution explorer, one of the tabs under the project is called References. Right click there and select Add Reference. Scroll down a bit an check the checkbox next to System.IO.Compression.FileSystem. Once you click OK, you shouldn't even need to explicitly reference System.IO.Compression.FileSystem in your code!
Good luck (:
Just for Update: -
With .Net 4.6.1 version
Adding reference to System.IO.Compression.FileSystem and using System.IO.Compression is enough.
using System.IO.Compression.FileSystem is giving below error.

issue with loading .dll lib in C# code

I have found a few posts about loading .dll libraries directly into C# projects through code. Here is the current code I am using:
if (System.IO.File.Exists(dir + lib + ".dll"))
{
Assembly type = Assembly.LoadFrom(dir + lib + ".dll");
object obj1 = type.CreateInstance(_namespace);
assm.Add(obj1);
return assm.Count - 1;
}
else
{
Console.WriteLine(dir + lib + ".dll: file does not exist");
return -1;
}
The code with:
Assembly type = Assembly.LoadFrom(dir + lib + ".dll");
object obj1 = type.CreateInstance(_namespace);
is suppose to locate the .dll file and load it as an instance then grabbing the class and creating an object from it. So I could make a library that has one function to print hello and I then load it into the code, I could then access that function by creating an Instance of the class. The problem is when I do the code:
object obj1 = type.CreateInstance(_namespace);
obj1 is null, I know to give the namspace to the function (which I double checked and is correct), but no matter what it is always null. I checked to see if the Library is being loaded in as an assembly and it is! Here is the details of the assembly when I do a breakpoint (hovering over the object type):
{ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
Thank you in advance for your help, I am not sure what is wrong with my code.
What is _namespace? It must contents full name of class (with namespace), for example System.Collections.ArrayList

ReportingService2010 could not be found

I have:
private readonly ReportingService2010 _rs = new ReportingService2010();
Error:
The type or namespace name 'ReportingService2010' could not be found (are you missing a using directive or an assembly reference?)
I setup a reference to the SSRS service. The reference does not give me access to ReportingService2010 as I expect. The closest thing is:
MySsrsServiceNamespace.ReportingService2010SoapClient
How am I supposed to use the ReportingService2010 class? MSDN lists this class vaguely.
Please note I tried using ReportingService2010SoapClient. This class does not match the documentation for ReportingService2010. For example, ListChildren() only accepts 4 parameters and the Url property does not exist.
Just ran into the exact same issue. ReportingService2010SoapClient class was available, but the ReportingService2010 class was not. Was driving me nuts. I had added it as a "Service References", but you have to add it as a "Web References", like so:
Delete your old Service Reference
Right click on References. The "Add Service Reference" dialog comes up.
Do not enter the WSDL URL now, instead: Click on the "Advanced" button at the bottom left.
The "Service Reference Settings" dialog comes up.
At the bottom left, click the "Add Web Reference" button.
Now enter the URL for the WSDL. (for me that was servername/ReportServer/ReportService2010.asmx)
Click the small arrow on the right, it will take its sweet time to load.
Name the web reference, I used "ReportingService2010WebReference", but ReportingService2010" probably works just as well.
Click "Add Reference"
In your code, update your using statements to "using .ReportingService2010WebReference (or whatever name you picked)
Code:
private MySol.ReportService2010WebReference.ReportingService2010 rsClient;
rsClient = new ReportingService2010();
rsClient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
CatalogItem[] items = null;
items = rsClient.ListChildren("/", false);
foreach (var item in items)
{
tr.ErrorMessage += (item.Path + " " + item.CreatedBy);
}
Worked on the first try. Web.config file wasn't touched.
Either create a proxy class and include it in your application or add a web reference to ReportingService. The tutorial is available there:
http://technet.microsoft.com/en-us/library/ms155134.aspx
Note that if you are going for proxy class and you are using more than one endpoint (ReportExecution, ReportingService) you should generate proxy classes on different namespaces, otherwise you will get clashes.
Did you do it by web reference? If so, try using WSDL at the command line. Command line syntax:
wsdl /language:CS /n:"Microsoft.SqlServer.ReportingServices2010" http://serverName/reportserver/ReportService2010.asmx?wsdl
Do not add a Webreference
Follow the following steps and it would work just fine.
1) Make sure you have .netframework >= 4.6.1
2) Run command prompt as administrator
3) cd C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools
4) Generate class: wsdl /proxyusername:Username /proxypassword:Password -out:Reportingservice2010.cs http://Servername/Reportserver/ReportService2010.asmx?wsdl
Additional) Run wsdl /? for help Files will output in: C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools
5) Add the .cs file to your project
Change this;
private readonly ReportingService2010 _rs = new ReportingService2010()
to
private readonly ReportingService2010SoapClient _rs = new ReportingService2010SoapClient()
You are attempting to create an instance to a class that does not exists and adding the reference creates a corresponding *Client class for you to instantiate.

Embedding boo in C#, does not recognise executing assembly

scripts/ai/Dream.boo
import CultLib
import LonelyHero
class Dream(Enemy):
pass
C#
var bc = new BooCompiler();
bc.Parameters.Input.Add(new FileInput("rsc/script/ai/" + "Dream" + ".boo"));
bc.Parameters.Pipeline = new CompileToMemory();
bc.Parameters.References.Add(Assembly.GetExecutingAssembly());
bc.Parameters.References.Add(Assembly.LoadFile(new DirectoryInfo("CultLib.dll").FullName));
bc.Parameters.References.Add(Assembly.LoadFile(new DirectoryInfo("sfmlnet-audio-2.dll").FullName));
bc.Parameters.References.Add(Assembly.LoadFile(new DirectoryInfo("sfmlnet-graphics-2.dll").FullName));
bc.Parameters.References.Add(Assembly.LoadFile(new DirectoryInfo("sfmlnet-window-2.dll").FullName));
var cc = bc.Run();
if(cc.GeneratedAssembly!=null)
{
cc.GeneratedAssembly.CreateInstance("Dream", true, BindingFlags.NonPublic, null,
new object[] {Parent, pos}, null, null);
}
else
{
foreach (var error in cc.Errors)
Console.WriteLine(error);
}
In the line bc.Parameters.References.Add(Assembly.GetExecutingAssembly()); I add the executing assembly, which contains the namespace "LonelyHero". However, the error
rsc/script/ai/Dream.boo(2, 8): BCE0021: Namespace LonelyHero not found. maybe you forgot to add an assembly reference?
appears.
LonelyHero should exist, why does this error occur and what can I do to resolve it?
Note:
Upon replacing Assembly.GetExecutingAssmebly() with Assembly.GetAssembly(typeof(Enemy)) , thus assuring it adds the assembly with a class under the LonelyHero namespace, the same error occurs. Also with Assembly.LoadFile(new DirectoryInfo("LonelyHero.exe").FullName)
Occurs in Boo 0.9.4.9 and booxw-1203
Imported namespaces in BOO need to contain at least one public type for the import to succeed; otherwise you will get the BCE0021 error, so you want to make sure the Enemy type is public (or another one).
I don't know Boo or C# but I found someone asking a similar question on the Boo Programming Google Group. The question they were asking:
"Namespace 'Pathfinding' not found, maybe you forgot to add an assembly reference?"
Specifically they were getting this error:
I am converting some existing code I had from C# into Boo. One of my
classes had a "using Pathfinding" which got converted to "import
Pathfinding" by the script converter.
I get this error when trying to compile:
Assets/Script/VehicleController.boo(4,8): BCE0021: Namespace
'Pathfinding' not found, maybe you forgot to add an assembly
reference?
The Pathfinding library I'm using is written in C#. Could this cause
problems? Is there anything additional I need to do to make this work?
This looked like your error message and the solution someone mentioned was that you needed to put your scripts into your compilation phase earlier to ensure that they're accessible from scripts written in other languages.
This URL was cited as a reference/source for more information on script compilation.

GetExportedTypes() FileNotFoundException: Assembly couldn't be found

My task: Find all Forms (WindowsForm or WPF, doesn't matter) in a dll or exe file and return that list. In theory that works (meaning: if I've an assembly with a WPF or WindowsForm my code manages to get all Forms, TextBoxes, Labels etc. ). When it comes to "real" assemblies it fails. I get FileNotFound exceptions when calling GetExportedTypes() for every "custom" assembly (.NET assemblies are found, no problems there). I already use GetReferencedAssemblies() to load the referenced assemblies (Reflection.Assembly.LoadFrom) and yes it does work (all assemblies are found and loaded into the AppDomain) but it doesn't help.
I checked the version numbers (they match), I copied my executable and the assembly into one directory with all referenced assemblies, doesn't work.
Here is my code, maybe someone figures out what I'm (obviously) doing wrong:
foreach (AssemblyName reference in selectedAssembly.GetReferencedAssemblies())
{
if (System.IO.File.Exists(
System.IO.Path.GetDirectoryName(selectedAssembly.Location) +
#"\" + reference.Name + ".dll"))
{
System.Reflection.Assembly.LoadFrom(
System.IO.Path.GetDirectoryName(selectedAssembly.Location) +
#"\" + reference.Name + ".dll");
}
else if (System.IO.File.Exists(#"C:\dll\" + reference.Name + ".dll"))
{
System.Reflection.Assembly.LoadFrom(#"C:\dll\" + reference.Name + ".dll");
}
else
{
System.Reflection.Assembly.ReflectionOnlyLoad(reference.FullName);
}
selectedAssembly.GetExportedTypes();
}
at first check if the referenced dll exists in the directory where the assembly is, if not check if it exists in C:\dll and if it's not there try and use the GAC. it does work and I've no errors from there but as soon as I come to GetExportedTypes it fails with a FileNotFound exception on the first custom library.
*edit 1 what do I mean by "real assemblies": I mean assemblies which are more complex and have references to non-standard-.NET libraries/assemblies
Thanks for the hint to fuslogvw.exe Hans Passant but what do you mean by "with code like this"?
okay I used fuslogvw.exe and I get two exceptions for every single dll that is referenced by the "selectedAssembly".
The first one says something like
"The binding starts in LoadFrom-context
The image owned by the system isn't searched in LoadFrom-Context"
the other logentry says that the dll referenced by the selectedAssembly couldn't be found and it tried to download it from application's base path and all directories below...but not from it's actual location...so, key question: how do I change the Load-context to LoadFrom? And why is .NET so stubborn on this? I mean the assemblies are loaded in the AppDomain, it shouldn't care about the actual location of the assembly.
okay problem solved. Here is the solution:
http://ayende.com/blog/1376/solving-the-assembly-load-context-problem
I implemented that into my existing class (removed the static-keyword and put the body of the Init method into my method), compiled it and it worked.
Thanks for your help guys.
okay problem solved. Here is the solution: http://ayende.com/blog/1376/solving-the-assembly-load-context-problem
I implemented that into my existing class (removed the static-keyword and put the body of the Init method into my method), compiled it and it worked.
Thanks for your help guys.
just in case the website will someday be unavailable, here is the sourcecode from ayende
static Dictionary<string, Assembly>assemblies;
public static void Init()
{
assemblies = new Dictionary<string, Assembly>();
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(CurrentDomain_AssemblyLoad);
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly assembly = null;
assemblies.TryGetValue(args.Name, out assembly);
return assembly;
}
static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
Assembly assembly = args.LoadedAssembly;
assemblies[assembly.FullName] = assembly;
}
I would recommend using Reflector to see which references you may not have loaded. For instance, you are only loading the referenced assemblies that the current assembly is looking at. Do you step down through each child to find their referenced assemblies as well? The FileNotFound error is probably pointing you in the direction of a type that is declared in another assembly that isn't loaded.

Categories