Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Friday, December 17, 2010

Create an event receiver script within your ActiveScriptEventConsumer with PowerEvents

I’ve had the pleasure of meeting Trevor Sullivan when I convinced him he should learn all about SQL Server.  Not really, but we did chat it up on Twitter and decided to both go to Cleveland for an intro on SQL Server 2008 R2.  Little did I know what he was working on.  Quite simply one of the coolest projects I’ve used from Codeplex.  Trevor has created PowerEvents!  I’ll admit, some of it is way over my head at the moment.  It’s directly related to how much I really know about WMI, but I feel that’s about to change drastically.

I posted a tweet earlier about what I’ve created with PowerEvents.  Actually, I feel as if it would be a best practice for the ActiveScriptEventConsumer.  You can be the judge of that Winking smile.  Since it’s almost impossible to see what you’ve created as an Event Consumer, I’ve simply created only one: ActiveScriptEventConsumer.  That way I don’t have to worry about what has been added under the hood to WMI.  All I have to do is tweak the script that is fired when the event occurs.  So, I’ve built a basic script that looks for the arguments you have passed to it.  Based on these arguments, you can dynamically call different scripts or functions.  Pretty slick, eh?  Here’s a basic script that will email two different people based on what the WMI query results are.

Option Explicit
Const strFrom = "example@example.com"
Const strMailserver = "smtp.example.com"
Const strSchema = "http://schemas.microsoft.com/cdo/configuration/"
Dim objArgs, objEmail
Dim strProcessName, strSubject, strBody, strTo
'Get arguments from command line
set objArgs = WScript.Arguments
strProcessName = WScript.Arguments(0)
strSubject = WScript.Arguments(1)
strBody = Wscript.Arguments(2)
'Dynamically change the email recipient
'Or even change the function to be called
'Or call a completely different script: .bat, .vbs, .ps1
'Endless possibilities
If strProcessName = "NotePad.exe" Then
	strTo = "myboss@example.com"
ElseIf strProcessName = "Outlook.exe" Then
	strTo = "me@example.com"
End If
'Call to send email, but many different functions could be within this script and
'dynamically called based on arguments
Call SendEmail(strSubject, strBody)
'Function(s)
Sub SendEmail(Subject, Body)
	Set objEmail = CreateObject("CDO.Message")
	objEmail.From = strFrom
	objEmail.To = strTo
	objEmail.Subject = Subject
	objEmail.Textbody = Body
	objEmail.Configuration.Fields.Item _
	    (strSchema & "sendusing") = 2
	objEmail.Configuration.Fields.Item _
	    (strSchema & "smtpserver") = strMailserver
	objEmail.Configuration.Fields.Item _
	    (strSchema & "smtpserverport") = 25
	objEmail.Configuration.Fields.Update
	objEmail.Send
End Sub
'Clean up vars
set strProcessName = nothing
set strSubject = nothing
set strBody = nothing


 



I hope you find this useful.  I’m brand new to creating PowerEvents, but I do feel this is the best way to handle scripting based on events.  Feel free to post a comment if I’m an idiot Rolling on the floor laughingand there is a much easier way…

Wednesday, October 6, 2010

PowerShell: Backup Script

I hooked up a quick script to backup important items from a PC.  It’s is a quick and dirty solution that I may revisit sometime in the future with enhancements. 

  1: # http://geekswithblogs.net/Lance/archive/2009/12/29/program-files-environment-variable-in-powershell.aspx
  2: # http://itknowledgeexchange.techtarget.com/powershell/deleting-files-older-than-a-certain-date/
  3: 
  4: $Today = (Get-Date -format "yyyy-MM-dd")
  5: $targetFolder = "\\BackupServer\Share"
  6: $backupDir = "$targetFolder\$env:username\$Today"
  7: 
  8: function Remove-Items
  9: { 
 10:     $testFolderPath = $targetFolder
 11: 
 12:     if (Test-Path -Path $testFolderPath)
 13:     { 
 14:         $fiveDaysAgo = (Get-Date).AddDays(-5)        
 15:         Get-ChildItem -Path $testFolderPath -Recurse | Where-Object { $_.CreationTime -lt $fiveDaysAgo } | Remove-Item -recurse -force
 16:     }
 17:     else 
 18:     {
 19:         Write-Host "$testFolderPath does not exist."
 20:         #Kill Script
 21:         Exit
 22:     }
 23: }
 24: 
 25: function is64bit()
 26: {
 27:   return ([IntPtr]::Size -eq 8)
 28: }
 29: 
 30: function Get-ProgramFilesDir()
 31: {
 32:   if (is64bit -eq $true) {
 33:     (Get-Item "Env:ProgramFiles(x86)").Value
 34:   }
 35:   else {
 36:     (Get-Item "Env:ProgramFiles").Value
 37:   }
 38: }
 39: 
 40: function Create-Folders 
 41: { 
 42:     if (Test-Path -Path $backupDir) 
 43:     { 
 44:         #do nothing. Folders have been setup already
 45:     }
 46:     else 
 47:     {
 48:         md "$backupDir" -force
 49:     }
 50: }
 51: 
 52: # Remove Folders older than $fivedaysago
 53: Remove-Items
 54: 
 55: # Kills Outlook in preparation for backup
 56: if((get-process "OUTLOOK" -ea SilentlyContinue) -eq $Null){ }else{ Stop-Process -processname Outlook }
 57: 
 58: # Start backup operation
 59: Create-Folders
 60: 
 61: #Robocopy /MIR /Z /COPYALL /MT:20 /R:5 /W:2 /NP "$env:appdata\Microsoft\Outlook" "$backupDir\OutlookAppdata" /LOG+:"$backupDir\backup.log"
 62: #Robocopy /MIR /Z /COPYALL /MT:20 /R:5 /W:2 /NP "$env:userprofile\AppData\Local\Microsoft\Outlook" "$backupDir\Outlook" /LOG+:"$backupDir\backup.log"
 63: #Robocopy /MIR /Z /COPYALL /MT:20 /R:5 /W:2 /NP "$env:userprofile\Documents" "$backupDir\Docs" /LOG+:"$backupDir\backup.log"
 64: #Robocopy /MIR /Z /COPYALL /MT:20 /R:5 /W:2 /NP "$env:userprofile\Favorites" "$backupDir\Favorites" /LOG+:"$backupDir\backup.log"
 65: #Robocopy /MIR /Z /COPYALL /MT:20 /R:5 /W:2 /NP "$env:userprofile\Desktop" "$backupDir\Desktop" /LOG+:"$backupDir\backup.log"
 66: 
 67: #Start Outlook
 68: $programfilespath = Get-ProgramFilesDir
 69: 
 70: if (Test-Path -Path "$programfilespath\Microsoft Office\Office12\Outlook.exe") 
 71: {
 72:     Start-Process "$programfilespath\Microsoft Office\Office12\Outlook.exe"
 73: }
 74: else
 75: {
 76:     Start-Process "$programfilespath\Microsoft Office\Office11\Outlook.exe"
 77: }





Please note: This script is designed for Vista and above.  It uses Robocopy to backup.  You can get Robocopy on XP by installing the Resource Kit Tools.  I’ve only tested this on Vista and above though.  I’m also using version 2 of PowerShell.

Tuesday, September 7, 2010

Remove-Item –recurse will actually make you curse

Walking in today, I found myself with a challenge.  Definitely not a unique one, but a challenge.  I have to delete an .xls template from a file server within many different project folders.  Our setup looks like this: \\server\Projects\{JobNumber}\*.  Within each job number are many different folders and sub-folders.  I’ve been tasked to remove the old excel template that we were using and replace it with the new one.

Sounds like a job for PowerShell eh?  I’ve done some recursion in the past using VBScript and I’d rather not revisit that…  It was a bit of torture to get the logic sorted out using that language.  With PowerShell, you just slap a –recurse to what you are doing and you *should* be good to go. Or so you thought…  A quick ping to Bing showed me the Remove-Item cmdlet usage doc on TechNet.  Reading over this, it seems very easy to setup recursion and manipulate files, until you do something like this:

   1:  $path = "c:\test\*"


   2:   


   3:  Remove-Item $path -recurse -include .xls






These simple lines of code simply fail without any notification or errors.  I’ve sent a tweet out to the Scripting Guys to get a reason why.  I haven’t heard back from them so far, but all is not lost!  You simply have to think outside the box.  To get this to work you have to use these lines of code instead:




   1:  $path = "c:\test\*"


   2:   


   3:  Get-ChildItem $path -recurse -include *.xls | Remove-Item






This works consistently and will give you the results you’d expect.  I’ll update this article if I hear back from the Scripting Guys ;-).



2010-09-07 11:10 a.m. Update:  As always the Scripting Guys are awesome and answer my question.  Take a look at their response.

Tuesday, July 20, 2010

Convert XML to a CAML Query with Powershell

You might ask yourself, “Why would I want to do that?”  Well, as you probably could tell, I use SharePoint A LOT!  I’ve recently started deep diving into DVWP’s (Data View Web Parts), thanks to the USPJA and Marc Anderson’s excellent DVWP course.  CAML piqued my interest a whole lot and because of that I found easy ways to construct my CAML queries.  These free tools are absolutely excellent: U2U CAML Query Builder and Stramit SharePoint CAML Viewer.  These tools are simply the best when it comes to ease of use and quality of results.  However, with a DVWP, I cannot simply copy and paste the query from these tools into it.  I must escape all of the characters CAML chokes on.  For that I’ve built a simple tool in Powershell that will ask you which file you’d like to convert and then it’ll even trim the white space in the file.  Literally all you have to do is copy the query from one of these tools to notepad and save it.  Run my XML2CAML script and your CAML Query is ready to be dropped into your DVWP.  I know there are other tools out there that are similar, but are they free?  Also do they trim the whitespace for you? 

I hope you find this as useful as I do…

Monday, June 21, 2010

Integrating PowerShell and Sharepoint pt. 1

If you follow me on Twitter (@iOnline247), then you have probably noticed me tweeting  a lot about POSH (PowerShell) lately.  When I was first introduced to this language, it was about 4-5 years ago.  At that point, I was knee deep in VB code and building some cool HTA’s.  I figured I should backburner POSH and learn it later.  Fortunately, that time has come.  Unfortunately, it should’ve came sooner…  As I take you through what I’m currently working on, you’ll see why ;-).

I’ll give you an aerial view of my current project.  The setup I’m working with is MSSX, single server deployment; farm, server… Whatever you want to call a single server hosting SharePoint.  A PMA (Project Management Application) was recently rolled out and as I integrate more forms from excel and word, the lists related to the initial project will become bigger and bigger.  I’m expecting about 8 at the end of it all that will support the project’s main information.  With all of these different lists, there will have to be an easy way to purge or archive the information once the project data is stale. 

So what does that mean?  I need to come up with a way that will handle recursive deletes in SharePoint across multiple lists.  It was only natural to turn to POSH to handle a job like this.  The decision makers also want to be able to do this from the browser.  “Wha?”, I replied…  After trolling the net for a day or so, I’m close to setting it all up.

List of tools I’ll be using:

  1. PowerShell v2
  2. iLoveSharepoint PowerActivities v1.2
  3. Idera PowerShell Plus v3.1

I do not accept any compensation from any one of those sources.  As a matter of fact, I owe @cglessner a beer for his help!  He built PowerActivities and was gracious enough to share.  Without him building this, I wouldn’t be able to build my solution whatsoever.  Cheers to Christian!

Friday, March 26, 2010

My first go around with PowerShell

Figured I’d start with math since I was good at it in school…

Well, school was a long time ago!  And I’ve come to find out DateTime math via computers, really isn’t my forte.  What I’m trying to do is setup a simple stop-watch like function.  When I start any of my scripts, I always love to have time involved~~~ somehow, someway…  This particular script (when completed) will give me the ability to set the start time of a script and the end time.  With those variables set, I’ll then be able to do a time difference to determine how long the script ran.  Here’s my first go around:

Function StartTimeD {

    [int] $day = (Get-Date).Day
    Return $day
}

Function StartTimeH {

    [int] $hour = (Get-Date).Hour
    Return $hour
}

Function StartTimeM {

    [int] $minute = (Get-Date).Minute
    Return $minute
}

Function StartTimeS {

    [int] $second = (Get-Date).Second
    Return $second
}

Function EndTimeD {

    [int] $endday = (Get-Date).Day
    Return $endday
}

Function EndTimeH {

    [int] $endhour = (Get-Date).Hour
    Return $endhour
}

Function EndTimeM {

    [int] $endminute = (Get-Date).Minute
    Return $endminute
}

Function EndTimeS {

    [int] $endsecond = (Get-Date).Second
    Return $endsecond
}

 

Function HelloWorld {

    $startday = StartTimeD
    $starthour = StartTimeH
    $startminute = StartTimeM
    $startsecond = StartTimeS
}

Function EndOfTime {

    $endday = EndTimeD
    $endhour = EndTimeH
    $endminute = EndTimeM
    $endsecond = EndTimeS

}

HelloWorld
Start-Sleep 5
EndOfTime

Write-Output $startday $starthour $startminute $startsecond EndTimes are $endday $endhour $endminute $endsecond

New-TimeSpan $(Get-Date -day $startday -hour $starthour -minute $startminute -second $startsecond) $(Get-Date -day $endday -hour $endhour -minute $endminute -second $endsecond)

 
 

Unfortunately for me, it’s not working properly.  The Write-Output spits out the same numbers for both StartTime and EndTime functions.  There’s gotta be a much simpler way…  Maybe there’s something already under the hood for what I’m trying to do.  So far, I haven’t found it, but I am working on it! ^_^