簡體   English   中英

是否可以通過代碼中的名稱引用Visual Studio中的嵌入式文件資源?

[英]Can an embedded file resource in Visual Studio be referenced by name in code?

在Visual Studio 2010中,我將一個zip文件作為嵌入式資源包含到我的可執行文件中,並將其解壓縮以在運行時使用。 這樣的文件不能作為文件資源(文本或二進制)包括在內,因為文件資源總是作為單獨的項目鏈接的,這不是我想要的。 因此,我無法通過Properties.Resources在代碼中引用該文件。

要解壓縮該zip文件,我必須在代碼中將其名稱硬編碼如下:

stream = Assembly.GetEntryAssembly().GetManifestResourceStream("myembeddedfile.zip");

我注意到在.csproj文件中引用了zip文件,如下所示:

<ItemGroup>
    <EmbeddedResource Include="myembeddedfile.zip" />
    <None Include="packages.config" />
</ItemGroup>

但是,我認為以上內容不能從代碼中引用。 (我從#1060870問題中了解“ None用法。)

有什么辦法可以將該文件作為真實項目/解決方案項包括在內,而不必對文件名進行硬編碼?

編輯:

以非硬編碼方式在代碼中引用文件的方式將類似於以下內容:

GetManifestResourceStream(Properties.Resources.EmbeddedFile);

但是,正如我已經提到的,以上是不可能的,因為Properties.Resources對象中沒有包含嵌入式資源。

跟進DRapp編輯接受的答案后進行編輯:

下面的DRapp涉及枚舉的方案是對該問題的最終解決方案,但有一個修改:當嵌入多個資源文件時, GetManifestResourceNames()將按字母順序返回資源文件名。 因此,必須相應地安排enum名稱。 在調試期間拍攝以下快照之前,已按以下順序手動添加了三個嵌入式文件: 1_FIRST, 3_THIRD, 2_SECOND ,但是可以看出,內部存儲是按字母順序排列的:

對於具有三個文件的上述示例,相應的enum將定義為:

public enum MyResources
{
    EmptyZipTest_1_FIRST_zip,
    EmptyZipTest_2_SECOND_zip,
    EmptyZipTest_3_THIRD_zip
}

使用Jon Skeet的 CopyStream函數答案的二進制寫流功勞並調用它,您可以嵌入一個zip文件。

另外,正如hintham所提到的,您需要做的事情(我做了並測試了),我創建了一個空zip文件並將其添加到我的項目中。 我稱它為“ EmptyZipFile.zip”。 在該文件的屬性上,單擊“生成操作”,然后更改為“嵌入資源”。 我的項目(和名稱空間)的名稱是“ EmptyZipTest”

您與資源的獲取非常接近,但是必須包含完全限定的名稱空間以及嵌入的文件名。 快速查看資源中所有內容的列表。

StringBuilder sb = new StringBuilder();
foreach (string s in Assembly.GetEntryAssembly().GetManifestResourceNames())
   sb.AppendLine(s);

MessageBox.Show(sb.ToString());

這樣,它將(根據我的示例項目)公開以下資源:

"EmptyZipTest.EmptyZipFile.zip"

這是可執行文件中的文件。 現在,如果要將此基准zip文件OUT復制到某個新文件名,請創建一個簡單的函數,該函數可能會獲取另一個文件名/位置,並提供該功能來創建文件並寫出zip文件。

public void WriteNewZipFile( string newFilePathAndName )
{
   Stream zipStream = Assembly.GetEntryAssembly().GetManifestResourceStream(
      "EmptyZipTest.EmptyZipFile.zip" );

   if (zipStream != null)
   {
      using (Stream outStream = File.Create( newFilePathAndName ))
      {
         CopyStream(zipStream, outStream);
      }
   }
}

public static void CopyStream(Stream input, Stream output)
{
   byte[] buffer = new byte[8 * 1024];
   int len;
   while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
   {
      output.Write(buffer, 0, len);
   }
}   

顯然,我沒有快速進行錯誤檢查/驗證,但是應該可以為您提供所需的東西。 內部文件名將始終是固定值...您將流OUT寫入的內容是不同的...

OPTION與硬編碼字符串。

我想我明白您的意思了,您可以嘗試一下...創建一個“枚舉”實例並在其中放置資源,但用“”代替。 枚舉中的“ _”,因為對象名稱中不能包含句點...

   public enum MyResources
   {
      EmptyZipTest_EmptyZipFile_zip,
      EmptyZipTest_SomeOtherFile_jpg,
      EmptyZipTest_AnotherFile_ini
   }

然后,使用該枚舉作為參數,您不會在整個地方意外地拼寫硬編碼名稱,而是需要具有適當的引用實例。 然后,在處理獲取流式資源的函數中,可以將“ _”替換為“。”。

   public Stream GetMyResource( MyResources myRes )
   {
      string actualResource = myRes.ToString().Replace( "_", "." );
      // This would convert the sample enums above to
      // EmptyZipTest.EmptyZipFile.zip,
      // EmptyZipTest.SomeOtherFile.jpg,
      // EmptyZipTest.AnotherFile.ini
   }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM