Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Including an external exe in project 1

Status
Not open for further replies.

Tve

Programmer
May 22, 2000
166
FR
Hi,

I'm new to C# and I'm trying to build a small application.

This application needs an external program that will be called from inside my own application. Considering that this is a rather small *.exe, I was thinking of including the external exe in my own app and at runtime, extracting it to %TEMP% from where I could call it. These seems much easyier that parsing the registry or the local drives to find if the external exe is present.

Question 1:
Does this seem a reasonable approach?

Question 2:
If so, can anybody point me the majors steps in acheiving this..ie: How do I include the external exe in my own exe and how could I copy it to %TEMP% at runtime?

PS: I forgot to mention: I do not want to build an install, otherwise I understand I could have included the external exe in the install.



AD AUGUSTA PER ANGUSTA

Thierry
 
Question: Why embed the the file?
> So your app would be only one file ?
> Or not to let the user find copy that file ?


Q1 answer:
I don't know. Do you have the code of the .exe file?

Yes?
You can include the code files into your project and run
it normally.
No?
You can embed the .exe into your app.


Q2 answer:
- Add the .exe to the solution explorer, at root or any folder(s).
- Change the Build action to Embedded Resource.

CODE IN VB.NET (later i'll post it in C#)
Code:
        Dim executingAssembly As System.Reflection.Assembly = System.Reflection.Assembly.GetEntryAssembly()
        Dim myNamespace As String = executingAssembly.GetName().Name.ToString()

        Dim stream As New FileStream("C:\theFile.exe", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)
        [b]Dim reader As New BinaryReader(executingAssembly.GetManifestResourceStream(myNamespace + ".yourFile.exe"))[/b]

        Dim input As Byte() = reader.ReadBytes(reader.BaseStream.Length)

        reader.Close()

        If Not (input Is Nothing) Then
            Dim writer As New BinaryWriter(stream)
            writer.Write(input)
            writer.Close()
            stream.Close()
        End If

        MsgBox("Done!")

That way, you can extract it anywhere (in that example in C:\) and then launch it using shell or process.start(..) .


NOTES:
1. You can extract it anywhere.. any weird path so the user cannot find it. In fact he can, if he uses a file system watcher To prevent this (i have not yet found it how), you must not extract the .exe in any physical path, but in a memorystream... and launch the file from the stream!

2. The bold line in the code above, works for a file that is on the root of the executing assembly. If you place the file in a folder e.g. 'myFolder' then you have to change it to: myNamespace + ".myFolder.yourFile.exe"

________________
Hope these help.
Post again if you have problems.
 
TipGiver (and Tve), regarding the second sentence in your note 1, there is a lot more to loading and executing a program than simply providing a byte stream - the OS does a lot of "behind the scenes" work.

In the good old days of DOS, what you suggest was achievable as long as you understood things like the PSP and (if it was an exe as opposed to a com program, the relocation table structures), however today things are nowhere near as straightforward and whilst I am sure that it is not impossible (although security issues may come into play to add to the difficulty) I would suggest that the amount of research involved, let alone the amount of work involved would make it untenable without an exceptionally good reason to proceed.

If chiph (who seems to have a good understanding of all things low-level) is monitoring this thread, I would be interested in his thoughts on this. (No disrepect intended to any other low-level gurus, whose comments would also be invaluable).


Hope this helps.

[vampire][bat]
 
AFAIK, you cannot start a new process directly off a byte stream. But you can copy your byte stream to the user's temp directory and execute it from there (security permissions allowing).

Chip H.


____________________________________________________________________
If you want to get the best response to a question, please read FAQ222-2244 first
 
To all,

Thanks for your answers...[thumbsup]
I think I understand what I need to do.

For information, I am talking of a stand-alone exe so I believe TipGiver's solution will work...thanks again.

Now that I have the general idea, I will investigate for C# and do some tests to see if this solution is viable.

Wish you all a nice evening.





AD AUGUSTA PER ANGUSTA

Thierry
 
Hi,

I'm back with this thread and I "re-wrote" (please note the quotes) TipGivers code above in C#

This is what I know have:
Code:
//This is the caller...
string filepath = this.extract(@"file.exe",@"files.file.exe");
	

private string extract(string strFileLocal, string strFileAssem) {

	System.Reflection.Assembly executingAssembly = System.Reflection.Assembly.GetExecutingAssembly();
	String myNamespace = executingAssembly.GetName().Name.ToString();
  
  //Get the temporary path and append the passed local file
	string strPathLocal = Path.GetTempPath() + strFileLocal;
	string strPathAssem = myNamespace + "." + strFileAssem;
	  
	//Declare variables that could be used out of the if
	BinaryReader brdAssem;

  //If the file already exists locally
	if (File.Exists(strPathLocal)) {
	  
	  //Declare MD5
	  MD5 md5 = new MD5CryptoServiceProvider();
	
	  //
		FileStream fsLocal  = new FileStream( strPathLocal, FileMode.Open );
		brdAssem = new BinaryReader(executingAssembly.GetManifestResourceStream(strPathAssem));

    //Create MD5SUM for both file (local & ressources)
		string strMd5Local = ByteArrayToString(md5.ComputeHash(fsLocal));
		string strMd5Assem = ByteArrayToString(md5.ComputeHash(executingAssembly.GetManifestResourceStream(strPathAssem)));
	  
	  //Close the local file
		fsLocal.Close();
		  
		//If the MD5 are equal
		if (strMd5Local == strMd5Assem) { 
		  //Return the local file
		  return strPathLocal;
		} else {	
		  //Delete the file
		  File.Delete(strPathLocal);
	  }
	  
	}

	brdAssem = new BinaryReader(executingAssembly.GetManifestResourceStream(strPathAssem));
	FileStream fs = new FileStream(strPathLocal,FileMode.CreateNew);
	BinaryWriter writer = new BinaryWriter(fs);
	writer.Write(brdAssem.ReadBytes( (int) brdAssem.BaseStream.Length));
	writer.Close();
	fs.Close();
	brdAssem.Close();                                      

	//Return the local file
	return strPathLocal;

}

private string ByteArrayToString(byte[] arrInput) {
	int i;
	StringBuilder sOutput = new StringBuilder(arrInput.Length);
	for (i=0;i < arrInput.Length -1; i++) {
		sOutput.Append(arrInput[i].ToString("X2"));
	}
	return sOutput.ToString();
}

Being new to C#, I was wondering if anybody could give comments. I have to admit I'm often afreaid of memory leakage of code unefficeancy.

Thanks,


AD AUGUSTA PER ANGUSTA

Thierry
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top