Category Archives: PowerShell

Know about WinRM (Remote Management) and WinRS (Remote Shell)

 

I just recently migrated my data to another machine (to use as a file server) since it has a Sans Digital NAS attached to it. Normally working with files across the network (I now map a shared drive to the share on the server) is perfectly acceptable – however, there are some operations better left on the remote machine, for instance: extracting or compressing [rar/zip] archives.

Ideally, I’d prefer to have a solution where I can (in this case) right click on an item on my machine and run a command on the remote machine, and with WinRS and some programming I may get it done eventually, but in the meantime as a quick and dirty solution I set up WinRM on both machines and I currently start a command prompt instance using WinRS and I can use the command line rar.exe or 7za.exe for dealing with archives on the remote machine.

TechNet has more information on WinRM and WinRS, for brevity I am just going to outline what I had to do to get my current solution working:

First, from an administrative [read: elevated, if applicable] command prompt execute: winrm quickconfig on both machines, answering each prompt with yes.

If the machines are domain joined then they already trust each other thanks to Kerberos, however if the machines are part of a workgroup you need to tell each machine to trust the other by executing: winrm set winrm/config/client @{TrustedHosts=”%remotecomputername%”}. (Note: replace %remotecomputername% with the hostname of the remote computer.)

Now you should have all that is needed to either remotely manage each machine from the other using winrm (e.g. starting or stopping a service, or querying information using WMI) or run commands on the remote machine using winrs. My particular usage is: winrs –r:%remotecomputername% cmd.exe. This command will start a remote command prompt instance that I can then use to navigate directories on the server and run command line utilities like 7za.exe or netsh, ipconfig, etc.

If you prefer PowerShell, there is one more step that needs to be taken from within an elevated PowerShell command prompt, on the machine that you want to remotely connect to execute: Enable-PSRemoting. This will enable the PowerShell listener and PowerShell should then accept connections from remote PowerShell instances. To connect to the remote PowerShell session execute: Enter-PSSession %remotecomputername%.

Again, I did not go into any detail on this because 1) I am not an authority and I didn’t look further than this, and 2) there is plenty of information on the web and TechNet regarding this topic.

I will probably post an update to this post if/when I ever decide and have enough time to write some code that will allow me to execute canned commands on a remote machine (mainly targeted at extracting archives on the remote machine right now).

Enjoy reading up on WinRM/WinRS.

Work with files using PowerShell

Quick reminder to myself, since this can easily be looked up online, the following code snippets are useful for mass renaming files in a directory, for instance when renaming a series of TV Show episodes into a format that TV Rename can recognize and subsequently rename with correct episode title information for use in XBMC.

By the way, these code snippets were spread out to multiple lines for ease of reading, but PowerShell doesn’t care about them and when I write them into the console myself, they are all in a single line.

   1: $count=1; 

   2: foreach ($f in gci) 

   3: { 

   4:     $s = "S01E{0:0#}" -f $count; 

   5:     $count++; 

   6:     $s2 = "{0}{1}" -f $s, $f.extension; 

   7:     ren $f -newname $s2 

   8: }

While I am pretty sure that the above code can be made much more inline than what I have made it, or more elegant, for a beginner with PowerShell (who still has a book on PowerShell to read) like myself, this is sufficient, again, not sure how efficient it is, but I know it can be made better. What this particular snippet does is, keep a counter, and rename each file it finds with a number that sequentially increments by 1, yielding: S01E01.avi, S01E02.avi, S01E03.avi. You will notice that the file is renamed while retaining the extension of the original file, so if the files are .mpg or .jpg, the extension will not change with the new filename.

 

This next snippet, is useful if you have a few files that you can want to convert to AVI (or any other format that FFmpeg supports converting to) all the files in a directory, this was useful when I had a few WMV files that I needed to convert to AVI so that I could then use HandBrake to convert to MP4s that I could view on my iPhone.

(This snippet requires the .basename property to be registered/added to the FileInfo object: http://blogs.msdn.com/powershell/archive/2006/06/24/645981.aspx has details)

   1: foreach ($f in gci) 

   2: { 

   3:     if ($f.extension -eq ".wmv") 

   4:     {

   5:          .\ffmpeg -i $f.name -b 900 -vcodec libx264 -f avi -threads 6 "$($f.basename).avi" 

   6:     }

   7: }

In essence, this snippet queries all the files in the directory, if their extension is .WMV the files are then passed through an ffmpeg command which will convert the files to an H.264 encoded AVI file, keeping the audio stream the same. It is stuff like this that makes scripting (and PowerShell in particular) so interesting and useful, it saves you the time and repetition of certain tasks and allows you to set them overnight and wake up to them having completed in the morning.

 

This concludes my first post, I will be posting some more in the future, mainly for my own self reference, but I am sure that if I need to remember something, someone else might be interested in these little bits of information that I am storing away, at the very least I know where I am filing them away so that I can get rid of the sticky notes that they occupy on my desktop!