ILMerging Windows Forms application with couple localizations problem - winforms

I've created a Windows Forms (C#) application called "Image Processing". It uses many external dlls so I decided to use ILMerge to merge all of them into one exe file and it worked. But today I've localized my application. After building I had 3 new folders in Debug folder: "en-US", "ru-RU", "uk-UA" with one dll with the same name "ImageProcessing.resources.dll". So I included all of them in a ILMerge command:
ILMerge.exe /t:winexe /out:ImageProcessingRelease.exe ImageProcessing.exe AForge.dll AForge.Imaging.dll AForge.Math.dll DevExpress.Data.v10.2.dll DevExpress.Utils.v10.2.dll DevExpress.XtraBars.v10.2.dll DevExpress.XtraEditors.v10.2.dll FreeImageNET.dll uk-UA\ImageProcessing.resources.dll ru-RU\ImageProcessing.resources.dll en-US\ImageProcessing.resources.dll
My program stores language locale in settings. After merging I can't change language, but settings are changing.
I don't know what else I can include here for more details so tell me please what.

The answer is simple. ILMerge is not suitable in this case, as .NET Framework relies on the folder structure to determine which resource file to use.
It is meaningless to combine assemblies in that way, and some third party assembly vendor's end user license does not permit you to merge their product with your own assemblies.

Related

How does a WinForms .Net sub-application in a solution embed its app.config into itself?

I am using a variation of Jeff Atwood’s Unhandled Exception handler it steps in when there is an Unhandled Exception in the application. It then logs the error, generates a screen shot and notifies the user.
When compiled in a solution the project generates an EXE that is called when needed. In updating the program I am using Visual Studio 13 to edit the existing settings items in the project properties. In the code I use commands such as this from ConfigurationManager.
string appProduct = unhandledExceptions.Properties.Settings.Default.AppProduct;
I was happy to see that it worked and reflected the changes I made in the IDE. However I couldn’t find the settings in the solutions generated confg file (MyApplication.exe.config). I assumed it was reaching back to the other project folder for the UnhandledExceptions.exe.config.
I created an installer and installed it to a virtual machine. My settings carried over, but again I could not see a config file.
It turns out the values are embedded in the executable UnhandledException.exe.
The project does not have any resources listed. Searching the web and StackOverflow looking a questions that want to do this, and there are a lot of them, it seems this was generally considered not possible and not desirable. Questions usually end in “You don’t want to do that, it’s called config for a reason”.
I may want to turn this off, so it is editable externally. The properties of app.config in both projects are identical.
What setting is making this possible after all? Is it a new capability with Visual Studio 2013?
There is no Visual Studio setting required. If you don’t want the user to have access to the configuration file, don’t include it in the distribution. One can always be added if the settings names are known.
In the description below application generically represents the name of the application being used.
I’ve found through observation some interesting things about the way ConfigurationManager works.
For User settings it will look in the following places in order of priority:
user.config for the application in the user’s AppData area
application.exe.config in the program folder
application.exe itself
Each setting is searched for individually. If your application requests a setting that is not found in either user.config or the application.exe.config it will get it from the executable.
For Application settings it looks in the following places in order of priority:
application.exe.config in the program folder
application.exe itself.
There is no equivalent to user.config for application settings.
Opening the application.exe in the Visual Studio IDE does not reveal a resource for the configuration information.
application.exe.config is handy because it can be modified externally and used as a default value for new installations. Once a setting is overridden in the user.config the value in application.exe.config is ignored.
The same is not true for the AppSettings section, the older configuration method from .Net 1.0. If I delete the configuration file it does not have them in the executable.
These observations were made with Visual Studio 2013 Update 4 and tested in Windows 7 Professional 64-bit. I suspect they are true in all versions.

How to stop Silverlight xap files including "Copy Local=False" dlls?

In the past I've used the solution outlined in the following URL to avoid multiple downloads of 3rd party dlls in modular Silverlight applications:
How to optimize the size of silverlight XAP file by removing common files?
However I am working on a Visual Studio 2010/Silverlight 5 solution application where this is not working.
I have a PRISM module let's call it Parent1.csproj that has no references to my 3rdParty dlls but it does have a reference to two other project files which reference the 3rdParty dlls child1.csproj and child2.csproj
child1.csproj and child2.csproj both have "Copy Local" set to false for 3rdParty.dlls but in spite of this the .xap file for Parent1.csproj contains the 3rd party dlls.
If I set child1.csproj and child2.csproj references in the Parent1.csproj file with "Copy Local" set to false then I get a dramatically reduced xap file with no 3rd party dlls but also none of the other code in the child projects that I actually need to be able to run.
It seems as if included project files get their "Copy Local" setting ignored and use the parent "Copy Local" setting instead, and there's no way for me to exclude those 3rdParty.dlls
Have I missed something subtle here? Is there some other way I can avoid downloading those 3rdParty.dlls in multiple modules when the shell application has already downloaded them?
I'm not 100% sure why this problem occurs, but it is related to Prism. The way we've solved it is add references to all the startup project and each of the sub projects even though they're not directly referenced but that project.
Make sure that the "Reduce XAP size by using application library caching" is enabled for all your projects.
Make sure that Parent1.csproj has references to all your 3rd party dlls.
Add these same references to child1.csproj and child2.csproj.
Double check you have extmap files for all your 3rd party dlls. If these are missing the dlls will be loaded into the XAP files.
Adding the references to the module projects and setting Copy Local to false on them will work, which is more or less what the accepted answer describes. However, Application Library Caching is not supported in Prism modules, so that may not work as expected.
If you have a lot of assembly references, adding them in this fashion is not very maintainable. You could also use a post-build step that removes unneeded assemblies from the XAP. Here's a short article that I wrote about how.

Silverlight fails to fetch resource assemblies

We use the .NET resource manager to localize our Silverlight application and want to embed the satellite assemblies for the german language ("de") into the XAP file. Therefor, we set the neutral language to "en" and added "de" to the list of supported languages in the csproj file. This works fine, when we build the project locally. If we build the Silverlight solution with MSBuild (TFS), Silverlight will try to fetch the satellite assemblies with HTTP requests from /ClientBin/de/*.dll instead of taking those files embeded into the XAP (which do exist). Because the webserver returns 404 error codes for the non existent files, Silverlight crashes with an initialization error.
It turned out that if we remove a custom TFS build activity manipulating the assembly info code files, the Silverlight applications works as expected. Strangely, after re-enabling the activity the compiled XAP application still works (verified for two different build definitions working on seperate branches). The custom activity manipulates the assembly attributes AssemblyConfiguration, AssemblyCompany, AssemblyProduct, AssemblyCopyright, AssemblyTrademark, AssemblyVersion, and AssemblyFileVersion.
Some additional hints:
The custom activity will change the assembly info files before any compilation is done
Compiling the manipulated sources with Visual Studio will build a working XAP
The content of the XAP files (working and not working) is equal (nearly same sizes, no difference in manifest file)
The resource manager is instantiated using ResourceManager("Resource", Assembly.GetExecutingAssembly())
My questions are:
Why does Silverlight try to fetch those satellite assemblies from /ClientBin/de/ instead of just using those in the XAP file?
What kind of attribute in the assembly info file could cause such a behavior?
Why does re-enabling the versioning activity not break the XAP again?
And here's the solution: We use a tool named "Total Commander" for editing a file in the generated XAP to adjust the URL the (generic) client connects to. Since we added the localization dlls, editing the XAP with the Total Commander will lead to the behavior described above. If we manipulate the XAP with WinRAR or the internal Windows archive manager, all works as expected.
Edit: After comparing the XAP files we found, that Total Commander uses the backslash (\) to seperate directories, whereas WinRAR and the Silverlight Tools use slashes (/). It seems that we discovered a hidden Silverlight feature here ;-)

Registered an Assembly for COM, but only works on dev computer

Hey, I was wondering if you guys could see what is wrong/suggest a solution.
I have a dll Assembly for COM that I built with C#, and i am trying to get the COM object from Silverlight Out-of-browser. I want the siverlight application to be mobile between computers, so i put all the neccesary files in a zip along with a batch installer that does the followingto register the assembly:
cd %windir%\Microsoft.NET\Framework\v4.0.30319\
RegAsm.exe "%USERPROFILE%\My Documents\Homework Clock\windowsHook.dll" /tlb /nologo
My application finds the assembly and it works fine on my dev computer, but when I move my application to a test computer (along with the dll and any other neccesary files), my batch file says it registers successfully but the application doesn't find it.
However, when i rebuild the assembly with C# on the test computer and replace the dll i moved from the dev computer with the rebuilt dll, the application finds it fine. It would be convenient for my clients if they didn't have to rebuild the assembly using C# if they wish to use my application, so i was wondering if there was a way to fix this.
I looked into this problem for a while and thought it might be because my assembly wasn't a strong named assembly, since I think C# does that automatically, so i tried doing it in my batch file and it couldn't recognize the 'al' and 'sn' commands necessary to generate the cryptographic key to give an assembly a strong name, and i tried doing it in the
'signing' tab in the C# project properties, but i encountered the same problem. Any ideas how to fix this?
Thanks in advance
The reason it works when you rebuild with VS is because it runs Regasm.exe with the /codebase option. Required if you don't plan to put the assembly in the GAC.
C# does not automatically give assemblies a strong name. If you're using Visual Studio, open the project's Properties page, and look under the Signing tab. Check Sign the Assembly, and generate a new strong name key file. Build your project, and you should be able to do what you need to do with your existing batch file.

EXE generated in obj\Debug folder

I have inherited a Windows Forms application and I have found that a .EXE file gets generated into the obj\Debug folder everytime I compile.
I am more a Web Forms kind of developer so I am a little confused as to what is happening here. Why is it a .EXE and not a .DLL? What does this file actually represent? Is this the default behaviour for Windows Forms applications? Or, did my predecessor have to set it up up somehow?
As far as I can tell, the solution does not have a deployment project.
Their are many types of win application in delhpi. If u create windows form, .exe will be craeted in the debug folder similarly if you are creating Dynamic Link Liberary (DLL) .dll files will b created. These files are created each time when you compile the application.
Why this is a problem? Console application projects have exe file in the obj/Debug folder too. The obj folders are NOT used for running the application - they are used for creating the end binaries in the bin folders.
If the question is about exe vs dll then compiled exe file is used to run the application. In the web environment you used dll because ASP.NET new how to run code from it. But Windows knows how to run exe files, so any of your code actually can be compiled to an executable.
Every application be it web or windows would have an entry-point for execution. Anything in compiled form in .Net is an assembly which need not always be a DLL file. An EXE file is a .Net assembly with an entry point and few headers in the beginning of the file that identifies itself as a stand-alone executable to the windows operating system. In case of your web-application your asp.net pages are the entry points that users would type in a browser and start the application. In case of a stand-alone windows forms desktop application, it is an EXECUTABLE file, which user can click on run.
I am more a Web Forms kind of developer so I am a little confused as to what is happening here. Why is it a .EXE and not a .DLL?
Having said this, It is also important to note that, just like the asp.net is not the only platform to develop web-applications [you have php, jsp, etc.], .Net windows forms is also not the only way to create stand-alone executables. You can make EXEs in C, C++, VB, Delhpi, etc. only difference would be that they will not be .Net assemblies but all of them including .Net executables will have an entry-point to start execution from and the EXE header that identifies them as executables on the host windows operating system.
Why would it be a DLL? It's an application - it has to be launchable, unlike a website which lives "inside" a web server (effectively). The exe file is the application (along with any libraries it requires, of course). You double-click on it, it will launch the application. No problem.
Having said that, you should pretty much ignore the obj directory - it's just an intermediate directory. The bin directory is the one you should be taking build results from.

Resources