我在看如何用C#.Net实现linux dd命令的功能:
添加 if=/dev/sdX of=disk_image_file
dd if=disk_image_file of=/dev/sdX
磁盘映像的创建我已经在this和this主题的帮助下实现了,现在我正在尝试类似地将这样的磁盘映像写回设备,在我的例子中是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:在写入操作之前,应用程序可能会卸载并锁定设备。我会调查这个问题。