将磁盘映像写入设备,类似于 linux dd 命令

问题描述 投票:0回答:0

我在看如何用C#.Net实现linux dd命令的功能:

添加 if=/dev/sdX of=disk_image_file
dd if=disk_image_file of=/dev/sdX

磁盘映像的创建我已经在thisthis主题的帮助下实现了,现在我正在尝试类似地将这样的磁盘映像写回设备,在我的例子中是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

取自here:在写入操作之前,应用程序可能会卸载并锁定设备。我会调查这个问题。

c# winapi device dd diskimage
© www.soinside.com 2019 - 2024. All rights reserved.