There is an old MS sample but it crashed on my PC : https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/winbase/imapi/IBurnBut this test worked on my Windows 10 OS (22H2) :
{
Guid CLSID_CDBurn = new Guid("fbeb8a05-beee-4442-804e-409d6c4515e9");
var pCDBurn = (ICDBurn)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_CDBurn));
StringBuilder sbDriveLetter = new StringBuilder(255);
HRESULT hr = pCDBurn.GetRecorderDriveLetter(sbDriveLetter, (uint)sbDriveLetter.Capacity);
string sDriveLetter = sbDriveLetter.ToString();
IntPtr pPath = IntPtr.Zero;
hr = SHGetKnownFolderPath(FOLDERID_CDBurning, 0, IntPtr.Zero, out pPath);
// C:\Users\Christian\AppData\Local\Microsoft\Windows\Burn\Burn
string sPath = Marshal.PtrToStringUni(pPath);
string sSource = @"E:\Images\Fire";
string sDest = sPath;
var fos = new SHFILEOPSTRUCT
{
wFunc = FO.FO_COPY,
pFrom = sSource + '\0',
pTo = sDest + '\0',
fFlags = FILEOP_FLAGS.FOF_ALLOWUNDO
};
int nReturn = SHFileOperation(ref fos);
pCDBurn.Burn(this.Handle);
}
with :
[ComImport, Guid("3d73a659-e5d0-4d42-afc0-5121ba425c8d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ICDBurn
{
HRESULT GetRecorderDriveLetter(StringBuilder pszDrive, uint cch);
HRESULT Burn(IntPtr hwnd);
HRESULT HasRecordableDrive(out bool pfHasRecorder);
}
public enum HRESULT : int
{
S_OK = 0,
S_FALSE = 1,
E_NOINTERFACE = unchecked((int)0x80004002),
E_NOTIMPL = unchecked((int)0x80004001),
E_FAIL = unchecked((int)0x80004005),
E_UNEXPECTED = unchecked((int)0x8000FFFF),
E_OUTOFMEMORY = unchecked((int)0x8007000E)
}
[DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern HRESULT SHGetKnownFolderPath([In, MarshalAs(UnmanagedType.LPStruct)] Guid rfid, int dwFlags, IntPtr hToken, out IntPtr ppszPath);
public static readonly Guid FOLDERID_Desktop = new Guid(0xB4BFCC3A, 0xDB2C, 0x424C, 0xB0, 0x29, 0x7F, 0xE9, 0x9A, 0x87, 0xC6, 0x41);
public static readonly Guid FOLDERID_CDBurning = new Guid(0x9E52AB10, 0xF80D, 0x49DF, 0xAC, 0xB8, 0x43, 0x30, 0xF5, 0x68, 0x78, 0x55);
public enum FO : int
{
FO_MOVE = 0x0001,
FO_COPY = 0x0002,
FO_DELETE = 0x0003,
FO_RENAME = 0x0004
}
[Flags]
public enum FILEOP_FLAGS : uint
{
FOF_MULTIDESTFILES = 0x0001,
FOF_CONFIRMMOUSE = 0x0002,
FOF_SILENT = 0x0004, // don't create progress/report
FOF_RENAMEONCOLLISION = 0x0008,
FOF_NOCONFIRMATION = 0x0010, // Don't prompt the user.
FOF_WANTMAPPINGHANDLE = 0x0020, // Fill in SHFILEOPSTRUCT.hNameMappings
// Must be freed using SHFreeNameMappings
FOF_ALLOWUNDO = 0x0040,
FOF_FILESONLY = 0x0080, // on *.*, do only files
FOF_SIMPLEPROGRESS = 0x0100, // means don't show names of files
FOF_NOCONFIRMMKDIR = 0x0200, // don't confirm making any needed dirs
FOF_NOERRORUI = 0x0400, // don't put up error UI
FOF_NOCOPYSECURITYATTRIBS = 0x0800, // dont copy NT file Security Attributes
FOF_NORECURSION = 0x1000, // don't recurse into directories.
FOF_NO_CONNECTED_ELEMENTS = 0x2000, // don't operate on connected file elements.
FOF_WANTNUKEWARNING = 0x4000, // during delete operation, warn if nuking instead of recycling (partially overrides FOF_NOCONFIRMATION)
FOF_NORECURSEREPARSE = 0x8000, // treat reparse points as objects, not containers
FOFX_NOSKIPJUNCTIONS = 0x00010000, // Don't avoid binding to junctions (like Task folder, Recycle-Bin)
FOFX_PREFERHARDLINK = 0x00020000, // Create hard link if possible
FOFX_SHOWELEVATIONPROMPT = 0x00040000, // Show elevation prompts when error UI is disabled (use with FOF_NOERRORUI)
FOFX_EARLYFAILURE = 0x00100000, // Fail operation as soon as a single error occurs rather than trying to process other items (applies only when using FOF_NOERRORUI)
FOFX_PRESERVEFILEEXTENSIONS = 0x00200000, // Rename collisions preserve file extns (use with FOF_RENAMEONCOLLISION)
FOFX_KEEPNEWERFILE = 0x00400000, // Keep newer file on naming conflicts
FOFX_NOCOPYHOOKS = 0x00800000, // Don't use copy hooks
FOFX_NOMINIMIZEBOX = 0x01000000, // Don't allow minimizing the progress dialog
FOFX_MOVEACLSACROSSVOLUMES = 0x02000000, // Copy security information when performing a cross-volume move operation
FOFX_DONTDISPLAYSOURCEPATH = 0x04000000, // Don't display the path of source file in progress dialog
FOFX_DONTDISPLAYDESTPATH = 0x08000000, // Don't display the path of destination file in progress dialog
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
[MarshalAs(UnmanagedType.U4)]
public FO wFunc;
public string pFrom;
public string pTo;
public FILEOP_FLAGS fFlags;
[MarshalAs(UnmanagedType.Bool)]
public bool fAnyOperationsAborted;
public IntPtr hNameMappings;
public string lpszProgressTitle;
}
[DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp);