Can I attach a Word document to a Windows Application? - c#

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?

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:
In your project, include the Word document in the Project (Solution Explorer > Show All Files > (your doc, right-click) > Include File
Select the file then open Properties and under "Build Action" choose "Embedded Resource"
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).
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).

Related

Create the file before downloading and complete it after downloading by double tapping on it like OneDrive in c#

There is a feature in OneDrive that you can see a file that is on the OneDrive site on your system without actually having that file in your system. And when you double click on that file, that file starts to download and you can see its contents.
I want to implement such a possibility with C#.
I have a site where files are uploaded.
I download the files from there and put them in a folder on my C drive.
But I want that file not to be downloaded until it is double-clicked, something similar to OneDrive.
What should I do?
I compared the FileInfo of these two files, but I didn't see any difference and I couldn't find a solution for this problem.
This is a virtual filesystem implemented using a file system driver.
There are multiple ways to implement this feature using C/C++.
But in your case, using C# means you should use third-party libraries to create a virtual files system.
There is a library called Dokan, which lets you implement a full-featured virtual file system, and you have complete control over its behaviour in your C# project.
it called "Windows Shell namespace"
https://learn.microsoft.com/en-us/windows/win32/shell/namespace-intro
i used EZNameSpace Wrapper for handling this.
there is another library called "CBFS Shell" (formerly shelboost) that you can use.
You could create a dummy file that appears to be correct but is really just a pointer to some code that downloads the correct file. Then use File.Move or File.Copy to replace the dummy file with the actual file.

Storing additional metadata about a file

for a small project, I would like to be able to store additional information about a file and keep that information with the file even when it is moved.
The additional information will be stored in a XML-file. To keep the file and its description together, I thought about using ZIP-archives without any compression, but I would like these ZIP-archives to behave just like the original files (i.e. if the original file was a video file, a double-click on the archive should open the file in the media player). This requires me to write a small program that handles this 'new' file format.
However, I have not found a solution that would allow me to open the file without first extracting the file from the archive (even without compression), which does take some time and is not what I want.
My questions are: Is there a library (for C# or C/C++) that allows me to open a zip file and directly play/open a file inside it wihout extracting the archive? Or is there an easier way to implement what I need (maybe I am thinking in the wrong direction)?
Windows already allows you to store additional metadata about a shell item (including files) through the Windows Property System.
The Windows API Code Pack includes samples and documentation on how to work with many of the native OS capabilities, including the Property System.
The following excerpts come from the PropertyEdit sample.
To get a file's property by name:
var myObject= ShellObject.FromParsingName(fileName);
IShellProperty prop = myObject.Properties.GetProperty(propertyName);
To set a string property:
if (prop.ValueType == typeof(string))
{
(prop as ShellProperty<string>).Value = value;
}
If you don't want to use the Property System, you can use NTFS alternate data streams to store additional info about a file. There is no direct support for ADS in .NET but a simple search returns multiple wrappers, libraries and SO questions about them, eg NTFS - Alternate Data Streams

Alternatives to ZIP for combining many files into one on Windows using .NET

Im looking for methods to combine files including their name and relative path into one single file. A folder disguised as a file. I don't need any compression or encryption. Just the file data including some binary metadata attached to each file.
It would be great if this file was possible to open/inspect/unpack with a standard file browser in Windows such as with regular zip-files.
Yes I could use zip. But I'm researching alternatives and I would prefer a simple method I could implement myself in C#/.NET.
UPDATE
I've researched this some more and came across Microsoft's Structured Storage format. It looked promising at first but it seemes to be an obsolete format, replaced with the Open Package Format. And then I found out about the TAR-format. It seemes to be the most basic format. But I'm not sure yet if I can add any custom metadata to the entries with TAR.
UPDATE
I went with DotNetZip at the end anyway...
Why not use zip? You can use a third party library, like dotnetzip, to make the code easy to write. And, as you mentioned, Windows handles zip files well.
If you have specific reason to search an alternative to ZIP, take a look on virtual file systems, eg. CodeBase File System or our Solid File System. Solid File System lets you add alternate data streams (like in NTFS) or tags (small chunks of binary or text data) to each file or directory. And with OS edition of SolFS you can make the filesystem visible to Windows (including Explorer and third-party applications).
I must admit that while virtual file systems are easy to use (easier than ZIP), they are commercial products (I didn't see free virtual file system implementations yet).

Extract and open PPT from resources in C#

I want to view presentation in PowerPoint viewer, ppt file is in a resources. so the problem is that how can i access it and view in PowerPoint viewer.
Here is sample code
Process.Start(#"C:\Program Files\Microsoft Office\Office12\PPTVIEW.exe",**#"e:\presentation.ppt")**;
How can i replace this path by ppt containing in resources?
Actually, what you ask for is a common pattern and there are some related questions and answers here on SO.
Basically what you do in general is the following:
locate the resource in question and open a resource stream to it.
Save the stream to a (temporary) file if your target API cannot deal with streams or byte arrays directly.
Perform whatever operation on the file or directly on the stream/byte array (as I said, if supported).
Eventually remove the temporary file, if any, from step 1.
So, you first extract the PPT file (actually it doesn't really matter that it is a PPT file, could by any file or byte blob for that matter).
string tempFile = Path.GetTempFileName();
using (Stream input = assembly.GetManifestResourceStream("MyPresentation.PPT"))
using (Stream output = File.Create(tempFile))
{
input.CopyTo(output); // Stream.CopyTo() is new in .NET 4.0, used for simplicity and illustration purposes.
}
Then you open it using Process.Start(). You don't need to specify the path to the Powerpoint executable, as PPT should be a registered file extension with either PowerPoint or the PowerPoint Viewer. If you have both installed, you may still want to provide the path to the relevant executable to prevent launching the wrong application. Make sure that you don't hardcode the path though, but try to retrieve it from the registry (or similar, I haven't checked because that gets too specific now).
using (var process = Process.Start(tempFile))
{
process.WaitForExit();
// remove temporary file after use
File.Delete(tempFile);
}
Note: I left out quite some error handling that you might want to add in a real application.

C# wpf html help file

C3, WPF, Windows 7, Microsoft Ribbon, Visual studio 2010, dotnet 4.5
I would like to write the help files in html and include them inside the .exe file as an resource.
Is there a way of telling the explorer to get the html pages directly from the .exe file ?
If not, I assume the only way to archive it is to create a temporary directory, copy the
files and start the browser pointing to these files.
Is there a magic call that takes a resource directory and unpack/copy it to a directory ?
Like
tempDir = GetTempDirectory();
WPF_MAGIC_RESOURCE_UNPACKER("/help/*", tempDir );
System.Diagnostics.Process.Start(tempDir + Path.DirectorySeparatorChar + "index.html");
Regards Stefan
I agree with #Tigran, these should be stored separate to the binary or even online, but if you feel as though this is the best solution you could probably make use of the Pack URI functionality of WPF.
This is primarily used for images such as icon resources and splash screens, but could be used for any type of content.
You should be able to extract these resources and save them to the file system or to a stream and use as you see fit.
Example: Uri absoluteUri = new Uri("pack://application:,,,/help/contents.htm", UriKind.Absolute);

Categories

Resources