Thursday, September 26, 2013

Everyday Powershell - Part 1 - Scheduling Scripts

This is the first part in a series about Powershell. You may have heard about how awesome Powershell is but have struggled to find ways to make it useful in your day to day work. That's what this series is going to address. It'll provide scripts and knowledge to address practical everyday problems! 

In order to really see the power of the shell you must experience what it can do for automation. To do that we'll have to setup a windows scheduled task.

First this is to make sure Powershell will run your script (set-executionpolicy remotesigned) this sets your execution policy to allow local scripts to run. But prevents remote scripts.

So to the actual work you need a scheduled task... you know how to do those right? Of course you do! You wouldn't be looking at a scripting blog if you didn't know that. (If you don't know and would like to, add a comment below and we'll make sure to do a post about that.)

On Server 2003 you can hand it one command with the powershell.exe and the script as an argument;
C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe -PSConsoleFile "C:\Program Files\Microsoft\Exchange Server\bin\exshell.psc1" -command "& 'C:\scripts\MAHSCRIPT.ps1'" 

Set start in to;
C:\WINDOWS\system32\windowspowershell\v1.0



On Server 2008 you want to select the Action "start a program"
You'll get a box for the Program/Script;
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Then Add Arguments
-command "& 'C:\scripts\MAHSCRIPT.ps1' " 

Things to watch out for will be the credentials that the script will run as. Make sure it'll have access to whatever it needs. I usually test the script "Run As" the same account I'm planning to use in the scheduled task, just to be sure it won't break.

So the next thing you'll need is some kind of script to run everyday, if you don't have one tune in for the next post and I'll provide you with something awesome to run everyday!

Tuesday, September 24, 2013

Top 5 Powershell performance tips

Five quick tips to improve performance of powershell scripts. Don't take my word for them either, each tip links to an article written by people smarter than I am!

Don't use the += operator!
It's not appending to your array... It makes a copy of the original array adding the new data then deletes the old array. This won't scale well at all. Dave Wyatt has come up with a great solution.
http://powershell.org/wp/2013/09/16/powershell-performance-the-operator-and-when-to-avoid-it/

Foreach-object can be more efficient than Foreach
When you use a foreach the entire collection of objects is loaded into memory first. foreach-object processes them one at a time. There's an interesting explanation here from Ketan Thakkar
http://social.technet.microsoft.com/Forums/en-US/e8da8249-ea91-4772-ae85-582a4b37425b/powershell-foreachobject-vs-foreach

Filter on the "Left Side" of the Pipe
If you are using the pipeline see if you can filter before piping to the where-object commandlet. Most commonly for me in get-wimobject or get-aduser. If you use a -filter well you won't have to bring the entire dataset down to be filtered on your client. Martin Pugh has done some interesting analysis on this kind of thing here
http://thesurlyadmin.com/2012/10/08/powershell-and-string-searches/

Use Multiple Threads where you can
Can the job be run in Multiple threads? If so it'll be worth the effort to get your head around the complexities of Multithreading. Powershell has the concept of jobs. Here's a pretty good example;
http://stackoverflow.com/questions/16360019/how-do-i-add-multi-threading

Measuring performance of your Scripts
So how do we prove these tips will actually improve performance? Well we can use measure-command! It'll time how long it takes for a particular command to execute. So we can use this to benchmark and work on optimizing our scripts performance. Documentation is here;
http://technet.microsoft.com/en-us/library/ee176899.aspx

Tuesday, September 17, 2013

Copy files modified in the last X days with Powershell

A friend asked on the weekend for some powershell that would allow him to copy files modified in the last 7 days to a new machine. It's a great opportunity to showcase the powershell pipeline feature!
get-childitem "c:\Source" | where-object {$_.LastWriteTime -gt (get-date).AddDays(-7)} | Copy-Item -destination "C:\Target"

This one liner will work for files in a folder (it'll get messy if we recurse though, there's a fix for that coming later).

See the pipe command '|' this used to pass the output of one command as input to another command.

  1. So we get-childitem (which is the powershell name for DIR) 
  2. then we pass that to where-object with a bit of code that looks at the creationtime property. the little $_. refers to the "next object in the pipeline" so we can hook into the properties of all the obejcts we found with get-childitem, perform an evaluation on the creation time,
  3. Then the object is passed to copy-item

Now if we want to be able to recursively do this we'll need to be a little more tricksy!

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
$source = "c:\users\benh\documents"
$target = "c:\test"

$files = get-childitem $source -Recurse
foreach ($file in $files)
{
    if ($file.LastWriteTime -ge (get-date).AddDays(-7))
    {
        $targetFile = $target + $file.FullName.SubString($source.Length)
        New-Item -ItemType File -Path $targetFile -Force
        Copy-Item $file.FullName -destination $targetFile
    }
}

This process uses a foreach loop which is similar to the pipeline in that it'll iterate through each item. But it allows us to use a complete script block which gives us a bit more power at the cost of performance. The main difference here is;
  1. We use an IF statement to evaluate how old the file is
  2. We figure out what the target path should be by dropping the $source directory from the files full name
  3. We create a new-item with the path we've established
  4. Then it's just copying the item as normal
Feel free to add and comments or if you've got a more elegant way of solving this problem let us know!





Tuesday, August 13, 2013

Powershell Addin for Visual Studio

If you are like me you'll have just learned enough powershell to help you get the job done... and probalby done most of your script editing in Notepad or the built in powershell ISE. AND if you've got Visual Studio lying around, which I do because the CIO wants all our scripts in source control on the TFS

There's a neat addin you can use to get it to play nice with powershell scripts.

Hit this site (Adam Driscoll is a hero)!
Grab the PowershellTools.VSIX

VSIX is a visual studio extension so to install it right click and “run with”
C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\VSIXInstaller.exe

And hey presto you get all the fancy stuff that visual studio gives you while working on powershell! No more second rate treatment for powershell in Visual Studio!

Monday, July 22, 2013

So this might be why we compile code

So while goofing around and being a bit of a romantic I put Powershell into an infinite loop with a cheesy bit of text.


What was interesting to me (apart from the surprising amount of kudos from the missus) was the CPU load this created. One whole core running at full just to write a string and add 1 to a number.

I guess this is why we compile 'proper' code. Interpreted code is REALLY slow.

Tuesday, July 9, 2013

Deleting emails from Users Mailboxes

We've all had a moment when a white faced user comes up to us and asks THAT question about recalling emails.

"I've just hit send on a super secret document and CC'd the whole organisation..." they stammer "Is there any way to recall it?"

Well if they've sent it out to the world they're gunna have a bad time... If it's just within their orgnaisation their exchange admins can save the day! 3 lines of powershell and it'll be like it never happened.

LINE NUMBER 1
you need full access rights to the recipients mailbox, your exchange administrator can run this command;
Get-ADGroupMember "THEDISTROLISTTHATGOTTHEEMAIL" | Add-MailboxPermission -identity {$_.name} -User YOU -AccessRights FullAccess -InheritanceType All 

LINE NUMBER 2
You need 2 things from the user the subject of their email and the time frame it was sent;
Get-ADGroupMember "THEDISTROLISTTHATGOTTHEEMAIL" | Export-Mailbox -Identity {$_.name} -subject "SUBJECTOFUSERSSHAMEMAIL" –DeleteContent -StartDate "08/07/2013" -EndDate "09/07/2013"


LINE NUMBER 3
Now just cleanup after yourself
Get-ADGroupMember "THEDISTROLISTTHATGOTTHEEMAIL" | Remove-MailboxPermission -Identity {$_.name} -user YOU-AccessRights fullaccess


That's it. Run that and marvel in the power of the shell!

If you've never seen this work before you may be a little trepidatious. So why not try it out on your own mailbox before you pipe a while group through? Just use the includefolders argument and point it at a /test folder;

Export-Mailbox -Identity YOU -includefolders "/TEST" -subject "SUBJECTOFUSERSSHAMEMAIL" –DeleteContent -StartDate "08/07/2013" -EndDate "09/07/2013"

Monday, June 17, 2013

Marvel Heroes One Week In

Ok it's been a week and I'm still playing. There's something that keeps me coming back. Probably because it feels like there is always something new to do. Even though the story is long finished I can still jump on and feel like I'm doing something. They've put some thought into the end game and it goes beyond "play the same story but with harder baddies".

They've got daily quests which don't seem to have any requirements around being done daily, nor do they bear any resemblance to quests. They're essentially a short dungeon with a boss at the end. They are quick fun and good way to grind levels. These dailies are accessed through "terminals" in the main quest hubs. It looks like once you finish the first set in avengers tower you can do them all again in the next hub (Xavier's school) then again at the S.H.I.E.L.D Helicarrier. So there's content to be ground for sure. The difficulty seems to jump pretty quickly as you rank up through these dailies so you may have to level up a bit before you can complete some of them. OR you can group with higher leveled friends, which I cannot recommend enough, because as I've said before this game is at its best when you are in a big group!

So then there are group challenges where you need to meet certain requirements with limited respawns. This was great fun and quite tense. Making death more perilous and introducing a chance of failure bonds the team more and makes you concentrate on the task at hand. The boss at the end of our first run was dead in fifteen seconds though so that was a little anti climatic. Maybe we were just such badasses, or maybe some bosses need some tuning. Anyway it's good see some different thinking in the Action RPG genre in relation to what end game content should look like. If we get more of these group challenges on a steady basis I can see a community growing around them. They could really benefit from some "bragging rights" features around though. Leader boards or Titles or Vanity Items could help drive player interest.

PVP current is Beta, it says so when you enter the PVP zone. It does feel unfinished but is quite good fun. Well it's fun once you get past the level 50 Deadpool camping your teams spawn. Most characters have sufficient mobility to simply disengage from high level opponents and go find someone easier to kill. I enjoyed putting bleeds on my foes and watching their health drop as they tried to flee! That's probably how it should work for Wolverine. The set up has three teams each with a base defended by a giant NPC robot. The territory between bases is crawling with goons who will fire on anyone. It seems like the objective will be get into the bases and kill this Robot. Currently downing the defender robots gives nothing but XP. They have heaps of health but seem to do no damage at the moment. Hence the "unfinished" vibe of the PVP area. But it is fun to spawn into a persistent rolling battle, create a bit of carnage and then zone out again. It feels interesting and reminds me of the Alterac valley battle ground in the old days of world of warcraft.

Deadpool seems pretty OP in this version of the game. It took half a dozen heroes on my team to take down this level 50 Deadpool that was camping our spawn, dressed as a pirate, screaming "I needs me spinach!" So it wasn't an altogether humorless experience. Did make me want to buy Deadpool though.

I'm still leveling up so anything I'm doing feels like its building towards something and is not wasted effort. Guess we'll have to wait and see what happens once all the dailies and group challenges are done. Then see what the view is like from max level. But for now I feel like there's enough to keep my interest for the remaining 29 levels till level cap. That's a good chunk of gameplay I might add, pretty good for a free title (well in my case $20).

If you like your marvel or like your action RPGs I can say with relative confidence that Marvel Heroes would be worth the download.