Guest Post by Iouri Simernitski: Inserting an image into a Word file from VSTO
Editor's note: This is a guest post by Iouri Simernitski, a developer on the VSTO team.
Recently someone asked how to insert an image into a Word file from the VSTO DLL’s resources. There are several ways of doing this:
Saving the image to a temporary file and using InlineShapes.AddPicture (you’d need to delete the file afterwards)
Saving the image to the clipboard and pasting it into the document (you will lose the previous contents of the clipboard)
Inserting a PictureBox control with the picture in it (this will not work in Zoom mode)
There is actually a fourth way – call InlineShapes.AddPicture with a URL instead of a file name and implement a mini-Web server in your VSTO application. This is actually quite easy – the Web server will be listening on a private port and would only serve the one image that it is configured with.
Here’s the code:
ThisDocument.cs
private void ThisDocument_Startup(object sender, System.EventArgs e)
{
byte[] contents;
// This GUID will be used in the URL
Guid unique = Guid.NewGuid();
// Use any private port in the range 49152–65535
int portNumber = 50213;
// Read the new contents from embedded resources
using (System.IO.Stream resource = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("WordWebServer.ashura.jpg"))
{
using (System.IO.BinaryReader reader = new System.IO.BinaryReader(resource))
{
contents = reader.ReadBytes((int)resource.Length);
}
}
// Use any private port in the range 49152–65535
using (new WordWebServer.MyWebServer(portNumber, unique, contents))
{
// the request will land with the WebServer object in this process
this.Range(ref missing, ref missing).InlineShapes.AddPicture(@"https://localhost:" + portNumber + "/" + unique.ToString(), ref missing, ref missing, ref missing);
}
}
WordWebServer.cs
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace WordWebServer
{
class MyWebServer : IDisposable
{
private TcpListener myListener;
private static readonly Guid terminationGuid = new Guid("{7b0d9a9f-fbec-4fe5-8ea7-fc3b313510fc}");
byte[] contentsToServe;
Guid uniqueID;
int myPort;
//The constructor which makee the TcpListener start listening on the
//given port. It also creates a Thread on the method StartListen().
public MyWebServer(int port, Guid uniqueID, byte[] contents)
{
contentsToServe = contents;
this.uniqueID = uniqueID;
this.myPort = port;
//start listing on the given port
myListener = new TcpListener(IPAddress.Parse("127.0.0.1"), port);
myListener.Start();
//start the thread which calls the method 'StartListen'
Thread thread = new Thread(new ThreadStart(StartListen));
thread.Start();
}
public void StartListen()
{
int startPos = 0;
String errorMessage;
while (true)
{
//Accept a new connection
using (TcpClient tcpClient = myListener.AcceptTcpClient())
{
if (tcpClient.Connected)
{
System.Diagnostics.Debug.WriteLine(
String.Format(
"\nClient Connected!!\n==================\nClient IP {0}\n", tcpClient.Client.RemoteEndPoint));
NetworkStream stream = tcpClient.GetStream();
//make a byte array and receive data from the client
Byte[] receivedBytes = new Byte[1024];
// Only reading 1024 characters, this is enough to
// see if the GUID is there
stream.Read(receivedBytes, 0, receivedBytes.Length);
//Convert Byte to String
string receivedString = Encoding.ASCII.GetString(receivedBytes);
// Look for HTTP request
startPos = receivedString.IndexOf("HTTP", 1);
// Get the HTTP text and version e.g. it will return "HTTP/1.1"
string httpVersion = receivedString.Substring(startPos, 8);
//At present we will only deal with GET type
// if OPTION received, still OK
if (!receivedString.StartsWith("GET"))
{
System.Diagnostics.Debug.WriteLine("Only Get Method is supported..");
SendHeader(httpVersion, null, 0, "501 Not Implemented", tcpClient);
continue;
}
if (receivedString.Contains(terminationGuid.ToString()))
{
SendHeader(httpVersion, null, 0, "200 OK", tcpClient);
break;
}
if (!receivedString.Contains(uniqueID.ToString()))
{
errorMessage = "<H2>404 Error! File Does Not Exist...</H2>";
SendHeader(httpVersion, "", errorMessage.Length, "404 Not Found", tcpClient);
SendToBrowser(Encoding.ASCII.GetBytes(errorMessage), tcpClient);
continue;
}
SendHeader(httpVersion, null, contentsToServe.Length, "200 OK", tcpClient);
SendToBrowser(contentsToServe, tcpClient);
}
}
}
myListener.Stop();
}
public void SendHeader(string httpVersion, string mimeHeader, int totalBytes, string statusCode, TcpClient tcpClient)
{
StringBuilder responseBuilder = new StringBuilder();
// if Mime type is not provided set default to text/html
if (string.IsNullOrEmpty(mimeHeader))
{
mimeHeader = "text/xml"; // Default Mime Type is text/xml
}
responseBuilder.Append(httpVersion);
responseBuilder.Append(' ');
responseBuilder.AppendLine(statusCode);
responseBuilder.AppendLine("Server: VSTOServer");
responseBuilder.Append("Content-Type: ");
responseBuilder.AppendLine(mimeHeader);
responseBuilder.AppendLine("Accept-Ranges: bytes");
responseBuilder.Append("Content-Length: ");
responseBuilder.AppendLine(totalBytes.ToString());
responseBuilder.AppendLine("");
Byte[] bSendData = Encoding.ASCII.GetBytes(responseBuilder.ToString());
SendToBrowser(bSendData, tcpClient);
System.Diagnostics.Debug.WriteLine("Total Bytes : " + totalBytes.ToString());
}
public void SendToBrowser(Byte[] data, TcpClient tcpClient)
{
if (tcpClient.Connected)
{
NetworkStream stream = tcpClient.GetStream();
stream.Write(data, 0, data.Length);
stream.Flush();
}
else
{
System.Diagnostics.Debug.WriteLine("Connection Dropped....");
}
}
#region IDisposable Members
public void Dispose()
{
// Send a termination request to stop the web server
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://localhost:" + myPort + "/" + terminationGuid.ToString());
WebResponse response = request.GetResponse();
}
#endregion
}
}
Comments
- Anonymous
August 02, 2006
The comment has been removed - Anonymous
August 03, 2006
The comment has been removed - Anonymous
January 20, 2009
PingBack from http://www.hilpers.com/1008886-daten-aus-externen-datei