How to move DLL dependencies to another folder - wpf

My WPF application is using MahApps.Metro, it require the MahApps.Metro.dll and the system.windows.interactivity.dll. How do I shift them to a folder, for example folder bin and still make them work? If I just shift them, the application would not start at all. Please help!

It would probably be best if you left all these DLL files alone and let the .NET Framework sort it all out. If you have to move them anyway, you may edit the properties of a reference and set the Copy Local property to false, so it won't output the DLL file when compiling.
In you App.cs file (assuming you're using C#) add the following:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if (args.Name.StartsWith("MahApps.Metro"))
{
System.IO.BinaryReader stream = new BinaryReader(new FileStream("bin/MahApps.Metro.dll", FileMode.Open));
byte[] assembly = stream.ReadBytes((int)stream.BaseStream.Length);
return Assembly.Load(assembly);
}
return null;
}
Edit the above code to suit your needs so that it will work exactly the way you want it to.
You will have to verify that all the DLL files you're using are the same version as the one being targeted, or .NET will throw an exception. Also, the DLL file may not exist and loading the stream might raise some problems if it is used on a network location. All in all it is likely to work, but it's probably not worth the trouble.

Related

How can I deploy the .dna file from ExcelDna?

I am trying to create an Excel (2007) Add-in that will respond to PivotTable changes, using this code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Excel.Worksheet sh = this.Application.ActiveSheet;
sh.PivotTableUpdate += new
Excel.DocEvents_PivotTableUpdateEventHandler(sh_PivotTableUpdate);
}
void sh_PivotTableUpdate(Excel.PivotTable TargetPivotTable)
{
MessageBox.Show("sh_PivotTableUpdate event fired");
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
Once the .dll was created, deploying it/generating an .xll file became a challenge; I used this post for guidance there, and do now have an .xll file.
I was able to add this to the Excel spreadsheet (.xlsx file) that I want to respond to the code (via File > Excel Options > Add-Ins > Go... > Browse), but get this err msg on adding the .xll file:
I did see that there is a *.dna file here \packages\ExcelDna.AddIn.0.33.9\content\ExcelDna-Template.dna
...but making a copy of that file and changing the name of it to [projectName].dna (Excel2010AddInForRptRunner-AddIn.dna), and then copying it to the same location as the .xll file with the .xlsx file is not the solution (no pun intended). Changing the PivotTable manually does not fire the event/I see no "sh_PivotTableUpdate event fired" message.
The .dna file does reference the .dll like so:
<ExternalLibrary Path="Excel2010AddInForRptRunner.dll" LoadFromBytes="true" Pack="true" />
So what do I need to do to resolve the err msg I get and get the .xll file to be accepted by the spreadsheet so that its code will run and the PivotTableUpdate event handler is fired?
There are two issues that I see in your snippet:
The first is that you seem to have mixed the VSTO Office stuff with Excel-DNA (I see this from the ThisAddIn_... code, which relates to VSTO). These don't mix at all - you can't use Excel-DNA inside a VSTO add-in project. Any namespaces that start with Microsoft.Office.Tools... indicate there is a problem. This might happen is you start with an "Office Add-In" or "Excel Add-in" as your project type.
There is a also mess in your project related to the NuGet packages - somehow the output files are inside the package directory, or the package directory has been overwritten or changed somehow. You should not have to ever edit anything under packages\...
If everything is correct, then the files you are interested in will be found in bin\Debug and bin\Release under your project directory. Usually you can redistribute only the single ...-AddIn-packed.xll file (which you can also rename if you want to).
I suggest you make a new "Class Library" project (not an Office add-in or anything like that) and install the ExcelDna.AddIn package again. Then follow the instructions in the ReadMe file that pops up to make a simple add-in with a single UDF function, and check that this runs and can be debugged and deployed correctly.
After you have that working perfectly, you can incorporate access the COM object model into your add-in by following these two steps:
Add a reference to the Excel Interop assemblies (Microsoft.Office.Interop.Excel and Office), either directly via "Add Reference", or by installing the ExcelDna.Interop assembly from NuGet.
Get hold of the right Application root object by calling ExcelDnaUtil.Application. The object returned can be cast to a Microsoft.Office.Interop.Excel.Application and used to get to the whole COM object model from there, and hook up your event handlers etc.

Why is this DLL DevExpress.ExpressApp loading?

I am trying to deploy a plugin to a customer.
We use MEF, import, export attributes. I use the Export and the client imports it
My application uses DevExpress XtraGrid, XtraEditors and many other DevExpress DLL's(see screenshot), System.Data.Services.
Inspite of providing all these required DLL's and many of their dependencies, the plugin still seems to be requiring DevExpress.ExpressApp. DevExpress.ExpressApp and all its other dependencies are definitely not needed.
Since the client kept complaining that they have a FileNotFound exception, I decided to make a test project to import my own plugin. This is my test code to test the clients theory that he is getting is the following.
System.IO.FileNotFoundException: Could not load file or assembly 'DevExpress.ExpressApp.v14.2, Version=14.2.7.0,
Our Plugin
[Export(typeof (ISomething))]
public class MyClass : ISomething
{
}
TESTER
class Program
{
[ImportMany]
public IEnumerable<ISomething> Somethings { get; set; }
static void Main(string[] args)
{
var rp = new Program();
rp.Run();
}
public void Run()
{
Compose();
}
public void Compose()
{
try
{
AppDomain.CurrentDomain.FirstChanceException += FirstChanceHandler;
AggregateCatalog aggregatecatalogue = new AggregateCatalog();
aggregatecatalogue.Catalogs.Add(new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory));
CompositionContainer container = new CompositionContainer(aggregatecatalogue);
CompositionBatch batch = new CompositionBatch();
batch.AddPart(this);
container.Compose(batch);
}
catch (Exception ex)
{
throw ex;
}
}
static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
{
System.Text.StringBuilder msg = new System.Text.StringBuilder();
msg.AppendLine(e.Exception.GetType().FullName);
msg.AppendLine(e.Exception.Message);
System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();
msg.AppendLine(st.ToString());
msg.AppendLine();
String desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string logFilePath = String.Format("{0}\\{1}", desktopPath, "logfile.txt");
System.IO.File.AppendAllText(logFilePath, msg.ToString());
}
Sure enough, I saw in the output window and found out that it was indeed loading this DLL and some of the dependencies related to ExpressApp from GAC.
Question: How do I figure out where and why is ExpressApp needed?
I can simply just deliver the DLL but then it goes on and on about a TON of dependencies which I have clue why they would be needed.
there are tools for checking managed assembly dependencies. The MS Windows SDK contains the ildasm.exe utility. Chances are you already have it installed in:
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\ildasm.exe
When I had a similar problem (it was dll version mismatch) I have also used cygwin's 'grep' from command line to search for the missing dependency string across all DX and our custom assemblies to locate the actual .dll file referencing the missing dependency dll version. Then opened it in ildasm.exe and double clicked on the MANIFEST tree node. There I've seen the reference to the .dll version I didn't have.
You may follow the same steps to try to track the missing dependency. Run the "DevExpress.ExpressApp" string search against all DX dlls in your project's bin directory then if result is found, open the reported file with ildasm.exe
Note, most probably you don't have 'grep' from the https://www.cygwin.com/ package installed, so use the string search utility which is available to you.
There are also other 3rd party tools for checking dll dependencies but those have to be installed separately, while ildasm.exe is a part of Windows SDK. See this question's answers for other tools refs:
How do I determine the dependencies of a .NET application?
UPDATE:
if you don't have all your DX libs in the bin folder because your app is a plugin and uses DX libs directly from GAC, then you may search for DevExpress.ExpressApp references right in the DX installation folder, in my case:
C:\Program Files (x86)\DevExpress 15.2\Components\Bin\Framework
I've copied the above folder contents to a temp folder, removed all locale subfolders as well as all DevExpress.ExpressApp.* dlls and then ran a command:
grep -nr "DevExpress.ExpressApp"
which produced the following results:
Binary file DevExpress.EasyTest.v15.2.dll matches
Binary file DevExpress.Persistent.Base.v15.2.dll matches
Binary file DevExpress.Persistent.BaseImpl.EF.v15.2.dll matches
Binary file DevExpress.Persistent.BaseImpl.v15.2.dll matches
Binary file DevExpress.Workflow.Activities.v15.2.Design.dll matches
Binary file DevExpress.Workflow.Activities.v15.2.dll matches
See if any of the above dlls is used by either your plugin or the host app where the plugin is to be deployed.
HTH

Visual Studio 2010 Project - can't adjust the relative path

I have a Windows Forms project. I have a Resources folder and I wan to use the files there using relative path. Here is a printscreen of my project tree
As you may see I have folder UserControls where I have FileExplorer.cs it contains aa openFileDialog + pictureBox. I use this control in some of my forms which are in Forms folder. The case is that in Resources folder I have this T380.jpg image that I want to load by default but for now I can do it only by inserting the full path to it. Here is my code where I try to load the image:
private void FileExplorer_Load(object sender, EventArgs e)
{
pictureBox1.ImageLocation = #"ShoesUnlimitedAdmin\Resources\T380.jpg";
pictureBox1.Load();
}
I use the Load event of the user control to load my image but it only works when I set the full path to the image like C:\\... and so. How can I point to the Resources folder of the project using relative path?
If these images are small then favor adding them as resources in the executable file so you can use Properties.Resources in your code and don't have to deploy the files on the user's machine. Use Project + Properties, Resources. Click the arrow on the "Add Resource" button and select Add Existing File.
If they are big (more than a couple of megabytes) then you'll indeed want to deploy them as separate files. You can find them back by using the location of the EXE program, here's a helper method, spelled out for clarity:
public static string GetResourcePath(string filename) {
string exepath = System.Reflection.Assembly.GetEntryAssembly().Location;
string exedir = System.IO.Path.GetDirectoryName(exepath);
string resdir = System.IO.Path.Combine(exedir, "Resources");
return System.IO.Path.Combine(resdir, filename);
}

Recomposition issue with a Modular Silverlight application

I'm working with a Silverlight 4 application and we use Prism/MEF to build modules.
Each module is created as a Silverlight application. We then use a ModulesCatalog.xaml file to control how the modules are loaded.
We had 6 modules and everything was working perfect.
This week we're adding a 7th module and we just have the new Silverlight application created. We setup the module class as follows.
[ModuleExport(typeof(InsightModule))]
public class InsightModule : IModule
{
}
Then we added an entry to our ModulesCatalog file.
Now when we run the application we start getting all types of recomposition errors. The stack shows this.
at System.ComponentModel.Composition.CompositionResult.ThrowOnErrors(AtomicComposition atomicComposition)
at System.ComponentModel.Composition.Hosting.ExportProvider.OnExportsChanging(ExportsChangeEventArgs e)
at System.ComponentModel.Composition.Hosting.CatalogExportProvider.OnCatalogChanging(Object sender, ComposablePartCatalogChangeEventArgs e)
at System.ComponentModel.Composition.Hosting.ComposablePartCatalogCollection.OnChanging(Object sender, ComposablePartCatalogChangeEventArgs e)
at System.ComponentModel.Composition.Hosting.AggregateCatalog.OnChanging(ComposablePartCatalogChangeEventArgs e)
at System.ComponentModel.Composition.Hosting.ComposablePartCatalogCollection.RaiseChangingEvent(Lazy`1 addedDefinitions, Lazy`1 removedDefinitions, AtomicComposition atomicComposition)
at System.ComponentModel.Composition.Hosting.ComposablePartCatalogCollection.Add(ComposablePartCatalog item)
at Microsoft.Practices.Prism.MefExtensions.Modularity.MefModuleInitializer.CreateModule(ModuleInfo moduleInfo)
at Microsoft.Practices.Prism.Modularity.ModuleInitializer.Initialize(ModuleInfo moduleInfo)
Then you get the standard output.
The exception message was: The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced multiple composition errors, with 57 root causes. The root causes are provided below. Review the CompositionException.Errors property for more detailed information.
1) Change in exports prevented by non-recomposable import 'EyeCue.Common.AboutEyeCueView.ViewModel (ContractName="EyeCue.Common.AboutEyeCueVM")' on part 'EyeCue.Common.AboutEyeCueView'.
WHat's puzzling is why none of the other 6 modules caused this problem but now all of a sudden, this new module without anything going on in it is causing a recomposition of the catalogue. It makes no sense.
Plus I have ctor's that import in some cases and that's they what I had to do to get things to work, so this is not as simple as going to setting the Allow Recomposition attribut.
I've downloaded the VisualMFX but this line of code throws an Object Not initialized exception.
this.compositionInfo = new CompositionInfo(_aggregateCatalog, _container);
Both _aggregateCatalog & _container are not null when this happens.
In summary, why would a 7th module all of a sudden start causing recomposition? Especially when the module isn't even defining any exports or imports at this time? That leads to how do we stop it to address this problem?
The issue turned out to be a reference to an assembly which had Copy Local set to true.
Making sure all references which are also set in the main application assembly were set to Copy Local = false seems to resolved the problem.

silverlight 4, dynamically loading xap modules

I know that it is possible to load xap modules dynamically using Prism or MEF framework. However, I'd like not to use those frameworks; instead load my xap files manually. So, I created the following class (adapted from internet):
public class XapLoader
{
public event XapLoadedEventHandler Completed;
private string _xapName;
public XapLoader(string xapName)
{
if (string.IsNullOrWhiteSpace(xapName))
throw new ArgumentException("Invalid module name!");
else
_xapName = xapName;
}
public void Begin()
{
Uri uri = new Uri(_xapName, UriKind.Relative);
if (uri != null)
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += onXapLoadingResponse;
wc.OpenReadAsync(uri);
}
}
private void onXapLoadingResponse(object sender, OpenReadCompletedEventArgs e)
{
if ((e.Error == null) && (e.Cancelled == false))
initXap(e.Result);
if (Completed != null)
{
XapLoadedEventArgs args = new XapLoadedEventArgs();
args.Error = e.Error;
args.Cancelled = e.Cancelled;
Completed(this, args);
}
}
private void initXap(Stream stream)
{
string appManifest = new StreamReader(Application.GetResourceStream(
new StreamResourceInfo(stream, null), new Uri("AppManifest.xaml",
UriKind.Relative)).Stream).ReadToEnd();
XElement deploy = XDocument.Parse(appManifest).Root;
List<XElement> parts = (from assemblyParts in deploy.Elements().Elements()
select assemblyParts).ToList();
foreach (XElement xe in parts)
{
string source = xe.Attribute("Source").Value;
AssemblyPart asmPart = new AssemblyPart();
StreamResourceInfo streamInfo = Application.GetResourceStream(
new StreamResourceInfo(stream, "application/binary"),
new Uri(source, UriKind.Relative));
asmPart.Load(streamInfo.Stream);
}
}
}
public delegate void XapLoadedEventHandler(object sender, XapLoadedEventArgs e);
public class XapLoadedEventArgs : EventArgs
{
public Exception Error { get; set; }
public bool Cancelled { get; set; }
}
The above code works fine; I can load any xap the following way:
XapLoader xapLoader = new XapLoader("Sales.xap");
xapLoader.Completed += new XapLoadedEventHandler(xapLoader_Completed);
xapLoader.Begin();
Now, I have a UserControl called InvoiceView in the Sales.xap project, so I would like to instantiate the class. In the current project (Main.xap) I added reference to Sales.xap project, however, since I load it manually I set "Copy Local = False". But when executed, the following code throws TypeLoadException:
Sales.InvoiceView view = new Sales.InvoiceView();
It seems the code can't find InvoiceView class. But I checked that XapLoader's initXap() method was successfully executed. So why the code can't find InvoiceView class? Can someone help me with this problem?
This is based on the asker's self-answer below, rather than the question.
If you delete a project/module the output DLLs/XAP files do hang around. If you click the "show all files" button you will see some these left-over output files in your clientbin, bin and obj folders of related projects.
You can delete them individually from the project, or, when in doubt, search for all BIN and OBJ (e.g. using desktop explorer) and delete all those folders. The BIN/CLIENTBIN/OBJ folders will be recreated when needed (this the job that the "clean" option in Visual Studio should have done!)
Hope this helps.
Ok, I found the cause. The above code works. After creating a new silverlight project (Sales.xap) I happened to compile my solution once. Then I deleted App class in the Sales.xap and renamed default MainPage class to SalesView. However, no matter how many times I compile my solution, Visual Studio's development web server was loading the first version of Sales.xap (where from?), so my code couldn't find SalesView. In my host Asp.Net project I set development server's port to a different port number, and the problem gone. So the problem was with Visual Studio's development server. Apparently it is keeping compiled xap files in some temporary folder, and doesn't always update those xap files when source code changed.
What I do to avoid such problems when executing freshly compiled Silverlight is clear the browser cache, chrome even has a clear silverlight cache ;)
this XAP Cache phenomena is often due to the visual studio embedded web server (ASP.NET Development Server).
Just stop the occurence of this server and the cache will be cleared.
Start again your project and the latest build of your xap is called.

Resources