Jim @ imason

Internet Architect by day, environmentalist by night: Jim Schwartz @ imason.

  • Jim @ imason

    Silverlight in Desktop Applications

    • 2 Comments

    Earlier this year I headed up a development team to build 2 Silverlight applications for The Weather Network. The first application to be released a few weeks ago is “WeatherEye Golf” (press release) which provides weather information for over 17,000 golf courses in Canada and the U.S. The second app that was just released last week is called “TrafficEye” (press release) which provides up-to-the-minute traffic information for the Greater Toronto Area (With plans to expand out to other areas). It includes traffic flow, highway conditions, traffic incidents, and traffic cameras. You can save up to 10 of your favourite highway cameras (If you download it now, you will be entered to win 1 of 2 Xbox 360 Game Consoles!!).

    These applications were quite unique because they needed to be downloadable and run on the desktop. Silverlight has several benefits over the other options we had explored. First of all, Silverlight runs as a web application, so it’s very easy to update in the future; you don’t need to push out updates to the desktop, and the user doesn’t need to re-install anything.  One of the issues with the flagship WeatherEye product (Which is purely a desktop application) is that they need to push out updates to users which can be very time consuming since there are approximately 2 million active users of the WeatherEye product. With Silverlight, the IT Staff simply needs to update the Web Application and the next time the user runs the app, they will have the latest version.

    Another benefit of Silverlight is the fact that you can easily port the application over to any web site, by simply adding an <object> tag to the HTML. Whether it’s a PHP page, ASPX, JSP, HTML, you can display the Silverlight application anywhere.

    The third benefit of Silverlight is the platform independence. We have a Mac version of the TrafficEye application that we are planning to release in the near future. It’s pretty neat to see a Microsoft solution running on a Mac desktop.

    To display the Silverlight application on the desktop we built a Visual Basic 6 application that displays a browser frame, (while in Mac we are using a Cocoa application developed using the XCode tools). The desktop shim is very basic and allows us to consolidate the application functionality in Silverlight. Silverlight uses Isolated Storage to persist user settings. We chose VB6 so that it will run on various desktop configurations without requiring the .NET framework, and also to keep the installation as small as possible.

    Overall I’m happy with the result of the applications. There are a couple kinks on certain desktop configurations, but overall the response from the public has been positive so far.

    TrafficEye WeatherEye Golf

  • Jim @ imason

    Automated Publishing of InfoPath Forms (Part 2 of 2)

    • 2 Comments

    We’ve now surpassed 50 InfoPath forms on the InfoPath 2007 / SharePoint 2007 project I’m currently engaged on. If you’ve done InfoPath/SharePoint development before, you’ll know that it can be really painful to publish forms and then deploy them to SharePoint.

    In Part 1 of this 2 blog series, I showed you how to automate the deployment of InfoPath forms to SharePoint using NAnt. This time around I’ll show you how to automate the publishing of an InfoPath form.

    If you’ve published an InfoPath form to an Administrator-approved form template before, you’ll be all too familiar with the process of clicking next a whole bunch of times in order to publish the form. Why should you have to go through all these manual steps every time you make a change to a form?

    To automate this, I first found some VB code on this blog article to publish a form. I then converted it to C#, and built it as a custom NAnt task. So now I can publish a form by simply calling a custom NAnt task like this:

    <publishform outputfolder="c:\mypublishedforms" formname="MyFormName.xsn" cabsdkpath="..\tools\CabSDK\BIN" xsffilename="manifest.xsf" formsourcepath="..\trunk\src\SourceForms\MyFormName\InfoPath Form Template\" />

    In order to use this approach, you’ll need to either build your InfoPath form using the Visual Studio template, or you’ll need to extract the form source files from the XSN. To extract the source files from the XSN, choose “File” -> “Save As Source Files”. Then you can work with your form template by right clicking on “manifest.xsf” and choosing “Design”.

    Here is the code to build the custom NAnt task:

    using System;

    using System.Diagnostics;

    using System.IO;

    using System.Xml;

    using NAnt.Core;

    using NAnt.Core.Attributes;

     

    namespace My.Build.Tasks

    {

        [TaskName("publishform")]

        public class PublishFormTask : Task

        {

            [TaskAttribute("outputfolder", Required = true)]

            public string OutputFolder { get; set; }

     

            [TaskAttribute("formname", Required = true)]

            public string FormName { get; set; }

     

            [TaskAttribute("cabsdkpath", Required = true)]

            public string CabSdkPath { get; set; }

     

            [TaskAttribute("xsffilename", Required = true)]

            public string XsfFileName { get; set; }

     

            [TaskAttribute("formsourcepath", Required = true)]

            public string FormSourcePath { get; set; }

     

            protected override void ExecuteTask()

            {

                string makeCabPath = CabSdkPath + "\\MAKECAB.EXE";

                BuildCabFile(makeCabPath);

            }

     

            private void BuildCabFile(string makeCabExe)

            {

                try

                {

                    if (!File.Exists(makeCabExe))

                    {

                        throw new Exception(string.Format("CABSDK not found. Please check your CABSDK property value. Couldn't find makecab.exe @ '{0}'", makeCabExe));

                    }

     

                    var tempName = Path.GetFileNameWithoutExtension(Path.GetTempFileName());

                    //var tempName = Path.GetTempFileName();

                    var tempFolder = Path.GetTempPath();

                    var tempPath = PathCombine(tempFolder, tempName);

     

                    var ddfString = string.Empty;

                    ddfString += ".Set DiskDirectoryTemplate='" + tempFolder + "'" + Environment.NewLine;

                    ddfString += ".Set CabinetNameTemplate='" + tempName + "'" + Environment.NewLine;

     

                    var xsfDom = new XmlDocument();

                    xsfDom.Load(PathCombine(FormSourcePath, XsfFileName));

                    var nm = InitNamespaceManager(xsfDom);

     

                    ddfString += QuoteString(PathCombine(FormSourcePath, XsfFileName)) + Environment.NewLine;

                    var fileNodes = xsfDom.SelectNodes("/xsf:xDocumentClass/xsf:package/xsf:files/xsf:file/@name", nm);

     

                    for (int i = 0; i <= fileNodes.Count - 1; i++)

                    {

                        ddfString += QuoteString(PathCombine(FormSourcePath, fileNodes[i].InnerText)) + Environment.NewLine;

                    }

     

                    var ddfPath = PathCombine(tempFolder, "makecab.ddf");

                    SaveToFile(ddfString, ddfPath);

                    ShellExecute(QuoteString(makeCabExe), "/V1 /F " + QuoteString(ddfPath));

                    File.Delete(ddfPath);

     

                    if (File.Exists(PathCombine(OutputFolder, FormName)))

                    {

                        File.Delete(PathCombine(OutputFolder, FormName));

                    }

     

                    File.Move(tempPath, PathCombine(OutputFolder, FormName));

     

                    string[] oScratchFiles = new string[] { "setup.inf", "setup.rpt" };

                    foreach (string strScratchFile in oScratchFiles)

                    {

                        if (File.Exists(strScratchFile))

                        {

                            File.Delete(strScratchFile);

                        }

                    }

                }

                catch (Exception ex)

                {

                    throw new Exception("Could not create XSN file from files.", ex);

                }

            }

     

            private static void SaveToFile(string data, string filePath)

            {

                var fs = File.Create(filePath);

                fs.Close();

                var TextStream = new StreamWriter(filePath);

                TextStream.Write(data);

                TextStream.Flush();

                TextStream.Close();

            }

     

            private static void ShellExecute(string command, string args)

            {

                var info = new ProcessStartInfo(command, args);

                info.UseShellExecute = false;

                var process = Process.Start(info);

                process.WaitForExit(60000);

            }

     

            private static string QuoteString(string s)

            {

                return "\"" + s + "\"";

            }

     

            private static string PathCombine(string folder, string fileName)

            {

                return Path.Combine(folder, fileName);

            }

     

            public static XmlNamespaceManager InitNamespaceManager(XmlDocument xmlDOMDoc)

            {

                XmlNamespaceManager xnmMan;

                xnmMan = new XmlNamespaceManager(xmlDOMDoc.NameTable);

     

                foreach (XmlAttribute nsAttr in xmlDOMDoc.DocumentElement.Attributes)

                {

                    if (nsAttr.Prefix == "xmlns")

                        xnmMan.AddNamespace(nsAttr.LocalName, nsAttr.Value);

                }

     

                return xnmMan;

            }

     

            public void RunTask()

            {

                ExecuteTask();

            }

        }

    }

     

     

  • Jim @ imason

    Advanced InfoPath Development with SharePoint

    • 1 Comments

    Thanks to everyone who made it out to our Advanced InfoPath Development session yesterday at the Toronto SharePoint Camp. We had quite a good turnout; so I’m glad to see there are lots of other people out there using browser-based InfoPath forms using Forms Services on SharePoint.

    InfoPath makes it easy to quickly develop forms, but it doesn’t come without its limitations. It’s very heavy on JavaScript, thus performance isn’t great when you have a lot of fields and rules. It doesn’t support multilingual, and it’s not very good at field validation. In this session we showed the audience how to get around these limitations by writing some simple C# code.

    I’ve posted the PowerPoint slides as well as the source code for the InfoPath form, the Web Service, the Web Part, and the NAnt XML build definition.

    If you’re interested in learning more about NAnt, send me an e-mail because I’m thinking about organizing a NAnt lunch and learn session at the imason office open to all Developers. We’re located in downtown Toronto on Adelaide Street near Peter St.

    Download the source code (SharePointCamp.zip), and PowerPoint slides (SharePointCamp-2009.pptx) here.

    image

    image

  • Jim @ imason

    Movember @ imason

    • 1 Comments

    A bunch of us at imason are taking part in Movember to raise awareness and raise money for Prostate Cancer.  For those of you who aren’t familiar with Movember, the idea is that you grow a moustache during the month of November to raise awareness for men's health. I don’t want to say that we’re “embarrassing” ourselves to raise money, because that could be perceived as a shot against people who normally wear a moustache.

    There  is nothing wrong with having a moustache, but for those of us who don’t normally wear a moustache, it is a bit embarrassing (but fun at the same time).

    It’s interesting to me how everyone looks completely different when they grow a moustache. My co-worker Boyan looks like Freddie Mercury, Rez looks like a scary hitman, Shahzad looks like a Venice Taxi Paddler and Steve looks like a Medieval Viking.

    I wasn’t sure what I would look like until I trimmed up today. Due to my inept ability to grow hair on my face combined with my “overtrimming”, I unfortunately ended up looking a bit like Adolf Hitler.  I have one more week remaining to let it “thicken out” a bit. Hopefully by the end of the month I’ll look more like Tom Selleck.

    Jim

    Tom Selleck 

  • Jim @ imason

    India: More than Technology Outsourcing

    • 0 Comments

    Over the years, India has evolved from being a cheap-labour offshore destination in the late 90's to becoming a premier full-range IT services destination in the 21st century. The primary reason for this trend is the highly educated and English-speaking workforce in India, as well as their hard work ethic and enormous population.

    In the early 2000's, India had achieved some great accomplishments in the area of software quality; 75% of the world's CMM Level 5 software centres were in India (At the time, CMM Level 5 was known as one of the highest levels in standards of quality).

    Offshoring has not been without difficulties. Many projects that I've personally been an observer of have not lived up to expectations, mainly as a result of miscommunications or lack of sufficient business requirements. I can imagine how difficult it would be to get clarification on business requirements with the time zone differences and the long distance. Technology consulting companies have enough difficulties as it is even when having the luxury of a nearby client.

    But alas, the point of this article was not to delve into the pros and cons of offshoring, but to point out how India's services have evolved over the years.

    Just today, the Pittsburgh Pirates have signed two 20-year old Indian baseball players who have never played baseball. Rinku Singh and Dinesh Patel took part in a pitching competition reality TV show in India sponsored by a California sports management company, who awarded Singh $100,000 and Patel $2,500 for winning the contest.

    The Pittsburgh Pirates are hoping to teach these young men how to play baseball in the minor leagues in the hopes they could become Major League pitchers in 3-4 years. Being cricket players, they weren’t accustomed to wearing a baseball glove, so they had to be taught not to catch the ball with their bare hands.

    In our world of globalization companies both inside IT and outside IT are scouting the global pool of talent to find the best and the brightest people. The Pittsburgh Pirate recruitment from India is symbolic of the direction business is headed in our ever-shrinking world, and countries like China and India will become more than just offshore destinations, they will open the door to many new possibilities previously untouched.

Page 2 of 5 (22 items) 12345