2011-08-17 32 views
9

Tôi đang viết một ứng dụng C# .Net để chạy trên các cửa sổ cần chụp ảnh đĩa di động và đưa nó vào Linux Live USB. Live USB được lắp vào máy mục tiêu và khởi động, khi khởi động nó chạy một tập lệnh sử dụng lệnh dd như vậy để flash nó lên một ổ đĩa khác:Windows C# triển khai lệnh linux dd

dd if =/path/to/file/from/csharp/program of =/dev/sdX

Sự cố tôi đang gặp đang tạo hình ảnh ở phía cửa sổ. Tôi đã thử Live Linux của tôi với các tệp tôi đã tạo trên hệ thống Linux bằng dd và hoạt động tốt, nhưng tôi cần có khả năng tạo các tệp này từ trong ứng dụng C# .Net trên Windows. Tôi không muốn phải dựa vào Cygwin hoặc một số phụ thuộc khác nên cố gắng sử dụng chức năng Win32 CreateFile để mở thiết bị vật lý.

CreateFile được gọi với arg đầu tiên thiết lập để "\ \ F:." (Nếu F: là ổ đĩa tôi muốn hình ảnh), như vậy:

SafeFileHandle TheDevice = CreateFile(_DevicePath, (uint)FileAccess.Read, (uint)(FileShare.Write | FileShare.Read | FileShare.Delete), IntPtr.Zero, (uint)FileMode.Open, (uint)FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_SEQUENTIAL_SCAN, IntPtr.Zero); 
if (TheDevice.IsInvalid) 
{ 
    throw new IOException("Unable to access drive. Win32 Error Code " + Marshal.GetLastWin32Error()); 
} 
FileStream Dest = System.IO.File.Open(_SaveFile, FileMode.Create); 
FileStream Src = new FileStream(TheDevice, FileAccess.Read); 
Src.CopyTo(Dest); 
Dest.Flush(); 
Src.Close(); 
Dest.Close(); 

Nhưng khi các tập tin đầu ra là dd 'd trở lại vào một đĩa bằng cách sử dụng USB Linux Live kết quả không như mong đợi (đĩa không thể khởi động được, nhưng từ kiểm tra tệp đầu ra trong trình chỉnh sửa hex, có vẻ như có một MBR ở đầu vv).

Đây có phải là vấn đề với endianess hay tôi nên sử dụng thứ gì đó không phải là FileStream để sao chép dữ liệu vào tệp. Ngoài ra là có một ví dụ về dd cho mã nguồn Windows (C# hoặc C + +, tôi đã nhìn vào Delphi cho http://www.chrysocome.net/dd và không hoàn toàn hiểu nó hoặc có một IDE Delphi phong nha để chọn mã ngoài) vì vậy tôi có thể thấy nó hoạt động như thế nào?

UPDATE/EDIT:

Dưới đây là một chuỗi hex của 512 Bytes đầu tiên mà sản lượng dd chứa:

33 C0 FA 8E D8 8E D0 BC 00 7C 89 E6 06 57 8E C0 FB FC BF 00 06 B9 00 01 F3 A5 EA 1F 06 
00 00 52 52 B4 41 BB AA 55 31 C9 30 F6 F9 CD 13 72 13 81 FB 55 AA 75 0D D1 E9 73 09 66 
C7 06 8D 06 B4 42 EB 15 5A B4 08 CD 13 83 E1 3F 51 0F B6 C6 40 F7 E1 52 50 66 31 C0 66 
99 E8 66 00 E8 21 01 4D 69 73 73 69 6E 67 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 
65 6D 2E 0D 0A 66 60 66 31 D2 BB 00 7C 66 52 66 50 06 53 6A 01 6A 10 89 E6 66 F7 36 F4 
7B C0 E4 06 88 E1 88 C5 92 F6 36 F8 7B 88 C6 08 E1 41 B8 01 02 8A 16 FA 7B CD 13 8D 64 
10 66 61 C3 E8 C4 FF BE BE 7D BF BE 07 B9 20 00 F3 A5 C3 66 60 89 E5 BB BE 07 B9 04 00 
31 C0 53 51 F6 07 80 74 03 40 89 DE 83 C3 10 E2 F3 48 74 5B 79 39 59 5B 8A 47 04 3C 0F 
74 06 24 7F 3C 05 75 22 66 8B 47 08 66 8B 56 14 66 01 D0 66 21 D2 75 03 66 89 C2 E8 AC 
FF 72 03 E8 B6 FF 66 8B 46 1C E8 A0 FF 83 C3 10 E2 CC 66 61 C3 E8 62 00 4D 75 6C 74 69 
70 6C 65 20 61 63 74 69 76 65 20 70 61 72 74 69 74 69 6F 6E 73 2E 0D 0A 66 8B 44 08 66 
03 46 1C 66 89 44 08 E8 30 FF 72 13 81 3E FE 7D 55 AA 0F 85 06 FF BC FA 7B 5A 5F 07 FA 
FF E4 E8 1E 00 4F 70 65 72 61 74 69 6E 67 20 73 79 73 74 65 6D 20 6C 6F 61 64 20 65 72 
72 6F 72 2E 0D 0A 5E AC B4 0E 8A 3E 62 04 B3 07 CD 10 3C 0A 75 F1 CD 18 F4 EB FD 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 19 16 9F 29 00 00 80 01 01 00 06 FE 3F 0E 3F 00 00 00 61 C8 03 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA 

và đây là những gì mã của tôi sản xuất:

EB 76 90 4D 53 44 4F 53 35 2E 30 00 02 04 04 00 02 00 02 00 00 F8 F2 00 3F 00 FF 00 3F 
00 00 00 61 C8 03 00 80 00 29 7A E8 21 04 4E 4F 20 4E 41 4D 45 20 20 20 20 46 41 54 31 
36 20 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 E9 05 01 B4 0E 53 33 DB CD 10 5B C3 8A 07 3C 00 74 06 E8 EE FF 43 EB F4 C3 
0D 4E 6F 20 42 50 42 3A 20 43 61 6E 27 74 20 62 6F 6F 74 20 75 73 69 6E 67 20 43 48 53 
20 66 75 6E 63 74 69 6F 6E 73 00 50 B0 2E E8 BC FF 58 33 DB 8E 06 E4 01 F6 06 DC 01 02 
75 42 F6 06 DC 01 04 75 07 80 3E E8 01 80 72 34 53 53 52 50 06 53 55 6A 10 8B F4 52 50 
8A 16 E8 01 B8 00 42 F9 CD 13 8A EC 58 5A 8D 64 10 72 14 80 FD 00 75 0F 03 C5 83 D2 00 
C3 BB 91 00 E8 78 FF F4 EB FD 83 3E 18 00 00 74 F0 52 50 8B CD F7 36 18 00 8B F2 03 D1 
3B 16 18 00 76 06 8B 0E 18 00 2B CE 33 D2 F7 36 1A 00 88 16 E9 01 8B F8 8B D7 51 8A C1 
8D 4C 01 C0 E6 06 0A CE 8A EA 8B 16 E8 01 B4 02 CD 13 59 73 15 80 FC 09 75 0A 49 EB DE 
8A C4 04 30 E8 18 FF B4 00 CD 13 EB D1 58 5A 03 C1 83 D2 00 2B E9 74 07 C1 E1 09 03 D9 
EB 94 C3 00 00 00 00 FA FC E8 00 00 5E 81 EE 85 01 2E 8B 84 E4 01 8E D8 8E C0 8E D0 2E 
C7 84 7C 01 AF 01 2E 89 84 7E 01 B9 00 01 BF 00 00 F3 2E A5 2E FF AC 7C FF BC 00 0A FB 
80 3E E8 01 FF 75 04 88 16 E8 01 83 06 E4 01 20 A1 E0 01 8B 16 E2 01 BD 02 00 E8 E9 FE 
50 52 EB 74 90 00 00 00 00 00 00 00 00 00 00 00 D3 20 00 00 00 30 80 00 FF 00 68 41 00 
40 09 FF 40 5A AC 04 00 00 AC 04 00 00 00 00 12 00 55 AA 

Điều này được lấy từ chính xác cùng một thẻ CF mà không có bất kỳ chỉnh sửa/ghi vv xảy ra, vì vậy tôi bối rối là tại sao chúng khác nhau, nhưng cả hai e nd với chính xác 55 AA byte quá. Windows có làm xáo trộn MBR trên các thẻ khi chúng được truy cập theo cách này hay là một số thứ lạ khác dưới những thứ mà tôi không biết?

+0

Tôi giả sử sử dụng tính năng "dd" từ cygwin từ mã C# của bạn không nằm trong câu hỏi? – Greg

+0

Nó sẽ là một phương sách cuối cùng, vấn đề tôi nghĩ có là chuyển đổi //./F: đường dẫn vào một cái gì đó mà dd dưới Cygwin hiểu. Vì vậy, vấn đề (đối với tôi) sau đó trở thành làm thế nào để trong ứng dụng C# chuyển đổi //./F: đường dẫn của tôi vào/dev/sdX trong Cygwin. –

+1

@Kragen Tôi nghĩ rằng những gì đang xảy ra ở đây là phiên bản cửa sổ đang nhận được bản ghi khởi động âm lượng không phải là bản ghi khởi động chính. Điều này có lẽ vì tôi đang chuyển đến nó //./F: và F: chỉ là phân vùng đầu tiên, không phải là Đĩa vật lý.Sẽ được tốt đẹp nếu một người nào khác có thể xác nhận nếu tôi là chính xác hay không trước khi tôi nhận được vào câu hỏi tiếp theo về làm thế nào để truy cập vào đĩa vật lý (thay vì phân vùng/khối lượng). –

Trả lời

4

Tôi nghĩ bạn nên làm gì - tôi đã thử bản thân mình bằng ảnh đĩa mềm có khả năng khởi động (được gắn dưới dạng ổ đĩa ảo bằng cách sử dụng ImDisk) và tệp kết quả là nhị phân giống với hình ảnh gốc.

Đối với đầy đủ ở đây là mã tôi đã sử dụng (trong entirity của nó):

using System; 
using System.IO; 
using System.Runtime.InteropServices; 
using Microsoft.Win32.SafeHandles; 

namespace ConsoleApplication1 
{ 
    public class Program 
    { 
     const int FILE_ATTRIBUTE_SYSTEM = 0x4; 
     const int FILE_FLAG_SEQUENTIAL_SCAN = 0x8; 

     [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); 

     [STAThread] 
     static void Main() 
     { 
      using (SafeFileHandle device = CreateFile(@"\\.\E:", FileAccess.Read, FileShare.Write | FileShare.Read | FileShare.Delete, IntPtr.Zero, FileMode.Open, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_SEQUENTIAL_SCAN, IntPtr.Zero)) 
      { 
       if (device.IsInvalid) 
       { 
        throw new IOException("Unable to access drive. Win32 Error Code " + Marshal.GetLastWin32Error()); 
       } 
       using (FileStream dest = File.Open("TempFile.bin", FileMode.Create)) 
       { 
        using (FileStream src = new FileStream(device, FileAccess.Read)) 
        { 
         src.CopyTo(dest); 
        } 
       } 
      } 
     } 
    } 
} 

Nếu điều này không làm việc sau đó nó dường như chỉ ra rằng:

  1. Có một vấn đề với ảnh gốc.
  2. Vấn đề là với bất kỳ thứ gì đang sử dụng hình ảnh đĩa bạn vừa mới viết.
  3. Có một số khác biệt tinh tế trong việc đối phó với các thiết bị cụ thể mà bạn đang truy cập (mặc dù tôi không thể nghĩ gì)

Các thủ phạm rất có thể là bước 2. Chính xác là nó mà bạn đang làm với kết quả hình ảnh đĩa?


Cập nhật: này được viết trong các ý kiến, nhưng cho đầy đủ tôi nghĩ rằng tôi muốn thêm nó vào câu trả lời của tôi - có vẻ như whats xảy ra là những nội dung của phân vùng đầu tiên của ổ đĩa đang được bằng văn bản, khi thay vào đó những gì được mong muốn là nội dung của toàn bộ đĩa.

Khi bạn hãy nhìn vào chuỗi thứ hai hex (một trong những sản xuất bởi mẫu mã) trong một cái gì đó giống như HxD chúng ta thấy điều này:

ëv.MSDOS5.0..........øò.?.ÿ.?...aÈ..€.)zè!.NO NAME FAT16 .. 
........................................................é..´.S3Û 
Í.[Ê.<.t.èîÿCëôÃ.No BPB: Can't boot using CHS functions.P°.è¼ÿX 
3ÛŽ.ä.ö.Ü..uBö.Ü..u.€>è.€r4SSRP.SUj.‹ôRPŠ.è.¸.BùÍ.ŠìXZ.d.r.€ý.u. 
.ŃÒ.û‘.èxÿôëýƒ>...tðRP‹Í÷6..‹ò.Ñ;...v.‹...+Î3Ò÷6..ˆ.é.‹ø‹×QŠÁ. 
L.Àæ..Ίê‹.è.´.Í.Ys.€ü.u.IëÞŠÄ.0è.ÿ´.Í.ëÑXZ.ÁƒÒ.+ét.Áá..Ùë”Ã.... 
úüè..^.î…..‹„ä.ŽØŽÀŽÐ.Ç„|.¯..‰„~.¹..¿..ó.¥.ÿ¬|ÿ¼..û€>è.ÿu.ˆ.è.ƒ. 
ä. ¡à.‹.â.½..èéþPRët............Ó ...0€.ÿ[email protected]ÿ@Z¬...¬.......Uª 

này có vẻ với tôi như boot sector of a FAT16 partition - sự hiện diện của chuỗi "MSDOS5.0", "NO NAME" và "FAT16" gần đầu là một giveaway chết.

Hãy so sánh này để đầu ra của chuỗi hex đầu tiên (một trong những sản xuất bởi đ):

3ÀúŽØŽÐ¼.|‰æ.WŽÀûü¿..¹..ó¥ê....RR´A»ªU1É0öùÍ.r..ûUªu.Ñés.fÇ...´B 
ë.Z´.Í.ƒá?Q.¶Æ@÷áRPf1Àf™èf.è!.Missing operating system...f`f1Ò». 
|fRfP.Sj.j.‰æf÷6ô{Àä.ˆáˆÅ’ö6ø{ˆÆ.áA¸..Š.ú{Í..d.faÃèÄÿ¾¾}¿¾.¹ .ó¥ 
Ãf`‰å»¾.¹..1ÀSQö.€[email protected]‰ÞƒÃ.âóHt[y9Y[ŠG.<.t.$.<.u"f‹G.f‹V.f.Ðf!Òu. 
f‰Âè¬ÿr.è¶ÿf‹F.è ÿƒÃ.âÌfaÃèb.Multiple active partitions...f‹D.f. 
F.f‰D.è0ÿr..>þ}Uª.….ÿ¼ú{Z_.úÿäè..Operating system load error...^ 
¬´.Š>b.³.Í.<.uñÍ.ôëý......................................Ÿ)..€. 
...þ?.?...aÈ..................................................Uª 

Và chúng ta thấy cái gì đó trông tôi rất giống một master boot record. Tại sao? Bởi vì trong MBR tất cả 440 byte đầu tiên là mã khởi động, không giống như sector khởi động FAT có chứa khối tham số bios đặc biệt (nó trông giống như rác ở trên, nhưng nếu bạn đặt thông qua bộ tách rời, bạn sẽ nhận được thứ gì đó có giá trị 16 bit mã).

Ngoài ra, cả hai đều giống như các phần khởi động hợp lệ và hoàn toàn khác nhau (hoàn thành với thông báo lỗi). Không có cách nào mà một lỗi lập trình có thể bị "làm xáo trộn" một cái để trông giống cái kia - nó phải chỉ là cái sai được đọc.


Để có được CreateFile để trả lại đĩa thay vì phân vùng có vẻ như bạn chỉ cần vượt qua nó một chuỗi khác nhau, ví dụ @"\\.\PhysicalDrive0" mở đĩa vật lý đầu tiên.

Xem:

+0

Một số thông tin cơ bản, điều đó sẽ giải thích những gì tôi đang làm chi tiết hơn. Các hệ thống cũ của chúng tôi được sử dụng để khởi động từ thẻ CF có định dạng FAT, vì vậy để cập nhật phần mềm trên hệ thống, bạn chỉ cần khởi động lại thẻ CF bằng ứng dụng cửa sổ. Hệ thống mới không hỗ trợ khởi động từ thẻ CF, nhưng nó có ổ cứng và cổng USB. Kế hoạch là, giống như trước khi sử dụng ứng dụng cửa sổ để flash thẻ CF, sau đó chụp ảnh thẻ CF đó (trong cửa sổ bằng ứng dụng C# của tôi) sao chép vào USB trực tiếp sau đó sẽ flash ổ cứng, từ Môi trường Linux trực tiếp sử dụng dd, với hình ảnh thẻ CF –

+0

Tôi không nghĩ đó là bước 2 như thể tôi đã đặt một hình ảnh mà tôi đã tạo từ CF bằng máy ảo Linux và dd vào Live USB nó hoạt động. –

+0

@rb_ 7 Ah tôi thấy - vì vậy hình ảnh cuối cùng được ghi vào một đĩa cứng. Trong trường hợp đó, tôi không chắc tại sao nó không hoạt động - miễn là sector đầu tiên (512 byte) kết thúc bằng các byte ký hiệu "valid bootsector" (0x55, 0xAA) BIOS chỉ cần tiếp tục và khởi động bằng boot sector đó. ** Giả sử của tôi ** sẽ là BIOS thực tế sử dụng sector khởi động đó, nhưng sự khác biệt về phần cứng có nghĩa là bộ tải khởi động (mà trước đây đã làm việc trên hệ thống cũ của bạn) đang bị lỗi trên hệ thống mới. – Justin

1

Đây là những gì tôi đã viết để làm được \ \ PhysicalDriveX con đường cho một ký tự ổ đĩa nhất định.. Nếu vượt qua ký tự ổ đĩa này và lấy giá trị trả về và chuyển vào CreateFile như là Param đầu tiên tôi sẽ nhận được một cái gì đó tương tự như dd dưới Linux.

using System.Management; //Add in a reference to this as well in the project settings 
public static string GetPhysicalDevicePath(char DriveLetter) 
{ 
    ManagementClass devs = new ManagementClass(@"Win32_Diskdrive"); 
    { 
     ManagementObjectCollection moc = devs.GetInstances(); 
     foreach(ManagementObject mo in moc) 
     { 
      foreach (ManagementObject b in mo.GetRelated("Win32_DiskPartition")) 
      { 
       foreach (ManagementBaseObject c in b.GetRelated("Win32_LogicalDisk")) 
       { 
        string DevName = string.Format("{0}", c["Name"]); 
        if (DevName[0] == DriveLetter) 
         return string.Format("{0}", mo["DeviceId"]); 
       } 
      } 
     } 
    } 
    return ""; 
} 
Các vấn đề liên quan