.Net的資源文件
VS.Net 支持三種文件類型的resource:.txt、.resx、.resources。
system.resources 名字空間支持三種資源文件:
-
- txt 文件,只能有字符串資源。因為不能被嵌入到 assembly 中,所以非常容易暴露,被客戶修改。最大缺點是僅支持字符串資源,所以不推薦使用。
- .resx 文件,由 xml 組成,能加入所有資源,包括二進制。同樣不能被嵌入到 assembly 中。在 system.resources 名字空間中有專用讀寫的類。vs.net 創建這種文件然后將其轉成 .resources 文件並根據設置將其嵌入到 assembly 中。
- .resources 文件,pe 格式,能加入所有資源。唯一能被嵌入到 assembly 的文件,在 system.resources 名字空間中有專用讀寫的類。
- 把resx文件通過vs加入到.net工程中后,編譯完成時,它會被轉化為resources文件並embed到assembly中。
- System.resources.resourceManager負責讀取.net assembly中嵌入的resources文件中的資源信息。
- 三種文件類型,必須要轉為resources文件,才能被resourcemanager讀取(顯然的)。ResGen.exe主要完成此項工作。
- C++/CLI, vb.net, c#,大家都可以用resx文件是自然的。只不過在Vs里添加resx文件時,c#工程要支持的更完備些:直接替你封裝好了對resourcemanager的使用。
- 推薦工具
-
- resgen.exe:sdk 中的工具,專門用來做資源文件類型之間的轉換。支持 .txt <-> .resx <-> .resources 之間的轉換。
- resourcer:專門用來創建資源文件,簡單易用,支持 .resx 和 .resources 文件格式。
- .net reflector:用來瀏覽 assembly。如果你不確定一個資源文件的完整名時能用這個工具在 assembly 中查看。
ResX資源文件中圖標的提取
ResX文件中,是將所有資源(包括二進制)都寫入到XML文件中,每個圖標不再以獨立文件的形式存在。在編程工程中,尤其在學習、分析現有.Net應用程序過程中,需要提取現有應用程序中的圖標。基本思路是利用工具軟件,將應用程序的資源文件提取出來(具體方法可以進行網上搜索),生成resx或resources文件。當生成resources文件時,可以利用resgen.exe進行格式轉換。
通過對resx文件格式分析,開發了針對resx格式文件的圖標提取工具,本工具的具體代碼如下:
界面設計代碼:

1 <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _ 2 Partial Class frmMain 3 Inherits System.Windows.Forms.Form 4 5 'Form 重寫 Dispose,以清理組件列表。 6 <System.Diagnostics.DebuggerNonUserCode()> _ 7 Protected Overrides Sub Dispose(ByVal disposing As Boolean) 8 Try 9 If disposing AndAlso components IsNot Nothing Then 10 components.Dispose() 11 End If 12 Finally 13 MyBase.Dispose(disposing) 14 End Try 15 End Sub 16 17 'Windows 窗體設計器所必需的 18 Private components As System.ComponentModel.IContainer 19 20 '注意: 以下過程是 Windows 窗體設計器所必需的 21 '可以使用 Windows 窗體設計器修改它。 22 '不要使用代碼編輯器修改它。 23 <System.Diagnostics.DebuggerStepThrough()> _ 24 Private Sub InitializeComponent() 25 Me.components = New System.ComponentModel.Container() 26 Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(frmMain)) 27 Me.ImageList1 = New System.Windows.Forms.ImageList(Me.components) 28 Me.ListView1 = New System.Windows.Forms.ListView() 29 Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog() 30 Me.MenuStrip1 = New System.Windows.Forms.MenuStrip() 31 Me.FleToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem() 32 Me.mnuFileOpen = New System.Windows.Forms.ToolStripMenuItem() 33 Me.mnuFileExport = New System.Windows.Forms.ToolStripMenuItem() 34 Me.mnuFileExit = New System.Windows.Forms.ToolStripMenuItem() 35 Me.FolderBrowserDialog1 = New System.Windows.Forms.FolderBrowserDialog() 36 Me.MenuStrip1.SuspendLayout() 37 Me.SuspendLayout() 38 ' 39 'ImageList1 40 ' 41 Me.ImageList1.ImageStream = CType(resources.GetObject("ImageList1.ImageStream"), System.Windows.Forms.ImageListStreamer) 42 Me.ImageList1.TransparentColor = System.Drawing.Color.Transparent 43 Me.ImageList1.Images.SetKeyName(0, "bmp00002.bmp") 44 Me.ImageList1.Images.SetKeyName(1, "") 45 Me.ImageList1.Images.SetKeyName(2, "") 46 Me.ImageList1.Images.SetKeyName(3, "") 47 Me.ImageList1.Images.SetKeyName(4, "") 48 Me.ImageList1.Images.SetKeyName(5, "") 49 Me.ImageList1.Images.SetKeyName(6, "") 50 Me.ImageList1.Images.SetKeyName(7, "") 51 Me.ImageList1.Images.SetKeyName(8, "") 52 Me.ImageList1.Images.SetKeyName(9, "") 53 Me.ImageList1.Images.SetKeyName(10, "") 54 Me.ImageList1.Images.SetKeyName(11, "") 55 Me.ImageList1.Images.SetKeyName(12, "") 56 Me.ImageList1.Images.SetKeyName(13, "") 57 Me.ImageList1.Images.SetKeyName(14, "") 58 ' 59 'ListView1 60 ' 61 Me.ListView1.Dock = System.Windows.Forms.DockStyle.Fill 62 Me.ListView1.HideSelection = False 63 Me.ListView1.LargeImageList = Me.ImageList1 64 Me.ListView1.Location = New System.Drawing.Point(0, 25) 65 Me.ListView1.Name = "ListView1" 66 Me.ListView1.Size = New System.Drawing.Size(763, 544) 67 Me.ListView1.SmallImageList = Me.ImageList1 68 Me.ListView1.TabIndex = 3 69 Me.ListView1.UseCompatibleStateImageBehavior = False 70 Me.ListView1.View = System.Windows.Forms.View.SmallIcon 71 ' 72 'OpenFileDialog1 73 ' 74 Me.OpenFileDialog1.FileName = "OpenFileDialog1" 75 ' 76 'MenuStrip1 77 ' 78 Me.MenuStrip1.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.FleToolStripMenuItem}) 79 Me.MenuStrip1.Location = New System.Drawing.Point(0, 0) 80 Me.MenuStrip1.Name = "MenuStrip1" 81 Me.MenuStrip1.Size = New System.Drawing.Size(763, 25) 82 Me.MenuStrip1.TabIndex = 4 83 Me.MenuStrip1.Text = "MenuStrip1" 84 ' 85 'FleToolStripMenuItem 86 ' 87 Me.FleToolStripMenuItem.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.mnuFileOpen, Me.mnuFileExport, Me.mnuFileExit}) 88 Me.FleToolStripMenuItem.Name = "FleToolStripMenuItem" 89 Me.FleToolStripMenuItem.Size = New System.Drawing.Size(36, 21) 90 Me.FleToolStripMenuItem.Text = "&Fle" 91 ' 92 'mnuFileOpen 93 ' 94 Me.mnuFileOpen.Name = "mnuFileOpen" 95 Me.mnuFileOpen.Size = New System.Drawing.Size(180, 22) 96 Me.mnuFileOpen.Text = "&Open" 97 ' 98 'mnuFileExport 99 ' 100 Me.mnuFileExport.Name = "mnuFileExport" 101 Me.mnuFileExport.Size = New System.Drawing.Size(180, 22) 102 Me.mnuFileExport.Text = "&Export..." 103 ' 104 'mnuFileExit 105 ' 106 Me.mnuFileExit.Name = "mnuFileExit" 107 Me.mnuFileExit.Size = New System.Drawing.Size(180, 22) 108 Me.mnuFileExit.Text = "e&Xit" 109 ' 110 'frmMain 111 ' 112 Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!) 113 Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font 114 Me.ClientSize = New System.Drawing.Size(763, 569) 115 Me.Controls.Add(Me.ListView1) 116 Me.Controls.Add(Me.MenuStrip1) 117 Me.MainMenuStrip = Me.MenuStrip1 118 Me.MaximizeBox = False 119 Me.MinimizeBox = False 120 Me.Name = "frmMain" 121 Me.Text = "Export Images From ImageList" 122 Me.MenuStrip1.ResumeLayout(False) 123 Me.MenuStrip1.PerformLayout() 124 Me.ResumeLayout(False) 125 Me.PerformLayout() 126 127 End Sub 128 129 Friend WithEvents ImageList1 As ImageList 130 Friend WithEvents ListView1 As ListView 131 Friend WithEvents OpenFileDialog1 As OpenFileDialog 132 Friend WithEvents MenuStrip1 As MenuStrip 133 Friend WithEvents FleToolStripMenuItem As ToolStripMenuItem 134 Friend WithEvents mnuFileOpen As ToolStripMenuItem 135 Friend WithEvents mnuFileExport As ToolStripMenuItem 136 Friend WithEvents mnuFileExit As ToolStripMenuItem 137 Friend WithEvents FolderBrowserDialog1 As FolderBrowserDialog 138 End Class
程序代碼:

1 Imports System.Resources 2 Imports Microsoft.VisualBasic.CompilerServices 3 Public Class frmMain 4 Private Sub mnuFileOpen_Click(sender As Object, e As EventArgs) Handles mnuFileOpen.Click 5 Me.OpenFileDialog1 = New OpenFileDialog 6 Me.OpenFileDialog1.DefaultExt = "resx" 7 Me.OpenFileDialog1.AddExtension = True 8 Me.OpenFileDialog1.Filter = ("Microsoft.Net managed Resource File") + " (*.resx)|*.resx" 9 Me.OpenFileDialog1.FilterIndex = 1 10 If Me.OpenFileDialog1.ShowDialog() = DialogResult.OK AndAlso Operators.CompareString(Me.OpenFileDialog1.FileName, "", False) <> 0 Then 11 filename = Me.OpenFileDialog1.FileName 12 mnuFileExport.Enabled = True 13 Dim rsxr As ResXResourceReader = New ResXResourceReader(filename) 14 Dim resxSet As New ResXResourceSet(filename) 15 Dim d As DictionaryEntry 16 Dim n As Integer = 0 17 For Each d In rsxr 18 If Operators.CompareString(d.Value.ToString(), "System.Drawing.Bitmap", False) = 0 Then 19 Console.WriteLine(d.Key.ToString() + ":" + ControlChars.Tab + "'" + d.Value.ToString() + "'") 20 Dim image As Bitmap = CType(resxSet.GetObject(d.Key.ToString(), True), Bitmap) 21 If image IsNot Nothing Then 22 ImageList1.Images.Add(image) 23 ListView1.Items.Add(New ListViewItem(n.ToString(), n)) 24 n += 1 25 End If 26 End If 27 Next d 28 rsxr.Close() 29 End If 30 End Sub 31 Private filename As String = "" 32 Private Sub mnuFileExport_Click(sender As Object, e As EventArgs) Handles mnuFileExport.Click 33 If Operators.CompareString(filename, "", False) <> 0 Then 34 Me.FolderBrowserDialog1.SelectedPath = "C:\" 35 Me.FolderBrowserDialog1.Description = "選擇保存圖標的目錄" 36 If Me.FolderBrowserDialog1.ShowDialog() = DialogResult.OK AndAlso Operators.CompareString(Me.FolderBrowserDialog1.SelectedPath, "", False) <> 0 Then 37 Dim rsxr As ResXResourceReader = New ResXResourceReader(filename) 38 Dim resxSet As New ResXResourceSet(filename) 39 Dim d As DictionaryEntry 40 For Each d In rsxr 41 If Operators.CompareString(d.Value.ToString(), "System.Drawing.Bitmap", False) = 0 Then 42 Console.WriteLine(d.Key.ToString() + ":" + ControlChars.Tab + "'" + d.Value.ToString() + "'") 43 Dim image As Bitmap = CType(resxSet.GetObject(d.Key.ToString(), True), Bitmap) 44 If image IsNot Nothing Then 45 image.Save(Me.FolderBrowserDialog1.SelectedPath + "\" + d.Key.ToString() + ".bmp") 46 End If 47 End If 48 Next d 49 rsxr.Close() 50 End If 51 End If 52 End Sub 53 Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load 54 mnuFileExport.Enabled = (Operators.CompareString(filename, "", False) <> 0) 55 End Sub 56 End Class
程序運行后,通過File-Open加載resx資源文件,圖標將列在ListView控件中,界面如下:
通過File——Export...選擇目標目錄,將圖標導出到指定目錄。
另外,針對System.Drawing.Icon、ImageList的ImageStream也可以進行相應處理,代碼如下:

1 If Operators.CompareString(d.Value.ToString(), "System.Drawing.Icon", False) = 0 Then 2 Dim image As Icon = CType(resxSet.GetObject(d.Key.ToString(), True), Icon) 3 If image IsNot Nothing Then 4 ImageList1.Images.Add(image) 5 ListView1.Items.Add(New ListViewItem(n.ToString(), n)) 6 n += 1 7 End If 8 End If 9 If Operators.CompareString(d.Key.ToString(), "ImageList1.ImageStream", False) = 0 Then 10 imgList.ImageStream = CType(resxSet.GetObject(d.Key.ToString(), True), System.Windows.Forms.ImageListStreamer) 11 For i As Integer = 0 To imgList.Images.Count - 1 12 ImageList1.Images.Add(imgList.Images(i)) 13 ListView1.Items.Add(New ListViewItem(n.ToString(), n)) 14 n += 1 15 Next 16 End If
其中,可以輸入ImageList控件名稱,來選擇具體解析對象。
代碼更新

1 Imports System.Resources 2 Imports Microsoft.VisualBasic.CompilerServices 3 Public Class frmMain 4 Private Sub mnuFileOpen_Click(sender As Object, e As EventArgs) Handles mnuFileOpen.Click, tsbOpen.Click 5 Me.OpenFileDialog1 = New OpenFileDialog 6 Me.OpenFileDialog1.DefaultExt = "resx" 7 Me.OpenFileDialog1.AddExtension = True 8 Me.OpenFileDialog1.Filter = ("Microsoft.Net managed Resource File") + " (*.resx)|*.resx" 9 Me.OpenFileDialog1.FilterIndex = 1 10 If Me.OpenFileDialog1.ShowDialog() = DialogResult.OK AndAlso Operators.CompareString(Me.OpenFileDialog1.FileName, "", False) <> 0 Then 11 Me.ListView1.Clear() 12 filename = Me.OpenFileDialog1.FileName 13 lblStatus.Text = filename 14 imgListName = Me.ilName.Text + ".ImageStream" 15 mnuFileExport.Enabled = True 16 Dim rsxr As ResXResourceReader = New ResXResourceReader(filename) 17 Dim resxSet As New ResXResourceSet(filename) 18 Dim d As DictionaryEntry 19 Dim n As Integer = 0 20 For Each d In rsxr 21 If Operators.CompareString(d.Value.ToString(), "System.Drawing.Bitmap", False) = 0 Then 22 Dim image As Bitmap = CType(resxSet.GetObject(d.Key.ToString(), True), Bitmap) 23 If image IsNot Nothing Then 24 ImageList1.Images.Add(image) 25 ListView1.Items.Add(New ListViewItem(n.ToString(), n)) 26 n += 1 27 End If 28 End If 29 If Operators.CompareString(d.Value.ToString(), "System.Drawing.Icon", False) = 0 Then 30 Dim image As Icon = CType(resxSet.GetObject(d.Key.ToString(), True), Icon) 31 If image IsNot Nothing Then 32 ImageList1.Images.Add(image) 33 ListView1.Items.Add(New ListViewItem(n.ToString(), n)) 34 n += 1 35 End If 36 End If 37 If Operators.CompareString(imgListName, "", False) <> 0 Then 38 If Operators.CompareString(d.Key.ToString(), imgListName, False) = 0 Then 39 imgList.ImageStream = CType(resxSet.GetObject(d.Key.ToString(), True), System.Windows.Forms.ImageListStreamer) 40 For i As Integer = 0 To imgList.Images.Count - 1 41 ImageList1.Images.Add(imgList.Images(i)) 42 ListView1.Items.Add(New ListViewItem(n.ToString(), n)) 43 n += 1 44 Next 45 End If 46 End If 47 Next d 48 rsxr.Close() 49 End If 50 End Sub 51 Private filename As String = "" 52 Private imgList As New ImageList() 53 Private imgListName As String = "" 54 Private Sub mnuFileExport_Click(sender As Object, e As EventArgs) Handles mnuFileExport.Click, tsbExtract.Click 55 If Operators.CompareString(filename, "", False) <> 0 Then 56 Me.FolderBrowserDialog1.SelectedPath = "C:\" 57 Me.FolderBrowserDialog1.Description = "選擇保存圖標的目錄" 58 If Me.FolderBrowserDialog1.ShowDialog() = DialogResult.OK AndAlso Operators.CompareString(Me.FolderBrowserDialog1.SelectedPath, "", False) <> 0 Then 59 Dim rsxr As ResXResourceReader = New ResXResourceReader(filename) 60 Dim resxSet As New ResXResourceSet(filename) 61 Dim d As DictionaryEntry 62 For Each d In rsxr 63 If Operators.CompareString(d.Value.ToString(), "System.Drawing.Bitmap", False) = 0 Then 64 Dim image As Bitmap = CType(resxSet.GetObject(d.Key.ToString(), True), Bitmap) 65 If image IsNot Nothing Then 66 image.Save(Me.FolderBrowserDialog1.SelectedPath + "\" + d.Key.ToString() + ".bmp") 67 End If 68 End If 69 If Operators.CompareString(d.Value.ToString(), "System.Drawing.Icon", False) = 0 Then 70 Dim image As Icon = CType(resxSet.GetObject(d.Key.ToString(), True), Icon) 71 If image IsNot Nothing Then 72 image.ToBitmap().Save(Me.FolderBrowserDialog1.SelectedPath + "\" + d.Key.ToString() + ".bmp") 73 End If 74 End If 75 If Operators.CompareString(d.Key.ToString(), imgListName, False) = 0 Then 76 imgList.ImageStream = CType(resxSet.GetObject(d.Key.ToString(), True), System.Windows.Forms.ImageListStreamer) 77 For i As Integer = 0 To imgList.Images.Count - 1 78 imgList.Images(i).Save(Me.FolderBrowserDialog1.SelectedPath + "\" + d.Key.ToString() + i.ToString() + ".bmp") 79 Next 80 End If 81 Next d 82 rsxr.Close() 83 End If 84 End If 85 End Sub 86 Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load 87 mnuFileExport.Enabled = (Operators.CompareString(filename, "", False) <> 0) 88 End Sub 89 90 Private Sub btnExtract_Click(sender As Object, e As EventArgs) Handles btnExtract.Click 91 If Operators.CompareString(filename, "", False) <> 0 Then 92 Me.ListView1.Clear() 93 imgListName = Me.ilName.Text + ".ImageStream" 94 Dim rsxr As ResXResourceReader = New ResXResourceReader(filename) 95 Dim resxSet As New ResXResourceSet(filename) 96 Dim d As DictionaryEntry 97 Dim n As Integer = 0 98 For Each d In rsxr 99 If Operators.CompareString(imgListName, "", False) <> 0 Then 100 If Operators.CompareString(d.Key.ToString(), imgListName, False) = 0 Then 101 imgList.ImageStream = CType(resxSet.GetObject(d.Key.ToString(), True), System.Windows.Forms.ImageListStreamer) 102 For i As Integer = 0 To imgList.Images.Count - 1 103 ImageList1.Images.Add(imgList.Images(i)) 104 ListView1.Items.Add(New ListViewItem(n.ToString(), n)) 105 n += 1 106 Next 107 End If 108 End If 109 Next d 110 rsxr.Close() 111 End If 112 End Sub 113 End Class