2016-07-04 41 views
0

我試圖做一些SFX:使一個程序生成一個wrapping.exe圍繞另一個wrapped.exe。如何從exe文件中提取與用於創建此exe文件相同的.ico文件?

Wrapping.exe將wrapped.exe作爲資源嵌入,並在執行時將wrapped.exe保存到臨時文件夾中,並使用特定命令行參數執行,然後將其刪除。 wrapped.exe並不總是一個.Net程序,我沒有它的源代碼。

wrapping.exe應該在.net 3.5中完成,以便可以在Windows 7 SP1和更高版本上使用,而無需事先安裝.Net。

Wrapping.exe是使用.Net 4.6中的Roselyn在C#程序中生成的。

我需要wrapping.exe通過資源管理器像wrapped.exe一樣可視化。我用硬編碼的.ico文件做了一個成功的測試。代碼看起來像這樣(簡體):

var compilation = CSharpCompilation.Create(...); 
var resourceDescription = new ResourceDescription(resourceName: "SFX.resourceName", 
                dataProvider:() => File.OpenRead("wrapped.exe"), 
                isPublic:  false); 

using (var iconStream = File.OpenRead(@"wrapped.ico")) 
using (var peStream = File.Create("wrapping.exe")) 
using (var pdbStream = File.Create("wrapping.pdb")) 
using (var win32resStream = compilation.CreateDefaultWin32Resources(
                   versionResource: true, 
                   noManifest:  false, 
                   manifestContents: null, 
                   iconInIcoFormat: iconStream)) 
{ 
    var emitResult = compilation.Emit(peStream:   peStream, 
             pdbStream:   pdbStream, 
             manifestResources: new[] { resourceDescription }, 
             win32Resources: win32resStream, 
             options:   new EmitOptions(subsystemVersion: SubsystemVersion.Windows7)); 
    return emitResult; 
} 

現在我試圖從「wrapped.exe」得到iconStream。我試圖取代:

using (var iconStream = File.OpenRead(@"wrapped.ico")) 

有:

var iconStream = new MemoryStream(); 
Icon icon = Icon.ExtractAssociatedIcon("wrapped.exe"); 
icon.Save(iconStream); 
iconStream.Seek(0, SeekOrigin.Begin); 

但我只得到了32 * 32的圖標。

如何提取完全相同的.ico文件(包括所有格式,例如16 * 16 32位BMP,32 * 32 32位BMP,48 * 48 32位BMP,64 * 64 32位BMP和256 * 256 32位PNG)用於創建'wrapped.exe'?

+1

這只是錯誤的做法。該圖標由程序集鏈接器作爲* unmanaged *資源嵌入到可執行文件中。必需的,因爲操作系統不知道有關管理資源的bean。所有原生的winapi便利功能只會從資源中產生一個圖標圖像,從文件中挖掘完整的圖標需要一個痛苦的拼寫錯誤。使用Assembly.GetManifestResourceStream()的圖標的託管版本。 –

+0

@HansPassant我試圖從非託管資源提取圖標,因爲wrapped.exe並不一定是與.Net(我的firts使用是嵌入InnoSetup EXE)。 – MuiBienCarlota

+0

@HansPassant做了一個編輯來澄清它。 – MuiBienCarlota

回答

1

這很容易使用IconLib。迴應已在this question:Thx至@Plutonix

有了下面的輔助功能(當然,提取圖標文件名不會被硬編碼):

static Stream GetIconStream_ExtractIconUsingIconLib(string fileToExecute) 
{ 
    var multiIcon = new MultiIcon(); 
    multiIcon.Load(fileToExecute); 

    var extractedicoFileName = @"c:\temp\icon.ico"; 
    multiIcon.Save(extractedicoFileName, MultiIconFormat.ICO); 

    return File.OpenRead(extractedicoFileName); 
} 

我們只需要更換:

File.OpenRead(@"wrapped.ico") 

GetIconStream_ExtractIconUsingIconLib("wrapped.exe") 

這給了我們完整的解決方案:

var compilation = CSharpCompilation.Create(...); 
var resourceDescription = new ResourceDescription(resourceName: "SFX.resourceName", 
                dataProvider:() => File.OpenRead("wrapped.exe"), 
                isPublic:  false); 

using (var iconStream = GetIconStream_ExtractIconUsingIconLib("wrapped.exe")) 
using (var peStream = File.Create("wrapping.exe")) 
using (var pdbStream = File.Create("wrapping.pdb")) 
using (var win32resStream = compilation.CreateDefaultWin32Resources(
                   versionResource: true, 
                   noManifest:  false, 
                   manifestContents: null, 
                   iconInIcoFormat: iconStream)) 
{ 
    var emitResult = compilation.Emit(peStream:   peStream, 
             pdbStream:   pdbStream, 
             manifestResources: new[] { resourceDescription }, 
             win32Resources: win32resStream, 
             options:   new EmitOptions(subsystemVersion: SubsystemVersion.Windows7)); 
    return emitResult; 
} 
+0

**請注意**:IconLib只能在32位過程中工作,但我可以在.Net 4中使用它。61進程(這個庫是爲.Net 2.0製作的)。 – MuiBienCarlota

+1

答案指出它是一個.NET 2.0程序集,用戶可能想要重新編譯/更新它。我不知道這是否會允許它作爲'任何CPU'(不是那個問題的一部分;)) – Plutonix

+0

@Plutonix它必須是Win32.EnumResourceNames的問題。在一個64位的進程中,回調函數崩潰,但我沒有時間調查,我可以用32位進程來處理。謝謝。 – MuiBienCarlota