Satellite assemblies and strong names

  • Thread starter Thread starter Mário Sobral
  • Start date Start date
M

Mário Sobral

Hi,

I created an assembly (let's call it assembly (B)) that returns a localized
resource for a given key (similar to System.Globalization.ResourceManager).
I checks if the caller assembly (let's call it assembly (A)) has a satellite
assembly (let's call it assembly (sA)) with localized resources.
If it exists, it gets the resource with the given key and returns it,
otherwise it reads information from a support database and dinamically
compiles a new satellite assembly and places it in the calling assembly's
respective folder, and then returns the requested resource.
It is all working fine, but once I started signing the assemblies (A) and
(B) with strong names, I got a dreadful error:

"The located assembly's manifest definition with name '(A).resources' does
not match the assembly reference."

Naturally, I assume I need to sign (sA) with strong name too, so I tried to
do it when I create the satellite assembly, but so far I have been
unsuccessful. Below are my efforts to provide (sA) with a strong name
dinamically:

----------- 1st Try -----------------------------
AssemblyName assName = new AssemblyName();
assName.Name = assemblyName + ".resources";
assName.CultureInfo = new CultureInfo(culture);

// ------ Sign the satellite assembly -----
FileStream fs = null;
StrongNameKeyPair kp = null;

try
{
fs = new FileStream(@"MyKey.snk", FileMode.Open, FileAccess.Read,
FileShare.Read);
kp = new StrongNameKeyPair(fs);
}
catch (FileNotFoundException)
{
Diag.Trace.Write("Strong name key pair file not found.");
throw;
}
catch(Exception ex)
{
Diag.Trace.Write("Error obtaining strong name key pair from file." +
fs.Name);
throw;
}
finally
{
if (fs != null)
{
fs.Close();
}
}

assName.KeyPair = kp;



----------- 2nd Try -----------------------------
try
{
FileStream publicKeyStream = File.Open("MyKey.snk",
FileMode.Open,FileAccess.Read, FileShare.Read);
byte[] publicKey = new byte[publicKeyStream.Length];
publicKeyStream.Read(publicKey, 0, (int)publicKeyStream.Length);
// Provide the assembly with a public key.
assName.SetPublicKey(publicKey);
}
catch(Exception ex)
{
throw;
}
 
Do early signing as opposed to late signing of the assembly. The framework is going to verify the signature at load time. Try including this line in your assemblyinfo.cs class.

[assembly: AssemblyKeyFile(@"my.snk")]

Change the path of course! And take out your signing code.

jason.
 
Hi !

Thanks for the suggestion, but my problem is that the satellite assembly is
being generated dinamically with System.Reflection.Emit. That's why it
should be signed dinamically also.

There is a method that reads the resources associated to a certain calling
assembly from a database, then generate the satellite assembly for that
calling assembly:

----------------------------------------------------------------------------
-------
AssemblyName assName = new AssemblyName();

assName.Name = assemblyName + ".resources";

assName.CultureInfo = new CultureInfo(culture);

assName.Version = new System.Version(1,0,0,0);

AssemblyBuilder assBuilder =
Thread.GetDomain().DefineDynamicAssembly(assName,
AssemblyBuilderAccess.RunAndSave,outputPath);

[Code to sign the satellite assebly here (?)]
ModuleBuilder modBuilder = assBuilder.DefineDynamicModule(assName.Name +
".dll", assName.Name + ".dll", true);


IResourceWriter resourceWriter = modBuilder.DefineResource(assemblyName +
"." + culture + ".resources",

assemblyName + "." + culture + ".resources",

ResourceAttributes.Public);

resStream.Seek(0,System.IO.SeekOrigin.Begin);

// We need ResourceSet object for its GetObject function, to get images and
other binary objects.

System.Resources.ResourceReader reader = new
System.Resources.ResourceReader(resStream);

ResourceSet rs = new ResourceSet(reader);

IDictionaryEnumerator resourcesEnumerator = reader.GetEnumerator();

while(resourcesEnumerator.MoveNext())

{

if(resourcesEnumerator.Value.GetType().ToString().ToLower() ==
"system.string")

{

resourceWriter.AddResource(resourcesEnumerator.Key.ToString(),resourcesEnume
rator.Value.ToString());

}

else

{

resourceWriter.AddResource(resourcesEnumerator.Key.ToString(),rs.GetObject(r
esourcesEnumerator.Key.ToString()));

}

}

reader.Close();

rs.Close();


Diag.Trace.Write("Saving assembly to: " + assemblyPath + "\\" + assemblyName
+ ".resources.dll");

assBuilder.Save(assemblyName + ".resources.dll");



 
Back
Top