Entity Framework ExecuteStoreQuery fails on deployed systems - c#

Ok, a bit stumped here, and instead of banging my head any more on this, I thought I'd toss this out to all the bright people here.
I'm using Entity Framework and c# for a WinApp solution, and the core of the problem is that the darned thing runs fine on my system, but after I deploy it, it fails. Even when I install the deployed app on my development system, it fails. I find that a bit disturbing.
To the nuts and bold of the issue. The user performs a search, I build a query, tap SQL via the ExecuteStoreQuery call and return a generic list of SearchResult objects.
The call:
retVal = ctx.ExecuteStoreQuery<SearchResults>(sql).ToList();
Alternate call also generates the same error:
ObjectQuery<DbDataRecord> c = ctx.CreateQuery<DbDataRecord>(sql);
The Error:
************** Exception Text **************
System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.RuntimeModule.GetTypes()
at System.Reflection.Assembly.GetTypes()
at System.Data.Metadata.Edm.ObjectItemConventionAssemblyLoader.LoadTypesFromAssembly()
at System.Data.Metadata.Edm.ObjectItemAssemblyLoader.Load()
at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData)
at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData)
at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData)
at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData)
at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, KnownAssembliesSet knownAssemblies, EdmItemCollection edmItemCollection, Action`1 logLoadMessage, Object& loaderCookie, Dictionary`2& typesInLoading, List`1& errors)
at System.Data.Metadata.Edm.ObjectItemCollection.LoadAssemblyFromCache(ObjectItemCollection objectItemCollection, Assembly assembly, Boolean loadReferencedAssemblies, EdmItemCollection edmItemCollection, Action`1 logLoadMessage)
at System.Data.Metadata.Edm.MetadataWorkspace.ImplicitLoadAssemblyForType(Type type, Assembly callingAssembly)
at System.Data.Objects.ObjectContext.ExecuteStoreQueryInternal[TElement](String commandText, String entitySetName, MergeOption mergeOption, Object[] parameters)
at AMMCred.Data.Search.GetSearchResults(SearchTerms terms)
at AMMCred.frmMain.openProviderInfoToolStripMenuItem_Click(Object sender, EventArgs e)
at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
at System.Windows.Forms.ToolStripMenuItem.OnClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.ToolStripDropDown.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ToolStrip.WndProc(Message& m)
at System.Windows.Forms.ToolStripDropDown.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
SearchResults is a custom object, like so:
public class SearchResults : IEquatable<SearchResults>
{
private Guid id = Guid.Empty;
public Guid PROV_MPI_NO
{
get { return id; }
set { id = value; }
}
private string iPA = "";
public string IPA
{
get { return iPA; }
set { iPA = value; }
}
private string firstName = "";
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
private string middleName = "";
public string MI
{
get { return middleName; }
set { middleName = value; }
}
private string lastName = "";
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
private string license = "";
public string License
{
get { return license; }
set { license = value; }
}
private string provId = "";
public string ProvId
{
get { return provId; }
set { provId = value; }
}
/// <summary>
/// Used to help identify duplicates in a collection
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public bool Equals(SearchResults other)
{
return (this.PROV_MPI_NO == other.PROV_MPI_NO && this.License == other.License);
}
}
And finally, here is the select part of the SQL being used to obtain the search results:
SELECT a.PROV_MPI_NO, b.COMPANY_ID AS IPA, a.FIRSTNAME,a.MI,a.LASTNAME, b.PROVID, c.LICENSE
The problem seems to be coming from within Entity Framework as it's binding the results of the SQL to the custom object. I've verified that the custom object field names are the same as the SQL fields in case that mattered, which it didn't seem to.
It's darn near time for me to leave, and I'll be pondering this all weekend, so I'll probably check back in from time to time to answer any questions anyone might have.
Like I said, I'm completely stumped at the moment and would totally appreciate anyone's insight.
Thanks in advance!
Wayne
UPDATE 11/14/2011----------
Ran the Assembly Binding Log Viewer tool and came up with the following lead. Looks like Microsoft.Practices.Unity isn't loading. Thing is, I never once referenced these Practices assemblies in ANY application, but it seems that System.Data.Entity does...go figure. It's a lead...any info on this new development is so very appreciated.
*** Assembly Binder Log Entry (11/14/2011 # 3:10:52 PM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\Users\***me***\AppData\Local\Apps\2.0\1ND1AZ7G.HEJ\CWDQKK8A.LVO\ammc..tion_0000000000000000_0002.0000_456d6de62e1c40e4\AMMCred2.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = ***me***
LOG: DisplayName = Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
(Fully-specified)
LOG: Appbase = file:///C:/Users/***me***/AppData/Local/Apps/2.0/1ND1AZ7G.HEJ/CWDQKK8A.LVO/ammc..tion_0000000000000000_0002.0000_456d6de62e1c40e4/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = AMMCred2.exe
Calling assembly : Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Users\***me***\AppData\Local\Apps\2.0\1ND1AZ7G.HEJ\CWDQKK8A.LVO\ammc..tion_0000000000000000_0002.0000_456d6de62e1c40e4\AMMCred2.exe.config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Users/***me***/AppData/Local/Apps/2.0/1ND1AZ7G.HEJ/CWDQKK8A.LVO/ammc..tion_0000000000000000_0002.0000_456d6de62e1c40e4/Microsoft.Practices.Unity.DLL.
LOG: Attempting download of new URL file:///C:/Users/***me***/AppData/Local/Apps/2.0/1ND1AZ7G.HEJ/CWDQKK8A.LVO/ammc..tion_0000000000000000_0002.0000_456d6de62e1c40e4/Microsoft.Practices.Unity/Microsoft.Practices.Unity.DLL.
LOG: Attempting download of new URL file:///C:/Users/***me***/AppData/Local/Apps/2.0/1ND1AZ7G.HEJ/CWDQKK8A.LVO/ammc..tion_0000000000000000_0002.0000_456d6de62e1c40e4/Microsoft.Practices.Unity.EXE.
LOG: Attempting download of new URL file:///C:/Users/***me***/AppData/Local/Apps/2.0/1ND1AZ7G.HEJ/CWDQKK8A.LVO/ammc..tion_0000000000000000_0002.0000_456d6de62e1c40e4/Microsoft.Practices.Unity/Microsoft.Practices.Unity.EXE.
LOG: All probing URLs attempted and failed.

The error is a load exception.
Since this works in development, but not in the deployed program, it is probably due to the dll not being included.
Go into your VS project, expand the references and check the properties of each dll, make sure that copy local = true for the dll's that are not being deployed.

Based on your bind result, it looks like you are not deploying Microsoft.Practices.Unity.DLL with your application. And it looks like this is referenced from Microsoft.Practices.EnterpriseLibrary.Common, which is why you don't have a direct reference.
Here is the MSDN article that describes the various dependencies that the Enterprise Library has.
Update
I just checked the direct dependencies of System.Data.Entity using ildasm.exe (C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin) and it definitely does not reference the enterprise library. I would have been extremely surprised if it had, because they generally don't create dependencies between System DLLs and optional product DLLs (just for this reason).
Are you pulling in other DLLs/references that may include this? If you aren't sure, you can use ildasm.exe, navigate to the DLL, then open it's manifest. It's a little hard to read, but you are looking for references like:
module extern 'System.Data.dll, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
and
.assembly extern System.Data

Related

Google.Protobuf.dll is right next to my .dll but it is not being found or loaded

I have a Framework 4.8 C# app that uses ClearScript to allow JavaScript to be used as an extension language. I am able to write plugins as DLLs and attach them at runtime, viz
JSE.Script.attach = (Func<string, bool>)Attach;
...
private static bool Attach(string dllPath, string name = "")
{
var status = false;
var htc = new HostTypeCollection();
try
{
var assem = Assembly.Load(AssemblyName.GetAssemblyName(dllPath));
htc.AddAssembly(assem);
if (name.Length == 0)
{
name = assem.FullName.Split(',')[0];
}
JSE.AddHostObject(name, htc); //FIXME checkout the hosttypes
Console.Error.WriteLine($"Attached {dllPath} as {name}");
status = true;
}
catch (ReflectionTypeLoadException rtle)
{
foreach (var item in rtle.LoaderExceptions)
{
Console.Error.WriteLine(item.Message);
T.Fail(item.Message);
}
}
catch (FileNotFoundException fnfe)
{
Console.Error.WriteLine(fnfe.Message);
T.Fail(fnfe.Message);
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
T.Fail(e.Message);
}
return status;
}
This permits my scripts to have lines like
attach(".\\Plugin_GoogleAds_Metrics.dll");
H = Plugin_GoogleAds_Metrics.GoogleAds_Metrics.Historical;
H.EnableTrace("GAM");
...
I've made a public repo of the plugin for those interested.
What's not working in this situation is that when I try to execute the plugin's GetAccountInformation method, and execution reaches the GoogleAdsServiceClient googleAdsService = client.GetService(Services.V11.GoogleAdsService); line, an error is thrown complaining about Google.Protobuf, viz
Exception has been thrown by the target of an invocation.
at JScript global code (Script [23] [temp]:5:0) -> acc = H.GetAccountInformation(auths.Item1, 7273576109, true)
at Microsoft.ClearScript.ScriptEngine.ThrowScriptError(IScriptEngineException scriptError)
at Microsoft.ClearScript.Windows.WindowsScriptEngine.ThrowScriptError(Exception exception)
at Microsoft.ClearScript.Windows.WindowsScriptEngine.<>c__DisplayClass57_0`1.<ScriptInvoke>b__0()
at Microsoft.ClearScript.ScriptEngine.ScriptInvokeInternal[T](Func`1 func)
at Microsoft.ClearScript.ScriptEngine.ScriptInvoke[T](Func`1 func)
at Microsoft.ClearScript.Windows.WindowsScriptEngine.ScriptInvoke[T](Func`1 func)
at Microsoft.ClearScript.Windows.WindowsScriptEngine.Execute(UniqueDocumentInfo documentInfo, String code, Boolean evaluate)
at Microsoft.ClearScript.Windows.JScriptEngine.Execute(UniqueDocumentInfo documentInfo, String code, Boolean evaluate)
at Microsoft.ClearScript.ScriptEngine.Evaluate(UniqueDocumentInfo documentInfo, String code, Boolean marshalResult)
at Microsoft.ClearScript.ScriptEngine.Evaluate(DocumentInfo documentInfo, String code)
at Microsoft.ClearScript.ScriptEngine.Evaluate(String documentName, Boolean discard, String code)
at Microsoft.ClearScript.ScriptEngine.Evaluate(String documentName, String code)
at Microsoft.ClearScript.ScriptEngine.Evaluate(String code)
at RulesetRunner.Program.Run(JScriptEngine& jSE, String scriptText, Config cfg, Dictionary`2 settings) in C:\Users\bugma\Source\Repos\Present\BORR\RulesetRunner\RunManagementPartials.cs:line 72
Exception has been thrown by the target of an invocation.
Exception has been thrown by the target of an invocation.
Could not load file or assembly 'Google.Protobuf, Version=3.15.8.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604' or one of its dependencies. The system cannot find the file specified.
So
I am using the latest Google.Ads.GoogleAds library
AutoGenerateBindingRedirects has been set to true in the csproj file
Add-BindingRedirect has been executed in the context of the Plugin's project
The Plugin_GoogleAds_Metrics.dll is in the same folder as the Google.Protobuf.dll
Where to from here?
What fixed this was including Google.Ads.GoogleAds in the calling app. I didn't have to explicitly mention the symbols in the main binary, just have the library in the build. What I expect this did was to include all the relevant DLLs next to the main EXE.
This is definitely not what I wanted. I wanted to be able to hive off all the DLLs into a separate plugin folder and only have them connected when I attached the plugin. Sadly, this does not seem to be achievable at this point. And now I'm wondering about the other plugins I've written that use Google technologies.

internet explorer can't find my dll referenced by my activex control

I Have an activex control project in c# which references a dll file that I built myself.
Now I click a button and I see it failing with this exception:
System.IO.FileNotFoundException: Could not load file or assembly
'MtnLib, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=111045ceeaeac3e4' or one of its dependencies. The
system cannot find the file specified. File name: 'MtnLib,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=111045ceeaeac3e4'
at CSActiveX.MtnControl.button1_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e) at
System.Windows.Forms.Button.OnClick(EventArgs e) at
System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at
System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons
button, Int32 clicks) at
System.Windows.Forms.Control.WndProc(Message& m) at
System.Windows.Forms.ButtonBase.WndProc(Message& m) at
System.Windows.Forms.Button.WndProc(Message& m) at
System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&
m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32
msg, IntPtr wparam, IntPtr lparam)
I've enabled log and these are the logs:
LOG: DisplayName = MtnLib, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=111045ceeaeac3e4 (Fully-specified) LOG: Appbase =
file:///C:/Program Files (x86)/Internet Explorer/ LOG: Initial
PrivatePath = NULL Calling assembly : CSActiveX, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null.
=== LOG: This bind starts in LoadFrom load context. WRN: Native image will not be probed in LoadFrom context. Native image will only be
probed in default load context, like with Assembly.Load(). LOG: No
application configuration file found. LOG: Using host configuration
file: LOG: Using machine configuration file from
C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: MtnLib, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=111045ceeaeac3e4 LOG: Attempting download of new URL
file:///C:/Program Files (x86)/Internet Explorer/MtnLib.DLL. LOG:
Attempting download of new URL file:///C:/Program Files (x86)/Internet
Explorer/MtnLib/MtnLib.DLL. LOG: Attempting download of new URL
file:///C:/Program Files (x86)/Internet Explorer/MtnLib.EXE. LOG:
Attempting download of new URL file:///C:/Program Files (x86)/Internet
Explorer/MtnLib/MtnLib.EXE. LOG: Attempting download of new URL
file:///C:/temp/MtnControl/Debug/MtnLib.DLL. LOG: Attempting download
of new URL file:///C:/temp/MtnControl/Debug/MtnLib/MtnLib.DLL. LOG:
Attempting download of new URL
file:///C:/temp/MtnControl/Debug/MtnLib.EXE. LOG: Attempting download
of new URL file:///C:/temp/MtnControl/Debug/MtnLib/MtnLib.EXE.
My project references MtnLib.dll and I do see the file under C:\temp\MtnControl\Debug\MtnLib.dll So I don't understand why IE isn't finding the file.
this is my control:
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using MtnLib;
namespace CSActiveX
{
#region Interfaces
/// <summary>
/// AxCSActiveXCtrl describes the COM interface of the coclass
/// </summary>
[Guid("D4B8539E-3839-3913-8B1A-C551A9930864")]
public interface AxCSActiveXCtrl
{
#region Properties
bool Visible { get; set; } // Typical control property
bool Enabled { get; set; } // Typical control property
#endregion
#region Methods
void Refresh();
#endregion
}
#endregion
[ClassInterface(ClassInterfaceType.None)]
[Guid("80B59B58-98EA-303C-BE83-D26E5D8D6794")]
public partial class MtnControl : UserControl, AxCSActiveXCtrl
{
#region ActiveX Control Registration
// These routines perform the additional COM registration needed by
// ActiveX controls
[EditorBrowsable(EditorBrowsableState.Never)]
[ComRegisterFunction()]
public static void Register(Type t)
{
try
{
ActiveXCtrlHelper.RegasmRegisterControl(t);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); // Log the error
throw; // Re-throw the exception
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
[ComUnregisterFunction()]
public static void Unregister(Type t)
{
try
{
ActiveXCtrlHelper.RegasmUnregisterControl(t);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); // Log the error
throw; // Re-throw the exception
}
}
#endregion
private void button1_Click(object sender, EventArgs e)
{
//call a function from MtnLib
}
}
} // namespace CSActiveX
this is my ActiveXCtrlHelper:
[ComVisible(false)]
internal class ActiveXCtrlHelper : AxHost
{
internal ActiveXCtrlHelper()
: base(null)
{
}
#region ActiveX Control Registration
#region OLEMISC Enumeration
// Ref: http://msdn.microsoft.com/en-us/library/ms678497.aspx
const int OLEMISC_RECOMPOSEONRESIZE = 1;
const int OLEMISC_CANTLINKINSIDE = 16;
const int OLEMISC_INSIDEOUT = 128;
const int OLEMISC_ACTIVATEWHENVISIBLE = 256;
const int OLEMISC_SETCLIENTSITEFIRST = 131072;
#endregion
/// <summary>
/// Register the control as an ActiveX control.
/// </summary>
/// <param name="t"></param>
public static void RegasmRegisterControl(Type t)
{
// Check the argument
GuardNullType(t, "t");
GuardTypeIsControl(t);
// Open the CLSID key of the control
using (RegistryKey keyCLSID = Registry.ClassesRoot.OpenSubKey(
#"CLSID\" + t.GUID.ToString("B"), /*writable*/true))
{
RegistryKey subkey = null;
// Set "InprocServer32" to register a 32-bit in-process server.
// InprocServer32 = <path to 32-bit inproc server>
// Ref: http://msdn.microsoft.com/en-us/library/ms683844.aspx
subkey = keyCLSID.OpenSubKey("InprocServer32", /*writable*/true);
if (subkey != null)
// .NET runtime engine (mscoree.dll) for .NET assemblies
subkey.SetValue(null, Environment.SystemDirectory + #"\mscoree.dll");
// Create "Control" to identify it as an ActiveX Control.
// Ref: http://msdn.microsoft.com/en-us/library/ms680056.aspx
using (subkey = keyCLSID.CreateSubKey("Control")) { };
// Create "MiscStatus" to specify how to create/display an object.
// MiscStatus = <combination of values from OLEMISC enumeration>
// Ref: http://msdn.microsoft.com/en-us/library/ms683733.aspx
using (subkey = keyCLSID.CreateSubKey("MiscStatus"))
{
int nMiscStatus = OLEMISC_RECOMPOSEONRESIZE +
OLEMISC_CANTLINKINSIDE + OLEMISC_INSIDEOUT +
OLEMISC_ACTIVATEWHENVISIBLE + OLEMISC_SETCLIENTSITEFIRST;
subkey.SetValue("", nMiscStatus.ToString(), RegistryValueKind.String);
}
// Create "ToolBoxBitmap32" to identify the module name and the resource
// ID for a 16 x 16 bitmap as the toolbar button face.
// ToolBoxBitmap32 = <filename>.<ext>, <resourceID>
// Ref: http://msdn.microsoft.com/en-us/library/ms687316.aspx
using (subkey = keyCLSID.CreateSubKey("ToolBoxBitmap32"))
{
// If you want different icons for each control in the assembly you
// can modify this section to specify a different icon each time.
// Each specified icon must be embedded as a win32 resource in the
// assembly; the default one is at the index 101, but you can use
// additional ones.
subkey.SetValue("", Assembly.GetExecutingAssembly().Location + ", 101",
RegistryValueKind.String);
}
// Create "TypeLib" to specify the typelib GUID associated with the class.
using (subkey = keyCLSID.CreateSubKey("TypeLib"))
{
Guid libId = Marshal.GetTypeLibGuidForAssembly(t.Assembly);
subkey.SetValue("", libId.ToString("B"), RegistryValueKind.String);
}
// Create "Version" to specify the version of the control.
// Ref: http://msdn.microsoft.com/en-us/library/ms686568.aspx
using (subkey = keyCLSID.CreateSubKey("Version"))
{
int nMajor, nMinor;
Marshal.GetTypeLibVersionForAssembly(t.Assembly, out nMajor, out nMinor);
subkey.SetValue("", String.Format("{0}.{1}", nMajor, nMinor));
}
}
}
/// <summary>
/// Unregister the control.
/// </summary>
/// <param name="t"></param>
public static void RegasmUnregisterControl(Type t)
{
// Check the argument
GuardNullType(t, "t");
GuardTypeIsControl(t);
// Delete the CLSID key of the control
Registry.ClassesRoot.DeleteSubKeyTree(#"CLSID\" + t.GUID.ToString("B"));
}
private static void GuardNullType(Type t, String param)
{
if (t == null)
{
throw new ArgumentException("The CLR type must be specified.", param);
}
}
private static void GuardTypeIsControl(Type t)
{
if (!typeof(Control).IsAssignableFrom(t))
{
throw new ArgumentException(
"Type argument must be a Windows Forms control.");
}
}
}
I've checked Register for COM Interop in visual studio and my control is displaying correctly, just the MtnLib.dll cannot be found.
By the way I'm using IE 8 in windows 7 64 bit.
I turns out that I was testing the control using the 32 bit IE when MtnLib was an x64 library.

FileNotFound when return Types[] from loaded assembly via reflection

I am trying to load an addin assembly (placed at
D:\xyz\addin.dll
while my application is in
D:\MyApp\MyApp.exe
such way that addin file should not be locked so that new version of it can be copied again while application is running.
For that i created new app domain and loaded common dll which contains AssembltLoader Class, and then called AssemblyLoader to load addin and get all types available in it. Dependencies of Addin dll are already placed in same folder.
Now Getting types from addin dll works fine but when i
return assembly.GetTypes();
a very strange thing happens. it executes that line but on exit of that function it throws exception "d:\xyz\addin.dll" FileNotFound
public class ObjectLoader : IDisposable
{
public Type[] GetAllTypesFromAssembly(string filePath)
{
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
setup.ShadowCopyFiles = "true";
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
AssemblyLoader asemblyLoader = null;
AppDomain appDomain = AppDomain.CreateDomain(filePath, adevidence, setup);
appDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
domains.Add(filePath, appDomain);
object[] parms = { filePath };
BindingFlags bindings = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public;
try
{
asemblyLoader = (AssemblyLoader)appDomain.CreateInstanceFromAndUnwrap(
setup.ApplicationBase +
"Common.dll", "Common.AssemblyLoader",
true, bindings, null, parms, null, null, null
);
}
catch (Exception ex)
{
throw ex; // new AssemblyLoadFailureException();
}
object types = null;
if (asemblyLoader != null)
{
// On following line i am facing the error which occur on following line but when GetAllTypes exits.
types = asemblyLoader.GetAllTypes();
}
return (Type[])types;
}
}
internal class AssemblyLoader : MarshalByRefObject, IDisposable
{
private Assembly assembly = null;
public object GetAllTypes()
{
BindingFlags flags = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public;
object types = null;
if (assembly != null)
{
try
{
// following line works fine and loads a type (it contains one class)
types = assembly.GetTypes();
}
catch (Exception)
{
types = new ObjectLoadFailureException();
}
}
else
{
types = new AssemblyNotLoadedException();
}
return types;
}
}
Here is the exception detail:
System.IO.FileNotFoundException was unhandled
HResult=-2147024894
Message=Could not load file or assembly 'AddIn, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Source=mscorlib
FileName=AddIn, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
FusionLog==== Pre-bind state information ===
LOG: DisplayName = AddIn, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///D:/MyApp/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
if i copy my addin.dll both in D:\xyz\ and D:\MyApp\ then there is no error. I cannot do that in runtime environment.
You're marshalling the Type objects into the primary AppDomain.
This causes the CLR to load the assembly containing the types in that AppDomain, causing this error.
You probably shouldn't be using AppDomains at all.

AppDomain.Load() fails with FileNotFoundException

I'm trying to load my plugin dll into separate AppDomain, but Load() method fails with FileNotFoundException. Moreover, it seems like setting PrivateBinPath property of AppDomainSetup has no effect, because in log I see "Initial PrivatePath = NULL". All plugin have strong name. Normally each plugin is stored in [Application startp path]\postplugins\[plugindir]. If I put plugins subdirectories under [Application startp path] directory, everything works. I also have tried to change AppBase property manually but it does not change.
Here is the code:
public void LoadPostPlugins(IPluginsHost host, string pluginsDir)
{
_Host = host;
var privatePath = "";
var paths = new List<string>();
//build PrivateBinPath
var dirs = new DirectoryInfo(pluginsDir).GetDirectories();
foreach (var d in dirs)
{
privatePath += d.FullName;
privatePath += ";";
}
if (privatePath.Length > 1) privatePath = privatePath.Substring(0, privatePath.Length - 1);
//create new domain
var appDomainSetup = new AppDomainSetup { PrivateBinPath = privatePath };
Evidence evidence = AppDomain.CurrentDomain.Evidence;
var sandbox = AppDomain.CreateDomain("sandbox_" + Guid.NewGuid(), evidence, appDomainSetup);
try
{
foreach (var d in dirs)
{
var files = d.GetFiles("*.dll");
foreach (var f in files)
{
try
{
//try to load dll - here I get FileNotFoundException
var ass = sandbox.Load(AssemblyName.GetAssemblyName(f.FullName));
var f1 = f;
paths.AddRange(from type in ass.GetTypes()
select type.GetInterface("PluginsCore.IPostPlugin")
into iface
where iface != null
select f1.FullName);
}
catch (FileNotFoundException ex)
{
Debug.WriteLine(ex);
}
}
}
}
finally
{
AppDomain.Unload(sandbox);
}
foreach (var plugin in from p in paths
select Assembly.LoadFrom(p)
into ass
select
ass.GetTypes().FirstOrDefault(t => t.GetInterface("PluginsCore.IPostPlugin") != null)
into type
where type != null
select (IPostPlugin)Activator.CreateInstance(type))
{
plugin.Init(host);
plugin.GotPostsPartial += plugin_GotPostsPartial;
plugin.GotPostsFull += plugin_GotPostsFull;
plugin.PostPerformed += plugin_PostPerformed;
_PostPlugins.Add(plugin);
}
}
And here is the log:
'FBTest.vshost.exe' (Managed (v4.0.30319)): Loaded 'D:\VS2010Projects\PNotes - NET\pnfacebook\FBTest\bin\Debug\postplugins\pnfacebook\pnfacebook.dll', Symbols loaded.
A first chance exception of type 'System.IO.FileNotFoundException' occurred in FBTest.exe
System.IO.FileNotFoundException: Could not load file or assembly 'pnfacebook, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e2a2192d22aadc7' or one of its dependencies. The system cannot find the file specified.
File name: 'pnfacebook, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e2a2192d22aadc7'
at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection)
at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
at System.Reflection.Assembly.Load(String assemblyString)
at System.UnitySerializationHolder.GetRealObject(StreamingContext context)
at System.AppDomain.Load(AssemblyName assemblyRef)
at PNotes.NET.PNPlugins.LoadPostPlugins(IPluginsHost host, String pluginsDir) in D:\VS2010Projects\PNotes - NET\pnfacebook\FBTest\PNPlugins.cs:line 71
=== Pre-bind state information ===
LOG: User = ANDREYHP\Andrey
LOG: DisplayName = pnfacebook, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e2a2192d22aadc7
(Fully-specified)
LOG: Appbase = file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: pnfacebook, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e2a2192d22aadc7
LOG: Attempting download of new URL file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/pnfacebook.DLL.
LOG: Attempting download of new URL file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/pnfacebook/pnfacebook.DLL.
LOG: Attempting download of new URL file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/pnfacebook.EXE.
LOG: Attempting download of new URL file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/pnfacebook/pnfacebook.EXE.
when you load an assembly into the AppDomain in that way, it is the current AppDomain's PrivateBinPath that is used to find the assembly.
For your example, when I added the following to my App.config it ran fine:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="[PATH_TO_PLUGIN]"/>
</assemblyBinding>
</runtime>
This is not very useful to you though.
What I did instead was to create a new assembly that contained the IPostPlugin and IPluginsHost interfaces, and also a class called Loader that looked like this:
public class Loader : MarshalByRefObject
{
public IPostPlugin[] LoadPlugins(string assemblyName)
{
var assemb = Assembly.Load(assemblyName);
var types = from type in assemb.GetTypes()
where typeof(IPostPlugin).IsAssignableFrom(type)
select type;
var instances = types.Select(
v => (IPostPlugin)Activator.CreateInstance(v)).ToArray();
return instances;
}
}
I keep that new assembly in the application root, and it doesn't need to exist in the plugin directories (it can but won't be used as the application root will be searched first).
Then in the main AppDomain I did this instead:
sandbox.Load(typeof(Loader).Assembly.FullName);
Loader loader = (Loader)Activator.CreateInstance(
sandbox,
typeof(Loader).Assembly.FullName,
typeof(Loader).FullName,
false,
BindingFlags.Public | BindingFlags.Instance,
null,
null,
null,
null).Unwrap();
var plugins = loader.LoadPlugins(AssemblyName.GetAssemblyName(f.FullName).FullName);
foreach (var p in plugins)
{
p.Init(this);
}
_PostPlugins.AddRange(plugins);
So I create an instance of the known Loader type, and then get that to create the plugin instances from within the plug-in AppDomain. That way the PrivateBinPaths are used as you want them to be.
One other thing, the private bin paths can be relative so rather than adding d.FullName you could add pluginsDir + Path.DirectorySeparatorChar + d.Name to keep the final path list short. That's just my personal preference though! Hope this helps.
Thanks a lot to DedPicto and James Thurley ; I was able to implement a complete solution, I posted in this post.
I had the same problem as Emil Badh : if you try to return from "Loader" class an interface that represents a concrete class that is unknown in current AppDomain, you get a "Serialization Exception".
It is because the concrete type tries to be deserialized.
The solution: I was able to return from "Loader" class a concrete type of a "custom proxy" and it works. See referenced post for details :
// Our CUSTOM PROXY: the concrete type which will be known from main App
[Serializable]
public class ServerBaseProxy : MarshalByRefObject, IServerBase
{
private IServerBase _hostedServer;
/// <summary>
/// cstor with no parameters for deserialization
/// </summary>
public ServerBaseProxy ()
{
}
/// <summary>
/// Internal constructor to use when you write "new ServerBaseProxy"
/// </summary>
/// <param name="name"></param>
public ServerBaseProxy(IServerBase hostedServer)
{
_hostedServer = hostedServer;
}
public string Execute(Query q)
{
return(_hostedServer.Execute(q));
}
}
This proxy could be returned and use as if it was the real concrete type !

IronPython Sandboxing with CAS

I am trying to integrate IronPython into a C# application for scripting purposes. I would also like the scripts to run under a set of security policies that restrict their access to the file system/network/sensitive system resources.
Research indicates that the most popular approach is to use CAS. This works very well and it does not allow the user to use sockets, access the file system, etc. However, when I try to inject variables for the scrip to interact with, I get a security exception every time I access certain parameters. This only happens with variables I define in my assembly. If I use a standard .NET type (like Dictionary) it works just fine.
My Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Security.Policy;
using System.Security.Permissions;
using System.Security;
using System.IO;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;
using System.Runtime.Remoting;
using System.Net;
namespace python_in_appdomain
{
[Serializable]
public class Whatever
{
public int i;
public Whatever(int i)
{
this.i = i;
}
}
class Program
{
static void Main(string[] args)
{
Remoting();
}
public static void Remoting()
{
AppDomainSetup setup = new AppDomainSetup();
Assembly thisAssembly = Assembly.GetExecutingAssembly();
setup.ApplicationBase = Path.GetDirectoryName(thisAssembly.Location);
AssemblyName name = typeof(Program).Assembly.GetName();
StrongName sn = new StrongName(
new StrongNamePublicKeyBlob(name.GetPublicKey()),
name.Name,
name.Version
);
PermissionSet pset = new PermissionSet(PermissionState.None);
pset.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
pset.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
setup.PartialTrustVisibleAssemblies = new[] { sn.Name + ", PublicKey=" + sn.PublicKey.ToString() };
AppDomain domain = AppDomain.CreateDomain("Sandbox", AppDomain.CurrentDomain.Evidence, setup, pset, sn);
String script = #"
d.Add('hello', 1)
w.i = 5
";
Whatever w = new Whatever(4);
Dictionary<string, int> d = new Dictionary<string,int>();
ScriptRuntime py = Python.CreateRuntime(domain);
ScriptEngine engine = py.GetEngine("py");
ScriptScope scope = engine.CreateScope();
scope.SetVariable("w", w);
scope.SetVariable("d", d);
int result;
Console.WriteLine(w.i);
d.TryGetValue("hello", out result);
Console.WriteLine(result);
Console.WriteLine("-----");
try
{
engine.Execute(script, scope);
}
catch (Exception exc)
{
Console.WriteLine(exc.ToString());
}
w = scope.GetVariable<Whatever>("w");
d = scope.GetVariable<Dictionary<string,int>>("d");
Console.WriteLine("-----");
Console.WriteLine(w.i);
d.TryGetValue("hello", out result);
Console.WriteLine(result);
}
}
}
Commenting out the "w.i=5" on line 55 causes the program to execute normally under restricted security settings. Setting the PermissionState to Unrestricted on line 47 allows both lines of the script to execute normally. The following is the error message I receive:
System.Security.SecurityException: Request failed.
at System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(IRuntimeMethodInfo method)
at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type delegateType, Object target)
at System.Dynamic.Utils.TypeExtensions.CreateDelegate(MethodInfo methodInfo, Type delegateType, Object target)
at System.Linq.Expressions.Compiler.LambdaCompiler.CreateDelegate()
at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator)
at System.Linq.Expressions.Expression`1.Compile()
at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet](T0 arg0, T1 arg1)
at IronPython.Compiler.PythonScriptCode.RunWorker(CodeContext ctx)
at IronPython.Compiler.PythonScriptCode.Run(Scope scope)
at IronPython.Compiler.RuntimeScriptCode.InvokeTarget(Scope scope)
at IronPython.Compiler.RuntimeScriptCode.Run(Scope scope)
at Microsoft.Scripting.SourceUnit.Execute(Scope scope, ErrorSink errorSink)
at Microsoft.Scripting.Hosting.ScriptSource.Execute(ScriptScope scope)
at Microsoft.Scripting.Hosting.ScriptEngine.Execute(String expression, ScriptScope scope)
at Microsoft.Scripting.Hosting.ScriptEngine.Execute(String expression, ScriptScope scope)
at python_in_appdomain.Program.Remoting() in C:\Users\dave\Documents\Visual Studio 2010\Projects\IronPythonTest\IronPythonTest\Program.cs:line 7
6
The action that failed was:
Demand
The type of the first permission that failed was:
System.Security.PermissionSet
The demand was for:
<PermissionSet class="System.Security.PermissionSet"
version="1"
Unrestricted="true"/>
The granted set of the failing assembly was:
<PermissionSet class="System.Security.PermissionSet"
version="1">
<IPermission class="System.Security.Permissions.ReflectionPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Unrestricted="true"/>
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="Execution"/>
</PermissionSet>
The assembly or AppDomain that failed was:
Microsoft.Dynamic, Version=1.1.0.20, Culture=neutral, PublicKeyToken=7f709c5b713576e1
The method that caused the failure was:
Int32 Run(Microsoft.Scripting.Interpreter.InterpretedFrame)
The Zone of the assembly that failed was:
Internet
The Url of the assembly that failed was:
file:///C:/Users/dave/Documents/Visual Studio 2010/Projects/IronPythonTest/IronPythonTest/bin/Debug/Microsoft.Dynamic.DLL
Unhandled Exception: System.Security.SecurityException: Request failed.
at System.Delegate.BindToMethodInfo(Object target, IRuntimeMethodInfo method, RuntimeType methodType, DelegateBindingFlags flags)
at System.Delegate.CreateDelegate(Type type, MethodInfo method, Boolean throwOnBindFailure)
at System.Dynamic.Utils.TypeExtensions.CreateDelegate(MethodInfo methodInfo, Type delegateType)
at System.Runtime.CompilerServices.CallSite`1.MakeUpdateDelegate()
at System.Runtime.CompilerServices.CallSite`1.GetUpdateDelegate(T& addr)
at System.Runtime.CompilerServices.CallSite`1.GetUpdateDelegate()
at System.Runtime.CompilerServices.CallSite`1.Create(CallSiteBinder binder)
at System.Func`2.Invoke(T arg)
at Microsoft.Scripting.Runtime.DynamicOperations.GetOrCreateSite[T](CallSiteBinder siteBinder, Func`2 factory)
at Microsoft.Scripting.Runtime.DynamicOperations.GetOrCreateSite[T1,TResult](CallSiteBinder siteBinder)
at Microsoft.Scripting.Runtime.DynamicOperations.ConvertTo[T](Object obj)
at IronPython.Runtime.PythonContext.ScopeGetVariable[T](Scope scope, String name)
at Microsoft.Scripting.Hosting.ScriptScope.GetVariable[T](String name)
at Microsoft.Scripting.Hosting.ScriptScope.GetVariable[T](String name)
at python_in_appdomain.Program.Remoting() in C:\Users\dave\Documents\Visual Studio 2010\Projects\IronPythonTest\IronPythonTest\Program.cs:line 8
3
at python_in_appdomain.Program.Main(String[] args) in C:\Users\dave\Documents\Visual Studio 2010\Projects\IronPythonTest\IronPythonTest\Program.
cs:line 31
The error is shockingly straight forward. It says that it is expecting to have totally unrestricted access for this kind of action. Is there any way around this? Why does the dictionary work but my variable does not? Is there a way for me to make IronPython treat my variable like the Dictionary? Am I missing something very obvious?
Thank you very much for you help.
Update 12/21/2012
I kept messing around and came up with a solution that worked. Creating the AppDomain like this (with the same permission object) allows everything to work.
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = System.Environment.CurrentDirectory;
AppDomain domain = AppDomain.CreateDomain("IPyEngine", new Evidence(), setup, pset);
I can't say I totally understand why, though I can see that I'm not providing my assembly's Evidence nor am I adding any Assemblies to the trust list. I don't want to mark this as the answer until I know for certain I'm not doing anything monumentally stupid.
This is suspicious:
The Zone of the assembly that failed was:
Internet
The Url of the assembly that failed was:
file:///C:/Users/dave/Documents/Visual Studio 2010/Projects/IronPythonTest/IronPythonTest/bin/Debug/Microsoft.Dynamic.DLL
I wonder if the file has a zone identifier. Can you check the file properties, and Unblock it if necessary?

Categories

Resources