AppDomain.Load() fails with FileNotFoundException - c#

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 !

Related

How to Spin up a new app domain in an SSIS Script Task for a Dynamically Loaded Assembly

I have built an assembly that make calls to the ClosedXML library. Everything works perfectly until I have to export large Excel files,
then things go south and I receive the following exception:
System.IO.IsolatedStorage.IsolatedStorageException: Unable to determine the identity of domain.
at System.IO.IsolatedStorage.IsolatedStorage._GetAccountingInfo(Evidence evidence, Type evidenceType, IsolatedStorageScope fAssmDomApp, Object& oNormalized)
at System.IO.IsolatedStorage.IsolatedStorage.GetAccountingInfo(Evidence evidence, Type evidenceType, IsolatedStorageScope fAssmDomApp, String& typeName, String& instanceName)
at System.IO.IsolatedStorage.IsolatedStorage._InitStore(IsolatedStorageScope scope, Evidence domainEv, Type domainEvidenceType, Evidence assemEv, Type assemblyEvidenceType, Evidence appEv, Type appEvidenceType)
at System.IO.IsolatedStorage.IsolatedStorage.InitStore(IsolatedStorageScope scope, Type domainEvidenceType, Type assemblyEvidenceType)
at System.IO.IsolatedStorage.IsolatedStorageFile.GetStore(IsolatedStorageScope scope, Type domainEvidenceType, Type assemblyEvidenceType)
at MS.Internal.IO.Packaging.PackagingUtilities.ReliableIsolatedStorageFileFolder.GetCurrentStore()...
So, after some research, I found some info on how to address the above exception, which is detailed in the questions below:
EPPlus 2.9.0.1 throws System.IO.IsolatedStorage.IsolatedStorageException when trying to save a file bigger than ~1.5 MiB from a SSIS package
Unable to determine the identity of domain using System.IO.Packaging
Isolated Storage Exception: Unable to determine the identity of domain
As suggested in the answers to the questions above, I made sure that all of the classes in my custom assembly inherit from MarshalByRefObject and are marked as Serializable.
I have also added a custom assembly ResolveEventHandler.
Saying that, because I am loading the assembly from a file at runtime (this is done because I do not have the option of adding it to the GAC), I am having trouble figuring out how to correctly implement the new domain and its resolve event. When I execute the code below, I recieve following error:
repository.GetWorkFlows() is called:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''System.MarshalByRefObject' does not contain a definition for 'GetWorkFlows''
Code:
using System;
using System.Data.SqlClient;
using System.Reflection;
namespace ST_1736b3ab1e134250a6c05bffb44d449f
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public Assembly CustomResolveEventHandler(object sender, ResolveEventArgs args)
{
Assembly assembly = null;
try
{
assembly = LoadAssembly(args, assembly);
}
catch (Exception exception)
{
Dts.Log(exception.ToString(), 0, new byte[0]);
throw;
}
Dts.Log("Exiting CurrentDomain_AssemblyResolve", 0, new byte[0]);
return assembly;
}
public Assembly LoadAssembly(ResolveEventArgs args, Assembly assembly)
{
Dts.Log(string.Format("Entering CurrentDomain_AssemblyResolve with args.Name [{0}]", args.Name), 0, new byte[0]);
string referencedAssembliesFilePath = Dts.Variables["$Package::referencedAssembliesFilePath"].Value.ToString();
var assemblyName = string.Format("{0}.dll", args.Name.Split(',')[0]);
Dts.Log("Assembly Name: " + assemblyName, 0, new byte[0]);
var assemblyFilePath = System.IO.Path.Combine(referencedAssembliesFilePath, assemblyName);
if (System.IO.File.Exists(assemblyFilePath))
{
Dts.Log(string.Format("Currently Loading [{0}]", assemblyFilePath), 0, new byte[0]);
assembly = Assembly.LoadFile(assemblyFilePath);
}
else
{
Dts.Log(string.Format("Could Not Find Assembly File [{0}].", assemblyFilePath), 0, new byte[0]);
}
return assembly;
}
public void Main()
{
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory.ToString();
Evidence evidence = new Evidence();
evidence.AddHostEvidence(new Zone(System.Security.SecurityZone.MyComputer));
AppDomain domain = AppDomain.CreateDomain("SeparateDomain", evidence, setup);
separateDomain.AssemblyResolve += new ResolveEventHandler(CustomResolveEventHandler);
const string referencedAssemblyName = "SSISDataExportManager";
string query = Dts.Variables["$Package::queryGetDataExportWorkFlowTasks"].Value.ToString();
dynamic repository = separateDomain.CreateInstanceAndUnwrap(referencedAssemblyName, referencedAssemblyName + "." + "DataExportManagerRepository");
using (SqlConnection connection = (SqlConnection)Dts.Connections["DbConnection"].AcquireConnection(Dts.Transaction))
{
if (connection.State == System.Data.ConnectionState.Closed) connection.Open();
//***Exception thrown here***
dynamic workflows = repository.GetWorkFlows(connection, query, 60);
dynamic factory = separateDomain.CreateInstanceAndUnwrap(referencedAssemblyName, "DataExportWorkflowSessionFactory");
dynamic session = factory.CreateSession(workflows);
session.Execute(connection);
}
Dts.TaskResult = (int)ScriptResults.Success;
}
#region ScriptResults declaration
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
}
}
I assume that this is because I need to explicitly cast to the types in my custom assembly, but again, I cannot do this due to it begin dynamically loaded.
What am I missing? Is there another way to do this, or is this even possible?

xaml parse exception issue only on win7

I have an issue where I got error
id 1000 (KERNELBASE.dll)
and
error id 1026 System.IO.FileNotFoundException
When I try to run my program on Win 7 (witch had run fine before), but it runs perfectly on win 8/8.1/10. I am running .Net Framework 4.5.
I had been trying to deleting the code, but then the error just appears on other lines off my code and thats keeps going on, so does anyone know how to fix it or know how to find out what actually are causing that issue
Binding Failure occurred
Message : Managed Debugging Assistant ' Binding Failure ' has detected a problem in ' F: \ Omini \ Omini Dækberegner.exe ' .
Additional information : the assembly with the display name ' PresentationFramework.Aero2 ' could not be loaded into the binding context '
C#
InitializeComponent();
bredebox_nu.Focus();
textBoxes = new List<TextBox> { bredebox_nu, profilbox_nu, Fælgestr_nu, bredebox_ny, profilbox_ny, Fælgestr_ny, oprofilbox, obredebox, oFælgestr };
win.SourceInitialized += new EventHandler(win_SourceInitialized);
List<biler> items = new List<biler>();
the other error
System.Windows.Markup.XamlParseException occurred
HResult=-2146233087
Line Number = 616
Line Position = 48
Message = ' There were triggered an exception at setting the property ' System.Windows.FrameworkElement.Style ' . ' Line number ' 616 ' and line position ' 48' .
Source = Presentation Framework
Stack Trace :
by System.Windows.Markup.WpfXamlLoader.Load ( XamlReader xamlReader , IXamlObjectWriterFactory writer factory , Boolean skipJournaledProperties , Object rootObject , XamlObjectWriterSettings settings , Uri baseUri )
by System.Windows.Markup.WpfXamlLoader.LoadBaml ( XamlReader xamlReader , Boolean skipJournaledProperties , Object rootObject , XamlAccessLevel access level , Uri baseUri )
by System.Windows.Markup.XamlReader.LoadBaml ( Stream stream , ParserContext parserContext , Object parent , Boolean close stream)
by System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
by Omini_Tires_And_rims.MainWindow.InitializeComponent() i C:\Users\Sindakewin\documents\visual studio 2015\Projects\omini_dækberegner\omini_dækberegner\MainWindow.xaml:linje 1
by Omini_Tires_And_rims.MainWindow..ctor() i C:\Users\Sindakewin\documents\visual studio 2015\Projects\omini_dækberegner\omini_dækberegner\MainWindow.xaml.cs:linje 210
InnerException:
FileName=PresentationFramework.Aero2, PublicKeyToken=31bf3856ad364e35
FusionLog ==== state information prior binding ===
LOG: Display Name = PresentationFramework.Aero2, PublicKeyToken = 31bf3856ad364e35
(Partial)
WRN: There was delivered about a partial binding for assembly:
WRN: Assemblyname: PresentationFramework.Aero2, PublicKeyToken = 31bf3856ad364e35 | Domain ID: 1
WRN: A partial binding Occurs tabloid is only given part of assemblyens display name.
WRN This may cause the binder inputting a wrong assembly.
WRN: It is recommended to give up fully specified text ID for the Assembly,
WRN: consisting of the simple name, version, culture and token for the public key.
WRN: For more information and common solutions to this problem in the white paper http://go.microsoft.com/fwlink/?LinkId=109270.
LOG: Appbase = file: /// F: / Omini /
LOG: First PrivatePath = NULL
Calling assembly: Presentation Framework, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35.
LOG: This binding initiates in loadingcontex default.
LOG: User application configuration file: F: \ Omini \ Omini Dækberegner.exe.Config
LOG: User host configuration file:
LOG: User machineconfigurationsfile from C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ config \ machine.config.
LOG: Policy not applied to reference at this time (private, custom, partial, or location-based assemblybinding).
LOG: Attempting to download new URL file: /// F: /Omini/PresentationFramework.Aero2.DLL.
LOG: Attempting to download new URL file: /// F: /Omini/PresentationFramework.Aero2/PresentationFramework.Aero2.DLL.
LOG: Attempting to download new URL file: /// F: /Omini/PresentationFramework.Aero2.EXE.
LOG: Attempting to download new URL file: /// F: /Omini/PresentationFramework.Aero2/PresentationFramework.Aero2.EXE.
)
HRESULT = -2147024894
Message = The file or the assembly ' PresentationFramework.Aero2 , PublicKeyToken = 31bf3856ad364e35 ' or one of its dependencies could not be loaded . The specified file was not found.
Source = mscorlib
StackTrace:
by System.Reflection.RuntimeAssembly._nLoad (AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly location hint, Stack Crawl Mark & ​​stack field, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
by System.Reflection.RuntimeAssembly.nLoad (AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly location hint, Stack Crawl Mark & ​​stack field, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
by System.Reflection.RuntimeAssembly.InternalLoadAssemblyName (AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, Stack Crawl Mark & ​​stack field, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
by System.Reflection.Assembly.Load (AssemblyName assemblyRef)
by System.Windows.Baml2006.Baml2006SchemaContext.ResolveAssembly (BamlAssembly bamlAssembly)
by System.Windows.Baml2006.Baml2006SchemaContext.ResolveBamlTypeToType (BamlType bamlType)
by System.Windows.Baml2006.Baml2006SchemaContext.ResolveBamlType (BamlType bamlType, int16 typeid)
by System.Windows.Baml2006.Baml2006SchemaContext.GetXamlType (int16 typeid)
by System.Windows.Baml2006.Baml2006Reader.Process_ElementStart ()
by System.Windows.Baml2006.Baml2006Reader.Process_OneBamlRecord ()
by System.Windows.Baml2006.Baml2006Reader.ReadObject (KeyRecord record)
by System.Windows.ResourceDictionary.CreateObject (KeyRecord key)
by System.Windows.ResourceDictionary.OnGettingValue (Object key, Object & value, Boolean & canCache)
by System.Windows.ResourceDictionary.OnGettingValuePrivate (Object key, Object & value, Boolean & canCache)
by System.Windows.ResourceDictionary.GetValueWithoutLock (Object key, Boolean & canCache)
by System.Windows.ResourceDictionary.GetValue (Object key, Boolean & canCache)
by System.Windows.DeferredResourceReference.GetValue (Base Value Source Internal value source)
by System.Windows.DependencyPropertyChangedEventArgs.get_NewValue ()
by System.Windows.Controls.Control.OnTemplateChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
by System.Windows.DependencyObject.OnPropertyChanged (DependencyPropertyChangedEventArgs e)
by System.Windows.FrameworkElement.OnPropertyChanged (DependencyPropertyChangedEventArgs e)
by System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
by System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
by System.Windows.StyleHelper.ApplyStyleOrTemplateValue(FrameworkObject fo, DependencyProperty dp)
by System.Windows.StyleHelper.InvalidateContainerDependents(DependencyObject container, FrugalStructList`1& exclusionContainerDependents, FrugalStructList`1& oldContainerDependents, FrugalStructList`1& newContainerDependents)
by System.Windows.StyleHelper.DoStyleInvalidations(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle)
by System.Windows.StyleHelper.UpdateStyleCache(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle, Style& styleCache)
by System.Windows.FrameworkElement.OnStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
by System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
by System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
by System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
by System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
by System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
by System.Windows.Baml2006.WpfKnownMemberInvoker.SetValue(Object instance, Object value)
by MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(XamlMember member, Object obj, Object value)
by MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value)
InnerException:
Xaml <GridViewColumn Header="Model" Width="140" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="Txt" Text="{Binding Model}" Foreground="#FF00FB0B" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
i removed PresentationFramework.Aero2 from the references in visual studio and replaced it with PresentationFramework.Aero and deleted some of the themes and replaced the namespaces and now it runs fine on win 7 and win vista without any issues

Entity Framework ExecuteStoreQuery fails on deployed systems

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

Intermittent errors while de-serializing object from XML

I have a program that takes objects stored as XML in a database (basicly a message queue) and de-serializes them. Intermittently, I will get one of the following errors:
System.Runtime.InteropServices.ExternalException: Cannot execute a program. The command being executed was "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe" /noconfig /fullpaths #"C:\Documents and Settings\useraccount\Local Settings\Temp\lh21vp3m.cmdline".
at System.CodeDom.Compiler.Executor.ExecWaitWithCaptureUnimpersonated(SafeUserTokenHandle userToken, String cmd, String currentDir, TempFileCollection tempFiles, String& outputName, String& errorName, String trueCmdLine)
at System.CodeDom.Compiler.Executor.ExecWaitWithCapture(SafeUserTokenHandle userToken, String cmd, String currentDir, TempFileCollection tempFiles, String& outputName, String& errorName, String trueCmdLine)
at Microsoft.CSharp.CSharpCodeGenerator.Compile(CompilerParameters options, String compilerDirectory, String compilerExe, String arguments, String& outputFile, Int32& nativeReturnValue, String trueArgs)
at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames)
at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources)
at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, String[] sources)
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromSource(CompilerParameters options, String[] sources)
at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence)
at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type)
.....
Or I'll get this one:
System.InvalidOperationException: Unable to generate a temporary class (result=1).
error CS0016: Could not write to output file 'c:\Documents and Settings\useraccount\Local Settings\Temp\nciktsd7.dll' -- 'Could not execute CVTRES.EXE.'
at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence)
at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type)
....
The program process thousands of messages a day successfully, but I only get these errors maybe 2 or 3 times a day. They don't appear to be correlated to any specific kind of message, just completely random.
Any idea what causes those errors and how to fix it?
ETA - Here's the code that is causing the errors, in case that helps:
public class MessageContextBuilder<T> where T : MessageContextBase
{
private static IDictionary<string, XmlSerializer> SerializerCache { get; set; }
public ILog Logger { get; set; }
public MessageContextBuilder() {
if (SerializerCache == null) SerializerCache = new Dictionary<string, XmlSerializer>();
Logger = LogContextManager.Context.GetLogger<MessageContextBuilder<T>>();
}
public T BuildContextFromMessage(IEmailQueueMessage msg) {
XmlSerializer serializer = GetSerializer(typeof(T));
XmlReader r = XmlReader.Create(new StringReader(msg.MessageDetails));
if (serializer.CanDeserialize(r)) {
T rval = (T)serializer.Deserialize(r);
rval.EmailAddress = msg.EmailAddress;
rval.LocaleID = msg.LocaleID;
rval.StoreID = msg.StoreID;
rval.MessageID = msg.UniqueKey;
return rval;
} else {
throw new ArgumentException("Cannot deserialize XML in message details for message #" + msg.UniqueKey);
}
}
public XmlSerializer GetSerializer(Type t) {
if (!SerializerCache.ContainsKey(t.FullName)) {
SerializerCache.Add(t.FullName, new XmlSerializer(t)); // Error occurs here, in XmlSerializer constructor, intermittently
}
return SerializerCache[t.FullName];
}
}
You can pre-create serializers: http://msdn.microsoft.com/en-us/library/bk3w6240%28v=VS.100%29.aspx Just give it a try. The next canonical candidate for such problems is your virus scanner. Your tool is writing to disc while creating serializers. I have seen virus scanner producing all kind of strange errors in such situations.
XmlSerializer is supposed to be thread safe.
Even if that's the case, you can notice the behavior you are getting is in both cases failing at: XmlSerializer..ctor(Type type)
Given that, it seriously look like a multi-threading limitation trying to create serializers.
I suggest to take this code you have:
public XmlSerializer GetSerializer(Type t) {
if (!SerializerCache.ContainsKey(t.FullName)) {
SerializerCache.Add(t.FullName, new XmlSerializer(t)); // Error occurs here, intermittently
}
return SerializerCache[t.FullName];
}
And implement a lock on the Add. This way you are only creating 1 serializer at a time. The hit is small if you aren't processing tons of different types.
Note that you need the lock anyway, as the way it is you could get duplicate exceptions when 2 types try to be added at the same time.
static object serializerCacheLock = new object();
public XmlSerializer GetSerializer(Type t) {
if (!SerializerCache.ContainsKey(t.FullName))
lock(serializerCacheLock)
if (!SerializerCache.ContainsKey(t.FullName)) {
SerializerCache.Add(t.FullName, new XmlSerializer(t));
}
return SerializerCache[t.FullName];
}
If the above still isn't enough, I'd try with a read/write lock on serializer constructor vs. serializers usage. Line of thought being that maybe the multi-threading issue is worth than 2 ctors running at the same time.
All above is a Huge guess, but if it were me I'd definitely confirm is not that.
For the first error (cannot execute a program), you might be running into the same XmlSerializer bug that we ran into. It turns out XmlSerlializer throws that exception when Directory.CurrentDirectory is set to a folder that no longer exists.
Our specific situation is different than yours, but I'll give the details in case it helps shed light on what might be happening for you, or it helps anyone else. In our case, a small number of our customers would get that error after launching our WinForms application directly from the installer, i.e. they chose the "run now" option after installing or upgrading. (Unclear why it happened to some but not others). What we suspect is happening is that our installer (InstallAware) occasionally starts our application with the current directory set to a folder that no longer exists, or is about to be deleted. To test this theory, I wrote a test app which simulates launching from the installer:
string dir = #"C:\Users\me\Documents\Temp\WillBeDeleted";
Directory.CreateDirectory(dir);
Directory.SetCurrentDirectory(dir);
Process.Start(#"C:\Program Files (x86)\...\our.exe");
Directory.SetCurrentDirectory(#"C:\"); // otherwise, won't be able to delete
Directory.Delete(dir);
Sure enough, as soon as the launched application created a new instance of XmlSerializer, the exception would be thrown. I put in trace statements to show the result of GetCurrentDirectory(), and indeed it was set to the WillBeDeleted folder. The fix was to SetCurrentDirectory to a valid location during application initialization, before any serialization took place.
This is a sign that you are not caching your serialisers which is not good at all => it leads to memory leak and I suspect you will experience this.
Remember that .NET generates code and compiles them into assemblies every time you create a serialiser.
Always create your serialisers and then cache them.
Here is a sample:
public class SerialiserCache
{
private static readonly SerialiserCache _current = new SerialiserCache();
private Dictionary<Type, XmlSerializer> _cache = new Dictionary<Type, XmlSerializer>();
private SerialiserCache()
{
}
public static SerialiserCache Current
{
get { return _current; }
}
public XmlSerializer this[Type t]
{
get
{
LoadIfNecessary(t);
return _cache[t];
}
}
private void LoadIfNecessary(Type t)
{
// double if to prevent race conditions
if (!_cache.ContainsKey(t))
{
lock (_cache)
{
if (!_cache.ContainsKey(t))
{
_cache[t] = new XmlSerializer(typeof(T));
}
}
}
}
}

Load independent assembly in a another App Domain

simple question, probably easy for you to answer.
I have a dll named "MigrationSteps.dll" in the same output folder of my application.
What I want to do, is to load this assembly in a new AppDomain and execute a method on an instance of a class inside this DLL.
Here's my code
string migrationStepsDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MigrationSteps.dll");
AppDomainSetup appDomainSetup = new AppDomainSetup() { PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory };
Evidence evidence = AppDomain.CurrentDomain.Evidence;
AppDomain appDomain = AppDomain.CreateDomain("MigrationAppDomain", evidence, appDomainSetup);
//NOT WORKING
Assembly assembly = appDomain.Load(#"C:\Output\Debug\OptimeToolbench\MigrationSteps.dll");
//WORKING
Assembly assembly = Assembly.LoadFrom(#"C:\Output\Debug\OptimeToolbench\MigrationSteps.dll"); ****works.
//This part works well
Type type = assembly.GetType("MigrationSteps.Foo");
object foo = Activator.CreateInstance(type);
MethodInfo methodInfo = type.GetMethod("HelloWorld");
methodInfo.Invoke(foo, null);
AppDomain.Unload(appDomain);
Everytime the line indicated as not working throws a
FileNotFoundException
.
Why's that ?
Thanks for you time.
Add "C:\Output\Debug\OptimeToolbench\" to the PrivateBinPath of the AppDomain. Also do not pass in the file name, pass in the assembly name -- I'm assuming that would be MigrationSteps.
appDomain.Load(string) takes in an assembly name (the strong-name) - NOT the path of where the file is on disk!

Categories

Resources