Regex; Getting Dates

August 11th, 2010 by Mr.M | No Comments » Read More

I’m recently reading up on Regular Expression and was having some issue getting the data I need. I have a html text file that has the following as its content:

  1. <tbody>
  2. <tr><td class="n"><a href="../">Parent Directory</a>/</td><td class="m"></td><td class="s">- </td><td class="t">Directory</td></tr>
  3. <tr><td class="n"><a href="20091103/">20091103</a>/</td><td class="m">2009-Dec-29 19:31:07</td><td class="s">- </td><td class="t">Directory</td></tr>
  4. <tr><td class="n"><a href="20100116/">20100116</a>/</td><td class="m">2010-Jan-30 01:54:24</td><td class="s">- </td><td class="t">Directory</td></tr>
  5. <tr><td class="n"><a href="20100130/">20100130</a>/</td><td class="m">2010-Mar-26 05:31:56</td><td class="s">- </td><td class="t">Directory</td></tr>
  6. <tr><td class="n"><a href="20100730/">20100730</a>/</td><td class="m">2010-Aug-08 15:59:47</td><td class="s">- </td><td class="t">Directory</td></tr>
  7. <tr><td class="n"><a href="latest/">latest</a>/</td><td class="m">2010-Aug-05 03:46:25</td><td class="s">- </td><td class="t">Directory</td></tr>
  8. </tbody>

The only part of this html file I need is the YYYYMMDD section between between <a href=”…”></a>. I tried a few ways of stripping out the desire date as using Powershell’s -match but I found that -match has its own shortcoming and was frustrating the hell out of me. I went to a co-worker of mine who excel in regular expression and he threw my regex syntax into Regulator and it would give me the result I want, so I know my criteria is correct but Powershell doesn’t like it or not showing me what I want.

Thus, I ended up using the .Net regex class and was able to get my desire result:

  1. $c = gc ".\Desktop\powershell\local_site.txt"
  2. ([regex]'<a\s+href=\"\d+/?\">(\d+)</a>').matches($c) | foreach {$_.Groups[1].Captures}

Without the foreach loop, you will get a listing that look like this:

  1. Groups : {20091103, 20091103}
  2. Success : True
  3. Captures : {20091103}
  4. Index : 1301
  5. Length : 32
  6. Value : 20091103
  7. ...
  8. ...

Change Windows Service Password

August 10th, 2010 by Mr.M | No Comments » Read More

In my environment, I have over 100+ servers and every so many days, the account that runs SQL services are changed and it is a bitch to change it via point and click on 100+ servers. The script first look at the local machine and return services that has the [log on as] that matches PHX. It will then go into a foreach loop and change the password for only those services. The win32_service wmi has a [-computer] option, in which, you can use to access remote server.

  1. $services = Get-WmiObject win32_service | where {$_.StartName -match '^PHX\\*'}
  2. $pwd = "pwd_here"
  3. if ($matches[0] -ne $null)
  4. {
  5. foreach ($service.Name in $services)
  6. {
  7. write-host $service.Name
  8. $service.Change($null,$null,$null,$null,$null,$null,$null,$pwd,$null,$null,$null)
  9. }
  10. }

if there are no matches, the script will bomb.

PowerGUI Visual Studio Extension

August 7th, 2010 by Mr.M | No Comments » Read More

I found this addin for Visual Studio this evening. Ever since I started to write powershell code, I was wondering when Microsoft was going to incorporate powershell into Visual Studio. The addin can be found here.

Powershell WMI Explorer

August 6th, 2010 by Mr.M | No Comments » Read More

I was looking around to fix some wmiobject errors on one of my windows 2008 r2 and came across this script. It is pretty cool. You can either download it from my site, using the icon below or directly

Download PowerShell WMI Explorer
or
The PowerShell Guy

Syspolicy_purge_history

August 3rd, 2010 by Mr.M | No Comments » Read More

In SQL 2008, there’s a built in SQL job named: Syspolicy_purge_history. This sucker’s job is to purge your job history every day so that it doesn’t pile up on your server. In the past, it would take forever to get the SQL job log because it has to read all those past job run. By default, this job purge your SQL job once a day, sometimes making it rather hard to try to identify how long a job took to complete.

Use the following command to see the duration:

  1. SELECT current_value
  2. FROM msdb.dbo.syspolicy_configuration
  3. WHERE name = N'HistoryRetentionInDays';

Then use the following store proc to change the value:

  1. exec msdb.dbo.sp_syspolicy_set_config_history_retention [ @value = ] value

Downloading Files

July 30th, 2010 by Mr.M | No Comments » Read More

A while back, I was asked to download some files off the Internet whenever there was a change. Never wanting to manually do any work, I wrote up a Powershell function that will download the files for me. Of course, the following is just a small portion of the overall code. I have it wrapped in a foreach loop and it will download as many files and I have in the array.

  1. function download-files($dldFrom = $(throw "source URL is empty"), $dldTo = $(throw "download to where?"))
  2. {
  3. # if your company doesn't need a proxy server, you don't need this part
  4. $proxy = new-object System.Net.WebProxy "your_web_proxy_server:80"
  5. $proxy.UseDefaultCredentials = $true
  6. $webclient = new-object System.Net.WebClient
  7. $webclient.proxy = $proxy
  8. $webclient.DownloadFile($dldFrom, $dldTo)
  9. }

Checking file timestamp

July 23rd, 2010 by Mr.M | No Comments » Read More

A while back, a dev lead came over and asked me if I can write a script to monitor a file. Check to see if the file is older than 30minutes. If it is older than 30 minutes, an email should be to sent to a certain people and distribution list. I came up with the following.

  1. # Get file properties n compare time difference
  2. $hotlist = get-item "\path\to\file\filename.txt"
  3. $now = [datetime]::now
  4. $diff = $now - $hotlist.LastWriteTime
  5. write-output "Time Diff: " $diff.Minutes
  6. if ($diff.Minutes -ge 30)
  7. {
  8. "sending mail"
  9. send-email $emailaddress `
  10. " - filename.txt is older than 30 minutes" `
  11. "Please open a ticket to address/investigate why the txt file is older than 30 minutes. The location of the file is: \path\to\file"
  12. # Keep checking the file until it is -lt 5 minutes
  13. do
  14. {
  15. "checking timestamp"
  16. sleep 60
  17. $hotlist = get-item "\path\to\file\filename.txt"
  18. $now = [datetime]::now
  19. $diff = $now - $hotlist.LastWriteTime
  20. }
  21. until ($diff.Minutes -lt 5)
  22. {
  23. "sending green email"
  24. send-email $emailaddress `
  25. " - filename.txt up-to-date" `
  26. "The txt file has been updated less than 1 minute ago"
  27. }
  28. }

The send-email is a function I wrote which utilize powershell’s Send-MailMessage cmdlet.

Stopping Windows Service

July 22nd, 2010 by Mr.M | No Comments » Read More

After patching Windows servers, I had to check whether or not the firewall service is enabled. If it is, they need to be disable.

  1. $servers = gc "D:\Patch\bin\not_useServers.txt"
  2. $serviceName = "MpsSvc"
  3. foreach($server in $servers)
  4. {
  5. $service = get-service -computername $server -name $serviceName
  6. if($service.Status -eq "Running")
  7. {
  8. write-output "Windows firewall is running on: $($server). Attempting to stop it."
  9. $service | stop-service
  10. }
  11. }

Enjoy.

pinging servers

July 21st, 2010 by Mr.M | No Comments » Read More

On my SQL server, I wrote a stored procedure that ping servers and if the result come back as “request not found” an email will be sent. It is a pretty ugly looking script, use of temp table, memory table, etc, and was slated to run every 45 seconds. Looking at the system recompiled plan, this stored procedure dominated the list. Not that it was doing anything to the server because it was an ops server, meaning it is lightly used. Heck, I hardly log onto that server now a days.

Keen on converting anything I can into powershell, I wrote a little function to ping servers. The following function will take one or more servers. Using a foreach loop to run thru the array, any server w/ statusCode != 0, an email will be sent, using the send-mail function I wrote.

  1. function ping-server([string[]]$servers = $(throw "Nothing to Ping!"), $emailaddress = $(throw "empty email list!"))
  2. {
  3. foreach($server in $servers)
  4. {
  5. $result = get-wmiobject win32_pingStatus -f "address = '$($server)'"
  6. if ($result.StatusCode -ne 0)
  7. {
  8. send-email $emailaddress "$($server) is unavailable " "."
  9. }
  10. }
  11. }

The send-email is a function I put together yesterday. You can find it here at the bottom of the post.

  1. Usage:
  2. #import the function
  3. . .\ping_server.ps1
  4. #declaring variables
  5. $servers = get-content "d:\listOfServers.txt"
  6. $emailaddress = "abc@xyz.com","def@xyz.com"
  7. #making use of the function
  8. ping-server $servers $emailaddress

params and invoke-command

July 20th, 2010 by Mr.M | No Comments » Read More

Yesterday, I was working with invoke-command in powershell. I was basically making a call to a remote server that can send emails. The command look like so:

  1. invoke-command -computername smtp1 {send-mailmessage -from "abc@def.com" `
  2. -to "xyz@gogo123.com" `
  3. -subject "Regarding: http://www.cbtr.net" `
  4. -body "New section has been added: Powershell "`
  5. -smtpserver "some.smtp.server"}

This worked as expected; But I wanted to pass the value of a variable ($url) into the subject line or body of the email:

  1. $url = "http://www.cbtr.net"
  2. invoke-command -computername smtp1 {send-mailmessage -from "abc@def.com" `
  3. -to "xyz@gogo123.com" `
  4. -subject "Regarding: $($url)" `
  5. -body "New section has been added: Powershell "`
  6. -smtpserver "some.smtp.server"}

I got the email for this one as well except that the subject of the email was [Regarding:] and was missing “http://www.cbtr.net.”

I’ve tried to set the $url to be a global variable ($global:url = “http://www.cbtr.net”) and calling it in the scriptblock of the invoke-command but that didn’t work. So much for the global variable idea. I finally caved in and used the param within the script block:

  1. $url = "http://www.cbtr.net"
  2. invoke-command -computername smtp1 {param($url) send-mailmessage -from "abc@def.com" `
  3. -to "xyz@gogo123.com" `
  4. -subject "Regarding: $($url)" `
  5. -body "New section has been added: Powershell "`
  6. -smtpserver "some.smtp.server"} -ArgumentList $url

This worked. It sent me the result I was looking for; but I wanted to try another method.

  1. $url = "http://www.cbtr.net"
  2. $command = "invoke-command -computername smtp1 {write-host `"hello: $($url)`"}"
  3. $command | invoke-expression

This work as well except that I didn’t want to send an email. This last method can get real ugly real fast because you have to make use of the escape char (`).

In fact, I’ve made a function out of it:

  1. function send-email($from, [string[]]$to, $subject = $(throw "subject required"), $body = $(throw "body required"))
  2. {
  3. # eg: $a = "abc@xyz.com","gef@xyz.com"
  4. # eg: send-email "opq@xyz.com" $a "Subject" "Body"
  5. invoke-command -computername servername {param($from, $to, $subject, $body) send-mailmessage -from $from `
  6. -to $to `
  7. -subject $subject `
  8. -body $body `
  9. -smtpserver "some.smtp1.server"} -ArgumentList $from, $to, $subject, $body
  10. }