Jun 292011
 

Are the users of the application that you developed using the latest version? If your application doesn’t have automatic checking built in, you have to rely on the users to periodically check the site where you host the software for updates, or else you have to email the users or otherwise notify them. Certainly, the very best solution is to have your application self check itself to see if a newer version is available. I will present a simple solution here that uses a small php script placed on a web server. Data about my applications is stored in a mysql database. Then I will show you how I have a C# application check for updates. It’s a really easy solution and anyone with a little programming experience will be able to do it. First, here is the php code that is placed on the server where I host my applications for download.

<!--?php
/*
* To use, place this on a web server of your choice.  Next, create a mysql database
* where you will store information about your applications, such as the latest version.
* From now on, when you update an application, you will also need to update the
* information in the database about that application. Configure the database with the
* following columns: app_name, latest_version, build_date, url
*
* Then, in your application, when it checks for updates, have it send a request to the
* web server formed like this:
* http://myserver.com/app_updates.php?app_name=MyAppName
* where MyAppName above is exactly the same as the app_name stored in the mysql
* database. If MyAppName is found in the database, then it will return a small
* xml string with the data for that record.  If MyAppName is not found, it will
* return nothing. The xml output will look like this
*
* <?xml version="1.0"?-->
*
*   SevereWeatherGrowler
*   1.2.0
*   20110629
*   http://skipstechtalk.net/severe-weather-growler/
*
*
*
* It is up to your application to decide what to do with the returned data. For
* instance, one way to check if an update is available is to always store the build
* date in your application. Then when your application checks the sever, it can
* compare its build data to the build date for the latest version. If they are
* different, then an update is required. You can then direct the user to the url
* provided to get the update.
*/
$dbuser = 'my_database_user_name';
$dbname = 'my_database_name';
$dbpasswd = 'my_super_secret_password';
$dbhost = 'my_db_host'; // might be 'localhost'
$table_name = 'app_updates';
 
// test the connection
$dbh = @mysql_connect($dbhost, $dbuser, $dbpasswd);
if (!$dbh)
{
  echo "Could not connect to MySQL server on " . $dbhost;
  die();
}
 
// get the app_name from the url
$app_name = $_REQUEST['app_name'];
 
// get the data from the database for that app_name
$query = "SELECT * FROM $dbname.$table_name WHERE app_name = '$app_name'";
$result = query($query);
$row = mysql_fetch_object($result);
//print_r ($row);
 
// build the xml output
if ($row != null)
{
  $xmlstr = "<!--?xml version='1.0' ?-->\n";
  $xml = new SimpleXMLElement($xmlstr);
  $xml->addChild('app_name', $row->app_name);
  $xml->addChild('latest_version', $row->latest_version);
  $xml->addChild('build_date', $row->build_date);
  $xml->addChild('url', $row->url);
  //print_r($xml);
  echo $xml->asXml();
}
 
function query($query) {
  if(!($result = mysql_query($query)))
  {
    //can't execute query
    echo ( "Couldn't query table!\n");
    echo ( "MySQL Reports: " . mysql_error() . "\n" . "Query was: " . $query);
    exit();
  }
  return $result;
}
 
?&gt;

 

 

The code is pretty well documented (in my opinion). As it says in the comments, just have your application check http://yourwebserver.com/app_updates.php?app_name=MyAppName. The server will then return a small xml string that can be parsed by your application.  Here’s how I do it with C#

 

public const string UPDATE_CHECKER_URL = "http://my_webserver.com/app_updates.php";
public const int BUILD_DATE = 20110629;
 
public static void appUpdateTimer_Elapsed(object sender, ElapsedEventArgs e)
{
  try
  {
    WebClient wc = new WebClient();
    string updateCheckerUrl = UPDATE_CHECKER_URL + "?app_name=" +
         System.Windows.Forms.Application.ProductName;
    string updateText = wc.DownloadString(updateCheckerUrl);
    XmlDocument myXmlDoc = new XmlDocument();
    myXmlDoc.LoadXml(updateText);
 
    string latestVersion =
       myXmlDoc.SelectSingleNode("/appdata/latest_version").InnerText;
    string build_date =
       myXmlDoc.SelectSingleNode("/appdata/build_date").InnerText;
    string updateUrl =
       myXmlDoc.SelectSingleNode("/appdata/url").InnerText;
    int result = 0;
    Int32.TryParse(build_date, out result);
 
    if (BUILD_DATE != result)
    {
      MessageBox.Show("There is an update available. Please check " +
           updateUrl + " for details.");
    }
  }
  catch
  {
    //do nothing.
  }
}

Then all that’s left is to set a timer to periodically call this function.  Put this in your Main() or someplace appropriate.

appUpdateTimer.Interval = 4 * 60 * 60 * 1000; //check every four hours
appUpdateTimer.AutoReset = true;
appUpdateTimer.Elapsed += new ElapsedEventHandler(appUpdateTimer_Elapsed);
appUpdateTimer.Start();

 

 Posted by at 1:40 pm
May 112010
 

I’ve mentioned my Panasonic BL-C1A network cameras before in a post about monitoring the garage door. I happen to have two of these cameras, and I have automated them to do quite a lot for me. The software that comes with the cameras is pretty lousy, and it makes you think you have to use Internet Explorer and nothing else to look at the images coming out of the camera. Well, I can tell you it’s not true. Although, if you want to use the ActiveX controlling software that comes with the camera, you are limited to only IE. Not good enough for me. I want to be able to see the images on my cell phone, and I don’t like being tied to a single browser, especially IE. For instance, wget (as I used in yesterday’s post about pulling images from a web site) could be used to pull the images from the camera. I also want the images to be saved on a web server so that if my cameras themselves are stolen, or if my home computer is stolen, I will still have a backup of the images. Now, I don’t normally store or watch video from the cameras, but instead focus on storing still images. I can watch video, but I don’t currently know of an easy way to save the video to my web server.

There will be several steps to this process. First install the camera. Next, set up the port forwarding on your router so you can view the camera from outside your local network. Then we will set up some cron jobs on the web server to retrieve and save the images. Finally we will set up a web page so we can view the images that have been saved. If desired, the entire system can be controlled by the home automation system, and I will show you how I did that as well.

The first thing to do is install the cameras. Install the cameras using the software provided, but don’t worry. We won’t be sticking with that software. Make sure you can connect to your camera from a computer on your local network, using the software provided. I would now recommend that you set static IP addresses for your cameras. It defaults that way, so this should not be a problem. The default IP address should be something like 192.168.x.253, where ‘x’ is the same number as the rest of your networked computers, probably a 1 or a 0. Also, set the port to some high number, such as 8001. You will also want to set usernames and passwords for the camera. Next, using the IP address for the camera, use your NON-Internet Explorer web browser to view the images by going to this website:
192.168.x.253:8001?mode=local
If that works, then we have lots of other options:

http://192.168.x.253:8001/SnapshotJPEG?Resolution=320×240&Quality=Precision&mode=local

http://192.168.x.253:8001/SnapshotJpeg?Resolution=640×480&Quality=Standard&mode=local

http://192.168.x.253:8001/ImageViewer?Resolution=640×480&Quality=Standard&mode=local

There is a little more information about these addresses here:

http://tatethatcher.com/wp/archives/57

Great. Now we can see the images with any web browser. Video still requires a web browser that can handle java. Now let’s set it up so we can view the images from outside our local network by using port forwarding.

If you have a cable modem or DSL that is connected to the internet all the time, then you can probably set up port forwarding with that device. I use the world famous Linksys WRT-54G with the upgraded firmware DD-WRT. I certainly can’t tell you how to do this on every device out there, but port forwarding is quite common and searching google for “port forwarding yourdevicename” should give you a good place to start. However, the idea is simple. You want your router to recognize incoming traffic on a certain port and then automatically forward it to another port, such as 8001 in this case. The idea here is that you could be on a public computer in your library and go to http://some_site_yet_to_be_named.com:someportnumber and you will see the video on that camera. If you have more than one camera, you would go to the same site, but a different port number, such as http://some_site_yet_to_be_named.com:someotherportnumber. I used the same portnumber, 8001, but you could use a different one. So I can go to http://mysecretsite:8001 from any browser and see the video. So I need to go into the firmware settings for the router, and I will want to forward any traffic that comes into http://mysecretsite:8001 to http://192.168.x.253:8001. The port forwarding rules will not need to know anything about “mysecretsite”, so you won’t find any place to enter that setting. All you will have to enter is the incoming port, outgoing IP address and outgoing port. The incoming and outgoing ports in this case are both 8001 and the outgoing IP address is 192.168.x.253. At this point you could check and make sure the port forwarding is working by going to your router’s IP address (find it by going to http://whatismyip.com) followed by :8001, such as http://123.45.67.890:8001.

Related to the port forwarding is dynamic DNS. If you are lucky enough to have a static IP address, you can skip this paragraph. Otherwise you will need to follow the steps here to create a dynamic DNS host name. You can set up a free account at http://dyndns.com. Once your account is set up, add a host service with a hostname that you can remember. Have it point to your current IP address for now, but you will want to configure automatic updating. You can either use free software or even easier, you might be able to configure the automatic updating right within your router. If it works, you should be able to go to your new host:

http://mynewhost.homedns.org:8001/SnapshotJpeg?Resolution=640×480&Quality=Standard&mode=local

and see the images from the camera. At this point step two is complete. You can save that URL and you will always be able to view your camera from any web browser on the internet.

The last step is to set up some cron jobs on your web server to grab the images from your camera and save them to a specific directory on your web server. This way you will be able to review past images as needed. It will require you to have a web server that you have shell access to. Some web hosts out there that do allow shell access do not allow scripts to run for extended periods of time. I use dreamhost (http://dreamhost.com), which works perfectly.

#!/bin/bash
# getfamroomwebcam.sh

while :
do
THISFILE=`date +/home/httpdocs/FamilyRoomWebCam/%Y%m%d%H%M%S.jpg`
wget --http-user=camera_user --http-passwd=topsecret -O ${THISFILE} -q http://mynewhost.homedns.org:8001/SnapshotJpeg?Resolution=640x480&Quality=Standard&mode=local
sleep 20
chmod 644 ${THISFILE}
done

As long as this script is running it will grab a new image from the camera every 20 seconds. It saves the images with a timestamped file name. You could configure this to start running at server startup, maybe have a cron job that checks to see if it is running periodically (like once an hour) and if it finds that the script is not running, restart it. I have it set up so that whenever I arm my burglar alarm (Elk M1G), the elk sends an email to my web server with a special code. Procmail reads the email and if it sees the special code, it starts (or stops, on disarming) the script. Here is my Procmail script to start the web cam:
:0
* ^Subject:.*SecretStartCode
{
:0w
| /home/script/getfamroomwebcam.sh &

:0
/dev/null
}

Finally, I have another cron job to delete old pictures every night. Otherwise the picture directory would get very full very fast. I don’t think dreamhost would like that at all.

find /home/httpdocs/FamilyRoomWebCam -mtime +3 -exec rm {} \;

This will delete any pictures older than three days old.

The very last step is I wrote a small web page to display the images. It uses javascript to play the images in a slideshow, or it can display all images from a specific time period. For now I will leave that up to you, but I will post the code for it in a few days.

May 102010
 

This isn’t just another “how to rotate your Windows Desktop image” post.  Search for that on Google and you will find many solutions for that.  I am going to show you how to use a specific image that is posted periodically to the web and have that as your desktop image.  For instance, let’s say your favorite cat photo website has a feature where they post the Cat Photo of the Day.  If they always post that image with the same file name (cpotd.jpg, perhaps), each day over-writing the image with the new image, then you could use that image as your windows desktop wallpaper, and whenever the photo is updated, you would have the latest photo on your desktop as well.  Now, there are RSS solutions to do something similar, but the difference here is that the file must always be named the same each time they update the photo.  Actually, this method is quite common for images that are updated periodically.  Many weather sites use the same image name for the latest weather map, for instance.  And many sites that do have a photo of the day feature as I described above use this method of updating their image.  Ready to do it yourself?

There are three parts to this.  First we need to identify an image that is suitable for our needs.   Remember, it must always have the same filename.  This method won’t work if today they name the image “20100509_cpotd.jpg” and tomorrow they name it “20100510_cpotd.jpg”.  Although with a little creative programming (perhaps using windows power shell), this could be worked around quite easily.  Step two involves writing a batch file and creating a shortcut to pull these steps into one small program. The final step will automate a means to download the updated images on schedule.

I am going to use an image from a very cool website, http://www.die.net/earth/.  This site displays an image of the earth rendered in real time, with a correct display for where it is daylight and evening.  It also shows the latest cloud cover.  It makes for a really cool image and it can easily be used for your desktop image.  But first, we need to make sure that the image filename is always the same.  Right click on the image and choose “Copy image URL”.  Then paste the image URL into the address bar of your browser and hit enter.  You should see a “web page” with nothing more than the image itself.  And we can now see the image URL, http://static.die.net/earth/mercator/1024.jpg.  Ok, it doesn’t look like they have any time or date strings in there, so my guess is, the filename is always the same.  But why is it named 1024.jpg?  1024 is a common width for desktop resolution, and is a common width for online images as well.  I wonder if a higher resolution is also available?  Let’s change the 1024 to 1600 and see what happens.  Sure enough, that gives us a larger image.  We will use http://static.die.net/earth/mercator/1600.jpg as our source image.  Now, how often is the image updated?  Well, I have been looking at this site for a little while, and it would appear that the image is updated about every half hour.  I’ll keep that in mind as we go along.

Next, we need a means to automate the download and storage of the image.  I like a program called wget which is originally a command line tool for unix/linux just for retrieval of web pages and images.  It’s actually a quite powerful tool, and of course it is free and yes, there is a windows version available for us right here. After you are done with this exercise, I am sure you will find other uses for wget, such as backing up your website. Go ahead and install the windows binary for wget.  I used the “Complete package, except source” setup file.  If you prefer zipped files, go ahead and choose that.  When the installation is complete, wget should be installed in your c:\Program Files\GnuWin32\bin folder.  Open a command prompt by clicking on the start menu and typing “cmd” and pressing enter.  Then type

cd c:\Program Files\GnuWin32\bin

(here’s a hint:  try typing cd c:\Pro{Tab}\Gn{Tab}\bin{enter}).  Once you are in the correct folder, type

wget http://static.die.net/earth/mercator/1600.jpg

and press enter.  You should see wget do its thing and download the file.  The only trouble is, the file is downloaded to the current folder–not a really good thing to do.  Let’s make a folder just for our Earth Image and tell wget to store the image in that folder.  Make a suitable folder somewhere and name it something appropriate.  I used c:\users\skip\Pictures\EarthImage.  I would recommend using a path that has no spaces, like “My Pictures”.  Spaces can sometimes mess up automated programs like this.  Now that we have created that folder, let’s run wget again, this time using the -O option.  Option O tells wget where to store the output.  So the command this time will be: (type this command all on one line. Do not type the &&. That just shows that this line continues to the line below.)

wget -O C:\Users\skip\Pictures\EarthImage\earth.jpg &&

http://static.die.net/earth/mercator/1600.jpg

Note that I also changed the name of the file itself to earth.jpg.  Look in the folder and you should see our earth.jpg image, saved and ready to be used.  Now let’s see if we can apply that image as our wallpaper. I like a free program called “command line wallpaper changer portable”. Once it is installed, you just open a command prompt and enter

C:\Users\skip\CLWCP.exe C:\Users\skip\Pictures\EarthImage\earth.jpg

And you should see the image on your desktop. As you can see, I copied the executable clwcp.exe to my profile folder, but you can run it from wherever you want. If that works, step one is complete.

Step two is to automate the retrieval of these images. I want to do a few things to make the scheduling go easier and I also want to prevent the command prompt window from taking focus when it runs (I would like to update the wallpaper in the background without you really noticing that it is happening.) To do this, we will make a batch file called “GetEarthShot.bat” and save it somewhere like a utilities folder (I save mine in my profile folder, c:\users\skip). The batch file will only have two lines:

"C:\Program Files\GnuWin32\bin\wget.exe" -O C:\Users\skip\Pictures\EarthImage\earth.jpg http://static.die.net/earth/mercator/1600.jpg
C:\Users\skip\CLWCP.exe C:\Users\skip\Pictures\EarthImage\earth.jpg

Can you see how it works? When this batch file runs, it will execute those two lines. First it will download the latest image. Then it will apply the image as the wallpaper. Save the file and double-click in in Explorer and you should see the command window pop up and see the two commands execute. Now, in order to make the command window itself NOT pop up (I find it distracting, and it can take the keyboard focus away), we will create a Windows shortcut to the batch file and set some properties to make sure it runs in the background. Right click on the GetEarthShot.bat file in Explorer and choose “Create Shortcut”. You should see the shortcut appear in explorer. Rename it so the “- Shortcut” isn’t there. I renamed mine to the same thing as the batch file itself: “GetEarthShot.bat”. Now right click on the shortcut and choose properties. You should see that the target is set to point to your batch file. Change the “Start in” parameter to “C:\Program Files\GnuWin32\bin\” (including the quotes). Finally set the “Run” parameter to “Minimized”. Click OK to save the changes and test it by double clicking the shortcut. If you watch VERY carefully, you might see the window pop up for a very, very brief moment, and then you may notice the icon on the task bar indicating that the batch file is running. After two or three seconds, the icon should go away and your desktop image should be updated. Now, if you are running this right away after initially setting the image when we first tested it, you may not be applying a NEW image, so you may not notice anything different. Step two is complete. Now let’s automate the whole process.

Go to Control Panel -> Administrative Tools -> Schedule Tasks.  On the left side, if you click on Task Scheduler Library, you will see all of your scheduled tasks in the center pane.  On the right, click on “Create Basic Task”.  I used “Update Earth Image” as the name and I gave it a nice description as well.  Click the “Next” button.  For the trigger, choose “After logon”.   Click “Next”.  Under “Action”, chose “Start a program”.  After clicking “Next” you will enter

c:\users\skip\GetEarthShot.bat.lnk

And under “Start in”, enter

c:\Program Files\GnuWin32\bin\

Note that the full path to wget is in the command line.  Click “Next”.  Click to enable to “Open the properties dialog for this task when I click finish” and then click finish.  The properties dialog should pop up.  Click the Triggers tab and then “Edit”.  Under Advanced setting, click the “Repeat task every” and set the frequency to 30 minutes, for a duration of Indefinitely.  Click OK to exit and save the task.  This task should now run every 30 minutes.  So now, every 30 minutes, that folder will be updated with the latest earth image, over-writing the image already there.  If you right click on the task and choose “Run”, the task should run. You should see the batch file run minimized as we did before. If all is well, reboot your computer to get the task going. Step three is complete and you are done.

Using the process here, you could do a lot of things with wget setting up some cool rotating images. Good luck!

May 042010
 

I hate it when I send an email only to get an email back from the recipient saying that I forgot to include the attachment that I referred to in my email.  How annoying.  I also hate it when I forget to fill in the subject line.  I don’t like receiving emails with no subject lines and I hate it even more when I accidentally send one myself.  So I found some VBA macros that I could add to Outlook which will look for certain criteria which may indicate a forgotten attachment.  The missing subject line is a little more straightforward. I always want a subject line and when I hit the send button, it’s either there or it isn’t, but the attachment detector has to first figure out if I intended to attach something.  So, let’s just jump into the code.  I found the majority of this code at http://msmvps.com/blogs/athif/pages/48968.aspx but you will see that I made some changes to it to suit my needs.


Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim lngres As Long
If InStr(1, Item.Body, "attach") Or InStr(1, Item.Subject, "attach") <> 0 Then
If Item.Attachments.Count = 0 Then
lngres = MsgBox("word 'Attach' found, but no attachment - send anyway?", _
vbYesNo + vbDefaultButton2 + vbQuestion + vbSystemModal, "You asked me to warn you...")
If lngres = vbNo Then Cancel = True
End If
End If

If InStr(1, Item.Body, "include") Or InStr(1, Item.Subject, "include") <> 0 Then
If Item.Attachments.Count = 0 Then
lngres = MsgBox("word 'include' found, but no attachment - send anyway?", _
vbYesNo + vbDefaultButton2 + vbQuestion + vbSystemModal, "You asked me to warn you...")
If lngres = vbNo Then Cancel = True
End If
End If

If InStr(1, Item.Body, "enclose") Or InStr(1, Item.Subject, "enclose") <> 0 Then
If Item.Attachments.Count = 0 Then
lngres = MsgBox("word 'Enclose' found, but no file enclosed - send anyway?", _
vbYesNo + vbDefaultButton2 + vbQuestion + vbSystemModal, "You asked me to warn you...")
If lngres = vbNo Then Cancel = True
End If
End If

strSubject = Item.Subject
If Len(Trim(strSubject)) = 0 Then
Prompt$ = "Subject is Empty. Are you sure you want to send the Mail?"
If MsgBox(Prompt$, vbYesNo + vbQuestion + vbMsgBoxSetForeground, "Check for Subject") = vbNo Then
Cancel = True
End If
End If
End Sub

The first thing to notice is that this macro is executed whenever you click the send button (or press ctrl-enter). Whenever you start the send process, this macro executes. The first three parts of the code look for the words “Attach”, “Include” and “Enclose” in the body of the email as well as the subject line. Sometimes I just send an email with the subject line “Final report attached” and nothing in the body. I want the trigger to recognize this. Also, the triggers are not case sensitive and they will also hit on other forms of the word, such as “Attached”. So, if one of those key words is found, it will then check to see if there are any attachments in the email. If there are no attachments, a dialog box is presented stating that one of the keywords was spotted yet there were no attachments found. Do you still want to send the email? It can happen that you might be replying to a quoted email that someone sent you and had the word “attach” in it. Most people when they reply to an email, they include the original sender’s quoted email. You may not have any intention of including an attachment in this case, but the macro will still find the word “attach”, so it gets triggered. I wish there was a way to have the macro only look at the new text that you added, but there doesn’t seem to be. If you answer “No” to the question “Do you still want to send”, then the send process is cancelled and you will have a chance to add your attachment. If you choose “Yes” then the email is sent as usual.

The last section of code looks for blank subject lines. The methodology is the same as the other sections, and is probably self explanatory.

To make this code work in your Outlook, just copy the code to the clipboard, open Outlook and press alt-F11. On the left side, you will see a standard navigation tree. Under Project1 (VbaProject.OTM) expand Microsoft Office Outlook Objects. Double Click on “ThisOutlookSession” and then paste the code in the code pane. Save your work, close Outlook and restart it. Try and test the code by sending yourself some test emails.

I hope this helps some of you.