Forklift
Forklift

Reputation: 969

Can I attach a Word document to a Windows Application?

I have a Windows Forms application for which I have written an extensive manual in Word with helpful pictures. Is there a way to include the .docx in the .exe so that users can click a button in the application to open to manual in Word?

Upvotes: 3

Views: 2368

Answers (1)

Dai
Dai

Reputation: 155658

Instead of "attach" I think you mean "embed".

And yes, you can, by storing it as an Embedded Resource.

There are three ways to embed resources in .NET Win32 programs:

  • As a Win32 PE Resource. This is not easily used from within .NET code as there's no built-in API for them (so you'll need P/Invoke (DllImport)), but means that other programs can acces the resources.
  • As an Embedded Resource Stream stored directly, this is accessed using the Assembly.GetManifestResourceStream() API in the .NET Framework. This is the fastest way (as it's exposed as a Stream instead of a byte array, so it isn't loaded into memory unnecessarily).
  • As a Byte[] inside a .NET .resx/.resources resource. This is suboptimal because the file is wrapped in another abstraction and exposed as a Byte[] instead of a Stream, but you can more easily manage the files in Visual Studio.

I recommend the GetManifestResourceStream method, so do this:

  1. In your project, include the Word document in the Project (Solution Explorer > Show All Files > (your doc, right-click) > Include File
  2. Select the file then open Properties and under "Build Action" choose "Embedded Resource"
  3. Note that the project-root relative folder-path will be translated into a dot-separated name prefix for your resource, so if the file is My Project\Documents\Readme.doc then the resource name will be Documents.Readme.doc. You can override this, but you will need to edit your .csproj file directly (using the <LogicalName> element).
  4. Then build, and your *.doc file will be embedded.

In your code, do this:

// use a GUID generator to create a new GUID in a string literal (do not run `Guid.NewGuid()` or `new Guid()` at runtime!) to create a globally unique filename so you don't accidentally overwrite other files
const String _myFileName = "12345.doc"; 

static void ShellInvokeReadmeDocument() {

    String destFileName = Path.Combine( Path.GetTempPath(), _myFileName );
    if( !File.Exists( destFileName ) ) {

        Assembly assembly = Assembly.GetExecutingAssembly(); // change as appropriate
        using( Stream source = assembly.GetManifestResourceStream("Documents.Readme.doc") )
        using( Stream destination = File.OpenWrite( destFileName ) ) {

            source.CopyTo( destination );
        }
    }

    Process.Start( destFileName );
}

Note that I don't recommend using a .doc or .docx file as it is not guaranteed that the user will have Word installed (unless you know your customers will have it).

Note that WordPad in Windows does not necessarily have the ability to open .doc files! On Windows 7 and later WordPad only opens .docx files and does not support all formatting options, only a small subset, and WordPad on Windows Vista and earlier does not support opening .docx files.

If you want to maximize compatibility, I recommend using .pdf files if you want to preserve printed-page formatting and layout, or an .rtf file.

If this file is meant to constitute a Help or Documentation file, then you should use a .chm file instead, which is structured and fully supported by all Windows versions from Windows 98 onwards - you can also integrate .chm files with WinForms with the "What's this?" button and tooltips (.chm files are not to be confused with .hlp files which are not supported by Windows after Windows Vista).

Upvotes: 4

Related Questions