Updating Open Live Writer Auto Links with PowerShell

Open LIve WriterI’m sure it comes as no surprise to you that I do a fair bit of blogging and writing. This means I am always on the look out for tools and tricks to make the process easier. Recently Scott Hanselmen and others announced a resurrection of the old Microsoft Live Writer tool into an open source project. You can learn more about Open Live Writer here.

I decided to give it a try and while obviously there’s a lot of updating to do, one feature I like is the automatic linking.  When I type something, like Get-Eventlog the program will automatically insert a link. You can manually set these links up in the program. But because I write a lot about PowerShell cmdlets, which have online links, I didn’t want to manually have to create hundreds of links.

So with some pointers from other community members I learned that the autolink information is stored as a simple XML file under $env:APPDATA\OpenLiveWriter\LinkGlossary\linkglossary.xml. The file layout is pretty simple.

image

This means I can use PowerShell to create new entries.

First, I get the existing XML content.

Then I create new Entry element.

The node has properties for text, url, title, rel and openInNewWindow, all of which are case sensitive which is important to remember when working with XML.  I’ll need to create an entry for each property.  The process is the same for all the items.

Now I have a new XML object.

image

The text that I want to auto link to is going to be PowerShell.org.

I like using Trim() on strings, to eliminate any extra spaces. Once this is complete all I need to do is append the text entry to the entry node.

I repeat the process for the URL

The Title:

The Rel link I’m not using so I’ll create an empy setting.

And finally whether the link should open in a new window.

Note that this needs to be a string and not a PowerShell boolean value. I now have a complete autolink entry.

image

All I need to do is append it to the XML document and save the file.

Naturally I needed a function to do all of this which I have posted as a Gist on GitHub.

With this function, I also added code to update an existing entry. But now I can use PowerShell to find all commands that have a help link and add them to the autolink XML file.

I recommend updating the file when Open Live Writer is not in use. When you update the file, you should see all of your new entries.

olw-links

You may not be a blogger or author, but hopefully my script will give you some pointers on working with XML files.

Where Did the Time Go?

antique watchLike many of you the work day just seems to fly by. At the end of the day I start wondering what I really got accomplished and what I actually did all day. Well if you are willing to face the truth I have a way to help. Last year I wrote about a PowerShell module I called MyMonitor. As part of my ongoing effort to make some of my larger projects more accessible, I have revised it and published to GitHub.

The MyMonitor module works under the premise of keeping track of what window is currently active and how long it has been running. I can also extract other information using Get-Process that indicates the window title, the associated product, when the process started and when it ended. I include the processID as well, although that probably doesn’t have any practical value.

The data collection process starts with Get-WindowTime. You can specify a time duration in minutes such as 60 minutes. Or perhaps you want to collect your usage data until 4:00PM. You can do that as well. One way that I use the command is with the ProcessName parameter. The concept is that you can start an application that you rarely use. When Get-WindowTime detects the process, it terminates collection. I typically use Windows Calculator as a “flag” process. Finally, you can run all of this as a background job so that you can get your PowerShell prompt back. Just don’t close your session before you stop the job and collect the data.

The new version also includes categories. I created an XML file in the module with categories for different applications. You can have an application with more than one category. This adds another way to see where you are spending your time. More on that in a moment. When you collect your usage statistics, you’ll get an object like this for each application.


data sample

The module includes a few cmdlets for reporting and analyzing the data.


Getting a summary report

Or you can use Measure-WindowTotal to slice and dice the data.


Measuring window time by application


Measuring window time by category

You can even get a bit more granular be filtering on text in window titles.


Measuring time by window title (Image Credit: Jeff Hicks)

All of the commands in the module have complete help and examples. There is also an About topic.


About_MyMonitor

The module is still a work in project. One of the items on the wish list is a better way to archive usage. This would allow you get a better idea of where your time goes on a weekly or monthly basis.

But for now, you can get the module source files from the repository on GitHub. I strongly recommend you read the About topic and help before you start using the module. Comments are welcome here but please use GitHub to report any problems or feature requests.

Friday Fun: Open Last File in the PowerShell ISE

Over the last few articles I’ve been sharing some shortcuts to get most recently used or edited files. For today’s Friday Fun I thought I’d share something that I use in my PowerShell ISE profile. Whenever I start the ISE, I automatically open the last file I was working on. Instead of launching the ISE and then finding the most recent file in list under File, this happens automatically.

I found some information on this topic at PowerShell.com and revised it to meet my needs. The most recently used files are stored in an XML configuration file, which is good because I can use PowerShell to parse out the information I need. Unfortunately, the path to this file is pretty unwieldy:

$env:LocalAppData\microsoft_corporation\powershell_ise.exe_StrongName_lw2v2vm3wmtzzpebq33gybmeoxukb04w\3.0.0.0

Which translates to something like this:

C:\Users\Jeff\AppData\Local\microsoft_corporation\powershell_ise.exe_StrongName_lw2v2vm3wmtzzpebq33gybmeoxukb04w\3.0.0.0

The XML file is called user.config. With that, let’s get some PowerShell in here to get the XML.

The recent used list is stored under user settings.

The value should have what I need.

Looks like it is an array of strings.

Getting closer. It seems the last step I need is that string property.

This should be the same list as I see under File. But while this works, it assumes that the setting I want will always be at position 5 and that I know how to get there in the first place. The smarter way is to use an XPATH filter to find the data. I can use the SelectNodes() method.

The query essentially says find any node that is a <setting> and that has a name attribute of “MRU”. XML is case-sensitive so I have to match what is in the XML file.

With this it is just as easy to get the most recent file.

Once I know the file name it is trivial to load it into the ISE.

The other way I could have selected the node is with Select-XML.

The node property has the setting I need. I can simply keep drilling until I get the value I want.

In this case I’m only selecting the first item. I could have used these code snippets in my profile, but I decided to create a function to retrieve the MRU list.

The function encapsulates everything I’ve shown you. Although I set a default path using a wildcard.

I did this to keep things easier to read and on the off chance that the strong name value might change at some point. By the way I am running this on PowerShell 4.0. I have not tested with v5.

To get the full path, I can resolve this path with a wildcard.

Most everthing else is the same. This function is in my PowerShell ISE profile script and at the end I open the most recent file.

It’s that easy. And because the function is in my profile, I can run it anytime. Although note that the XML file won’t get updated until you close the ISE. Personally, all these little things add up over the course of a day and make my work a bit more fun. Enjoy.

A PowerShell Weather Service

I’ve been having some fun this week sharing a few tools for getting weather information and forecasts using PowerShell. To complete the story, today I have one more technique. Using PowerShell, you can query a web service for weather information. In simple terms a web service is like an application you can “run” via a web connection and sometimes even in a browser. The web service has “methods” you can invoke to do something. In the past if you wanted to interact with a web service in PowerShell you most likely needed to get down and dirty with the .NET Framework. Then PowerShell 3.0 brought us a new cmdlet, New-WebServiceProxy. With this cmdlet you can create an object that in essence becomes a wrapper to the web service. The web service methods become the object’s methods. Let me show you.

First, I’ll create my proxy object.

This object also has methods:

So how do I use the GetWeather method?

Seems straight forward. Let’s try. Wonder what it is like someplace warm?

Interesting. I can read it, but this sure looks like XML. If so, I should be able to retrieve the weather as an XML document.

Now I can explore it.

Wow. This seems simple. All I need is the CurrentWeather property and I have an easy to read result. I could probably run this as a one-liner.

Not necessarily easy to read but it works.

What about another city? Perhaps Charlotte, North Carolina, the site of the upcoming PowerShell Summit.

Well that worked, but that isn’t the city I had in mind. Going back to the web service methods, I remember seeing something to get cities by country. Let’s try that.

More XML. That’s find. I can use Select-XML to parse out the City node.

Now, expand each node.

Let’s try with the US now and find cities with Charlotte in the name.

It seems to me that the weather service data comes primarily from locations with airports. So if you live in a town without an airport, the best you can probably do is find a location near you with an airport. But now that I see what I need for Charlotte, North Carolina, I can revise my command.

Much better. But I don’t want to have to do that much typing for all of this so I put together a few functions to simplify the entire process. First, is a function to get a location.

The function does all the work of creating the web service proxy and retrieving cities by country. You can change the default to your country. I also added a parameter that will match on a city name.

I then wrote a function to make it easier to get weather information.

In looking at the XML, there were a few minor issues. One, the Wind node was repeated so I decided to combine the two into a single property. I also noticed that some of the node values had extra spaces. So I trimmed up the values as a I built an ordered hashtable which I then turned into a custom object. The end result is an easy to use tool.

You can even pipe between commands.

The object properties are all strings which means sorting or filtering is troublesome, but there is some good data here so I guess it is a trade-off.

Now you have several ways to check the weather, assuming you can’t simply look out a window. And hopefully you’ve learned a few new things about PowerShell along the way.

Getting the Weather Where On Earth

Yesterday I posted a popular article about using Invoke-WebRequest to get weather conditions. That function used the Yahoo web site but really only worked for US cities. So I also cleaned up and revised another set of advanced PowerShell functions (required PowerShell 3) that can retrieve weather information for probably any location on Earth. The first piece of information you need is your WOEID, or “Where On Earth ID”. Here is a function to do just that.

To use the function you specify some sort of search criteria such as a postal code or city name.

I saved my WOEID as a variable in my PowerShell profile. This function also uses Invoke-RestMethod. I included a parameter to write an XML document to the pipeline instead in case you want to modify the function and need some help discovering the data. The second function, Get-Weather, uses the WOIED to get the current weather conditions. It too uses Invoke-RestMethod to retrieve the data. The resulting XML document is then parsed out using Select-XML to build an output object.

You can also change the temperature units.

I wrote these as two separate functions, I suppose I could have nested Get-Woeid inside Get-Weather, although the better option is probably to build a module. I’ll leave that for you. The functions are designed to take advantage of pipeline binding so that you can pipe Get-Woeid to Get-Weather.

You can even get weather for multiple locations.

This weather source includes a lot of information so I created a parameter to control how much detail to display. What you see above is basic information. But there is ‘extended’.

Or you can see everything with a detail setting of ‘all’.

Notice that url at the end? As the cherry on top, you can open the weather forecast in a browser using the Online parameter.

There you have it. No matter where you are you can check the weather. Or look out a window.

Enjoy.