<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5 : winforms</title><link>http://msmvps.com/blogs/omar/archive/tags/winforms/default.aspx</link><description>Tags: winforms</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Make a surveillance application which captures desktop and emails you as attachment</title><link>http://msmvps.com/blogs/omar/archive/2007/01/07/make-a-surveillance-application-which-captures-desktop-and-emails-you-as-attachment.aspx</link><pubDate>Sun, 07 Jan 2007 17:15:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:476137</guid><dc:creator>omar</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=476137</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2007/01/07/make-a-surveillance-application-which-captures-desktop-and-emails-you-as-attachment.aspx#comments</comments><description>&lt;p&gt;Some time back I needed to capture a certain computers desktop
in order to find out what that user is doing every day. So, I made
a .NET 2.0 Winforms Application which stays on system tray
(optional) and capture the desktop in given time&amp;nbsp;interval (say
every 60 secs)&amp;nbsp;and emailed the captured images to me as
message attachment (say every 30 mins). It ensures the captures are
small enough and embedded inside HTML email so that I don&amp;#39;t need to
open hundreds of attachments and see the screenshots. I could just
read through the email and see the captures made. You will find
this application quite handy in many use cases including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep an eye on developers who spend too much time on web and
chatting. See what they really do.&lt;/li&gt;
&lt;li&gt;Keep an eye on your better half incase s/he is cheating on
you.&lt;/li&gt;
&lt;li&gt;Keep an eye on your teenagers and see how they use
computer.&amp;nbsp;Find the amount of time they browser porn on
web.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All you do is sit back and relax in your office and the app
informs you every 30 mins via email what your subject is doing on
the computer. You don&amp;#39;t need to worry about missing some captures
when you are away from your computer. It will be safely kept in
your inbox and you can go through all the captures on your
weekend.&lt;/p&gt;
&lt;p&gt;Configure the following settings from the Visual Studio Settings
Designer (if you have Visual Studio):&lt;/p&gt;
&lt;p&gt;
&lt;img height="384" src="http://omar.mvps.org/images/Makeasurveilenceapplicationwhichcaptures_139D9/image0.png" width="637" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;Configure the path where the screenshots will be stored. Then
configure the duration, default is every 1 minute, one screenshot
is taken. &amp;quot;To&amp;quot; contains the email address of yours. Use free email
services because very soon you will find it&amp;#39;s filled up. Username
and Password is for the SMTP authentication. &amp;quot;SMTP&amp;quot; contains the
SMTP Server name or IP. &amp;quot;MailSendDelay&amp;quot; is the delay between
sending emails.&lt;/p&gt;
&lt;p&gt;All you need to do is build the app and install/run it once on
the computer which you want to keep an eye on. It will hide itself
on the system tray as a harmless icon and register itself on the
startup and start capturing immediately. After a week or two,
cleanup the &amp;quot;C:\temp&amp;quot; folder where the screenshots are kept.&lt;/p&gt;
&lt;p&gt;You can also configure the properties at run time after running
it once on a computer. This is for those who does not have Visual
Studio in order to&amp;nbsp;configure&amp;nbsp;the settings before building
it.&lt;/p&gt;
&lt;p&gt;In order to launch the configuration dialog box while the
application is running, find the icon on the system tray and click
mouse buttons exactly in this order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Press left and right mouse button on the icon one after
another&lt;/li&gt;
&lt;li&gt;Release only the right mouse button while holding the left
mouse button down&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will bring up the configuration dialog:&lt;/p&gt;
&lt;p&gt;
&lt;img height="300" src="http://omar.mvps.org/images/Makeasurveilenceapplicationwhichcaptures_139D9/image01.png" width="300" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;Here you can make changes while it is running.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s learn some interesting stuffs from this application:&lt;/p&gt;
&lt;p&gt;1. Prevent closing the application when close button is
clicked:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:a3e31da1-671e-465c-ac51-5c73052efad0" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;
 
&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;MainForm_FormClosing(&lt;/span&gt;
&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;sender, FormClosingEventArgs e) {
Settings.Default.Save();&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;
&lt;span style="color:#000000;"&gt;.Hide(); e.Cancel&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;true&lt;/span&gt;
&lt;span style="color:#000000;"&gt;; }&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;2. Capturing the screenshot&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:148a7330-30d4-4bde-9b4e-e0731c23e854" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;

&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(Bitmap bmpScreenshot&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb))
{&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;Create a graphics object from the
bitmap&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(Graphics gfxScreenshot&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;Graphics.FromImage(bmpScreenshot))
{&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;try&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;{ Log(&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;Capture screen&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;);&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;Take the screenshot from the upper
left corner to the right bottom corner&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;0&lt;/span&gt;
&lt;span style="color:#000000;"&gt;,&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;0&lt;/span&gt;
&lt;span style="color:#000000;"&gt;, Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;First a bitmap object for the whole screen size is created and
then the graphics from the screen is copied to the Bitmap
object.&lt;/p&gt;
&lt;p&gt;3. Convert the Bitmap to low resolution JPEG&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:d9d1ce91-5cb4-4417-8fa3-43b665255c85" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;

&lt;span style="color:#008000;"&gt;//&lt;/span&gt;
&lt;span style="color:#008000;"&gt;Get the ImageCodecInfo for the
desired target format&lt;/span&gt;
&lt;span style="color:#000000;"&gt;ImageCodecInfo codec&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;GetEncoderInfo(&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;image/jpeg&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;);&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;Set the quality to very low&lt;/span&gt;
&lt;span style="color:#000000;"&gt;System.Drawing.Imaging.Encoder
qualityEncoder&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;System.Drawing.Imaging.Encoder.Quality;
EncoderParameter ratio&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;EncoderParameter(qualityEncoder,&lt;/span&gt;

&lt;span style="color:#000000;"&gt;10L&lt;/span&gt;
&lt;span style="color:#000000;"&gt;);&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;Add the quality parameter to the
list&lt;/span&gt;
&lt;span style="color:#000000;"&gt;EncoderParameters codecParams&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;EncoderParameters(&lt;/span&gt;
&lt;span style="color:#000000;"&gt;1&lt;/span&gt;
&lt;span style="color:#000000;"&gt;); codecParams.Param[&lt;/span&gt;
&lt;span style="color:#000000;"&gt;0&lt;/span&gt;
&lt;span style="color:#000000;"&gt;]&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;ratio;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Here we configure the JPEG codec with very low resolution (10%).
GetEncoderInfo is a function which runs through all available
codecs and finds the one we need.&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:c1c8764a-97ab-4672-a919-1b18a7965fd6" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;
 
&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;ImageCodecInfo GetEncoderInfo(String
mimeType) {&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;j; ImageCodecInfo[] encoders;
encoders&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;ImageCodecInfo.GetImageEncoders();&lt;/span&gt;

&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(j&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;0&lt;/span&gt;
&lt;span style="color:#000000;"&gt;; j&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;encoders.Length;&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;++&lt;/span&gt;
&lt;span style="color:#000000;"&gt;j) {&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(encoders[j].MimeType&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;==&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;mimeType)&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;encoders[j]; }&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;
&lt;span style="color:#000000;"&gt;; }&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;4. Saving bitmap using codec&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:1faa5b79-096e-47d4-b94b-5639df7fe649" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;

&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(FileStream fs&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;FileStream(filePath,
FileMode.Create)) { bmpScreenshot.Save(fs, codec, codecParams);
fs.Close(); }&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;5. Handling Win32Exception&lt;/p&gt;
&lt;p&gt;I noticed sometimes during screen capture, an unknown
Win32Exception throws up. There&amp;#39;s no way to work around this
problem until I restart the application. Here&amp;#39;s how I do it:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:05cb450b-d65c-4003-ab7e-dfa455b5bde9" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;

&lt;span style="color:#0000FF;"&gt;catch&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(Exception x) {
Log(x.ToString());&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(x&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;is&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;Win32Exception) { Log(&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;Restarting...&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;); Application.Restart(); }
}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;6. Email the pictures as embedded image in HTML format&lt;/p&gt;
&lt;p&gt;First connect to the mail server using
System.Net.SmtpClient:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:86601d3f-8ce7-4abb-b3df-6ffcb79cf3bb" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;

&lt;span style="color:#000000;"&gt;SmtpClient client&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;SmtpClient(Settings.Default.Smtp);
client.Credentials&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;NetworkCredential(Settings.Default.UserName,
Settings.Default.Password); MailMessage msg&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;MailMessage(Settings.Default.To,
Settings.Default.To); msg.Subject&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;DateTime.Now.ToString();
msg.IsBodyHtml&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;true&lt;/span&gt;
&lt;span style="color:#000000;"&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We are going to construct an Html mail where the images will be
inline. The tricky part is to build the body of the message. The
body requires that we create &amp;lt;img&amp;gt; tag for each image inside
the body in this format:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:baac3bf9-d779-4f34-b1c8-67fa8bc1a516" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;

&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;
&lt;span style="color:#800000;"&gt;img&lt;/span&gt; 
&lt;span style="color:#FF0000;"&gt;src&lt;/span&gt;
&lt;span style="color:#0000FF;"&gt;=cid:ID_OF_THE_IMAGE&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The ID needs to be the ContentID of the LinkedResource instance
which is created for each image. Here&amp;#39;s the code:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:34c3df6a-a853-449b-b717-ef2a890c4a62" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;

&lt;span style="color:#000000;"&gt;List&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;LinkedResource&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;resources&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;List&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;LinkedResource&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;();&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(&lt;/span&gt;
&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;i&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;Settings.Default.LastSentFileNo;
i&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;Settings.Default.LastFileNo; i&lt;/span&gt;
&lt;span style="color:#000000;"&gt;++&lt;/span&gt;
&lt;span style="color:#000000;"&gt;) {&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;filePath&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;FilePath(i);&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt;
&lt;span style="color:#008000;"&gt;then we create the Html part&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt;
&lt;span style="color:#008000;"&gt;to embed images, we need to use the
prefix &amp;#39;cid&amp;#39; in the img src value&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt;
&lt;span style="color:#008000;"&gt;the cid value will map to the
Content-Id of a Linked resource.&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt;
&lt;span style="color:#008000;"&gt;thus &amp;lt;img
src=&amp;#39;cid:companylogo&amp;#39;&amp;gt; will map to a LinkedResource with a
ContentId of &amp;#39;companylogo&amp;#39;&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;body.AppendLine(&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;lt;img src=cid:Capture&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;+&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;i.ToString()&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;+&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;);&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt;
&lt;span style="color:#008000;"&gt;create the LinkedResource (embedded
image)&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;LinkedResource logo&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;LinkedResource(filePath);
logo.ContentId&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;Capture&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;+&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;i.ToString();&lt;/span&gt; 
&lt;span style="color:#008000;"&gt;//&lt;/span&gt;
&lt;span style="color:#008000;"&gt;add the LinkedResource to the
appropriate view&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;resources.Add(logo); }&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I keep a counter for the last capture file name and the last
emailed file number. Then for each capture file which has not been
emailed yet,&amp;nbsp;I create a LinkedResource for the image and then
add it in the resources list. I also build the body of the message
which contains the &amp;lt;img&amp;gt; tag with the LinkedResource
ContentID.&lt;/p&gt;
&lt;p&gt;Then we create something called AlternateView for the message
body which says the message has a HTML view:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:320d2606-0fa0-4dd8-96b7-f05b2d51c162" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;

&lt;span style="color:#000000;"&gt;AlternateView htmlView&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;AlternateView.CreateAlternateViewFromString(body.ToString(),&lt;/span&gt;

&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;
&lt;span style="color:#000000;"&gt;,&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;text/html&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;);&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;foreach&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(LinkedResource resource&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;in&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;resources)
htmlView.LinkedResources.Add(resource);
msg.AlternateViews.Add(htmlView);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This view contains the HTML body and the resource
collection.&lt;/p&gt;
&lt;p&gt;After this, the email is sent asynchronously so that the screen
capture process does not get stuck. It generally takes a while to
send the image with all the screenshots embedded. So, you can&amp;#39;t do
this synchronously.&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:d587577c-a20c-42f3-b0cd-2642fc6fce11" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;

&lt;pre style="background-color:White;"&gt;&lt;/pre&gt;
&lt;div&gt;

&lt;span style="color:#0000FF;"&gt;try&lt;/span&gt;
&lt;span style="color:#000000;"&gt;{ client.Timeout&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;=&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;10&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;*&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;60&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;*&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;1000&lt;/span&gt;
&lt;span style="color:#000000;"&gt;; client.SendAsync(msg,&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;); client.SendCompleted&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;+=&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;SendCompletedEventHandler(client_SendCompleted);
mailSendTimer.Stop(); Log(&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;Sending mail...&lt;/span&gt;
&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;
&lt;span style="color:#000000;"&gt;); }&lt;/span&gt; 
&lt;span style="color:#0000FF;"&gt;catch&lt;/span&gt; 
&lt;span style="color:#000000;"&gt;(Exception x) { Log(x.ToString());
}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;#39;s all folks!&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://omar.mvps.org/share/desktopcapture.zip"&gt;Download
the source here&lt;/a&gt;
&lt;/p&gt;
&lt;img src="http://msmvps.com/aggbug.aspx?PostID=476137" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/winforms/default.aspx">winforms</category></item><item><title>Stickout - .NET 2.0, Outlook Word Excel Add-in, VSTO, Remoting, you name it</title><link>http://msmvps.com/blogs/omar/archive/2006/04/23/stickout-net-2-0-outlook-word-excel-add-in-vsto-remoting-you-name-it.aspx</link><pubDate>Sun, 23 Apr 2006 15:49:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:92238</guid><dc:creator>omar</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=92238</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2006/04/23/stickout-net-2-0-outlook-word-excel-add-in-vsto-remoting-you-name-it.aspx#comments</comments><description>StickOut is a desktop sticky note application with multi-user support and Outlook integration. It is a .NET Framework 2.0 Windows Forms application that uses .NET Remoting to communicate with other StickOut users and exchange sticky notes with them. It uses the new .NET Framework 2.0 IPC Channel for communicating between Microsoft Outlook and the StickOut process. The Outlook Add-in allows you to stick anything out to the desktop from Outlook including e-mails, notes, tasks, appointments, etc., as sticky notes. Care has been taken to reduce the memory footprint of a .NET application significantly and to make a fast and smooth user experience. This article chronicles my first day of planning the application, through subsequent design, development, testing, and deployment days, revealing the evolution of the application, and the complications I dealt with at each step. You will read about lots of .NET tricks, deployment and versioning problems, Visual Studio tricks, and some other non-development–related tricks that might help you to boost your daily development work. 
&lt;p&gt;
&lt;a href="http://msdn.microsoft.com/netframework/default.aspx?pull=/library/en-us/dnwinforms/html/stickout.asp"&gt;http://msdn.microsoft.com/netframework/default.aspx?pull=/library/en-us/dnwinforms/html/stickout.asp&lt;/a&gt;
&lt;/p&gt;
Hope you enjoy it!&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=92238" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/winforms/default.aspx">winforms</category></item><item><title>Top questions asked about data grid</title><link>http://msmvps.com/blogs/omar/archive/2005/11/12/top-questions-asked-about-data-grid.aspx</link><pubDate>Sat, 12 Nov 2005 15:03:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:75278</guid><dc:creator>omar</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=75278</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2005/11/12/top-questions-asked-about-data-grid.aspx#comments</comments><description>&lt;p class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;This paper addresses some of the  questions about customizing grid display that are commonly asked in newsgroups,  on Web sites, and in other developer forums. The techniques described here are  sometimes quite simple and at other times somewhat involved. In each case,  however, they address a question of how to go beyond the basic functionality of  the DataGrid control.&lt;/span&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbtchtopquestionsaboutaspnetdatagridservercontrol.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbtchtopquestionsaboutaspnetdatagridservercontrol.asp&lt;/a&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Topics:&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="Section1"&gt;&lt;ul&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Windows Forms versus Web Forms    DataGrid Controls&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;&lt;/span&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;span&gt;Controlling Column    Width, Height, and Alignment&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Customizing Column Layout in    Display and Edit Mode&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Formatting Dates, Currency, and    Other Data&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Showing and Hiding Columns    Dynamically&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Adding Columns    Dynamically&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Adding New Records to a Data    Source Using the DataGrid Control&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Displaying a Drop-Down List in    Edit Mode&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Selecting Multiple Items Using a    Check Box (Hotmail Model)&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Editing Multiple Rows At    Once&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="MsoNormal"&gt;&lt;font size="2"&gt;&lt;span&gt;Selecting Rows by Clicking    Anywhere&lt;/span&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=75278" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/winforms/default.aspx">winforms</category></item><item><title>Simulate Windows Service using ASP.NET</title><link>http://msmvps.com/blogs/omar/archive/2005/11/01/simulate-windows-service-using-asp-net.aspx</link><pubDate>Tue, 01 Nov 2005 17:17:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:73716</guid><dc:creator>omar</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=73716</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2005/11/01/simulate-windows-service-using-asp-net.aspx#comments</comments><description>&lt;p&gt;How to run scheduled jobs from ASP.NET without requiring a
Windows Service to be installed on the server? Very often we need
to run some maintenance tasks or scheduled tasks like sending
reminder emails to users from our websites. This can only be
achieved using a windows service. ASP.NET being stateless provides
no support to run some code continuously or to run code at
scheduled time. As a result, we have to make our own Windows
Services in order to run scheduled jobs or cron jobs. But in a
shared hosted environment, we do not always have the luxury to
deploy our own windows service to our hosting provider&amp;rsquo;s web
server. We either have to buy a dedicated server which is very
costly, or sacrifice such features in our web solution. However,
running scheduled task is a very handy feature especially for
sending reminder emails to users, maintenance reports to
administrator, run cleanup operations etc. So, I will show you a
tricky way to run scheduled jobs using pure ASP.NET without
requiring any windows service. This solution runs on any hosting
service providing just ASP.NET hosting:&lt;/p&gt;
&lt;a href="http://www.codeproject.com/useritems/ASPNETService.asp"&gt;http://www.codeproject.com/useritems/ASPNETService.asp&lt;/a&gt;
&lt;p&gt;If you find this article useful, please vote for me.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=73716" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/winforms/default.aspx">winforms</category></item><item><title>.NET 2.0 Process Impersonation feature not working in Windows App</title><link>http://msmvps.com/blogs/omar/archive/2005/10/19/net-2-0-process-impersonation-feature-not-working-in-windows-app.aspx</link><pubDate>Wed, 19 Oct 2005 04:35:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:71651</guid><dc:creator>omar</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=71651</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2005/10/19/net-2-0-process-impersonation-feature-not-working-in-windows-app.aspx#comments</comments><description>&lt;p&gt;.NET 2.0 introduced an interesting feature in the &amp;quot;Process&amp;quot;
class where you can specify UserName, Password and it runs the
process as the specified user. However, it only works inside
Console Application. It does not run if the application is a
Windows Application. It throws &amp;quot;Win32Exception Access Denied&amp;quot; when
the Start() is called. Is it as designed? I really need this
feature in a windows service.&lt;/p&gt;
&lt;p&gt;Try the following code in a console app, it will run perfectly.
But change the application&amp;nbsp;type to &amp;quot;Windows Application&amp;quot; and
run, it will throw exception. IF you do not set the UserName,
Password, it will run then. I am using VS 2005 Release
Candidate.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s the code:&lt;/p&gt;
&lt;p&gt;ProcessStartInfo startInfo = new
ProcessStartInfo(@&amp;quot;SampleEXE.exe&amp;quot;);&lt;/p&gt;
&lt;p&gt;startInfo.Domain = &amp;quot;.&amp;quot;;&lt;/p&gt;
&lt;p&gt;startInfo.UserName = &amp;quot;test&amp;quot;;&lt;/p&gt;
&lt;p&gt;// create a secure string from the password we have&lt;/p&gt;
&lt;p&gt;SecureString securePassword = new SecureString();&lt;/p&gt;
&lt;p&gt;foreach (char c in &amp;quot;test&amp;quot;)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;securePassword.AppendChar(c);&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;securePassword.MakeReadOnly();&lt;/p&gt;
&lt;p&gt;startInfo.Password = securePassword;&lt;/p&gt;
&lt;p&gt;startInfo.UseShellExecute = false;&lt;/p&gt;
&lt;p&gt;startInfo.RedirectStandardOutput = true;&lt;/p&gt;
&lt;p&gt;startInfo.RedirectStandardError = true;&lt;/p&gt;
&lt;p&gt;startInfo.RedirectStandardInput = false;&lt;/p&gt;
&lt;p&gt;startInfo.CreateNoWindow = true;&lt;/p&gt;
&lt;p&gt;startInfo.WindowStyle = ProcessWindowStyle.Hidden;&lt;/p&gt;
&lt;p&gt;startInfo.WorkingDirectory =&lt;/p&gt;
&lt;p&gt;Path.GetDirectoryName(startInfo.FileName);&lt;/p&gt;
&lt;p&gt;startInfo.Arguments = &amp;quot;Hi Hello How are you?&amp;quot;;&lt;/p&gt;
&lt;p&gt;using (Process p = new Process())&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;p.StartInfo = startInfo;&lt;/p&gt;
&lt;p&gt;p.Start();&lt;/p&gt;
&lt;p&gt;string fileName = @&amp;quot;output.txt&amp;quot;;&lt;/p&gt;
&lt;p&gt;using (StreamWriter writer = new StreamWriter(fileName))&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;writer.Write(p.StandardOutput.ReadToEnd());&lt;/p&gt;
&lt;p&gt;writer.Close();&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;p.WaitForExit();&lt;/p&gt;
&lt;p&gt;p.Close();&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=71651" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/winforms/default.aspx">winforms</category></item></channel></rss>