Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
ProjectName="$(MSBuildProjectName)"
PublishDir="$(PublishDir)"
OutDirectory="$(OutDir)"
NativeOutputPath="$(NativeOutputPath)"
RunMultithreaded="$(ExcelDnaPackRunMultithreaded)"
PackManagedOnWindows="$(ExcelDnaPackManagedResourcePackingOnWindows)"
AddInInclude="$(ExcelAddInInclude)"
IncludePdb="$(ExcelAddInIncludePdb)"
>
</PackExcelAddInNativeAOT>
</Target>
Expand Down
15 changes: 13 additions & 2 deletions Source/ExcelDna.AddIn.Tasks/PackExcelAddInNativeAOT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ public override bool Execute()
useManagedResourceResolver = PackManagedOnWindows || !OperatingSystem.IsWindows();
#endif

string mainNativeAssembly = Path.Combine(PublishDir, ProjectName + ".dll");
string mainNativeAssembly = Path.Combine(NativeOutputPath, ProjectName + ".dll");
IEnumerable<string> includeAssemblies = BuildTaskCommon.SplitDlls(AddInInclude, OutDirectory).Select(i => Path.Combine(OutDirectory, i));
string xllOutput = Path.Combine(PublishDir, ProjectName + "-AddIn64.xll");
File.Copy(Xll64FilePath, xllOutput, true);

int result = ExcelDna.PackedResources.ExcelDnaPack.PackNativeAOT(mainNativeAssembly, includeAssemblies, xllOutput, RunMultithreaded, useManagedResourceResolver, _log);
int result = ExcelDna.PackedResources.ExcelDnaPack.PackNativeAOT(mainNativeAssembly, includeAssemblies, xllOutput, RunMultithreaded, useManagedResourceResolver, IncludePdb, _log);
if (result != 0)
throw new ApplicationException($"Pack failed with exit code {result}.");

Expand Down Expand Up @@ -80,6 +80,12 @@ public override bool Execute()
[Required]
public string OutDirectory { get; set; }

/// <summary>
/// The directory in which the native built files were written to
/// </summary>
[Required]
public string NativeOutputPath { get; set; }

/// <summary>
/// Use multi threading
/// </summary>
Expand All @@ -95,5 +101,10 @@ public override bool Execute()
/// Semicolon separated list of references
/// </summary>
public string AddInInclude { get; set; }

/// <summary>
/// Enable/disable including pdb files in packed add-in
/// </summary>
public bool IncludePdb { get; set; }
}
}
30 changes: 25 additions & 5 deletions Source/ExcelDna.Host.NativeAOT/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ TempDir tempDir(L"ExcelDna.Host.NativeAOT");

int load_and_run(const std::wstring& basePath, XlAddInExportInfo* pExportInfo, HMODULE hModuleXll, LPCWSTR pathXll)
{
std::wstring hostFile(GetAddInFullPath());
RenameExtension(hostFile, L".dll");
std::wstring hostFileName;
{
int r = LoadPropertyFromResource(hModuleXll, L"__MAIN___ORIGINAL_DLL_FILE_NAME", hostFileName);
if (r != EXIT_SUCCESS)
return r;
}
std::wstring hostFile(PathCombine(GetDirectory(GetAddInFullPath()), hostFileName));

if (!std::filesystem::exists(hostFile))
{
std::wstring hostFileName = hostFile;
StripPath(hostFileName);

hostFile = PathCombine(tempDir.GetPath(), hostFileName);
if (!std::filesystem::exists(hostFile))
{
Expand All @@ -29,6 +31,24 @@ int load_and_run(const std::wstring& basePath, XlAddInExportInfo* pExportInfo, H
}
}

if (FindResource(hModuleXll, L"__MAIN__", L"PDB") != NULL)
{
std::wstring pdbFileName;
{
int r = LoadPropertyFromResource(hModuleXll, L"__MAIN___ORIGINAL_PDB_FILE_NAME", pdbFileName);
if (r != EXIT_SUCCESS)
return r;
}
std::wstring pdbFile(PathCombine(GetDirectory(hostFile), pdbFileName));

if (!std::filesystem::exists(pdbFile))
{
int r = WriteResourceToFile(hModuleXll, L"__MAIN__", L"PDB", pdbFile);
if (r != EXIT_SUCCESS)
return r;
}
}

HINSTANCE handle = LoadLibrary(hostFile.c_str());

if (handle == NULL)
Expand Down
49 changes: 38 additions & 11 deletions Source/ExcelDna.Host.Shared/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,15 @@ HRESULT WriteAllBytes(const std::wstring& filePath, void* buf, DWORD size)
if (hFile == INVALID_HANDLE_VALUE)
return HResultFromLastError();

DWORD dwBytesWritten;
if (!WriteFile(hFile, buf, size, &dwBytesWritten, NULL))
if (size > 0 && buf != NULL)
{
HRESULT hr = HResultFromLastError();
CloseHandle(hFile);
return hr;
DWORD dwBytesWritten;
if (!WriteFile(hFile, buf, size, &dwBytesWritten, NULL))
{
HRESULT hr = HResultFromLastError();
CloseHandle(hFile);
return hr;
}
}

if (!CloseHandle(hFile))
Expand Down Expand Up @@ -418,26 +421,26 @@ BOOL IsBufferUTF8(BYTE* buffer, DWORD bufferLength)
return true;
}

int WriteResourceToFile(HMODULE hModuleXll, const std::wstring& resourceName, const std::wstring& resourceType, const std::wstring& filePath)
int LoadResourceBytes(HMODULE hModuleXll, const std::wstring& name, const std::wstring& type, std::vector<byte>& result)
{
HRSRC hResManagedHost = FindResource(hModuleXll, resourceName.c_str(), resourceType.c_str());
HRSRC hResManagedHost = FindResource(hModuleXll, name.c_str(), type.c_str());
if (hResManagedHost == NULL)
{
ShowHostError(L"Failure to find resource " + resourceName);
ShowHostError(L"Failure to find resource " + name);
return EXIT_FAILURE;
}

HGLOBAL hManagedHost = LoadResource(hModuleXll, hResManagedHost);
if (hManagedHost == NULL)
{
ShowHostError(L"Failure to load resource " + resourceName);
ShowHostError(L"Failure to load resource " + name);
return EXIT_FAILURE;
}

void* buf = LockResource(hManagedHost);
if (buf == NULL)
{
ShowHostError(L"Failure to lock resource " + resourceName);
ShowHostError(L"Failure to lock resource " + name);
return EXIT_FAILURE;
}

Expand All @@ -446,7 +449,19 @@ int WriteResourceToFile(HMODULE hModuleXll, const std::wstring& resourceName, co
byte* pData;
int nSize = safeBytes.AccessData(&pData);

HRESULT hr = WriteAllBytes(filePath, pData, nSize);
result = std::vector<byte>(pData, pData + resSize);

return EXIT_SUCCESS;
}

int WriteResourceToFile(HMODULE hModuleXll, const std::wstring& resourceName, const std::wstring& resourceType, const std::wstring& filePath)
{
std::vector<byte> bytes;
int r = LoadResourceBytes(hModuleXll, resourceName, resourceType, bytes);
if (r != EXIT_SUCCESS)
return r;

HRESULT hr = WriteAllBytes(filePath, bytes.empty() ? NULL : &bytes[0], bytes.size());
if (FAILED(hr))
{
std::wstringstream stream;
Expand All @@ -457,3 +472,15 @@ int WriteResourceToFile(HMODULE hModuleXll, const std::wstring& resourceName, co

return EXIT_SUCCESS;
}

int LoadPropertyFromResource(HMODULE hModuleXll, const std::wstring& name, std::wstring& result)
{
std::vector<byte> bytes;
int r = LoadResourceBytes(hModuleXll, name, L"PROPERTY", bytes);
if (r != EXIT_SUCCESS)
return r;

result = bytes.empty() ? std::wstring() : std::wstring(reinterpret_cast<const wchar_t*>(&bytes[0]), bytes.size() / 2);

return EXIT_SUCCESS;
}
1 change: 1 addition & 0 deletions Source/ExcelDna.Host.Shared/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,4 @@ std::wstring GetAddInFullPath();
BOOL IsBufferUTF8(BYTE* buffer, DWORD bufferLength);

int WriteResourceToFile(HMODULE hModuleXll, const std::wstring& resourceName, const std::wstring& resourceType, const std::wstring& filePath);
int LoadPropertyFromResource(HMODULE hModuleXll, const std::wstring& name, std::wstring& result);
9 changes: 9 additions & 0 deletions Source/ExcelDna.ManagedHost/AssemblyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ internal static string NativeLibraryResolve(string unmanagedDllName)
Directory.CreateDirectory(tempDirPath);
File.WriteAllBytes(dllPath, dllBytes);
}

byte[] pdbBytes = GetResourceBytes(unmanagedDllName.ToUpperInvariant(), 4);
if (pdbBytes != null)
{
string pdbPath = Path.ChangeExtension(dllPath, "pdb");
if (!File.Exists(pdbPath))
File.WriteAllBytes(pdbPath, pdbBytes);
}

return dllPath;
#else
return null;
Expand Down
32 changes: 25 additions & 7 deletions Source/ExcelDna.PackedResources/ExcelDnaPack.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using System;
using ExcelDna.Integration;
using ExcelDna.PackedResources.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using ExcelDna.Integration;
using ExcelDna.PackedResources.Logging;
using System.Reflection;
using System.Linq;
using System.Reflection;

namespace ExcelDna.PackedResources
{
Expand Down Expand Up @@ -150,14 +150,14 @@ public static int Pack(string dnaPath, string xllOutputPathParam, bool compress,
return 0;
}

public static int PackNativeAOT(string mainNativeAssembly, IEnumerable<string> includeAssemblies, string xllOutput, bool multithreading, bool useManagedResourceResolver, IBuildLogger buildLogger)
public static int PackNativeAOT(string mainNativeAssembly, IEnumerable<string> includeAssemblies, string xllOutput, bool multithreading, bool useManagedResourceResolver, bool includePdb, IBuildLogger buildLogger)
{
ResourceHelper.ResourceUpdater ru = new ResourceHelper.ResourceUpdater(xllOutput, useManagedResourceResolver, buildLogger);
ru.AddFile(File.ReadAllBytes(mainNativeAssembly), "__MAIN__", ResourceHelper.TypeName.NATIVE_ASSEMBLY, null, false, multithreading); // Name here must exactly match name in host.cpp.
AddDllAndPdb(ru, mainNativeAssembly, "__MAIN__", ResourceHelper.TypeName.NATIVE_ASSEMBLY, null, false, multithreading, includePdb, true); // Name here must exactly match name in host.cpp.

#if PACKEXTENDEDDEPS
foreach (var a in includeAssemblies.Where(IsNativeLibrary))
ru.AddFile(File.ReadAllBytes(a), Path.GetFileName(a).ToUpperInvariant(), ResourceHelper.TypeName.NATIVE_LIBRARY, null, true, multithreading);
AddDllAndPdb(ru, a, Path.GetFileName(a), ResourceHelper.TypeName.NATIVE_LIBRARY, null, true, multithreading, includePdb, false);
#endif

ru.EndUpdate();
Expand All @@ -166,6 +166,24 @@ public static int PackNativeAOT(string mainNativeAssembly, IEnumerable<string> i
return 0;
}

private static void AddDllAndPdb(ResourceHelper.ResourceUpdater ru, string dllPath, string name, ResourceHelper.TypeName typeName, string source, bool compress, bool multithreading, bool includePdb, bool addOriginalFileName)
{
ru.AddFile(File.ReadAllBytes(dllPath), name.ToUpperInvariant(), typeName, source, compress, multithreading);
if (addOriginalFileName)
ru.AddProperty(($"{name}_ORIGINAL_DLL_FILE_NAME").ToUpperInvariant(), Path.GetFileName(dllPath), source);

if (!includePdb)
return;

string pdbPath = Path.ChangeExtension(dllPath, "pdb");
if (!File.Exists(pdbPath))
return;

ru.AddFile(File.ReadAllBytes(pdbPath), name.ToUpperInvariant(), ResourceHelper.TypeName.PDB, source, compress, multithreading);
if (addOriginalFileName)
ru.AddProperty(($"{name}_ORIGINAL_PDB_FILE_NAME").ToUpperInvariant(), Path.GetFileName(pdbPath), source);
}

static private byte[] PackDnaLibrary(string dnaPath, byte[] dnaContent, string dnaDirectory, ResourceHelper.ResourceUpdater ru, bool compress, bool multithreading, List<string> filesToPublish, bool packManagedDependencies, string[] dependenciesToExcludeParam, string outputBitness, IBuildLogger buildLogger)
{
List<string> dependenciesToExclude = new List<string>();
Expand Down
7 changes: 7 additions & 0 deletions Source/ExcelDna.PackedResources/ResourceHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ internal enum TypeName
NATIVE_LIBRARY = 5,
DOC = 6,
NATIVE_ASSEMBLY = 7,
PROPERTY = 8,
}

// TODO: Learn about locales
Expand Down Expand Up @@ -217,6 +218,12 @@ public int AddTypeLib(byte[] data)
return typelibIndex;
}

public void AddProperty(string name, string value, string source)
{
Debug.Assert(name == name.ToUpperInvariant());
DoUpdateResource(TypeName.PROPERTY.ToString(), name, source, System.Text.Encoding.Unicode.GetBytes(value));
}

public void DoUpdateResource(string typeName, string name, string source, byte[] data)
{
lock (lockResource)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<ExcelAddInIncludePdb>True</ExcelAddInIncludePdb>
<ExcelAddInInclude>MyNativeLibrary.dll</ExcelAddInInclude>

<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishAOT>true</PublishAOT>
</PropertyGroup>

<ItemGroup>
<None Update="MyNativeLibrary.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="MyNativeLibrary.pdb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<Reference Include="ExcelDna.Integration">
<HintPath>..\..\.exceldna.addin\tools\net8.0-windows7.0\ExcelDna.Integration.dll</HintPath>
</Reference>
<Reference Include="ExcelDna.ManagedHost.dll">
<HintPath>..\..\.exceldna.addin\tools\net6.0-windows7.0\ExcelDna.ManagedHost.dll</HintPath>
</Reference>
<Reference Include="ExcelDna.Loader.dll">
<HintPath>..\..\.exceldna.addin\tools\net8.0-windows7.0\ExcelDna.Loader.dll</HintPath>
</Reference>
</ItemGroup>

<ItemGroup>
<Analyzer Include="..\..\.exceldna.addin\analyzers\ExcelDna.SourceGenerator.NativeAOT.dll" />
</ItemGroup>

<Import Project="$(ProjectDir)..\..\.exceldna.addin\build\ExcelDna.AddIn.NativeAOT.props" />
<Import Project="$(ProjectDir)..\..\.exceldna.addin\build\ExcelDna.AddIn.NativeAOT.targets" />

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using ExcelDna.Integration;
using System;
using System.IO;
using System.Runtime.InteropServices;

namespace AOTPackPdb
{
public class AddIn : IExcelAddIn
{
[DllImport("kernel32.dll")]
static extern void DebugBreak();

[DllImport("kernel32.dll")]
static extern bool IsDebuggerPresent();

[DllImport("MyNativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int MySum(int a1, int a2);

public void AutoOpen()
{
var thisAddInName = Path.GetFileName((string)XlCall.Excel(XlCall.xlGetName));
var message = string.Format("Excel-DNA Add-In '{0}' loaded!", thisAddInName);
message += Environment.NewLine + MySum(40, 2);

if (IsDebuggerPresent())
DebugBreak();

System.Diagnostics.Trace.WriteLine(message);
}

public void AutoClose()
{
}
}
}
Binary file not shown.
Binary file not shown.