Skip to content

Commit

Permalink
add facility for copying lib version to xll version
Browse files Browse the repository at this point in the history
You can now mark ExternalLibrary elements in the .dna file with UseVersionAsOutputVersion="true" to copy their version resource into the output .xll. If you specify this for more than one ExternalLibrary only the first will be used, and a warning will be emitted. If the version copying fails for some reason (like the source file doesn't have it, e.g. if it's a .dna file), then a warning is emitted.
  • Loading branch information
rosecodym committed Feb 17, 2017
1 parent 75591ec commit 8f0e6f4
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 4 deletions.
11 changes: 9 additions & 2 deletions Source/ExcelDna.Integration/DnaLibrarySerialization.cs
Expand Up @@ -227,6 +227,7 @@ public class XmlSerializationWriterDnaLibrary : System.Xml.Serialization.XmlSeri
WriteAttribute(@"LoadFromBytes", @"", System.Xml.XmlConvert.ToString((global::System.Boolean)((global::System.Boolean)o.@LoadFromBytes)));
WriteAttribute(@"ExplicitExports", @"", System.Xml.XmlConvert.ToString((global::System.Boolean)((global::System.Boolean)o.@ExplicitExports)));
WriteAttribute(@"ExplicitRegistration", @"", System.Xml.XmlConvert.ToString((global::System.Boolean)((global::System.Boolean)o.@ExplicitRegistration)));
WriteAttribute(@"UseVersionAsOutputVersion", @"", System.Xml.XmlConvert.ToString((global::System.Boolean)((global::System.Boolean)o.@UseVersionAsOutputVersion)));
WriteEndElement(o);
}

Expand Down Expand Up @@ -651,7 +652,7 @@ public class XmlSerializationReaderDnaLibrary : System.Xml.Serialization.XmlSeri
if (isNull) return null;
global::ExcelDna.Integration.ExternalLibrary o;
o = new global::ExcelDna.Integration.ExternalLibrary();
bool[] paramsRead = new bool[7];
bool[] paramsRead = new bool[8];
while (Reader.MoveToNextAttribute()) {
if (!paramsRead[0] && ((object) Reader.LocalName == (object)id16_Path && (object) Reader.NamespaceURI == (object)id2_Item)) {
o.@Path = Reader.Value;
Expand Down Expand Up @@ -681,8 +682,12 @@ public class XmlSerializationReaderDnaLibrary : System.Xml.Serialization.XmlSeri
o.@ExplicitRegistration = System.Xml.XmlConvert.ToBoolean(Reader.Value);
paramsRead[6] = true;
}
else if (!paramsRead[7] && ((object) Reader.LocalName == (object)id25_UseVersionAsOutputVersion && (object) Reader.NamespaceURI == (object) id2_Item)) {
o.@UseVersionAsOutputVersion = System.Xml.XmlConvert.ToBoolean(Reader.Value);
paramsRead[7] = true;
}
else if (!IsXmlnsAttribute(Reader.Name)) {
UnknownNode((object)o, @":Path, :TypeLibPath, :ComServer, :Pack, :LoadFromBytes, :ExplicitExports, :ExplicitRegistration");
UnknownNode((object)o, @":Path, :TypeLibPath, :ComServer, :Pack, :LoadFromBytes, :ExplicitExports, :ExplicitRegistration, :UseVersionAsOutputVersion");
}
}
Reader.MoveToElement();
Expand Down Expand Up @@ -735,6 +740,7 @@ public class XmlSerializationReaderDnaLibrary : System.Xml.Serialization.XmlSeri
string id4_RuntimeVersion;
string id8_CompilerVersion;
string id21_ComServer;
string id25_UseVersionAsOutputVersion;

protected override void InitIDs() {
id2_Item = Reader.NameTable.Add(@"");
Expand All @@ -761,6 +767,7 @@ public class XmlSerializationReaderDnaLibrary : System.Xml.Serialization.XmlSeri
id4_RuntimeVersion = Reader.NameTable.Add(@"RuntimeVersion");
id8_CompilerVersion = Reader.NameTable.Add(@"CompilerVersion");
id21_ComServer = Reader.NameTable.Add(@"ComServer");
id25_UseVersionAsOutputVersion = Reader.NameTable.Add(@"UseVersionAsOutputVersion");
}
}

Expand Down
8 changes: 8 additions & 0 deletions Source/ExcelDna.Integration/ExternalLibrary.cs
Expand Up @@ -76,6 +76,14 @@ public bool ExplicitRegistration
set { _ExplicitRegistration = value; }
}

private bool _UseVersionAsOutputVersion = false;
[XmlAttribute]
public bool UseVersionAsOutputVersion
{
get { return _UseVersionAsOutputVersion; }
set { _UseVersionAsOutputVersion = value; }
}

internal List<ExportedAssembly> GetAssemblies(string pathResolveRoot, DnaLibrary dnaLibrary)
{
List<ExportedAssembly> list = new List<ExportedAssembly>();
Expand Down
21 changes: 19 additions & 2 deletions Source/ExcelDnaPack/PackProgram.cs
Expand Up @@ -236,11 +236,12 @@ static byte[] PackDnaLibrary(byte[] dnaContent, string dnaDirectory, ResourceHel
}
if (dna.ExternalLibraries != null)
{
bool copiedVersion = false;
foreach (ExternalLibrary ext in dna.ExternalLibraries)
{
string path = dna.ResolvePath(ext.Path);
if (ext.Pack)
{
string path = dna.ResolvePath(ext.Path);
Console.WriteLine(" ~~> ExternalLibrary path {0} resolved to {1}.", ext.Path, path);
if (Path.GetExtension(path).Equals(".DNA", StringComparison.OrdinalIgnoreCase))
{
Expand Down Expand Up @@ -292,7 +293,23 @@ static byte[] PackDnaLibrary(byte[] dnaContent, string dnaDirectory, ResourceHel
}
}
}

if (ext.UseVersionAsOutputVersion)
{
if (copiedVersion)
{
Console.WriteLine(" ~~> Assembly version already copied from previous ExternalLibrary; ignoring 'UseVersionAsOutputVersion' attribute.");
continue;
}
try
{
ru.CopyFileVersion(path);
copiedVersion = true;
}
catch (Exception e)
{
Console.WriteLine(" ~~> Error copying version to output version: {0}", e.Message);
}
}
}
}
// Collect the list of all the references.
Expand Down
64 changes: 64 additions & 0 deletions Source/ExcelDnaPack/ResourceHelper.cs
Expand Up @@ -57,6 +57,28 @@ internal enum TypeName
IntPtr lpData,
uint cbData);

// This overload provides the resource type and name conversions that would be done by MAKEINTRESOURCE
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UpdateResource(
IntPtr hUpdate,
uint lpType,
uint lpName,
ushort wLanguage,
IntPtr lpData,
uint cbData);

[DllImport("version.dll", SetLastError = true)]
private static extern uint GetFileVersionInfoSize(
string lptstrFilename,
out uint lpdwHandle);

[DllImport("version.dll", SetLastError = true)]
private static extern bool GetFileVersionInfo(
string lptstrFilename,
uint dwHandle,
uint dwLen,
byte[] lpData);

[DllImport("kernel32.dll")]
private static extern uint GetLastError();

Expand Down Expand Up @@ -186,6 +208,48 @@ public void RemoveResource(string typeName, string name)
}
}

public void CopyFileVersion(string fromFile)
{
uint ignored;
uint versionSize = ResourceHelper.GetFileVersionInfoSize(fromFile, out ignored);
if (versionSize == 0)
{
throw new Win32Exception();
}

byte[] versionBuf = new byte[versionSize];
bool result = ResourceHelper.GetFileVersionInfo(fromFile, ignored, versionSize, versionBuf);
if (!result)
{
throw new Win32Exception();
}

GCHandle versionBufHandle = GCHandle.Alloc(versionBuf, GCHandleType.Pinned);
try
{
lock (lockResource)
{
uint versionResourceType = 16;
uint versionResourceId = 1;
result = ResourceHelper.UpdateResource(
_hUpdate,
versionResourceType,
versionResourceId,
localeNeutral,
versionBufHandle.AddrOfPinnedObject(),
versionSize);
if (!result)
{
throw new Win32Exception();
}
}
}
finally
{
versionBufHandle.Free();
}
}

public void EndUpdate()
{
EndUpdate(false);
Expand Down

0 comments on commit 8f0e6f4

Please sign in to comment.