Contact

Subscribe via Email

Subscribe via RSS/JSON

Categories

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Elsewhere

Get a list of users in an OU along with last logged on date

Trivial stuff. Wanted to note it down someplace for future reference –

 

Start-BitsTransfer does nothing

I had to copy some VMware templates from our head office to the branch offices. Thought I’d copy them out of the datastores manually, then do a BITS transfer to the remote offices. This way I can do the transfer during normal hours but with minimal user impact.

Since PowerShell 2.0 you had the Start-BitsTransfer cmdlet to do BITS transfers.

Oddly however, the command would just exit without any error for me. And it didn’t seem to be doing anything. Then I realized I was pointing the cmdlet to my source folder and that’s why it was failing! Start-BitsTransfer only takes files. You can specify wildcards to select multiple files but you can’t point it to a folder.

So the following doesn’t work:

But this works:

Since Start-BitsTransfer supports wildcards it’s mostly fine unless your folder contains sub-folders and you want to copy these and/ or preserve the structure. Fortunately this is PowerShell so it’s just a matter of creating some wrappers around the cmdlet to support folders too. Like this one for instance. Or use CSV files like in this MSDN article.

One thing to keep in mind – by default Start-BitsTransfer has a default priority (specified via the -Priority switch) of Foreground. This competes with other applications so is probably not what you want. You alternatives are High, Normal, or Low – each of which does the transfer in the background and uses the idle bandwidth of the client for transfer (the priority determines which transfer job gets priority over the other similar BITS transfers).

Another thing to keep in mind is that BITS only really looks at the bandwidth availability of the client (when I say “client” I am not sure if it’s the sender or receiver – I didn’t read much into this). In a LAN environment it could be the case that the WAN side is saturated but the particular client you are targeting is idle – in this case BITS will use the full client bandwidth available to it even though the network itself doesn’t have any spare bandwidth (this was the case prior to BITS 2.0 but since then BITS can use an Internet Gateway Device to try and assess the bandwidth availability on the WAN side – this requires an IGD be find-able via UPnP and also that the Internet Gateway Device support such reporting, so I am not sure how well it works in practice). You can also use GPOs to control BITS bandwidth usage.

Anyhoo, this is not a BITS intro so I’ll leave it at that. :)

Once you start a BITS transfer you can also pause it via Suspend-BitsTransfer or cancel it via Remove-BitsTransfer. The latter will also delete any files that are already transferred, so if you just want to cancel but leave the transferred files as it is use Complete-BitsTransfer instead.

That’s all for now!

p.s. Almost forgot. You can also use BITS to download HTTP files. Like in this post for instance.

PowerCLI – List all VMs in a cluster along with number of snapshots and space usage

More as a note to myself than anyone else, here’s a quick and dirty way to list all the VMs in a cluster with the number of snapshots, the used space, and the provisioned space. Yes you could get this information from the GUI but I like PowerShell and am trying to spend more time with PowerCLI.

 

PowerShell – Create a list of all Exchange mailboxes in an OU with mailbox size, Inbox size, etc

As the title says, here’s a one-liner to quickly create a list of all Exchange mailboxes in an OU with mailbox size, Inbox size, Sent Items size, and the number of items in each of these folders.

 

Adding DHCP scope options via PowerShell

Our deployment team needed a few DHCP options set for all our scopes. There was a brickload of these scopes, no way I was going to go to each one of them and right-click add the options! I figured this was one for PowerShell!

Yes, I ended up taking longer with PowerShell coz I didn’t know the DHCP cmdlets but hey (1) now I know! and (2) next time I got to do this I can get it done way faster. And once I get this blog post written I can refer back to it that time.

The team wanted four options set:

  • Predefined Option 43 – 010400000000FF
  • Custom Option 60 – String – PXEClient
  • Predefined Option 66 – 10.x.x.x
  • Predefined Option 67 – boot\x86\wdsnbp.com

PowerShell 4 (included in Windows 8.1 and Server 2012 R2) has a DHCP module providing a bunch of DHCP cmdlets.

First things first – I needed to filter out the scopes I had to target. Get-DhcpServerv4Scope is your friend for that. It returns an array of scope objects – filter these the usual way. For example:

Now, notice that one of the options to be added is a custom one. Meaning it doesn’t exist by default. Via GUI you would add it by right clicking on “IPv4” and selecting “Set Predefined Options” then adding the option definition. But I am doing the whole thing via PowerShell so here’s what I did:

To add an option the Set-DhcpServerv4OptionValue is your friend. For example:

I had a bit of trouble with option 43 because it has a vendor defined format and I couldn’t input the value as given. From the help pages though I learnt that I have to give it in chunks of hex. Like thus:

Wrapping it all up, here’s what I did (once I added the new definition):

And that’s it!

Use PowerShell to ping a device and email you when it’s up

While rebooting our servers today as part of the monthly patch cycle, one of the servers took longer than usual to shutdown and restart. I didn’t want to waste time keeping an eye out on it so I whipped up a simple script that will first keep pinging the server (until it’s down), then keep pinging the server until it’s up, and finally send me an email when the server is reachable. Pretty straight-forward script, here it is with some commenting and extra bits tacked on:

In a corporate environment you do not need to specify the SMTP server as it’s automatically picked up from the $PSEmailServer variable.

If you specify an SMTP server that requires authentication though you can pass this via the -Credential switch to Send-MailMessage. I didn’t add that above coz I didn’t need it but while typing this post I realize that that’s something others might find of use. Especially if you are using a 3rd party SMTP server that requires authentication.

For more Send-MailMessage switches check out this TechNet page and blog post.

Further updates to this script will be at GitHub.

Search Firefox bookmarks using PowerShell

I was on Firefox today and wanted to search for a bookmark. I found the bookmark easily, but unlike Chrome Firefox has no way of showing which folder the bookmark is present in. So I created a PowerShell script to do just that. Mainly because I wanted some excuse to code in PowerShell and also because it felt like an interesting problem.

PowerShell can’t directly control Firefox as it doesn’t have a COM interface (unlike IE). So you’ll have to manually export the bookmarks. Good for us the export is into a JSON file, and PowerShell can read JSON files natively (since version 3.0 I think). The ConvertFrom-JSON cmdlet is your friend here. So export bookmarks and read them into a variable:

This gives me a tree structure of bookmarks.

Notice the children property. It is an array of further objects – links to the first-level folders, basically. Each of these in turn have links to the second-level folders and so on.

The type property is a good way of identifying if a node is a folder or a bookmark. If it’s text/x-moz-place-container then it’s a folder. If it’s text/x-moz-place then it’s a bookmark. (Alternatively one could also test whether the children property is $null).

So how do we go through this tree and search each node? Initially I was going to iteratively do it by going to each node. Then I remembered recursion (see! no exercise like this goes wasted! I had forgotten about recursion). So that’s easy then.

  • Make a function. Pass it the bookmarks object.
  • Said function looks at the object passed to it.
    • If it’s a bookmark it searches the title and lets us know if it’s a match.
    • If it’s a folder, the function calls itself with the next level folder as input.

Here’s the function:

I decided to search folder names too. And just to distinguish between folder names and bookmark names, I use different colors.

Call the function thus (after exporting & reading the bookmarks into a variable):

Here’s a screenshot of the output:

search-fxbookmarks

A brief intro to XML & PowerShell

I am dealing with some XML and PowerShell for this thing I am working on. Thought it would be worth giving a brief intro to XML so the concepts are clear to myself and anyone else.

From this site, a simple XML based food menu (which I’ve slightly modified):

It’s obvious what the food menu is about. It’s a breakfast menu. It consists of food entries. Each food entry consists of the name of the food, its price, a description, and calories. One of these food items is today’s special, and is marked accordingly. Straightforward.

Items such as <name> and </name> are called tags. You have an opening tag <name> and a closing tag </name>. Between these tags you have an some content (e.g. “French Toast”). Tags can have attributes (e.g. offer = “Today’s Special!”). The entirety of an opening and ending tag, their attributes, and the content enclosed by these tags is called an element

In the example above, the element breakfast-menu is the the root element. If you visualize the listing above as a tree, you can see it all starts from breakfast-menu. This root element has 5 children elements, each of which is a food element. These children elements are also sibling elements to each other. Each food element in turn has 4 different children elements (name, price, etc), who are themselves sibling elements to each other.  

This site has a really good intro to XML. And this site is is a good reference on the various types such as elements, attributes, CDATA, etc.

XML Notepad is a good way to view and edit/ create XML documents. It gives a hierarchical structure too that’s easy to understand. Here’s the above XML viewed through XML Notepad. 

xml-notepad

Notice how XML Notepad puts some of the elements as folders. To create a new sibling element to the food element you would right click on the parent element breakfast-menu and create a new child element. 

xml-notepad-newchild

This will create an element that does not look like a folder. But if you right click this element and create a new child, then XML Notepad changes the icon to look like a folder. 

xml-notepad-newchild2

Just thought I’d point this out so it’s clear. An element containing another element has nothing special to it. In XML Notepad or when viewing the XML through a browser such as Internet Explorer, Firefox, etc they might be formatted differently, but there’s nothing special about them. Everyone’s an element just that some have children and so appear different. 

In PowerShell you can read an XML file by casting it into an [xml] accelerator thus:

Using the above XML, for instance, I can then do things like this:

Here’s a list of methods available to this object:

The methods vary if you are looking at a specific element:

Say I want to add a new food element to the breakfast-menu element. The AppendChild() method looks interesting. 

You can’t simply add a child by giving a name because it expects as input an object of type Xml.XmlNode

So you have to first create the element separately and then pass that to the AppendChild() method.  

Only the XML root object has methods to create new elements none of the elements below it have (notice the $temp output above). So I start from there:

Just for kicks here’s a snippet of the last two entries from the XML file itself:

Yay! That’s a crazy amount of work though just to get a new element added! 

Before I forget, while writing this post I came across the following links. Good stuff: 

  • A Stack Overflow post on pretty much what I described above (but in a more concise form, so easier to read)
  • Posts 1, 2, and 3 on XML and PowerShell from the The Scripting Guys
  • A post by Jeffrey Snover on generating XML documents from PowerShell 
  • Yet another Stack Overflow post with an answer that’s good to keep in mind

Removing an element seems to be easier. Each element has a RemoveAll() method that removes itself. So I get the element I want and invoke the method on itself:

Or since the result of the $temp.'breakfast-menu.food' element is an array of child elements, I can directly reference the one I want and do RemoveAll()

Or I can assign a variable to the child I want to remove and then use the RemoveChild() method. 

That’s all for now!

Using PowerShell to insert a space between characters (alt method using regular expressions and -replace)

A reader (thanks Jeff!) of my previous post wrote to mention that there’s an even easier way to insert a space between characters. Use the -replace operator thus:

So simple! 

The -replace help page doesn’t give much details on using regular expressions. Jeff pointed to the Regex.Replace() method help page, which is where he got the idea from. I tried to search for more info on this and came across this post by Don Jones and this Wiki page on TechNet. 

I had wanted to use the -replace operator initially but was stumped at how to get automatic variables like $1, $2, $3, … for each of the (bracketed) matches it finds. Turns out there’s no need to do that! Each match is a $1.

ps. From Jeff’s code I also realized I was over-matching in my regular expression. The thumbprints are hex characters so I only need to match [0-9A-F] rather than [0-9A-Z]. For reference here’s the final code to get certificate thumbprints and display with a space:

Using PowerShell to insert a space between characters (or: Using PowerShell to show certificate fingerprints in a friendly format)

I should be doing something else, but I got looking at the installed certificates in my system. That’s partly prompted by a desire to make a list of certificates installed on my Windows 8.1 machines, and read up on how the various  browsers use these certificates (my understanding is that Firefox and Chrome have their own stores in addition (or in exclusion?) to the default Windows certificate store). 

Anyways, I did the following to get a list of all the trusted CA in my certificate store:

I quickly got side tracked from that when I noticed the thumbprint and wondered what I could do to space it out. What I meant is: if you go to your browser and check the thumbprint/ fingerprint, it is usually a bunch of 40 characters but with spaces between every two characters. Like this: D5 65 8E .... In contrast the PowerShell output gave everything together. The two are same, but I needed and excuse to try something, so wondered how I could present it differently. 

Initially I thought of using the -replace operator but then I thought it might be better to -split and -join them. Both will make use of regular expressions I think, and that’s my ultimate goal here – to think a bit on what regular expressions I can use and remind myself on the caveats of these operators. 

The -split operator can take a regular expression as the delimiter. Whenever the expression matches, the matched characters are considered to identify the end of the sub-string, and so the part before it is returned. In my case I want to split along every two characters, so I could do something like this:

This, however, will return no output because every block of two characters is considered as the delimiter and split off, but there then remains nothing else to output. So the result is a bunch of empty lines. 

To make the delimiter show in the output I can enclose it within brackets:

Now the output will be an empty line followed a block of two characters (the delimiter), followed by an empty line, and so on …

I can’t -join these together with a delimiter because then the empty lines too get pulled in. Here’s an example -join using the + character as delimiter so you can see what happens:

What’s happening is that the empty objects too get sandwiched between the output we want.

Now, if only there was a way to cull out the empty objects. Why of course, that’s what the Where-Object cmdlet can do! 

Like this perhaps (I only let through non-empty objects):

Or perhaps (I only let through objects with non-zero length):

Or perhaps (I only let through non-empty objects; the \S matches anything that’s not whitespace):

Using any one of these I can now properly -join

And finally what I set out to get in the first place:

Update: While writing this post I discovered one more method. Only let through objects that exist (so obvious, why didn’t I think of that!):

Also check out this wiki entry for the Split() method to the String object. Doesn’t work with regular expressions, but is otherwise useful. Especially since it can remove empty entries by default. 

Update2: See this follow-up post for a typo in my regexp above as well as an alternate (simpler!) way of doing the above.

Updating PowerShell help on an air-gapped machine

My virtual lab is disconnected from the real Internet so there’s no way to run Update-Help and get the latest help files. Thankfully there’s Save-Help which can be used to download the help files on another machine and then transfer them over.

By default Save-Help only downloads help files for modules installed on the machine it’s run on. That doesn’t cut it for me because my host machine (where I run Save-Help) doesn’t have as many modules as my guest machines. You can specify the names of modules to download help files for, but simply specifying the names does not work.

That’s because Save-Help looks for the module in files stored under the PSModulePath environment variable (example output from my machine below).

So what one really needs to do is provide the module itself to Save-Help. You have many options here: (1) install the module on the computer (not what you want to do usually!) or (2) connect to a computer which has the module, save that module object in a variable, and pass that on to Save-Help (you can do an Invoke-Command, or a New-PSSession, or a New-CimSession to the remote machine, then issue the Get-Module -ListAvailable -Name ... cmdlet to get the module object and pass back to the computer you are on) (see the first example from the Save-Help help page for more on this).

In my case since the host machine (with Internet) and guest machine (which needs the updated help files) have no network connection between them I’ll have to resort to other means. Enter Export-CliXML and Import-CliXML. When you connect to a remote machine and store the module object in a variable, what’s happening behind-the-scenes is that the object is converted to a text representation in XML. This preserves all the properties of the object but not the methods, and once this XML is passed to the remote computer it is converted back to an object (without the methods of course). If you can remote to a machine all this happens behind the scenes, but you can also do this manually via the Export-CliXML and Import-CliXML cmdlets – convert all the module objects on the target computer to their XML representation, copy these XML files to the computer with Internet access, convert them back to modules and download help files, then copy these help files to the target computer so Update-Help can add.

Thus on the virtual machine I do something like this:

Copy them to the host, change to that directory, and run:

Copy the downloaded files back to the virtual machine and do something like this:

That’s all!

PowerShell scripts to download a file and expand zip file

It all began because I have a folder of Sysinternals tools and I thought now would be a good time to update it with the latest version. 

But downloading a zip file and expanding to the folder is so old-fashioned surely? ;-) Why not use PowerShell to make it a one-click process. 

Thus was born Download-File.ps1 which downloads a given link to a file and optionally passes it through down the pipeline. It’s a simple script, just a wrapper around the Invoke-WebRequest cmdlet. Then was born Expand-Zip.ps1 which takes a zip file – either as a file, or a stream of bytes down the pipeline (from Download-File.ps1 for instance) –  and expands this into a folder (over-writing the contents by default, but can optionally not over-write). 

Neither of these are a big deal but it’s been so long since I did some PowerShell coding that I felt I must mention them. Maybe it’s of use to someone else too!

Now I can do something like the following (put it in a script of its own of course) and it will download the latest version of Sysinternals and expand to the specified folder. 

 I added some progress bars too to show what’s happening. Both scripts can be found in my GitHub repo: Download-File.ps1 and Expand-Zip.ps1

PowerShell as wget/ curl

I needed to download OneGet for the previous post. I had the URL, but rather than open a browser as I would usually do I used PowerShell to download the file:

Nifty, eh! If you omit the -OutFile you get the headers and such:

Lastly, just for kicks, to get all elements of a certain tag from a website:

Got to love it when you can do such cool things with Windows/ PowerShell so easily! A few years ago I could have barely imagined such a thing would be possible on Windows.

Update: While I am at it, here’s how you can quickly download a bunch of files from a website. In this case I want to download all mp3 files from a music website (for example purposes!). Through trial and error I know the links have the text “download” in them, so I can filter for such links and then download each of these to an appropriate file:

Or a variant:

If you use a different site you’ll have to modify the filters accordingly, but it’s pretty straight-forward …

Quickly rename a bunch of files via PowerShell

Each time I do PowerShell now, it saddens me. I haven’t used it much for the past year I am slowly forgetting even the basic stuff. I really must do some PowerShell coding project soon just to amp up my skills. 

Anyhoo, I needed to rename a bunch of files quickly today. Used the following to rename them:

The files were of the format “The Title (digital) Extra Stuff.cbz“. I wanted to rename it such that the new file name is only the underlined parts. Above code does that to a directory full of such files. 

How to find the version of PowerShell

Two ways:

And if you want to check whether PowerShell is installed or not, check the Registry.