2012-01-26

Use Google Chrome to View .pdf Files

I now use Google Chrome to view .pdf files instead of Adobe Reader (formerly called Acrobat Reader). The Chome PDF Viewer plugin (chrome://plugins) has been shipping with Chrome since version 8 2010-12. Using Chrome to view .pdf files has several advantage over Adobe Reader:

  • Chrome loads the .pdf files much quicker.
  • The .pdf files are conveniently loaded in a new Chrome tab.
  • It is much more secure, because Chrome makes it play in a sandbox. Take a look at the long list of security bulletins for Adobe Reader.
  • If you uninstall Adobe Reader like I did, you don’t have to constantly update it.

To associate a .pdf file with Chrome, right click on a .pdf file and have it open with:
%localappdata%\Google\Chrome\Application\chrome.exe

These links have more detailed walkthroughs:
2011-03-21 How to Set Chrome As Your Default PDF Reader
2011-08-23 The Complete Guide to Using Google Chrome As Your PDF Reader With Added Perks

2012-01-25

Error Updating Windows Live Writer 2011

I just launched Windows Live Writer on my Windows 7 64-bit PC and it told me an update was available. While trying to run the update, it failed with this error:

It looks like another program is preventing the installer from working.
Error: 0x80070643
Source: wllogin-amd64

I reran the installer a few times, but kept getting the same error. I downloaded the offline installer and got the same error. I uninstalled Windows Live Essentials 2011, then tried reinstalling, but got the same error. I was able to find the installer logs in C:\ProgramData\Microsoft\WLSetup\Logs. Searching for “error” in the latest log, I saw this:

MSI_ERROR      :00001674 (01/25/2012 12:27:54.317) Service 'Windows Live ID Sign-in Assistant' (wlidsvc) could not be installed.  Verify that you have sufficient privileges to install system services.

When I took a look at that service, I saw it was disabled. When I tried to start it, it gave an error saying that it was “marked for deletion”. After a reboot, I noticed the service no longer existed. I restarted the install and everything went smoothly.

In summary, if you get the first error above, here is what worked for me:

  1. Uninstall Windows Live Writer 2011
  2. Reboot!
  3. Reinstall Windows Live Writer 2011

Hopefully this saves someone some time and frustration. There are tons of search results for this error without useful remedies. I upgraded from version 15.4.3502.922 to 15.4.3538.513.

2011-04-03

OData from JavaScript - Netflix Genres

Microsoft’s WCF Data Services Team announced a new JavaScript library for OData in February. The documentation for the new library gives several code snippet examples, but doesn’t provide live examples. Here is a live example that gets all the genres in the Netflix catalog. The source code is here.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load("jquery", "1"); // 1.5.2
    </script>
    <script type="text/javascript" src="datajs-0.0.2.min.js"></script>
    <script type="text/javascript">
      $(document).ready(function () {
 
        // http://datajs.codeplex.com/documentation
 
        OData.defaultHttpClient.enableJsonpCallback = true;
 
        OData.read("http://odata.netflix.com/v1/Catalog/Genres",
        function (data, request) {
          var html = "";
          for (var i = 0; i < data.results.length; i++) {
            html += "<div>" + data.results[i].Name + "</div>";
          }
          document.getElementById("Genres").innerHTML = html;
        }, function (err) {
          alert("Error occurred " + err.message);
        });
 
      });
    </script>
    <title>Genres</title>
  </head>
  <body>
    <div id="Genres"></div>
  </body>
</html>

2011-02-21

How to Enable Typing in Spanish

I am currently taking Spanish classes. The easiest way I’ve found to type in Spanish is to add “Spanish” as an input language for your keyboard in Windows. Once you add “Spanish” as an input language, the Language Bar allows you to easily switch between the languages. Here is a screenshot that shows how to do it in Windows 7:

Add Language

Run the On-Screen Keyboard application to see what characters your keys map to.

OnScreen Keyboard

The process on Mac OS X is very similar. Go to System Preferences > Language & Text > Input Sources. Add “Spanish – ISO” as an input source and check “Keyboard & Character Viewer”. You can then switch language input in the menu bar and use the Keyboard Viewer to see how the keys are mapped to characters.

¡Ahora puedes escribir en español! To type accents like á é í ó ú, press the accent key to the right of the ñ key first, then the vowel.

2010-12-03

Asynchronous Serial Port Communication with F#

Asynchronous programming in F# is almost as easy as programming synchronously. It is a compelling reason to use F# rather than another language like C#, which will not have an easy asynchronous model until C# 5.0. Below, I show how communicate to a device over a serial port both ways. The advantage of the asynchronous approach is that it does not lock up the user interface if the device does not respond right away.

module Program
 
open System.Windows
open System.Windows.Controls
open System.IO.Ports
open AsyncSerialPort
 
type Form() as this =
  inherit Window()
 
  do
    let sp = StackPanel()
    this.Content <- sp
    let tbRequest = TextBox();
    tbRequest.Text <- "*IDN?"
    let tbResponse = TextBlock()
    let btn = Button(Content="Query Device")
 
    sp.Children.Add tbRequest |> ignore
    sp.Children.Add tbResponse |> ignore
    sp.Children.Add btn |> ignore
 
    let sp = new SerialPort(PortName="COM1", BaudRate=9600, DataBits=8, Parity=Parity.None, StopBits=StopBits.One);
 
    // synchronous, blocks UI
//    btn.Click.Add(fun _ ->
//      sp.WriteLine tbRequest.Text
//      let rsp = sp.ReadLine();
//      tbResponse.Text <- rsp;
//    )
 
    // asynchronous, does not block UI
    btn.Click.Add(fun _ ->
      async {
        do! sp.AsyncWriteLine tbRequest.Text
        let! rsp = sp.AsyncReadLine()
        tbResponse.Text <- rsp;
      }
      |> Async.StartImmediate
    )
 
    sp.Open()
    ()
 
 
[<System.STAThread>]
do
  Application().Run(Form()) |> ignore

As you can see, the asynchronous code in the above example is just as easy as the synchronous code. The code to deal with the serial port was a bit trickier. The F# libraries provide extension methods like AsyncWrite and AsyncRead for classes like Stream. In this module, I use those extension methods to create ones for System.IO.Ports.SerialPort. These methods implementations may not be perfect, but they work.

module AsyncSerialPort
 
open System.IO.Ports
open System.Text
 
type SerialPort with
 
  member this.AsyncWriteLine(s:string) =
    this.BaseStream.AsyncWrite(this.Encoding.GetBytes(s+"\n"))
 
  // expects a terminating line feed '\n'
  member this.AsyncReadLine() =
    async {
      let sb = StringBuilder()
      let bufferRef = ref (Array.zeroCreate<byte> this.ReadBufferSize)
      let buffer = !bufferRef
      let lastChr = ref 0uy
      while !lastChr <> byte '\n' do
        let! readCount = this.BaseStream.AsyncRead buffer
        lastChr := buffer.[readCount-1]
        sb.Append (this.Encoding.GetString(buffer.[0 .. readCount-1])) |> ignore
      sb.Length <- sb.Length-1 // get rid of '\n'
      return sb.ToString()
    }

Like usual, the code for the solution is available. Feel free to browse the code there and add comments directly to it.