How do I embed an external executable inside my C# Windows Forms application?
Edit: I need to embed it because it's an external free console application (made in C++) from which I read the output values to use in my program. It would be nice and more professional to have it embedded.
Second reason is a requirement to embed a Flash projector file inside a .NET application.
Simplest way, leading on from what Will said:
Add the .exe using Resources.resx
Code this:
string path = Path.Combine(Path.GetTempPath(), "tempfile.exe");
File.WriteAllBytes(path, MyNamespace.Properties.Resources.MyExecutable);
Process.Start(path);
Here is some sample code that would roughly accomplish this, minus error checking of any sort. Also, please make sure that the license of the program to be embedded allows this sort of use.
// extracts [resource] into the the file specified by [path]
void ExtractResource( string resource, string path )
{
Stream stream = GetType().Assembly.GetManifestResourceStream( resource );
byte[] bytes = new byte[(int)stream.Length];
stream.Read( bytes, 0, bytes.Length );
File.WriteAllBytes( path, bytes );
}
string exePath = "c:\temp\embedded.exe";
ExtractResource( "myProj.embedded.exe", exePath );
// run the exe...
File.Delete( exePath );
The only tricky part is getting the right value for the first argument to ExtractResource. It should have the form "namespace.name", where namespace is the default namespace for your project (find this under Project | Properties | Application | Default namespace). The second part is the name of the file, which you'll need to include in your project (make sure to set the build option to "Embedded Resource"). If you put the file under a directory, e.g. Resources, then that name becomes part of the resource name (e.g. "myProj.Resources.Embedded.exe"). If you're having trouble, try opening your compiled binary in Reflector and look in the Resources folder. The names listed here are the names that you would pass to GetManifestResourceStream.
Just add it to your project and set the build option to "Embedded Resource"
This is probably the simplest:
byte[] exeBytes = Properties.Resources.myApp;
string exeToRun = Path.Combine(Path.GetTempPath(), "myApp.exe");
using (FileStream exeFile = new FileStream(exeToRun, FileMode.CreateNew))
exeFile.Write(exeBytes, 0, exeBytes.Length);
Process.Start(exeToRun);
Is the executable a managed assembly? If so you can use ILMerge to merge that assembly with yours.
Here's my version:
Add the file to the project as an existing item, change the properties on the file to "Embedded resource"
To dynamically extract the file to a given location: (this example doesn't test location for write permissions etc)
/// <summary>
/// Extract Embedded resource files to a given path
/// </summary>
/// <param name="embeddedFileName">Name of the embedded resource file</param>
/// <param name="destinationPath">Path and file to export resource to</param>
public static void extractResource(String embeddedFileName, String destinationPath)
{
Assembly currentAssembly = Assembly.GetExecutingAssembly();
string[] arrResources = currentAssembly.GetManifestResourceNames();
foreach (string resourceName in arrResources)
if (resourceName.ToUpper().EndsWith(embeddedFileName.ToUpper()))
{
Stream resourceToSave = currentAssembly.GetManifestResourceStream(resourceName);
var output = File.OpenWrite(destinationPath);
resourceToSave.CopyTo(output);
resourceToSave.Close();
}
}
Add File to VS Project
Mark as "Embedded Resource" -> File properties
Use name to resolve: [Assembly Name].[Name of embedded resource] like "MyFunkyNTServcice.SelfDelete.bat"
Your code has resource bug (file handle not freed!), please correct to:
public static void extractResource(String embeddedFileName, String destinationPath)
{
var currentAssembly = Assembly.GetExecutingAssembly();
var arrResources = currentAssembly.GetManifestResourceNames();
foreach (var resourceName in arrResources)
{
if (resourceName.ToUpper().EndsWith(embeddedFileName.ToUpper()))
{
using (var resourceToSave = currentAssembly.GetManifestResourceStream(resourceName))
{
using (var output = File.OpenWrite(destinationPath))
resourceToSave.CopyTo(output);
resourceToSave.Close();
}
}
}
}
Extract something as string, if needed:
public static string ExtractResourceAsString(String embeddedFileName)
{
var currentAssembly = Assembly.GetExecutingAssembly();
var arrResources = currentAssembly.GetManifestResourceNames();
foreach (var resourceName in arrResources)
{
if (resourceName.ToUpper().EndsWith(embeddedFileName.ToUpper()))
{
using (var resourceToSave = currentAssembly.GetManifestResourceStream(resourceName))
{
using (var output = new MemoryStream())
{
resourceToSave.CopyTo(output);
return Encoding.ASCII.GetString(output.ToArray());
}
}
}
}
return string.Empty;
}
Related
I have a c# program generating some WebPages. In my project I have added some JavaScript files to the project via the ResourceManager.
Now I want to get all the ResourceNames and save them to my Destination path.
I know this question have been asked a million times in here but I can not get it to work.
Here I try to list all my resources
foreach (var res in Assembly.GetExecutingAssembly().GetManifestResourceNames())
{
....
}
But I do not get the Resource names in res but
"WindowsFormsApplication3.Form1.resources" the first time in the loop
and "WindowsFormsApplication3.Properties.Resources.resources" second time
and "WindowsFormsApplication3.Properties.Resources.Designer.cs" third time
What am I doing wrong?
You are just getting the names of the manifest resources, which is not the same thing as Resource file (resx) resources.
To get the resource file resources from a manifest resource file name like "WindowsFormsApplication3.Properties.Resources.resources" you would have to do:
foreach (var manifestResourceName in Assembly.GetExecutingAssembly().GetManifestResourceNames())
{
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(manifestResourceName))
{
if (stream != null)
{
using (var rr = new ResourceReader(stream))
{
foreach (DictionaryEntry resource in rr)
{
var name = resource.Key.ToString();
string resourceType;
byte[] dataBytes;
rr.GetResourceData(name, out resourceType, out dataBytes);
}
}
}
}
}
And then you can save the bytes wherever you want.
I use the following code to get a C# assembly file version for files stored on a harddrive.
var vInfo = FileVersionInfo.GetVersionInfo("assemblyPath").FileVersion;
How could I get an assembly file version for a file stored in an archive without unpacking it? Imagine, you don't have a permission to write to a harddrive. You would probably use some in-memory library for opening the archive and checking what you need to know.
Sorry but you can't without having a phisical file.
The only way to read the FileVersion is to use FileVersionInfo.GetVersionInfo which accept only a path.
And if you use reflector to see how it read the fileversion then you will see some unsafe native internal methods you cannot use...
private static string GetFileVersionString(IntPtr memPtr, string name)
{
int num;
string str = "";
IntPtr zero = IntPtr.Zero;
if (UnsafeNativeMethods.VerQueryValue(new HandleRef(null, memPtr), name, ref zero, out num) && (zero != IntPtr.Zero))
{
str = Marshal.PtrToStringAuto(zero);
}
return str;
}
Maybe you could get it with some DllImport. But this is not in my knowledge.
If you settle for AssemblyVersion you can use DotNetZip library:
Assembly assembly;
using (var data = new MemoryStream())
{
using (ZipFile zip = ZipFile.Read(LocalCatalogZip))
{
zip["assembly.dll"].Extract(data);
}
data.Seek(0, SeekOrigin.Begin);
assembly = Assembly.ReflectionOnlyLoad(data.ToArray());
}
var version = assembly.GetName().Version;
----------------UPDATE-----------------
Last thought: maybe you have permission to write a file in the temp folder: Path.GetTempPath
You can use Nuget package Mono.Cecil
ModuleDefinition.ReadModule(stream)
You'll get a ModuleDefinition, containing all desired assembly info.
I have a relatively large Visual Studio solution.
I need to export all the source code into a text file. I would also want to include a file name somewhere. How can I do so?
For example if I have a type
namespace MyProject.Core
{
/// <summary>
/// Enumerates possible record status
/// </summary>
public enum RecordType
{
NonWearTime = 0,
WearTime = 1,
NotClassified = 2
}
}
I want this to go to the output.txt file (or any other text format) and appear like so
//***********************************
//Filename: RecordType.cs
//***********************************
namespace MyProject.Core
{
/// <summary>
/// Enumerates possible record status
/// </summary>
public enum RecordType
{
NonWearTime = 0,
WearTime = 1,
NotClassified = 2
}
}
All the other types shall just be appended to the end of the file. I tried Resharper, but its header file options can only contain static text (I tried Filename: $FILENAME$) and the template option only applies to the newly created classes.
Folks, this is a study project, where I have to provide the source code along with a thesis.
This should do the trick
string rootPath = #"path you your root folder";
var header = "***********************************" + Environment.NewLine;
var files = Directory.GetFiles(rootPath, "*.cs", SearchOption.AllDirectories);
var result = files.Select(path => new { Name = Path.GetFileName(path), Contents = File.ReadAllText(path)})
.Select(info =>
header
+ "Filename: " + info.Name + Environment.NewLine
+ header
+ info.Contents);
var singleStr = string.Join(Environment.NewLine, result);
Console.WriteLine ( singleStr );
File.WriteAllText(#"C:\output.txt", singleStr, Encoding.UTF8);
Remarks: if you experience performance or memory inefficiencies, try to use StringBuilder instead and set it's Capacity at the start to the sum of all files contents. This will eliminate lots of redundant strings, created in last Select method.
I would go for a homemade solution.
This helps you get into a String the content of each file.
using System.IO;
...
foreach (string file in Directory.EnumerateFiles(folderPath, "*.cs"))
{
string contents = File.ReadAllText(file);
}
You have the filename, so you can append it at the beginning.
All you still need to do is to parse through all directories.
public void DirSearch(string root)
{
foreach (string file in Directory.EnumerateFiles(root, "*.cs"))
{
string contents = File.ReadAllText(file);
// Write to your outputfile once you've happened what you want in your header.
}
foreach (string d in Directory.GetDirectories(root))
{
DirSearch(d);
}
}
As a none code soloution how about trying a windows command line to merge all files into one.
e.g. copy /b *.cs newfile.txt
https://superuser.com/questions/111825/any-command-line-or-batch-cmd-to-concatenate-multiple-files
Admittedly its quick and dirty, but it might produce what you require with some tailoring
I would write a simple console app to do that. It would search for all files with a *.cs extension, make the necessary modification and then save the file to the desired location. You can loop through directories iteratively using Directory.EnumerateDirectories().
Well In my C# project I add a .xml file to the resources, I want it to be extracted/copied from it to the application path, I was trying to doing this:
string appPath = Path.GetDirectoryName(Application.ExecutablePath);//Declaration of the apppath
File.Copy(appPath, Properties.Resources.config);//process for copy
But is not working :/, how can I do what I want?
Make sure the build action on your resource is set to "embed resource".
var assembly = Assembly.GetExecutingAssembly();
// See what resources are in the assembly (remove from the final code)
foreach (var name in assembly.GetManifestResourceNames()) {
Console.Writeline("'{0}'", name);
}
using (var inputStream = assembly.GetManifestResourceStream(resourcePath)) {
using( var outStream = File.OpenWrite(copyToPath)) {
input.CopyTo(outStream);
}
}
I'm using System.Diagnostics.Process.Start("my.exe"); to call an exe
Now that I can call my .exe, I want to bind/merge it into my c# application so that when I build my application, I can get the exe built inside the projectName\Debug\builtProgram.exe or any other way to finally get a single exe file with my desired exe file inside it.
For example, consider I create a program A and I want it to encase it inside another program B which contains only one button 'Launch Program A'. And let's say program B is portable - with a single exe file.
Question is - How to create program B?
You can include the .exe as an embedded resource in your .NET assembly, and then dump it to disk to a temporary file on startup:
var thisAssembly = Assembly.GetExecutingAssembly();
var executableFileName = Path.GetTempFileName();
using(resourceStream = thisAssembly.GetManifestResourceStream("name.of.resource.exe"))
using(fileStream = File.Create(executableFileName))
{
resourceStream.CopyTo(fileStream);
}
Then you call it just like you would normally.
Process.Start(executableFileName);
Since it's hard for me to extract embedded resource.
Here's my answer:
public static void getbytez(string file, string outp)
{
byte[] buffer = File.ReadAllBytes(file);
string base64Encoded = Convert.ToBase64String(buffer);
File.WriteAllText(outp+ ".txt", base64Encoded);
//copy the base64encoded text.
//Code by CursedGmod. credit me please :D
}
public static void extract2idk(string txtfile, string outp, string exten)
{
byte[] gu = Convert.FromBase64String(txtfile);
// use it like this: byte[] gu = Convert.FromBase64String(your base64 converted text that you copied from the txt file);
// or use File.ReadAllText if you're making a stub builder.
File.WriteAllBytes(outp + exten, gu);
Process.Start(Environment.ExpandEnvironmentVariables("%TEMP%") + Path.GetFileName(txtfile));
}