How can I swap resources for different versions of an application? - c#

I developing an application which will have at least 2 if not 3-4 different versions (don't ask). The applications will basically be identical except have different product names, window titles, application icon and some other minor differences in string or image resources.
My main goal is to avoid having to create multiple projects for each executable. I want to be able to have one main application project and have it just load those resources (name, icon, etc.) and be agnostic of which version it is. This way, I can simply configure my setup project to deploy the proper resources with the version of that application. Ideally it would not be that visible to the end-user after it was installed.
What I've tried: I've experimented with creating different .resx files and swapping them based off build configuration, or I've also experimented with adding environment variables and #if on the variable. But, I really do not want multiple build configurations. I want it to only depend on deployment.
Is it possible to create resx files, either in a different project or in the same project and exclude them from the build, and have them generated into satellite .DLL assemblies similar to localization, and then load whichever one is deployed with the application?
I'm confused if I should be looking at running my own RESGEN and AL tasks, or if I should just create a DLL project (but maybe then I'd have to have multiple DLL projects for only 1 resource file). Also, any article I can find about using .RESX files is for localization. It relies on setting the CurrentCulture to resolve the specific resources to use. My scenario has nothing to do with culture... I just want to load different resources for different deployments of the application.

Without knowing how deeply you need to go, you can package the resources into separate .dll files and differentiate that way. For instance, building the various different versions into a seperate DLLs and having your installer adjust the name to match what your application expects or use an XML configuration file to specify which to load and load it that way.
Assembly.Load() will allow you to load the alternative assembly.
Assembly _assembly;
_assembly = Assembly.GetExecutingAssembly();
Stream _imageStream;
_imageStream =
_assembly.GetManifestResourceStream(
"ThumbnailPictureViewer.resources.Image1.bmp");
Bitmap theDefaultImage = new Bitmap(_imageStream);
See: http://www.attilan.com/2006/08/accessing-embedded-resources-using.html

Related

Different resx for different deployments c#

I'm using an embedded resource generated by 'PublicResXFileGenerator' which generates my ResourceManager class.
I'm trying to find a way to support multiple resx files for the same language or in some way being able to modify it from a deployed application but this doesnt seem possbible.
For example client 'x' is using the en-US translation:
Flat
and the other client 'y' are using the en-US translation:
Appartment
Maybe the above example is stupid but I hope you get my point.
Different users are using different namings for the same thing and I'd like to support this.
Is it possible?
Note:
My code is written in C#.
The strings in your default resource file (probably Resources.resx) are embedded in your executable file.
If you define a language specific resource file (e.g. Resources.en-US.resx) then Visual Studio will automatically generate a satellite DLL containing the localized resources.
The same applies if you add localized resources to a WinForms form, as shown here for Form1.
The satellite DLL is generated in a sub-directory of the bin directory.
The DLL must be deployed on the target machine in a sub-directory with exactly the same name.
This works for localized strings in any language, but it works exactly the same for strings in the current default language.
If the current default is en-US, and there is a satellite DLL for en-US, and it contains the required resources, then the .NET Framework will automatically use resources from the satellite DLL.
If you don't want the resources from the satellite DLL, no problem. Don't deploy it to the target machine. Then the .NET framework will use the default resources which are embedded in the executable.
If you only have two variations, then it is easy to manage in Visual Studio using the default resource file and an en-US resource file. If you have more than two variations, you are going to need a strategy to generate the resources. The simplest way would probably be to misuse another language.
Alternatively, you could use some other tool. Winres might do the job, but I'm not 100% sure.
Technically, you can define custom cultures, e.g. en-US-medical, or en-US-legal, but in my experience that is more bother than it is worth. I don't think (just my opinion) that Microsoft is strongly committed the concept.

Proper procedure to import existing RESX files into a C#/WPF project

I have my auto generated Resource.resx file set up with keys and strings. I also have three other resx files for German, French and Spanish given to me from translators. I'm not able to get the localization functioning and I suspect that the resx files aren't being called correctly. I added them to the project by dragging them into the solution explorer under "Properties". I have a nagging suspicion that just dragging them in isn't creating the proper connections behind the scene.
Now It's totally possible my issue lies somewhere else. If anyone can tell me whether it's ok to add resource files this way or if not, what the correct way is, it would save me tons of time spent chasing my tail. Thanks!
Resx files in Visual Studio include a special tool which is run at build time and translates them into embedded resources. Right-click your original VS-created resx file and click Properties. You should see Build Tool or something similar. Also note the resource type (Embedded, etc.). Make sure that you match these settings for your manually added files.
Once this is set up, you will need to use the CurrentUICulture property to tell .NET to pick up the appropriate resources. You can choose to change the culture/language at install-time or run-time. Here is a comprehensive tutorial which describes the various options available to you:
WPF Localization Using RESX Files
That said, as a best practice, translated Resx files are generally deployed as satellite assemblies. The main application DLL/EXE contains only the language neutral resources file. Other resource files are compiled into separate assemblies and deployed side-by-side with specific naming conventions. This allows you to dynamically add translations, localizations, etc. even after the application is deployed. Here's an introduction: Packaging and Deploying Resources in Desktop Apps

what will happen to images in the Resources directory once the app is packed and how safe are those images for the app?

the Resources folder typically contains all the app images (those 16 X16) that we use to look our apps good. I haven't dealt with installation and resources folder before therefore :
When application needs to be deployed, what would happen to those images in that Resource folder?
I haven't tried this before so when I install the application where would that resource folder be saved?
If the installation creates another resource folder to keep those images, then what if a user manually deletes that folder? App would crash? what is the solution to overcome this?
I've heard some place the images in a .dll file, is this a common practice?
thanks
When you build your application, Visual Studio invokes the resgen.exe tool to convert your application resources into an internal class called Resources. This class is contained in the Resources.Designer.cs file which is nested under the Resources.resx file in Solution Explorer. The Resources class encapsulates all your project resources into static readonly get properties as a way of providing strongly-typed resources at run-time. When you build through the Visual C# IDE, all the encapsulated resource data, including both the resources that were embedded into the .resx file and the linked files, is compiled directly into the application assembly (the .exe or .dll file). In other words, the Visual C# IDE always uses the /resource compiler option. If you build from the command line, you can specify the /linkresource compiler option that will enable you to deploy resources in a separate file from the main application assembly. This is an advanced scenario and is only necessary in certain rare situations. A more common scenario for deploying resources separately from the main application assembly is to use satellite assemblies as discussed below.
All your queries is answered above
i.e.
When application needs to be deployed, what would happen to those images in that Resource folder?
I haven't tried this before so when I install the application where would that resource folder be saved?
If the installation creates another resource folder to keep those images, then what if a user manually deletes that folder? App would crash? what is the solution to overcome this?
I've heard some place the images in a .dll file, is this a common practice?
For More information
http://msdn.microsoft.com/en-us/library/7k989cfy(v=vs.80).aspx

Why my WPF program cannot run without Visual Studio?

I made a WPF program which uses SQLite. And by using Visual Studio 2012, it generates both Debug and Release version exe file. When I go to Debug or Release directory and run my exe file, e.g. MultiStart.exe, it can run normally.
But if I copy the MultiStart.exe to my Desktop and try to run it, it failed.
By several tests, I found that I also need to copy files MultiStart.exe.config and System.Data.SQLite.dll to my Desktop. And then it can run now.
But why? Do we have better solution so that I can make it run without addition files?
Thanks!
Why my WPF program cannot run without Visual Studio?
The question title is not really accurate since it's not really related Visual Studio. MultiStart.exe is dependent on configuration (MultiStart.exe.config) as well as other assemblies (System.Data.SQLite.dll). Without these dependencies the application cannot run (because that is how .NET works).
WPF doesn't necessarily need a config file to run so the question is what is in your config file that the application needs. It might be possible to move this configuration information into the code (e.g. connection string) and remove the app.config but then the values will be hard coded in the application.
In terms of dependent assemblies, instead of deploying them it is possible to embed them as resources and then use the AppDomain.AssemblyResolve Event to read the assembly from a resource (see Embedding assemblies inside another assembly for an example).
Another approach instead of embedding assemblies as resources is to merge them into one assembly. ILMerge is a popular choice for merging assemblies but I read that it can have issues with WPF assemblies (not sure if that applies to you). See Merging dlls into a single .exe with wpf for some other ideas for merging assemblies with WPF.
Note that setting PATH variables does not work because .NET does not use the PATH for resolving assemblies -- see How the Runtime Locates Assemblies for the details.
Another, option instead of copying the MultiStart.exe to the desktop is to use a shortcut on the desktop that links to the appropriate directory. Perhaps that is a simpler solution
You can also use ILMerge to merge all dependencies into single .exe file to simplify distributiuon of your application.
More detaiils on ILMerge can be found here: ILMerge on CodeProject
Example of usage: ilmerge /target:winexe /out:YourDestinationApp.exe
YourCurrentProgram.exe System.Data.SQLite.dll
Better solution that i used to do with my windows form apps is, Copy the entire folder, which contains supporting files. place it where you want. then create a shortcut of your .exe on your desktop. That always worked for me.
Because you are missing some dependency. You can open your config file and set the dependency...but I wouldn't recommend you to change config file manually.
You can also copy the dependent dll in system32 folder. ..but its only a trick because exe first search dlls in current folder than system 32 folder.
Because you're missing things from your PATH. Visual Studio is probably set to copy DLLs to the target directory on build.
You're almost certainly pulling in external libraries. Some of these are part of .NET, while others are packaged in libraries in specific folders. When you start your exe, it looks in your PATH and the current folder for everything (which includes all DLLs Visual Studio copied).
When you moved the exe to the desktop, suddenly it had no idea where those DLLs are. You haven't specifically added them to your PATH, and they are no longer in the current folder. This is why copying those DLLs to your desktop magically made them work.
Unless you stop use SQLite, there is not a way for you to not need that DLL (there are lots of ways to package/reference it though).

VS2010 Building Solution - Add Files to BIN folder

We have a solution comprising of a windows application and various library files. Not all of the library files are referenced by the main windows application however we would like to have all the library files included in the output build folder "bin".
Obviously one solution is to simply reference every single library from the Windows application however we would like to avoid any unnecessary referencing.
How can we include additional files into our build folder?
This is a C# project.
You can always use the pre-build or post-build events in the project settings to copy the additional files.
You can do this simply by doing a bunch of copy source target, or you could even be fancy and write an nmake file. You do have to maintain the list of source files however...
Edit:
One other thought. Your assumption is that this is "unnecessary referencing". However, if your application depends on these assemblies to run, whether or not they are compile time references, then don't these dependencies become "necessary" references? In that case, isn't adding them as references and letting Studio's build system work for you the best (and simplest) approach?
The solution was to change the build location for all "libraries" within the solution to the main output "bin" location. The main Windows application only references the libraries that it depends upon however all the libraries are built to the one "common" location.
Thanks to Nader Shirazie for help with this question.

Categories

Resources