Contact

Subscribe via Email

Subscribe via RSS/JSON

Categories

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Elsewhere

GUI script to shutdown and restart the computer

For various (silly) reasons our office has a policy disabling the shutdown & restart buttons on our Windows 7 machines. I am a fan of restarting and shutting down the computer, so thought I should make some shortcuts to allow users to do themselves easily.

It’s easy to restart/ shutdown – just use the shutdown command with the /r or /s switches, or use the Restart-Computer or Stop-Computer cmdlets. But I can’t expect users to do that, so a basic GUI is necessary.

Here’s a script I created:

I must mention that I have no clue designing GUIs with PowerShell. The script is mostly a copy-paste of this with some changes by me (like increasing the height of the box, adding three buttons, checking whether any Outlook/ Word processes are running, etc). The code’s pretty intuitive anyways. Here’s a screenshot of what you get:

shutdown-restart

I’d suggest placing the script in a location like c:\windows\system32 and creating a shortcut to it. Here’s the shortcut target I used:

It launches a PowerShell process, passes it the script, doesn’t load the profile (-noprofile), doesn’t show the copyright notice (-nologo), hides the window (-windowstyle hidden), doesn’t show a prompt to the user (-noninteractive), and sets the execution policy for that session to RemoteSigned (needed for the script to be executed).

I would suggest putting the shortcut in c:\ProgramData\Microsoft\Windows\Start Menu\Programs so users can find it/ search for in their Start menu.

Update: If you want the default selected button to be “Cancel” instead of “Shutdown” (as is the case above) move the “Cancel” block above the “Shutdown” block. The order of buttons will still be the same as they are decided by the Location property of each object, but since the “Cancel” block is first that will be selected as the default button.

Use splatting to pass parameters and arguments

A simple but useful trick. Instead of specifying parameters and arguments to a cmdlet on the same line as the cmdlet, you can put these into a hash-table and “splat” the table to the cmdlet. Here’s an example.

Old way:

New way:

Notice you pass the variable $colors with a @ sign instead of the usual $ sign. That’s what splats the variable. The hash-table is broken and the keys treated as parameter names and values treated as arguments.

You can use this trick with any cmdlet.

Find out if a script was dot-sourced or not

All PowerShell scripts have a default variable called $myinvocation.

Here’s the variable for a script I run directly:

And here’s the variable for a script I dot-source:

So if you want to check whether a script was dot-source or not check $myinvocation.InvocationName. If dot-sourced that would be a dot.

PowerShell functions can’t have a parameter called input

This bit me once in the past, and again today. What a waste of time!

PowerShell functions can’t have a parameter called input. No error is thrown when you define the parameter thus, it just doesn’t work that’s all.

What about if I try constraining the parameter type?

Still the same, just that I get a weird error too. Looks like the default parameter input is of type ArrayList.

Update: Later I learnt that all PowerShell functions have a default variable called $input (similar to the default variable $args). When the function accepts input from a pipeline this variable is what holds the input.

Using closure to capture the variable value in a script-block

You can’t use New-Item to create new functions or aliases. It only works for files and directories.

But you can use Set-Item to create new functions and aliases.

How would I go about making a bunch of functions via a loop? The following code creates functions named Hello-<num> which output <num> when run.

Does this work?

And there lies the problem. Instead of each definition containing the number as it’s supposed to be, they all contain the variable $i. And since $i is 10 when the foreach loop terminated, all functions return the number 10.

I can test this by setting $i to a different number:

What I need is for $i in the Set-Item script-block to not be left as a variable, but to be “captured” (for lack of a better word) and set to whatever the value of the variable is at the time the script-block is created.

If you examine the members of a script-block you’ll notice a method called GetNewClosure(). That’s what I need to use here. This method “closes off” (like “closing a deal” or “let’s close somebody”, similar to “capturing somebody”) all variables in the script-block when it’s created.

Good to know!

Closures work with function parameters too. No side-effects as far as I know.

Create and delete remote git branches

Creating and delete local git branches is easy:

Once you have created a local branch, you can push it to the remote. Note: the branch must exist locally.

  • OPTION 1: switch to the branch locally, and then push

  • OPTION 2: stay on the current branch, and when pushing specify the local branch you want to push

    Notice the syntax: you specific the remote repository name origin and then specify the local branch name, colon, the remote branch name. The remote branch can have a different name from the local branch too.

    The proper syntax of the git push command can be seen in option 2; while option 1 is the simplified special case version. The [local branch name]:[remote branch name] part is known as a refspec.

Which brings us to delete remote branches. To delete remote branches, you do the same as above except that you push an empty local branch to the remote branch that you want to delete – effectively nullifying the remote branch! It’s non-intuitive in a way, but I find it very geeky and logical. It’s as though you no longer had a delete command on your file system, and if you wanted to deleted a file you copied /dev/null to it thus deleting it.

Git branch verbose

This is worth remembering:

These switches work with the -a switch too:

Don’t forget: this is cached information.

Git pull default

The same way you can set the default repository and branch to push to, you can set defaults for git pull too.

The master branch has a default set automatically when you clone the repository the first time, but branches don’t have these unless you specify manually. We’ve already seen the command to specify upstream branches manually when pushing. The same command applies here too:

Here testing is the local branch and origin/<branch> is the remote branch. I can skip testing if I am already checked out to that branch locally. And I can skip the = sign between the switch and remote name. Also, -u can be used as a shorter alternative to --set-upstream-to.

Here’s what the command actually does:

What is Reflection?

I knew that PowerShell constructs such [bool] – which defines the boolean data type – were called accelerators, but I never knew why and didn’t bother much as I figured I’d learn more about them soon or later.

But yesterday while reading Bruce Payette’s “Windows PowerShell in Action” that book too mentioned the word accelerator without defining it, and so I started Googling a bit about it. This Googling introduced me to accelerators for WMI – very useful, something I must explore sometime – and that got me curious on how to find all the available accelerators in PowerShell. This in turn bought me to the topic of reflection as that’s what one uses to get a list of accelerators in PowerShell.

So what is reflection? Truth to be told it still does not make much sense to be but what I understand is that reflection is the act (or ability) of an object to look at itself (see it’s “reflection” in the mirror so to say) and learn what it’s capable of – what methods it has, what are it’s properties, and so on. And it is useful because sometimes you may encounter objects that you are getting from elsewhere, and reflection is what you need to learn more about the object.

I guess an example will make it clearer.

Say I define an object called $date as below:

As the creator of this object I know it’s of type [datetime]. And since PowerShell provides a cmdlet Get-Members I know I can use it to examine the methods and properties of this object.

But what if I wasn’t the creator of this object. All I know is that I have a script which will get some object as input and I am supposed to examine it and take further action depending on what sort of an object it is. Further, assume the Get-Member cmdlet isn’t available, or for some reason you can’t use it on the object you are receiving (or maybe Get-Member itself depends on reflection, which we’ll talk about below, so it won’t work unless the concept of reflection is supported by PowerShell). Either ways – you don’t have Get-Member available, period.

In such a situation how would you know what is contained inside the object? That’s where reflection comes into the picture.

Before we go further, it’s worth reading this WikiPedia page on reflection, and this and this StackOverflow post. All these links explain reflection, but the takeaway from the Wikipedia page are the examples it gives of reflection in various languages, and the takeaway from one of the answers in the second StackOverflow post is that all objects in Java have a getClass method which lets one reflectively examine an unknown object.

I created a custom PowerShell object to see if PowerShell objects have a similar method.

Sure enough, GetType() looks like what we are after. (GetHashcode() and ToString return an integer and string respectively (as seen from their definitions) so we can straightaway eliminate them).

Let’s dig deeper:

The GetType() method returns an object of type RuntimeType which contains many methods and properties. The interesting bits for us are GetProperties, GetMethods, and so on. Let’s explore these:

Now let’s try this on our “unknown” $date object:

As you can see, without knowing anything about the object we have managed to identify its type, the methods & properties it contains, and even invoke one of the methods. That’s reflection!

Now I have to figure how to use this info to get a list of accelerators in PowerShell. Which is the topic for another post, of course …