Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts
Tuesday, August 14, 2012
Windows PowerShell for Developers by Douglas Finke; O’Reilly Media
It is not often that a technical book makes you rethink how you think. Doug Finke (a Microsoft Most Valuable Professional) has achieved just that with this concise PowerShell reference.
He starts out our journey describing PowerShell as a glue language that is as programmable as Perl, Python and Ruby and takes its cues from Unix Shells. The next few steps describe getting started, and include a brief tour. He then shifts into high gear as we learn about template engines, adding PowerShell to our GUI apps and creating graphical applications within PowerShell.
The chapter on “Writing Little Languages in PowerShell” was a welcome paradigm shift for me. Having virtually no experience with Domain Specific Languages (DSL), it was a fun ride as Doug demonstrated how to create a better XML and a creating a DSL using Graphviz. The lessons in this chapter alone were worth the price of the book.
He completes our tour with coverage of integration with COM (Component Object Model – specifically Microsoft Excel) and some of highlights of PowerShell V3 (Workflows, JSON).
This was an enjoyable invigorating read; in fact, I went through it multiple times. I appreciate the developer-centric perspective that Doug displayed throughout the text. Whether you are a seasoned developer or a weekend hacker, if you have any interest in PowerShell, I encourage you to pick up “Windows PowerShell for Developers”.
Tuesday, August 7, 2012
PowerShell, Diskpart and Exchange (Oh my!)
Was given the opportunity to work a bit on an Exchange 2007 - 2010 migration. I was asked if supplied a csv that contained Server and folders could the following be scripted:
It took me a few tries to get the hang of the necessary DiskPart commands to string together to pipe, my experience with disks has primarily been with the GUI, so I able to add a bit more to my command line toolbelt.
So once the DiskPart commands were figured out, all that needed to be done is run these on the (new)Exchange servers. Enter Invoke-Command - you should be hearing cheering, whistling and much applause as this is darn near the most useful cmdlet in PowerShell V2.
Following is a script that could be used to create 100s of volumes.
- Step 1 - Create a mount point to hold the drives (M:)
- Step 2 - Create a series of folders on the above drive
- Step 3 - Create a series of volumes to be used to hold the database and log files
It took me a few tries to get the hang of the necessary DiskPart commands to string together to pipe, my experience with disks has primarily been with the GUI, so I able to add a bit more to my command line toolbelt.
So once the DiskPart commands were figured out, all that needed to be done is run these on the (new)Exchange servers. Enter Invoke-Command - you should be hearing cheering, whistling and much applause as this is darn near the most useful cmdlet in PowerShell V2.
Following is a script that could be used to create 100s of volumes.
############## Step 1 ############## # Create the mount point for the drives # We create a script block consisting of the commands we need to pipe to Diskpart $cmds = "`"Select Disk 2`"", "`"create partition primary`"", "`"assign letter=m`"", "`"format fs = ntfs unit=64k quick label='Databases'`"" $string = [string]::Join(",",$cmds) $sb = $ExecutionContext.InvokeCommand.NewScriptBlock("$string | DiskPart") # Iterate over the 6 Exchange Servers using Invoke-Command to run or # script block on each server 1..6 | foreach { Invoke-Command -ComputerName "ex10mbox-vp0$_" -ScriptBlock $sb } ############## Step 2 ############## # Using a supplied CSV file, create our directories $folders = Import-Csv -Path C:\temp\BrentFolders.csv $folders | foreach { $path = "\\$($_.server)\M$\$($_.folder)" if(-not(Test-Path -Path $path)) { New-Item -Path $path -ItemType Directory } } ############## Step 3 ############## # Create the 10 volumes that will be used to hold the individual database and log files. $disk = 3 foreach ($folder in $folders) { if($i -eq 13){$i=3} $cmds = "`"select disk $disk`"", "`"online disk`"", "`"attributes disk clear readonly`"", "`"convert mbr`"", "`"create partition primary`"", "`"assign mount=M:\$($folder.Folder)`"", "`"format fs = ntfs unit=64k quick label=$($Folder.Folder)`"" $disk++ $string = [string]::Join(",",$cmds) $sb = $ExecutionContext.InvokeCommand.NewScriptBlock("$string | DiskPart") Invoke-Command -ComputerName $folder.Server -ScriptBlock $sb }
This could also be utilzed for SQL Server rollouts, etc.
Enjoy!
Monday, April 16, 2012
Speed Reading with PowerShell
Many of you have had to read in large text files for processing in PowerShell. The Get-Content cmdlet is perfect for this. However, it can be very sloooow with large files. There are multiple ways to speed this up. For example, we could dive into .NET using the [System.IO.File]::ReadAllLines() method. For simplicity, let's stick with the Get-Content cmdlet. Following is an example that demonstrates a couple different techniques, the one to focus on is the use of the "-ReadCount" parameter.
# define some random nouns, verbs and adverbs $noun = "Ed","Hal","Jeff","Doug","Don","Kirk","Dmitry" $verb = "ran","walked","drank","ate","threw","scripted","snored" $adverb = "quickly","randomly","erratically","slowly","slovenly","loudly" # create an array with 10,000 random sentences $content = 1..10000 | foreach { "{0} {1} {2}." -f ($noun|Get-Random),($verb|Get-Random),($adverb|Get-Random) } # save our array to a text file $path = "c:\temp\RandomSentences.txt" $content | Out-File -FilePath $path # read in the files and measure the time taken. (measure-command -Expression { Get-Content -Path $path }).TotalMilliseconds
(measure-command { Get-Content $path -ReadCount 10 }).TotalMilliseconds
(measure-command { Get-Content $path -ReadCount 100}).TotalMilliseconds
(measure-command { Get-Content $path -ReadCount 1000}).TotalMilliseconds
The results....
164.6186 24.5987 19.7441 16.2411
Explanation
The Get-Content cmdlet does more behind the scenes then just present the data. There are a properties being populated as it reads in the file. By default, this happens for each line as it it read. For large files, this overhead can be reduced by setting the -ReadCount parameter. With this parameter set, you will only be manipulating the behind the scenes properties in a collection size that is equal to the number you set the -ReadCount attribute to.
Hope this helps!
Friday, March 2, 2012
Limit your use of the pipe
There have been many posts about the proper utilization of the powerful pipe. Filtering left to avoid piping to the Where-Object is always a good idea. Following is another example that demonstrates that judicious use of the pipe is a best practice. On my machine these were the results:
Enjoy!
We are going to define 3 scriptblocks that simply count to 100,000 and measure the time it takes them to run.
$limit = 100000
$test1 = { foreach ($num in 1..$limit ) {$num} }
$test2 = { for($x=1; $x -le $limit; $x++) {$x} }
$test3 = { 1..$limit | foreach{$_} }
"ForEach: {0} seconds" -f (Measure-Command $test1).TotalSeconds
"For: {0} seconds" -f (Measure-Command $test2).TotalSeconds
"Pipe: {0} seconds" -f (Measure-Command $test3).TotalSeconds
ForEach: 0.0348825 seconds
For: 0.2490948 seconds
Pipe: 6.7627934 seconds
Enjoy!
Monday, February 20, 2012
PowerShell and MongoDB
I was exploring MongoDB last weekend and was a bit skeptical at first. The relational model (I used to teach it) is so ingrained into my way of thinking. Like the florescent bulbs in my garage during the Winter, the light slowly started to brighten. I can now see a lot of uses for a schema free database (especially as a tool for prototyping). After playing around with the JavaScript interface, I decided to see what PowerShell could do with it.
Luckily, there is a driver available for download.
This yields:
I will be experimenting more with MongoDB.
Share your insights with me if you decide to explore it as well.
Enjoy!
Luckily, there is a driver available for download.
Assuming you have MongoDB, the C# driver and PowerShell installed, you can play around with the following code:
# Add a reference to our dll
Add-Type -Path 'C:\Program Files (x86)\MongoDB\CSharpDriver 1.3.1\MongoDB.Driver.dll'
# Name our test db (not actually created until we insert)
$db = [MongoDB.Driver.MongoDatabase]::Create('mongodb://localhost/PowerShellMongoTest');
# Name or test collection
$coll = $database["Stuff"]
# Define a couple list
$languages = @("C#","Haskell","PowerShell","Python")
$beers = @("Honkers Ale","Stella","Summer Shandy","Yuengling")
# Define our document
$doc = @{FirstName="Wes"; LastName="Stahler"; Languages=$languages; Beers=$beers}
$collection.Insert($doc)
$info = $collection.FindAll()
$info | Format-Table -AutoSize
#$collection.RemoveAll()
This yields:
Name Value
---- -----
_id 4f42b6798359da1e7ce51bfb
Beers {Honkers Ale, Stella, Summer Shandy, Yuengling}
LastName Stahler
Languages {C#, Haskell, PowerShell, Python}
FirstName Wes
I will be experimenting more with MongoDB.
Share your insights with me if you decide to explore it as well.
Enjoy!
Tuesday, February 7, 2012
Calling vbScript via PowerShell
Following is an example of how to call a vbScript from PowerShell. I recently had to do something similar to this for a Postini SafeSender list conversion to Exchange 2007/AD.
Yields...
First the vbScript:
Saved as CallFromPowerShell.vbs
Option Explicit
Dim strComputer, objWMI, OS
strComputer = WSH.Arguments(0)
On Error Resume Next
Set objWMI=GetObject("winmgmts://" & strComputer).InstancesOf("win32_operatingsystem")
If objWMI is nothing Then
WScript.Echo "Unable to connect to " & strComputer
Else
For Each OS In objWMI
wscript.Echo OS.Caption
Next
end If
To call this from PowerShell:
$computers = 'fatbeard-vp01','fatbeard-vp02','fatbeard-vp03'
$computers |
foreach {"{0,20}`t{1}" -f $_,$(cscript.exe //nologo c:\temp\callfrompowershell.vbs $_) }
Yields...
fatbeard-vp01 Microsoft Windows 7 Enterprise
fatbeard-vp02 Microsoft(R) Windows(R) Server 2003, Enterprise Edition
fatbeard-vp03 Unable to connect to fatbeard-vp03
Monday, January 23, 2012
Creating an LDIF file with PowerShell
Occasionally, I am asked to create a large batch of users for our eDirectory environment. Following is an example on how to create 500 test users (gotta love Here-Strings).
Enjoy!
$path = "c:\temp\LDIF$(get-date -Format yyyyMMdd).txt"
New-Item -Path $path -ItemType File -Force
Add-Content -Value "version: 1" -Path $path
100..600 | Foreach {
$value = @"
dn: cn=PSFTTest$_,ou=users,o=OSUMC
changetype: add
userPassword: P@ssw0rd
uid: PSFTTest$_
givenName: First$_
fullName: First$_ Last$_
sn: Last$_
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: Person
objectClass: Top
cn: PSFTTest$_
"@
Add-Content -Value $value -Path $path
}
Enjoy!
PowerShell - Project Euler Problem 102
I am always pleased when I can use PowerShell to solve a Project Euler problem. This one was straightforward. You are supplied with a text file containing 1000 random triangular coordinates and you need to determine how many of the triangles contain the origin (0,0). There are multiple ways to attack this, I went for he easier approach: if the area of the supplied triangle is equal to the 3 triangles created using the origin, then we know that the triangle contains the origin. I used Heron's Formula to calculate the area.
Enjoy!
Following is the code used to find the answer.
<# Get side lengths
$LengthAB = Length of AB = SquareRoot of (Ax - Bx)^2 + (Ay - By)^2
$LengthAC = Length of AC = SquareRoot of (Ax - Cx)^2 + (Ay - Cy)^2
$LengthBC = Length of BC = SquareRoot of (Bx - Cx)^2 + (By - Cy)^2
$s = .5($LengthAB +$LengthAC +$LengthAC)
$Area = SQRT($s($s-$LengthAB)($s-$LengthAC)($s-$LengthBC) #>
function Get-LengthOfSide {
param([Array]$X,[Array]$Y)
return [Math]::sqrt( [Math]::pow(($X[0]-$Y[0]),2) + [Math]::pow(($X[1]-$Y[1]),2))
}
function Get-AreaOfTriangle {
param([Array]$X,[Array]$Y, [Array]$Z)
$LengthAB = Get-LengthOfSide -X $X -Y $Y
$LengthAC = Get-LengthOfSide -X $X -Y $Z
$LengthBC = Get-LengthOfSide -X $Y -Y $Z
$s = .5*($LengthAB+$LengthAC+$LengthBC)
$Area = [Math]::sqrt( $s*($s-$LengthAB)*($s-$LengthAC)*($s-$LengthBC) )
return $Area
}
$path = 'C:\Users\stah06\Documents\triangles.txt'
$uri = 'http://projecteuler.net/project/triangles.txt'
# Using Invoke-WebRequest (PowerShell V3)
#Invoke-WebRequest -Uri $uri -OutFile $path
# Using System.Net.WebClient (PowerShell V2)
$web = New-Object System.Net.WebClient
$web.DownloadFile($uri, $path)
$match = 0
Get-Content $path |
foreach {
$A = $_.split(",")[0],$_.split(",")[1]
$B = $_.split(",")[2],$_.split(",")[3]
$C = $_.split(",")[4],$_.split(",")[5]
$D = 0,0
$TriangleABC = Get-AreaOfTriangle -X $A -Y $B -Z $C
$TriangleABD = Get-AreaOfTriangle -X $A -Y $B -Z $D
$TriangleACD = Get-AreaOfTriangle -X $A -Y $C -Z $D
$TriangleBCD = Get-AreaOfTriangle -X $B -Y $C -Z $D
$SumofTriangles = $TriangleABD +$TriangleACD + $TriangleBCD
if ( [math]::abs($TriangleABC -$SumofTriangles) -lt .5) {
#"{0} {1}" -f $TriangleABC, $SumofTriangles
$match++
}
}
$match
Enjoy!
Wednesday, January 18, 2012
More Training Questions: Connect to different domain
At a recent internal PowerShell training session, I was asked how to connect to a different domain. Following are a couple ways to accomplish this (using Quest cmdlets or the ActiveDirectory Module):
# Quest cmdlets
Add-PSSnapin Quest.ActiveRoles.ADManagement
$cred = Get-Credential 'ExtDomain.Local\FatBeard'
Connect-QADService -Service ExtDomain.Local -Cred $cred
Get-QADUser
# Active Directory Module
Import-Module ActiveDirectory
New-PSDrive –Name ExtDomain
–PSProvider ActiveDirectory
–Server ExtDomain.Local
–credential (Get-Credential ‘ExtDomain.Local\FatBeard’)
–root ‘//RootDSE/’
Get-ADUser -filter *
Enjoy!
# Quest cmdlets
Add-PSSnapin Quest.ActiveRoles.ADManagement
$cred = Get-Credential 'ExtDomain.Local\FatBeard'
Connect-QADService -Service ExtDomain.Local -Cred $cred
Get-QADUser
# Active Directory Module
Import-Module ActiveDirectory
New-PSDrive –Name ExtDomain
–PSProvider ActiveDirectory
–Server ExtDomain.Local
–credential (Get-Credential ‘ExtDomain.Local\FatBeard’)
–root ‘//RootDSE/’
Get-ADUser -filter *
Enjoy!
Tuesday, September 27, 2011
PowerShell ActiveDirectory Module vs Quest.ActiveRoles.ADManagement Snapin
I have used the Quest.ActiveRoles.ADManagement snapin for a few years and have enjoyed their ease of use. Now that we have migrated our domain controllers to 2008 R2, I often use the ActiveDirectory Module. In fact, I end up using both and see no reason to pick one over the other.
The results (for the most part) are not surprising.
Quest.ActiveRoles.ADManagement with Where-Object took 4.97 seconds.
Quest.ActiveRoles.ADManagement with LDAPFilter took 4.19 seconds.
Active Directory Module with filter took 3.20 seconds.
Active Directory Module with LDAPFilter took 3.21 seconds.
Being of curious nature, I wanted to compare the time it took for a standard query to run using both approaches. Following is a comparison of:
- Quest.ActiveRoles.ADManagement snapin with Where-Object
- Quest.ActiveRoles.ADManagement snapin with LDAP Filter
- ActiveDirectory Module with Filter parameter
- ActiveDirectory Module with LDAP Filter
The query is looking for "stale" servers and runs 10 times for each one and averages the result.
# Add required snapin and module
Add-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue
Import-Module ActiveDirectory -ErrorAction SilentlyContinue
$d = ((Get-Date).AddDays(-90)).ToFileTime()
$LDAP = "(&(OperatingSystem=*Server*)(pwdLastSet<=$d)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
$server = "DC-P01"
# Quest.ActiveRoles.ADManagement with Where-Object
$QAD_Where = (1..10 | foreach {
(Measure-Command -Expression {
Get-QADComputer -Service DC-P01 -OSName '*Server*' -PasswordNotChangedFor 90 `
| Where-Object {-not $_.AccountIsDisabled}}).TotalSeconds
} | Measure-Object -Average
).Average
# Quest.ActiveRoles.ADManagement with LDAP filter
$QAD_LDAP = (1..10 | foreach {
(Measure-Command -Expression {
Get-QADComputer -Service $server -LDAPFilter $LDAP }).TotalSeconds
} | Measure-Object -Average
).Average
# Active Directory Module with Filter parameter
$AD_Filter = (1..10 | foreach {
(Measure-Command -Expression {
Get-ADComputer -Server $server -Filter { (OperatingSystem -like "*Server*") -AND
(PasswordLastSet -le $d) -AND (Enabled -eq $True)}}).TotalSeconds
} | Measure-Object -Average
).Average
# Active Directory Module with LDAP Filter
$AD_LDAP = (1..10 | foreach {
(Measure-Command -Expression {
Get-ADComputer -Server $server -LDAPFilter $LDAP}).TotalSeconds
} | Measure-Object -Average
).Average
"Quest.ActiveRoles.ADManagement with Where-Object took {0:N2} seconds." -f $QAD_Where
"Quest.ActiveRoles.ADManagement with LDAPFilter took {0:N2} seconds." -f $QAD_LDAP
"Active Directory Module with filter took {0:N2} seconds." -f $AD_Filter
"Active Directory Module with LDAPFilter took {0:N2} seconds." -f $AD_LDAPThe results (for the most part) are not surprising.
Quest.ActiveRoles.ADManagement with Where-Object took 4.97 seconds.
Quest.ActiveRoles.ADManagement with LDAPFilter took 4.19 seconds.
Active Directory Module with filter took 3.20 seconds.
Active Directory Module with LDAPFilter took 3.21 seconds.
At some point, I need to run this again with a long running query.
Is this consistent with your results?
Enjoy!
Monday, August 29, 2011
PowerShell and Benford's Law
Was reading through a statistics blog (R) the other day when I read a posting on Benford's law. The definition according to the blog is:
"Benford's law, also called the first-digit law, states that in lists of numbers from many (but not all) real-life sources of data, the leading digit is distributed in a specific, non-uniform way. According to this law, the first digit is 1 about 30% of the time, and larger digits occur as the leading digit with lower and lower frequency, to the point where 9 as a first digit occurs less than 5% of the time."
"Benford's law, also called the first-digit law, states that in lists of numbers from many (but not all) real-life sources of data, the leading digit is distributed in a specific, non-uniform way. According to this law, the first digit is 1 about 30% of the time, and larger digits occur as the leading digit with lower and lower frequency, to the point where 9 as a first digit occurs less than 5% of the time."
The probabilities are distributed as demonstration here.
This seemed counter-intuitive and I wanted to validate it myself. Let's look at the leading digit of all the txt files in one of my directories. Enter PowerShell.....
# Explore Benford's Law
$array=@()
foreach ($item in (Get-ChildItem -Path p:\ -Filter *.txt -Recurse))
{
$array+= $item.length.toString()[0]
}
$array `
| Group-Object -NoElement `
| Sort-Object count -Descending `
| Format-Table @{label=”#”;expression={$_.Name}},
@{label=”Count”;expression={"{0:%##}" -f $($_.Count/$array.Count)}},
@{label=”Histogram”;expression={“▄” * $_.Count}} -autosize
I consider this a validation, but lets try one another example, this time looking at leading digits on the workingset of the processes on my desktop:
$array=@()
foreach($a in (Get-Process))
{
$array+= $a.WorkingSet.toString()[0]
}
$array `
| Group-Object -NoElement `
| Sort-Object count -Descending `
| Format-Table @{label=”#”;expression={$_.Name}},
@{label=”Count”;expression={"{0:%##}" -f $($_.Count/$array.Count)}},
@{label=”Histogram”;expression={“▄” * $_.Count}} -autosize
Again, this seems to hold true. Now that I have examples of Benford's law, I feel compelled to try and understand it. Wish me luck!
Thursday, August 25, 2011
Setting user LogonWorkstations and LogonHours in Active Directory
If you find the need to add restrictions to a user in Active Directory, specifically LogonWorkstations and logonHours then the following script will serve as a template.
A few notes:
- We are using the ActiveDirectory module
- We are using a set list of workstations
- We are using a template approach for the logon hours
Import-Module ActiveDirectory -ErrorAction SilentlyContinueChecking our results shows that the logonHours were set exactly to what our template was.
# Define the list of workstations we want to allow access
$WorkStations = "Workstation1,Workstation2,Workstation3"
$WorkStations+= "Workstation4,Workstation5,Workstation6"
$WorkStations+= "Workstation7,Workstation8,Workstation9"
# Create the logonHours array
[array]$logonHours = (Get-ADUser test010 -Properties logonHours).logonHours
# Iterate over users and assign accordingly
foreach ($user in Get-Content C:\temp\users.txt) {
Get-ADUser -Identity $user | `
Set-ADUser -LogonWorkstations $Workstations -Add @{logonhours=$logonHours}
}
Enjoy!
Thursday, June 23, 2011
Printer exploration with PowerShell
Following are a few printing related PowerShell one-liners that I demonstrated for a few colleagues at work. -Enjoy!
# List all printer drivers on a specific server
Get-WmiObject -Class Win32_PrinterDriver -ComputerName PrintServer `
| Sort-Object Name `
| Select-Object Name, DriverPath
# List all properties of a specifc printer driver on a server
Get-WmiObject Win32_PrinterDriver -ComputerName PrintServer -Filter "Name='Lexmark Universal XL,3,Windows x64'"
# List Printers for a specific server
Get-WmiObject Win32_Printer -ComputerName PrintServer `
| Sort-Object Name `
| Select-Object Name, DriverName, PortName, ShareName
# List a specific printer on a server
Get-WmiObject Win32_Printer -ComputerName PrintServer -Filter "Name='P-UHC6000M-IRC2550'"
# List info on print jobs
Get-WmiObject Win32_PrintJob -ComputerName PrintServer `
| Select-Object Document, Owner,
@{Label="Status";Expression={$_.JobStatus}},
@{Label="PageCount";Expression={$_.TotalPages}},
@{Label="DateSubmitted";Expression={[System.Management.ManagementDateTimeconverter]::ToDateTime($_.TimeSubmitted)}}
# List current number of jobs in each print queue
Get-WmiObject -Class Win32_PerfFormattedData_Spooler_PrintQueue -Computer PrintServer -Filter "Name <> '_Total' and Jobs > 0" `
| Sort Jobs -Descending `
| Select name, jobs `
| Format-Table -AutoSize
Saturday, February 5, 2011
PowerShell doesn't cure insomnia
Had a bit of trouble sleeping last night, when I noticed that there was a perceptible difference in the amount of light the digital clock emanates.


It got me wondering what time displays the most light. Sure I could have manually figured it out, but isn't more exciting to write a script?
Here it is:
<# Define a lookup table for the amount of light "bars" each number displays. #>
$hash = @{"1"=2;"2"=5;"3"=5;"4"=4;Enjoy!
"5"=5;"6"=6;"7"=3;"8"=7;
"9"=5;"0"=6;":"=0}
$max=0
for ($hour = 1; $hour -le 12; $hour++) {
for ($minute = 0;$minute -lt 60; $minute++) {
$time = "{0}:{1:0#}" -f $hour, $minute
$timeArray = $time.ToCharArray()
$sum=0
foreach ($char in $timeArray) {
$sum+= $hash[[string]$char]
}
if ($sum -gt $max) {
$max, $maxTime =$sum, $time
}
}
}
"{0}`t{1}"-f $max, $maxTime
Project Euler 112
A brute force attack on Project Euler #112. I suspect there is a more efficient algorithm for this (not using string conversions), but this works.
function Test-Bouncy {
param([int]$num)
$up=$down=$false
$numArray = $num.ToString().ToCharArray()
$length = $numArray.Length
for($i=1; $i -lt $length; $i++) {
if ($numArray[$i-1] -lt $numArray[$i]) {
$up = $true
}
elseif ($numArray[$i-1] -gt $numArray[$i]) {
$down = $true
}
if ($up -and $down) {
return $true
}
}
return $false
}
$isBouncy = $ratio = 0
$x = 1
while ($ratio -lt .99) {
if(Test-Bouncy $x) {
$isBouncy++
$ratio = $isBouncy/$x
}
$x++
}
"{0}`t{1}" -f ($x-1),$ratio
Enjoy!
Wednesday, October 20, 2010
Getting Database counts per Exchange Server via PowerShell
Was recently asked to generate a report of the total count of items per Exchange database per server. This one-liner (broken up for readability), takes care of it.
Enjoy!
Get-MailboxServer | Get-MailboxStatistics | `This will generate something like the following:
Sort-Object DatabaseName | `
Select DatabaseName, ItemCount | `
Group-Object -Property DatabaseName | `
Foreach {
$items = ($_.Group | Measure-Object -Property ItemCount -sum).Sum
"{0}`t{1:N0}" -f $_.Name,$items
}
| Exchange01-DB01 | 1,372,127 |
| Exchange01-DB02 | 1,522,356 |
| Exchange01-DB03 | 1,406,486 |
| Exchange01-DB04 | 1,345,962 |
| Exchange01-DB05 | 1,330,690 |
| Exchange01-DB06 | 1,392,853 |
| Exchange01-DB07 | 1,318,130 |
| ..... | ..... |
Enjoy!
Thursday, October 7, 2010
Managing Proxy Settings with PowerShell
I find myself changing proxy settings often on my laptop between various environments (Home, Production and Test). Generally this is no big deal. But today, I found myself switching multiple times as I was testing ISA and realized that PowerShell can easily take care of this.
At some point, I will wrap this into a GUI but for now, here is the script.
Note: I am using Jeff Hick's Test-RegistryItem.Enjoy!
function Set-Proxy {Enjoy!
[cmdletbinding()]
Param (
[Parameter(Position=0,Mandatory=$True,
HelpMessage="Enter either `"Home`", `"Production`" or `"Test`".")]
[ValidateNotNullOrEmpty()]
[ValidateSet("Home", "Production", "Test")]
[String]$Location
)
$path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
$url = "http://autoconf.FatBeard.com/proxy.pac"
switch ($location)
{
"Home" {
Set-ItemProperty -Path $path -Name ProxyEnable -Value 0
if (Test-RegistryItem -Path $path -Property ProxyServer) {
Remove-ItemProperty -Path $path -Name ProxyServer
}
if (Test-RegistryItem -Path $path -Property AutoConfigURL) {
Remove-ItemProperty -Path $path -Name AutoConfigURL
}
}
"Production" {
Set-ItemProperty -Path $path -Name ProxyEnable -Value 0
Set-ItemProperty -Path $path -Name AutoConfigURL -Value $url
}
"Test" {
Set-ItemProperty -Path $path -Name ProxyEnable -Value 1
Set-ItemProperty -Path $path -Name ProxyServer -Value "TestProxy-vt01:8080"
if (Test-RegistryItem -Path $path -Property AutoConfigURL) {
Remove-ItemProperty -Path $path -Name AutoConfigURL
}
}
}
}
Subscribe to:
Posts (Atom)
