I've created an assembly MyResources with two resx:
MyResources.resx
MyResources.en.resx
Inside the assembly I've added a handler-class containing a GetString-wrapper inside a ResHandler-class:
public string GetResString(string key)
{
return _manager.GetString(key, _culture);
}
_culture is simply a property which can be set from outside:
public void ChangeCulture(CultureInfo newCulture)
{
_culture = newCulture;
}
If I call this code from a lets say console-app, everything works fine:
var res = ResHandler.GetInstance(Guid.NewGuid().ToString());
//change the culture to "en"
res.ChangeCulture(new CultureInfo("en"));
Console.WriteLine(res.GetResString("TXT_0001"));
This code writes the english version to the console. However, if I call the exact same code from a unit-test-method, the contents of the MyResources.resx will appear. Whats wrong here? Are unit-tests unable to do this for some reason?
Beware that satellite assemblies are stored in a subdirectory of the directory that contains the EXE. Like "en-US" or "en" for English. Problem is, your test runs under a different EXE, mstest.exe and not your app.exe. It will therefore not find the satellite assembly. I think you can fix this by using Deployment in the test settings, not sure.
Related
I recently encountered an odd issue when performing unit tests. My solution contains a helper class with a property for getting the directory of the executing assembly. It looks like this:
public static class DirectoryHelper
{
public static string ExecutingAssemblyDirectory
{
get
{
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
var uri = new UriBuilder(codeBase);
var path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
}
This method is called through various test classes to get relative file paths to dependent resources.
Take the following contrived projects as examples:
TestProject1.dll - TestFixture1.cs
[TestFixture]
public class TestFixture1
{
[Test]
public void VerifyExecutingAssemblyDirectory1()
{
StringAssert.Contains(#"\TestProject1\bin\Debug",
DirectoryHelper.ExecutingAssemblyDirectory);
}
}
TestProject2.dll - TestFixture2.cs
[TestFixture]
public class TestFixture2
{
[Test]
public void VerifyExecutingAssemblyDirectory1()
{
StringAssert.Contains(#"TestProject2\bin\Debug",
DirectoryHelper.ExecutingAssemblyDirectory);
}
}
When these tests are ran individually they pass and the location of the returned assembly is the debug folder of the test class.
However, when ran together, TestFixture2.VerifyExecutingAssemblyDirectory2() is actually returning the path to the bin folder of TestProject1, rather than TestProject2.
I'm trying to determine why this behavior is happening and understand a better way of going about this.
I've found that using .GetCallingAssembly will resolve this problem, but it doesn't seem like I should have to do this.
I've created an example to reproduce this issue and posted to GitHub. TylerNielsen/NUnitExecutingAssemblyExample
Note: I'm aware of the TestContext.TestDirectory in NUnit, however this library is currently not dependent on NUnit and I'd prefer to keep it that way.
UPDATE
I'm running the NUnit tests through both Resharper in Visual Studio and via NUnit3-Console. When I run using NUnit3-Console, I'm only specifying the two individual .dlls and not providing any other arguments.
Both TestProject1 and TestProject2 reference the assembly containing DirectoryHelper. I'm assuming that your references cause the assembly to be copied to the individual (separate) output directories.
When you run both test assemblies together, one of them causes it's "personal" copy of that assembly to be loaded. The second one finds that the assembly is already in memory.
Of course, this behavior will depend on how you run the assemblies, which you haven't said. In the case where you use nunit3-console, it will also depend on your command-line arguments, especially whether you use a separate process for each assembly.
I have been using this code to obtain my programs version:
public string progVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
However, it doesn't always seem to grab the version I'm expecting. I don't really understand how this works entirely or what it's doing.
I think it is impart because I'm launching my program from another program then it appears to grab the version of the program that launched it instead, or the 'GetExecutingAssembly()' I'm assuming references the program that executed my program, like so:
System.Diagnostics.Process.Start(my_programs_path);
Is there a more reliable way to get the program version of the actual program at the time I ask for it?
Perhaps even launch my program without leaving some kind of trail, as if the user themselves just launched it.
Thanks for any help!
GetExecutingAssembly() returns the assembly that contains the method that calls it. If you call it from a library you will always get the version of the library not the application executable.
To get the application's executable use GetEntryAssembly()
Consider the following example:
In AssemblyA:
class VersionTest
{
void Test()
{
Console.Write("Executing assembly: {0}\n", Assembly.GetExecutingAssembly().GetName().ToString()); // returns AssemblyA
Console.Write("Entry assembly: {0}\n", Assembly.GetEntryAssembly().GetName().ToString()); // returns AssemblyB
}
}
In AssemblyB:
class Program
{
void Main()
{
var ver = new VersionTest();
ver.Test();
}
}
You could use the Assembly property of a known type via typeof which is defined in your application to ensure you got the 'correct' assembly and then retrieve the version of that, e.g.
typeof(YourKnownType).Assembly.GetName().Version.ToString();
Thanks for the great info. I finally settled on
Assembly.GetExecutingAssembly().GetName().Version.ToString()
for my solution.
I am trying to load a .net assembly using LuaInterface. If I place the assembly in the same folder as my executable (and my LuaInterface.dll and LuaNet.dll) then everything works great. I would like to move the assembly into a different folder, but when I try that I get "A .NET exception occured in user-code". I have tried:
package.path = package.path .. "C:\\path\\to\\my\\assembly\\?.dll"
luanet.load_assembly("MyAssembly")
and
luanet.load_assembly("C:\\path\\to\\my\\assembly\\MyAssembly")
and
luanet.load_assembly("C:\\path\\to\\my\\assembly\\MyAssembly.dll")
All of these return the .NET exception error. Is there a way to define the path that LuaInterface uses?
Your assembly is loaded by your "hosting" executable, and not really loaded by the Lua environment itself. luanet.load_assembly("MyAssembly") simply makes the assembly accessible to the Lua environment. For example (C#):
using MyAssembly; //you can't compile unless MyAssembly is available
namespace LuaRunner
{
class LuaRunner
{
void DoLua()
{
using (LuaInterface.Lua lua = new LuaInterface.Lua())
{
lua.DoString("luanet.load_assembly('MyAssembly')");
//... do what you want within Lua with MyAssembly
}
}
}
}
Your running program is the "host" for Lua to run within, so it's your running program that actually loads MyAssembly. Your executable needs a reference to MyAssembly.dll, (and needs to be able to find it at runtime in the usual locations).
To search other assemblies, set the package.cpath variable. For example:
package.cpath = DATA_DIR .. "\\clibs\\?.dll;" .. package.cpath
From the Lua 5.1 documentation:
require (modname)
First require queries package.preload[modname]. If it has a value, this value (which should be a function) is the loader. Otherwise require searches for a Lua loader using the path stored in package.path. If that also fails, it searches for a C loader using the path stored in package.cpath.
package.cpath
The path used by require to search for a C loader.
Lua initializes the C path package.cpath in the same way it initializes the Lua path package.path, using the environment variable LUA_CPATH or a default path defined in luaconf.h.
I have a project that needs to support French and English. I put all strings into resource files. When I debug the program in Visual Studio, I can successfully view the program in French. However, when I run the tests for the program, the program reverts to English. I added the French resource dll file to the deployment. This allows me to debug individual unit tests in French, but when I click Test -> Debug -> All Tests in Solution, the program runs in English.
I tried to add [DeploymentItem(#"..\bin\x86\Release\fr", "fr-FR")] to one of the tests also, but this didn't help. Does anyone have any suggestions on how to fix this? Thanks!
I wrap language tests in a using statement like this:
[Test]
public void Loads_correct_labels_from_language()
{
using(new LanguageSwitchContext("fr"))
{
var okayString = MyResources.Okay_Button;
Assert.Equals("your localized string here", okayString);
}
}
public class LanguageSwitchContext : IDisposable
{
public CultureInfo PreviousLanguage { get; private set; }
public LanguageSwitchContext(CultureInfo culture)
{
PreviousLanguage = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = culture;
}
public LanguageSwitchContext(string language)
{
//create culture from language
}
public void Dispose()
{
System.Threading.CurrentThread.CurrentCulture = PreviousCulture;
}
}
There are two potential issues here:
When your tests are run, CurrentUICulture may not be set to the language you wish to test
The satellite assemblies (only French in your example) may not be deployed in the unit test environment. When ResourceManager doesn't find a matching satellite assembly for a UI culture, it defaults to the base language embedded in the project's DLL itself (and so you get English, assuming that's your base language).
For 1. you can make sure to set System.Threading.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR"); in your test or at your test class's initialization.
For 2. the use of a DeploymentItemAttribute like you mentioned should work. Do verify that the satellite assembly deployed when your successfully run your app in French does get copied with the same name and in the same subfolder in your test's deployment. It's probably something more like [DeploymentItem(#"bin\fr-FR", "fr-FR")]
I'm trying to extract the version number from a AssemblyInfo.cs file!
And I'm trying to use System.Reflection.Assembly.LoadFile(path); But while doing this I get a BadImageFormatException; "The module was expected to contain an assembly manifest. (Exception from HRESULT: 0x80131018)". So now I wounder, is that not a possible way to go about it? And should I use RegEx instead?
I have read many examples with GetExecutingAssembly() but I do want to get the version from an other project.
Clarification: I want to read the version info from the AssemblyInfo.cs file! And not from a compiled file. I'm trying to make a tool to update my version numbers before I make a new release.
You can get Assembly version without loading it as:
using System.Reflection;
using System.IO;
...
// Get assembly
AssemblyName currentAssembly = AssemblyName.GetAssemblyName(path);
Version assemblyVersion = currentAssembly.Version;
Edit:
If you want to read file then you can do it like this:
string path = #"d:\AssemblyInfo.cs";
if (File.Exists(path))
{
// Open the file to read from.
string[] readText = File.ReadAllLines(path);
var versionInfoLines = readText.Where(t => t.Contains("[assembly: AssemblyVersion"));
foreach (string item in versionInfoLines)
{
string version = item.Substring(item.IndexOf('(') + 2, item.LastIndexOf(')') - item.IndexOf('(') - 3);
//Console.WriteLine(Regex.Replace(version, #"\P{S}", string.Empty));
Console.WriteLine(version);
}
}
//Output
1.0.*
1.0.0.0
Hope this help...
You can specify the target assembly path in AssemblyName.GetAssemblyName
AssemblyName.GetAssemblyName("ProjectB.exe").Version
AssemblyInfo.cs file gets compiled to IL assembly.
If you load that assembly you can read the version with all the examples that you have already seen. Which is reading an embedded version information from a compiled assembly file, and it may be overwritten by compilation process to a value different from what is in AssemblyInfo.cs
However it sounds like what you want instead is to read a version number from AssemblyInfo.cs text file, without compiling it down.
If this is the case you really just have to use regex with a format appropriate for your project, or even come up with a convention that will keep it simple.
This could be as simple as
var versionMatch = Regex.Match(File.ReadAllText(filename), #"AssemblyVersion\s*\(\s*""([0-9\.\*]*?)""\s*\)");
if (versionMatch.Success)
{
Console.WriteLine(versionMatch.Groups[1].Value);
}
You would have to consider convention around what goes there, since 1.0.* is a valid version string that translates to timestamp values of form 1.0.nnn.mmm at compile time, and nnn and mmm part closely guessable but not precisely guessable.
It sounds like you're trying to load an assembly compiled for x86 in an x64 environment or vice-versa.
Ensure the assembly this code resides in is built for the same environment as the target and you can get it with the examples it sounds like you've read.
You can proceed with Assembly.GetName().Version where your assembly could be the type of your class
public class Test
{
public static void Main()
{
Console.WriteLine("Current assembly : " + typeof(Test).Assembly.GetName().Version);
}
}
For the test application I have working on, shows me below details using above code: