如何用C#.Net实现Linux dd命令的磁盘镜像写入功能?
用C#/.Net实现Linux dd功能时写入SD卡遇权限拒绝问题解决
我正在尝试用C#/.Net实现Linux dd命令的核心功能:
dd if=/dev/sdX of=disk_image_file dd if=disk_image_file of=/dev/sdX
目前已实现从设备创建磁盘镜像,但将镜像写回SD卡时,抛出System.UnauthorizedAccessException: 路径访问被拒绝错误。
复现代码
class Program { [DllImport( "Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto )] public static extern SafeFileHandle CreateFile( string fileName, [MarshalAs( UnmanagedType.U4 )] FileAccess fileAccess, [MarshalAs( UnmanagedType.U4 )] FileShare fileShare, IntPtr securityAttributes, [MarshalAs( UnmanagedType.U4 )] FileMode creationDisposition, int flags, IntPtr template ); static void Main( string[] args ) { if( !IsAdministrator() ) { Console.Error.WriteLine( "Not an administrator" ); return; } var imageFile = Path.GetTempFileName(); Console.WriteLine( $"Image File: {imageFile}" ); try { var deviceId = GetUsbDevice(); Console.WriteLine( $"Device ID: {deviceId}" ); CreateDiskImage( deviceId, imageFile ); CreateDiskFromImage( deviceId, imageFile ); } catch( Exception exception ) { Console.WriteLine( $"ERROR: {exception}" ); } finally { File.Delete( imageFile ); } } private static string GetUsbDevice() { var searcher = new ManagementObjectSearcher( "SELECT DeviceID, MediaType FROM Win32_DiskDrive WHERE MediaType='Removable Media' AND InterfaceType='USB'" ); var drive = searcher.Get().Cast<ManagementObject>().FirstOrDefault(); return drive?[ "DeviceID" ].ToString(); } private static void CreateDiskImage( string deviceId, string imageFile ) { using( SafeFileHandle device = CreateFile( deviceId, FileAccess.Read, FileShare.Write | FileShare.Read | FileShare.Delete, IntPtr.Zero, FileMode.Open, (int) FileAttributes.System | (int) FileOptions.SequentialScan, IntPtr.Zero ) ) { using( FileStream dest = File.Open( imageFile, FileMode.Create ) ) { using( FileStream src = new FileStream( device, FileAccess.Read ) ) { CopyTo( src, dest, 1048576 ); //read first 1MB for simplifying } } } } private static void CreateDiskFromImage( string deviceId, string imageFile ) { using( SafeFileHandle device = CreateFile( deviceId, FileAccess.ReadWrite, FileShare.Write | FileShare.Read, IntPtr.Zero, FileMode.Open, (int) FileAttributes.System, IntPtr.Zero ) ) { using( FileStream src = File.Open( imageFile, FileMode.Open ) ) { using( FileStream dest = new FileStream( device, FileAccess.Write ) ) { src.CopyTo( dest ); } } } } public static long CopyTo( Stream input, Stream output, long length ) { byte[] buffer = new byte[ 1048576 ]; int read; long totalRead = 0; while( totalRead < length && (read = input.Read( buffer, 0, buffer.Length )) > 0 ) { output.Write( buffer, 0, read ); totalRead += read; } Console.WriteLine( $"Read first {length} bytes." ); return totalRead; } private static bool IsAdministrator() { using( WindowsIdentity identity = WindowsIdentity.GetCurrent() ) { WindowsPrincipal principal = new WindowsPrincipal( identity ); return principal.IsInRole( WindowsBuiltInRole.Administrator ); } } }
我找不到代码中的问题,难道这个功能无法实现?求提示。
更新记录
- 更新1:查阅资料后得知,写入操作前需要卸载并锁定设备,将针对此方向展开调查。
- 更新2:已确认写入失败的原因是SD卡上的挂载分区占用了设备,删除分区后代码成功将镜像写入磁盘。
删除分区的方法
用diskpart命令:
select disk N # N为磁盘编号 select part 1 # 选择第一个分区 delete part
用PowerShell命令:
Remove-Partition -DiskNumber N -PartitionNumber 1 -Confirm:$false
内容的提问来源于stack exchange,提问作者igor.br
相关产品推荐
相关产品推荐

