I am trying to build a release version of my vb.net project. My project references multiple dlls(I have both release and debug versions of these dlls). When I build my project, I set my configuration to Release (obviously), but do I also need to reference my release dlls or is referencing my debug dlls the same? I am simply curious to know if this makes any difference or not.
As far as calling the DLLs, it will work either way becuase PInvoke is being used to access the entry points (assuming that you are not trying to step-into the c code). PInvoke loads DLLs based on file name and loads functions based on entry point name (via GetProcAddress).
As far as what you ship, make SURE you don't ship the debug DLLs for a multitude of reasons.
For instance:
Debug code is slower.
Native debug DLLs will reference other debug libraries that machines without visual studio installed will not have.
Often, in debug code, there are assert() instructions and the like that you probably don't want in the shipping code.
Other stuff I forgot to mention
Related
I'm working on a C# project that is nearing release. As part of this, I have started building the project and testing it on another machine. This has revealed some odd problems. My biggest concern, though, is that my project is failing to run. I can do some basic things, but when I try to use my projects primary functionality it crashes. Using Visual Studio, I was able to determine the exception that was causing the crash.
Essentially, I'm getting a FileNotFoundException on the dll that contains most of my project's functional code. I'm not sure if I've made an error in adding the dll to my project, or if there's a problem in one of the files in the dll.
The dll was added as a reference using the Project -> Add Reerences feature of the user interface.
The dll contains three files which contain absolute file paths (these are for #import statements). Example follows.
#import "C:\Users\Me\Documents\Projects\MyProject\Delegates\bin\MyDelegate.tlb" raw_interfaces_only
My hang up is I'm not exactly sure what I'm doing wrong here. I suspect that those import statements are causing problems, but I'm not exactly sure how to fix them if they in fact are the problem. This is my first c#/c++ project so any help would be appreciated.
Adding the dll as a reference DOES NOT include the dll with your project--you are simply telling your project to use the library for your code. The dll will need to be installed on all computers that run your application, for your application to use the dll.
If the dll also uses three files (as you specified), then those files must also be included, and be installed in the expected path.
Presuming you have redistribution rights on the dll you mention, you can include the dll in your project. Be sure to set the "copy" property as "copy always" or "copy if newer" and change the reference to use the copy that ends up in you bin folder. Then you only need to be sure to include that dll and install it in the same folder as your application.
Using MS Visual Studio 2008, I created a C# library (let's call it main.dll) that relies on a second library (helper.dll). In the Debug version of main.dll, I set a reference to the debug version of helper.dll. But when I switch to build the Release version of main.dll, the output folder still includes the debug version of helper.dll. I do not see a way to select different versions of helper.dll for different build types. In C++, I could tell the linker what folder to get its files from, but I don't see a way to do that for C#.
The typical way of doing this is to have all of your projects in a single solution, and use project references between them. Then, when you build in Debug, all components will be built and referenced as debug - and likewise for Release.
Alternatively, you can use a single output folder for all your assemblies, reference each binary from there, and ensure that the build order is correct - so that your helper.dll is built to that folder before main.dll is built. This is more prone to failure, though, and requires a greater amount of manual maintenance.
When you switch from Debug to Release, Visual Studio switches from Debug to Release in the bin folder for the output.
Set the "Copy Always" property to true for main.dll. This will insure that it gets copied to the appropriate output folder, and is always referenced.
If the second library helper.dll is being built at the same time in the same solution, you can use a Project reference instead of referencing the .dll directly. Then, you can set up a solution-level configuration for Release mode, and build both projects in Release mode that way.
I was having trouble getting Visual Studio to build my project in release mode... it gives me errors about assemblies being the wrong format. Turns out some x86 assemblies were being referenced instead of x64 assemblies. Assemblies like PresentationCore, System.Data and so on.
Things I've tried:
Debug mode, any CPU builds fine.
Debug mode, x64 builds fine.
Release mode, any CPU fails
Release mode, x64 fails (this is the combination I'd LIKE to build my project in)
The issue comes when I try to remove the x86 reference and switch it to a x64 reference. Visual studio just adds the old x86 reference instead of the x64 reference. For example:
I remove the System.Data reference which is in C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll
I browse to and add C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Data.dll, but when I click on that System.Data reference, the path is CLEARLY still to the old dll and causes the same error to occur. This is happening with several other DLLs as well.
Does anyone know of a solution to this issue?
Assemblies like PresentationCore, System.Data and so on.
I hate to answer a question without seeing the error message. But this secondary evidence is enough to answer the question. First off, this is not an error, it is a warning. It looks like this:
warning CS1607: Assembly generation -- Referenced assembly 'System.Data.dll' targets a different processor
You'll also see one for mscorlib.dll. And PresentationCore.dll in a WPF project. What goes on here is that these assemblies are special, they are mixed-mode assemblies. In other words, they contain both native code and managed code. The native code is the trouble-maker, such an assembly can only be used in a project that targets the right processor flavor. If you mix it up then you get a BadImageFormatException at runtime.
This is not a real problem with .NET assemblies, your machine actually has two versions of these DLLs stored in the GAC. One that will be used if your program runs in 32-bit mode and another that is used in 64-bit mode. The CLR automatically picks the right one.
However, there is only one version of the reference assembly, the one that's stored in c:\windows\microsoft.net and that you pass to the compiler to read the metadata from. It is always the x86 version, there's no other one so don't bother looking for it. Again, this is not a problem, only the metadata of a reference assembly is used by the compiler, it doesn't execute any of its code. And the metadata does not depend on the bit-ness of the assembly.
Nevertheless, this all might be a problem if you create your own mixed-mode assembly. You can easily overlook the need to provide two versions. So what the compiler is fretting about is that it sees that you asked for an AnyCPU or x64 build of your project. But detects that the reference assembly can only work when you target x86. So it squeaks at you a bit, just a gentle reminder that there's some evidence that you're getting it wrong and that your program might fall over on a BadImageFormatException when you run it. It doesn't otherwise treat a framework reference assembly any different from your own reference assembly.
So, feature, not a bug. Just a warning that doesn't otherwise prevents your program from building. You can safely ignore the warning since you know that .NET has the right assembly available in the GAC at runtime. Notable is that .NET 4.0 doesn't have this problem, it uses very different reference assemblies that don't have the ILONLY metadata flag turned off.
Odd behavior. Turning "Generate serialization assembly" off under Build in project properties makes the project build just fine in release mode. Looking at this link reveals that this setting has to do with XML Serialization, which we don't even use in our entire solution.
Very weird. Still looking for an explanation for this question and behavior here.
Check out what your build configuration looks like. Sometimes this error happens because certain project on a solution is configured to be built in one build configuration, and not in another.
To do this:
Go to "Compile > Configuration administration..."
On "Active solutions configuration" select "Release" which is the configuration that is giving you problems.
On "Platform of active solutions" check "Any CPU". If "x64" is defined, you might be able to choose it too.
Look at the list of build projects. All projects needed for the solution must be marked with the correct values in "Configuration", "Platform" and have a "Compile" check.
In my case I have a sandcastle project that I uncheck most of the times, at least in debug mode, because it takes ages to compile. Sometimes it happens that one project does not have a configuration for the "Release" configuration and thus, when the build process tries to get its results, these don't exists (there is no DLL) and it throws an exception. In other situations, it might be that a project is forced to compile for x86 (or x64) and the rest is not, and so an error is thrown when trying to link other referencing projects to the proper version of the referenced DLLs.
Which version of .NET are you compiling for? If you can change the project to a later version of the .NET framework, that might help.
My VS2010 web project was generating these warnings too, and IIS was throwing a BadImageException. The Build/Configuration/Platform settings looked ok, but the Output window was showing that the dll was built in x64 folder for Any CPU configuration. Deleted all folders under bin and rebuilt. The warnings were gone and the BadImageException was gone.
I have a weird situation with some code that I inherited at work. Their application is a multi-project solution, with several of the solutions being (code) pieces of the MS Enterprise Library (not sure which version).
They also have an existing C++ (unmanaged) application which has a bunch of DLLs. One of these DLLs is built in a separate solution, both in 64-bit and 32-bit flavours.
The main application has a reference to this DLL, and calls a couple of static functions (I can see intellisense, even). I can compile and build the main application EXEs, but when I run it, I get an exception that this DLL from the unmanaged code (lets call it CPlusPlusCode.dll cannot be found:
FileNotFound Exception was unhandled: Could not load file or assembly 'CPlusPlusCode.dll' or one of its dependencies. The specified module could not be found.
I'm quite stumped, because I can compile the code, see intellisense for the imported classes, and dig into the DLL in the object browser. I even made sure there's a copy in the \bin\Debug folder (although I don't see why that would make a difference). This is for a Windows Forms application.
Also, if it matters, I had some build issues related to x86 vs. x64 for different projects; I think (hope?) that this is not related to that, but I solved that by using the Configuration Manager to build everything as x64.
Check the GAC, and if necessary you might need to add it or register the DLL there.
I had this problem with a project, it all works ok from Visual Studio and most of my times running the project locally on my machine. But because of the unmanaged code I needed specifically allow the project to be executed with correct permission levels.
So have a look in the manifest file, that enough permissions etc exist.
So I'm adding a "d" extension to my assembly name when building in debug mode. As far as I can tell the standard way to do this in C# is to edit the .csproj file and put in the following:
<PropertyGroup>
<AssemblyName Condition="'$(Configuration)' == 'V90 Debug'">$(AssemblyName)d</AssemblyName>
</PropertyGroup>
That has the desired effect, but now the darn project always rebuilds the output .dll, causing other projects that depend on it to relink, etc.. Without this change, I don't have any such problem.
So far increasing the verbosity of the project output hasn't helped.
Edit: An additional, important detail is that we're using names like "V90 Release", "V90 Debug", "V100 Release" etc.. for our configurations, so that we can target different versions of the Visual Studio runtime. I wrote a test app with the standard configuration names and found my problem doesn't happen in that case.
You are using an old standard in C/C++ development. The Big Difference with managed code is the absence of a linker. You used to configure the linker to use the "d" version of the library in the Debug build, the non-d version of the library in the Release build. That mechanism is completely absent in .NET, code in libraries are dynamically linked at runtime. Making the practically of having different names for different builds dramatically less.
One of the problems you'll encounter if you pursue this old strategy is that you'll have additional problems with the reference assemblies of a project. There is no decent way to use different names in different configurations. Dependent assemblies are listed in the Reference node of the project, this is a property of a project that is not configuration dependent. It is not impossible, you'll need a lot more Condition hacks to rename the reference assemblies. Build dependency checking is likely to be affected by this as well.
This is not actually necessary, the debug and release build of the assemblies will have the same metadata. But if you skip that, you'll now have a problem at runtime. The CLR will be told to use the wrong assembly name. Hacking around that is technically possible by hiding the assemblies in a sub-directory and using the AppDomain.AssemblyResolve event to load the correct one. You'll need a post-build event to rename and copy the assembly into this directory. This all gets ugly in a hurry when those assemblies have dependencies on other assemblies.
Long story short, your previous standard just isn't a good one for managed code.