Error_Unable_To_Connect = Unable to connect to specified server
Because each name-value pair is delimited by a new line, this character cannot be added to the
string. However, C-style escape characters can be used to insert new lines (\n) or tabs (\t) into
the text.
You can add comments to the resource file by prefixing a line with a semicolon, as shown here:
;Error message to be displayed when a connection could not be made to the server
Error_Unable_To_Connect = Unable to connect to specified server
Text resource files should be saved with the file extension of .txt or .restext. The latter is useful
when you want to distinguish text resource files from regular text files.
Although text resource files are easy to edit and update, it is harder to integrate them into your
application. As text files, they cannot be directly compiled into an application; they must instead be
converted into either resx or resources files. Do this using the Resource Generator utility, resgen.exe,
located in the \bin folder of the Windows SDK (located at C:\Program Files\Microsoft SDKs\
Windows\v7.0A\bin):
resgen StringResources.txt StringResources.resources
Include the output file — in this case, StringResources.resources — in your application to give
yourself access to those resources.
A prebuild event can be used to convert text resource files into a resources file that can be compiled
into the main application build. This will ensure that the resources files contained in the application
are always up to date. To do this, include the text resource file in the application and set the build
action property to None. Navigate to the Project Properties window for the project that contains the
text resource file and on the Compile tab select Build Events (VB) or the Build Events tab (C#). In
the prebuild events, enter the Resgen command required to compile your text resource file:
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\resgen.exe"
"$(ProjectDir)StringResources.txt" "$(ProjectDir)StringResources.resources"
What are resources? .
807
Building the application generates the resources file
that needs to be included within your application
with the build action property set to Embedded
Resource. Figure 38-1 illustrates how both the
text file and the resources file are included within
an application with appropriate build action
properties.
resx resource files
A much more user-friendly format for resources
is the XML resource file, commonly referred to
as a resx file. This is a simple XML data file that
contains name-value pairs of XML nodes. The
advantage of this format is that the value is not
restricted to just a string; it can be of any type that is serializable or that can be represented
as a string.
The following XML snippet shows a resource named HelloWorld, with an associated value
and comment. As you can see from the code, no information is available about the type of data
contained within the resource, because it is a string resource:
<data name="HelloWorld">
<value>Say Hello</value>
<comment>This is how we say hello</comment>
</data>
The next snippet illustrates how a more complex data type can be stored in a resource file as a string
representation. It also shows how an assembly alias can be used to reference an external assembly
that contains type information. When this resource is accessed, the type information will be used to
convert the string value to an object of this type:
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="Button1.Location" type="System.Drawing.Point, System.Drawing">
<value>71, 43</value>
</data>
Although resx files can be included in an application without your having to use the Resource File
Generator (Resgen), they are still converted prior to being compiled into the application. During
the build process, resources files are generated for each resx file in the application. These are
subsequently linked into the application.
binary resources
The third resource format is the binary resource file, indicated by the .resources file extension.
Behind the scenes, Visual Studio 2010 converts all resx files into .resources files as an intermediate
step during compilation (you can see these files in the \obj\debug folder for your project), and as you
fiGure 38-1
808 .
chaPter 38 reSource FileS
saw earlier in this chapter, you must manually convert text resources into .resources files using
Resgen. You can also integrate other binary resources into your project by simply including the
.resources file and setting the build action to Embedded Resource.
adding resources
Visual Studio 2010 supports a rich user interface for adding and modifying resource files. It is still
possible to view the contents of a resource file within the IDE. However, unless the resource is a
string, or has a string representation, it is not possible to modify the value within the resource file.
The resource editor provides support for strings, images, icons, audio files, and more.
Double-clicking the My Project (VB) or Properties (C#) node for a project in the Solution Explorer
opens the project properties editor, from which you can select the Resources tab to open the default,
or project, resource file. For C# projects you will then need to click the presented link to create
the resource file (VB projects already have a
default resource file). When the default resource
file opens, you will see that in the top left-hand
corner of the resource editor is a drop-down
list that navigates among resources of different
types, as shown in Figure 38-2. Double-clicking
any resx file within the Solution Explorer also
fiGure 38-2
brings up this resource editor.
The editor displays the resource in an appropriate format, according to its type. For example,
strings are presented in an editable textbox, whereas images are presented as thumbnails that can
be opened and edited. Adding new resources is as simple as selecting the Add Resource drop-down,
choosing the appropriate resource type, and
adding the necessary information. Once
you have added a resource, it appears in the
resource editor, as shown in Figure 38-3.
Figure 38-3 shows an additional column that
gives you the option to specify a comment
alongside your resource. Unfortunately, the
resource editor is the only place in Visual
Studio 2010 where this comment is displayed.
embedding files as resources
It is often necessary to embed an entire file in an application. You can do this by including the
file in the application and modifying the build action. Depending on the file type, when the item
is included in the application, the build action (click the file and open the Properties window) is
normally set to either Compile or None. If this is changed to Embedded Resource, the entire file
is added to the application as an embedded resource.
Alternatively, you can use the resource editor shown in Figure 38-2 to add a file resource. When
images, icons, and other files are added to an existing resource file by means of the resource editor,
they are added as a resxfileref item. The file will appear in the resources directory, but the build
fiGure 38-3
What are resources? .
809
action will be None. When the application is built, these files are compiled into the resources file
prior to being linked into the application. In the past, the data from these files was pulled out and
added to the resx file as a binary block. This meant that, once added, the data couldn’t be easily
modified. With the file reference item, the data remains in an associated file and can easily be
updated.
naming resources
Resources are named for the resource file to which they belong and the root namespace. For
example, if you have a resource file called Sample.resources in a project called MyProject, the full
resource name will be MyProject.Sample.
This is particularly important to remember when you make a file an embedded resource by
changing the build action. You can access any file by prefixing the filename with the project name.
Unlike with resource files, the name of the file retains the extension. For example, if you have a file
called ASimpleDataDocument.doc in a project called MyProject, it will need to be referenced as
MyProject.ASimpleDataDocument.doc.
Any directory structure will be ignored for the purpose of naming embedded
resources.
accessing resources
The method that you use to access resources depends on how they are embedded in the application.
You have already seen that you have two ways to embed resources: the first is to add a file to the
project and set the build action to Embedded Resource; the second is via the resource editor. To access
resources added by a change to the build action, you need to use the GetManifestResourceNames and
GetManifestResourceStream methods. The following code retrieves the names of all the resources
in the assembly by querying the manifest. It then creates a stream for accessing the relevant
resource file. As discussed in the previous section, the name of the embedded resource file returned
by the GetManifestResourceNames method and accepted by the GetManifestResourceStream
method is in the form Root namespace .Filename .File_extension (for example, MyProject.
ASimpleDataDocument.doc).
Vb
Dim names = Reflection.Assembly.GetExecutingAssembly.GetManifestResourceNames
Dim resources = From n In names
Select Assembly.GetExecutingAssembly.GetManifestResourceStream(n)
For Each r In resources
Using strm As New IO.StreamReader(r)
MsgBox(strm.ReadToEnd)
End Using
Next
810 .
chaPter 38 reSource FileS
c#
var names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
var resources = from n in names
select Assembly.GetExecutingAssembly().GetManifestResourceStream(n);
foreach (var r in resources){
using (var strm = new StreamReader(r)){
MessageBox.Show(strm.ReadToEnd());
}
}
Resources added via the resource editor can be accessed in code by means of a resource manager,
which you can easily create from the name of the resource file to which they belong and a reference
to the assembly from which the resource should be extracted:
Vb
Dim res As New ResourceManager("WorkingWithResources.Resources",
Assembly.GetExecutingAssembly)
c#
var res = new ResourceManager("WorkingWithResources.Properties.Resources",
Assembly.GetExecutingAssembly());
Once created, resources can be extracted by means of either the GetObject or GetString function:
res.GetObject("StringResource")
For more complex resources, such as files, you may also want to use the GetStream function. All
three functions take the name of the resource as the only parameter.
designer files
The Resource Generator utility, Resgen, has a number of improvements that enable you to build
strongly typed wrapper classes for your resource files. When you add a resx file to your application,
Visual Studio 2010 automatically creates a designer file that wraps the process of creating a resource
manager and accessing the resources by name. The accessor properties are all strongly typed and
are generated by the designer to reduce the chance of invalid type conversions and references. For
example, if you have a string resource, StringResource, contained in a resource file, MyResources,
you can use the following code to access the string:
Vb
My.Resources.MyResources.MyStringResource
c#
MyResources.StringResource
You will notice that the designer-generated code is different for VB and C#. This is
because C# uses the generic ResXFileCodeGenerator custom tool whereas VB uses the
VbMyResourcesResXFileCodeGenerator custom tool to integrate the resource file into
the My namespace.
resourcing Your application .
811
Unfortunately, Visual Studio 2010 does not automatically generate the designer file for text resource
files, because text resource files cannot be explicitly added to the application. The process of generating
a resource file from the text file can be extended to include the generation of the designer file.
A new argument has been added to Resgen that facilitates the generation of this designer file:
resgen sample.txt sample.resources /str:vb
Both of the output files need to be added to the application so that the resources are accessible.
To ensure that the resources can be correctly accessed, you must ensure that the naming used
within the designer file matches the naming of the compiled resources. You can provide additional
parameters to control the namespace, class name, and output filename:
resgen sample.txt defaultnamespace.sample.resources
/str:vb,defaultnamespace,sample,sample.vb
In this case, the fully qualified output class would be defaultnamespace.sample, and the use
of this file would allow access to resources without an exception being raised. Once the correct
command has been determined, you can update your prebuild event to include the generation of the
designer file. This way, every time the file is modified and saved and the application is compiled,
the designer file will be re-created.
resourcinG your aPPlication
Writing an application often requires data such as images, icons, or sounds (collectively known as
resources) to enhance the appearance of the application. Furthermore, best coding practices suggest
that the use of constant strings throughout your application be avoided. In either case, you can
put together a custom solution that stores these resources in files that need to be shipped with the
application.
An alternative is to include them in a resource file that can be compiled
into your application. This way you not only have the resources in a
format that you can work with, but they are also automatically available