Created
August 11, 2025 02:21
-
-
Save rkttu/9d92b36ff8f5c6a332e68716d0c28c4c to your computer and use it in GitHub Desktop.
Native DLL example that creates an XLSX file that can be run with rundll32.exe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env dotnet | |
#:package [email protected] | |
#:property OutputType=Library | |
#:property NativeLib=Shared | |
#:property RuntimeIdentifier=win-x64 | |
#:property AllowUnsafeBlocks=true | |
// dotnet publish .\script.cs -o bin | |
// %windir%\system32\rundll32.exe bin\script.dll,EntryA "HelloWorld.xlsx" | |
// start HelloWorld.xlsx | |
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
using ClosedXML.Excel; | |
public static unsafe class Exports | |
{ | |
// ANSI version: rundll32 "<...>\RundllXlsx.dll",EntryA "C:\path\HelloWorld.xlsx" | |
[UnmanagedCallersOnly(EntryPoint = "EntryA", CallConvs = new[] { typeof(CallConvStdcall) })] | |
public static void EntryA(nint hwnd, nint hinst, sbyte* cmdLine, int nCmdShow) | |
=> Run(hwnd, PtrToManagedAnsi(cmdLine)); | |
private static void Run(nint hwnd, string? rawArgs) | |
{ | |
try | |
{ | |
var path = ParseFirstToken(rawArgs); | |
if (string.IsNullOrWhiteSpace(path)) | |
{ | |
Show(hwnd, | |
"Usage:\nrundll32.exe \"<dll>\",EntryA \"C:\\out\\HelloWorld.xlsx\"", | |
"RundllXlsx - Missing Path"); | |
return; | |
} | |
path = Path.GetFullPath(path.Trim()); | |
var dir = Path.GetDirectoryName(path); | |
if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); | |
CreateXlsx(path); | |
Show(hwnd, $"XLSX written:\n{path}", "RundllXlsx - Success"); | |
} | |
catch (Exception ex) | |
{ | |
Show(hwnd, ex.ToString(), "RundllXlsx - Error"); | |
} | |
} | |
private static void CreateXlsx(string path) | |
{ | |
using var wb = new XLWorkbook(); | |
var ws = wb.Worksheets.Add("Sample Sheet"); | |
ws.Cell("A1").Value = "Hello World!"; | |
ws.Cell("A2").FormulaA1 = "=MID(A1, 7, 5)"; | |
wb.SaveAs(path); | |
} | |
// ---- helpers ---- | |
private static string? PtrToManagedAnsi(sbyte* p) | |
=> p == null ? null : Marshal.PtrToStringAnsi((nint)p); | |
private static string? PtrToManagedUni(char* p) | |
=> p == null ? null : Marshal.PtrToStringUni((nint)p); | |
private static string? ParseFirstToken(string? s) | |
{ | |
if (string.IsNullOrWhiteSpace(s)) return null; | |
s = s.Trim(); | |
if (s.StartsWith("\"") && s.EndsWith("\"") && s.Length >= 2) | |
return s.Substring(1, s.Length - 2); | |
var idx = s.IndexOf(' '); | |
return idx < 0 ? s : s.Substring(0, idx); | |
} | |
[DllImport("user32.dll", CharSet = CharSet.Unicode)] | |
private static extern int MessageBoxW(nint hWnd, string text, string caption, uint type); | |
private static void Show(nint hwnd, string text, string caption) => MessageBoxW(hwnd, text, caption, 0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment