Archive for the ‘PowerShell’ Category


The WordPress.com stats helper monkeys prepared a 2012 annual report for this blog.

Here’s an excerpt:

4,329 films were submitted to the 2012 Cannes Film Festival. This blog had 25,000 views in 2012. If each view were a film, this blog would power 6 Film Festivals

Click here to see the complete report.

Advertisements

Previous Post 1 of 3

Next Post  3 of 3

Part 2 – Configure the Arduino with the RF Transmission Sketch for your Energenie Power Strip

Continuing on from the previous post where we collect all the RF codes for my Energenie Power Strip we will disassemble the receive circuit and build one for RF transmission.

Connect up your circuit like the below diagram

Energenie-fritzingTx

Here is a photo of mine once completed

Energenie-PhotoTx

My sketch below is a modified version of the “Examples > RCSwitch > SendDemo” Sketch included with the library. Basically the Arduino listens on the Serial port for a byte and if one is found it will check for a matching if statement and actions that code block. Each if statement has been configured for one of the ten possible codes captured earlier and also set to send back a confirmation of which code block was ran, the latter is useful for debugging.

Here is my sketch


/*
 Example for different sending methods
 http://code.google.com/p/rc-switch/
 Edit by jfrmilner for Energenie PowerStrip using Serial input
*/

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
byte inByte = 0;
void setup() {

 Serial.begin(9600);

 // Transmitter is connected to Arduino Pin #10
 mySwitch.enableTransmit(10);

// Optional set pulse length.
 // mySwitch.setPulseLength(320);

 // Optional set protocol (default is 1, will work for most outlets)
 // mySwitch.setProtocol(2);

 // Optional set number of transmission repetitions.
 // mySwitch.setRepeatTransmit(15);

 //Serial.println("Ready"); // Ready to receive commands
}

void loop() {
 /* Switch using decimal code */
 if(Serial.available() > 0) { // A byte is ready to receive
 inByte = Serial.read();
 if(inByte == '1') { // byte is '1'
 mySwitch.send(4314015, 24);
 Serial.println("1 ON");
 }
 else if(inByte == '2') { // byte is '2'
 mySwitch.send(4314014, 24);
 Serial.println("1 OFF");
 }
 else if(inByte == '3') { // byte is '3'
 mySwitch.send(4314007, 24);
 Serial.println("2 ON");
 }
 else if(inByte == '4') { // byte is '4'
 mySwitch.send(4314006, 24);
 Serial.println("2 OFF");
 }
 else if(inByte == '5') { // byte is '5'
 mySwitch.send(4314011, 24);
 Serial.println("3 ON");
 }
 else if(inByte == '6') { // byte is '6'
 mySwitch.send(4314010, 24);
 Serial.println("3 OFF");
 }
 else if(inByte == '7') { // byte is '7'
 mySwitch.send(4314003, 24);
 Serial.println("4 ON");
 }
 else if(inByte == '8') { // byte is '8'
 mySwitch.send(4314002, 24);
 Serial.println("4 OFF");
 }
 else if(inByte == '9') { // byte is '9'
 mySwitch.send(4314013, 24);
 Serial.println("ALL ON");
 }
 else if(inByte == '0') { // byte is '0'
 mySwitch.send(4314012, 24);
 Serial.println("ALL OFF");
 }
 else { // byte isn't known
 Serial.println("Unknown");
 }
 }
}

Once the Sketch has been uploaded to your Arduino you could use the Serial Monitor to send one of the numbers or any serial aware software for that matter but if you read on to part 3 I will demonstrate doing this with an advanced PowerShell function.

This concludes part 2, I have included links to the next and previous posts below to ease navigation of this blog series

Previous Post 1 of 3

Next Post  3 of 3

Thanks for reading,

jfrmilner


Next Post (Part 2 of 3)

Final Post (Part 3 of 3)

Intro

In this post I’m going to try something a little different, I’m going to explain the process I used to control a four gang power socket with PowerShell. Now I’m only going to be sending serial commands with PowerShell as the hard work is being done by an Arduino and the “rc-switch” library but still this was a really fun project to do and one I wanted to share!

To start, you’ll need all the following items:

Bill of materials:

# Name Price Shop
1 Arduino Uno £15 Google/eBay
2 433 Mhz Transmitter and Receiver £3 eBay: search for “Arduino 433” or “RF Link kit”
3 Energenie Trailing Gang with Four Radio Controlled Surge Protected Sockets £20 https://energenie4u.co.ukwww.amazon.co.uk
4 Breadboard and a few jumper cables Google/eBay

Part 1 – Capture the RF codes for your Energenie Power Strip

To start you will need to connect up your circuit like the diagram below

Energenie-fritzingRx

This is a photo of how mine looked when completed

Energenie-PhotoRx

Like I mentioned in the intro we will be using the “rc-switch” library which can be downloaded from http://code.google.com/p/rc-switch/. Add this to your \arduino-1.0.1-windows\arduino-1.0.1\libraries\ directory and open the Arduino IDE.

Now open the “ReceiveDemo_Simple” sketch and upload this to your Arduino.

Energenie-LoadReciveSketch

Open the serial monitor, assuming everything is wired up correctly when you press the buttons on your remote the codes will appear as “Received <7Digit>  / 24bit Protocol: 1”, for example:

Energenie-COMResults

Collect each of the buttons 7 digit codes into a table so we can use them in the transmission circuit. I recommend using a table, for example:

Switch ON OFF

1

4314015

4314014

2

4314007

4314006

3

4314011

4314010

4

4314003

4314002

ALL

4314013

4314012

This concludes part 1, I have included links to the next and previous posts below to ease navigation of this blog series

Next Post (Part 2 of 3)

Final Post (Part 3 of 3)

Thanks for reading,

jfrmilner


At work this week I was working with one of our Linux engineers and he used the command “cURL ifconfig.me” which promptly provided him with the external IP of the system. I thought to myself, “I wonder if this is possible from PowerShell” and sure enough it is.

Using the Invoke-WebRequest cmdlet we can send http(s) requests to a web service. Note that this is a PowerShell 3.0 only cmdlet.

Let’s give it a try:

Invoke-WebRequest ifconfig.me

Get-ExternalIP-01

Not quite what we’re looking for. On inspection of the website http://ifconfig.me/ we can see that there are many command line options, lets try just the /IP option

Invoke-WebRequest ifconfig.me/ip

Get-ExternalIP-02

Much better and we can clearly see that the IP address is returned in Content which it fine for a quick check at the command line but not so great if your using it for scripting. To collect just the external IP we could wrap the command in parentheses, for example:

(Invoke-WebRequest ifconfig.me/ip).Content

Nice.

I thought that this would make a handy addition to my PowerShell Profile so I created a quick function


function Get-ExternalIP {
(Invoke-WebRequest ifconfig.me/ip).Content
}

Get-ExternalIP-03

Perfect!

An alternative to ifconfig.me is available at http://www.whatismyip.com/ip-faq/automation-rules/, for example

(Invoke-WebRequest http://automation.whatismyip.com/n09230945.asp).Content

Thanks for reading

Regards,

jfrmilner


The WordPress.com stats helper monkeys prepared a 2011 annual report for this blog.

Here’s an excerpt:

A New York City subway train holds 1,200 people. This blog was viewed about 5,800 times in 2011. If it were a NYC subway train, it would take about 5 trips to carry that many people.

Click here to see the complete report.


This month we have a new Avaya phone system being implemented for one of my customers and one of the prerequisites to get full functionality is to have all telephone numbers in the popular E.164 format. This would be a pretty simple task if the data was in a consistent format but unfortunately this was not the case, let’s take a look at the state of the data*:

*For security reasons I have recreated the data in my test lab with random names, area codes and telephone numbers etc.

First I will store a collection of Users in a variable named $users, throughout this post I will use the Quest AD cmdlets. This is mainly because they are backwards compatible with 2003 based domains but if you are lucky enough to be 2008 you should be able to convert the commands to Microsoft’s AD Module with little effort.

$users = Get-QADUser -Description "E164 Sample Accounts"

And now display just the name and telephoneNumber properties:

$users | Select-Object Name, telephoneNumber | Format-Table -AutoSize
Name              telephoneNumber
----              ---------------
Georgina.Stewart  554861
Georgina.Stewart1 01234 12 34 56 (only call on Tues)
Eden.Morris       01234-55(4487)
Sarah.Patel       559642
Marley.Adams      550998
Mya.Lewis         (01234) 127075
Sophia.Baker      (55)2912
Filip.Rogers      (55)8996
Noah.Mason        (Part Time)-(01234) 897740
Isabel.Webb       (01234) 036428
Steven.Matthews   (01234) 957823
Courtney.Walker   (01234) 679860
Rayyan.Mitchell   07123 530656
Mary.Graham       07123  822057
Maisy.Barnes      07123 364461
Arabella.Thompson +441234844048
Macy.Adams
Grace.Robinson    (01234) 538794
Summer.Stevens    Call me before 11AM 550997
Frederick.Taylor  01234588239

As you can see we have quite a mix bag here. One of the first things to notice is that the telephoneNumber property has not been strictly used for just numbers and as such it is difficult to see any format patterns, let’s strip all non-digit characters away and take another look:

$users | Select-Object Name, @{name="telephoneNumberDigitsOnly";expression={$_.telephoneNumber -replace "\D"}} | Format-Table –AutoSize

The above line uses a replace with a single argument so this is effectively a remove. The replace uses a regular expression of Non-Digit contained within a calculated property.

Name              telephoneNumberDigitsOnly
----              -------------------------
Georgina.Stewart  554861
Georgina.Stewart1 01234123456
Eden.Morris       01234554487
Sarah.Patel       559642
Marley.Adams      550998
Mya.Lewis         01234127075
Sophia.Baker      552912
Filip.Rogers      558996
Noah.Mason        01234897740
Isabel.Webb       01234036428
Steven.Matthews   01234957823
Courtney.Walker   01234679860
Rayyan.Mitchell   07123530656
Mary.Graham       07123822057
Maisy.Barnes      07123364461
Arabella.Thompson 441234844048
Macy.Adams
Grace.Robinson    01234538794
Summer.Stevens    11550997
Frederick.Taylor  01234588239

Now that looks better with the exception of Summer.Stevens, it’s expected that some accounts will need manual effort so I will need to filter for those as well. We can see from the above table that there are two common number formats (1,2), blanks (3), numbers already in E.164 format and finally we’ll need a catch all(5) for everything else:

  1. Starting with “55” followed by four numbers
  2. Starting with “01 or 07” followed by nine numbers
  3. Blank/Null values
  4. E.164 formatted numbers (No change required)
  5. Neither of the above formats, for example Summer.Stevens

The next step is to create regular expressions to match these four values as the fifth will be a catch for non-matched values, like so:

  1. “^(01|07)\d{9}”
  2. “^55\d{4}”
  3. “^$”
  4. “^44\d{10}”

Now let’s put all of this together and get a feel for how things will look:

foreach ($user in $users) {
	switch -regex ($user | % { $user.telephoneNumber -replace "\D" } ) {
	"^(01|07)\d{9}"		{ Add-Member -InputObject $user -Name "E164Number" -MemberType NoteProperty -Value ([regex]::matches(($user.telephoneNumber -replace "\D"),"^(01|07)\d{9}")[0].Value -replace '^0','+44') ; continue }
	"^55\d{4}"			{ Add-Member -InputObject $user -Name "E164Number" -MemberType NoteProperty -Value ([regex]::matches(($user.telephoneNumber -replace "\D"),"^55\d{4}")[0].Value -replace '^55','+44123455') ; continue }
	"^$"				{ Write-Warning "Blank" ; continue } #Empty
	"^44\d{10}"			{ if ($user.telephoneNumber -match "^\+\d{12}") { Write-Warning "E.164: $($user.sAMAccountName), $($user.telephoneNumber)" } else { Write-Warning "No Match: $($user.sAMAccountName), `"$($user.telephoneNumber)`""} ; continue}
	default 			{ Write-Warning "No Match: $($user.sAMAccountName), `"$($user.telephoneNumber)`"" }
	}
}

As you can see from the above script block I have used a foreach loop that then uses a switch statement. The switch then checks to see if it can match one of the regular expressions patterns from the previous step and if successful adds a new note property named “E164Number” else it will display a warning. Let’s give it a try:

WARNING: E.164: Arabella.Thompson, +441234844048
WARNING: Blank
WARNING: No Match: Summer.Stevens, "Call me before 11AM 550997"

As predicted we have a few warnings, now let’s have a look at the projected telephone numbers:

$users | Select-Object Name, telephoneNumber, E164Number | Format-Table -AutoSize
Name              telephoneNumber                     E164Number
----              ---------------                     ----------
Georgina.Stewart  554861                              +441234554861
Georgina.Stewart1 01234 12 34 56 (only call on Tues)  +441234123456
Eden.Morris       01234-55(4487)                      +441234554487
Sarah.Patel       559642                              +441234559642
Marley.Adams      550998                              +441234550998
Mya.Lewis         (01234) 127075                      +441234127075
Sophia.Baker      (55)2912                            +441234552912
Filip.Rogers      (55)8996                            +441234558996
Noah.Mason        (Part Time)-(01234) 897740          +441234897740
Isabel.Webb       (01234) 036428                      +441234036428
Steven.Matthews   (01234) 957823                      +441234957823
Courtney.Walker   (01234) 679860                      +441234679860
Rayyan.Mitchell   07123 530656                        +447123530656
Mary.Graham       07123  822057                       +447123822057
Maisy.Barnes      07123 364461                        +447123364461
Arabella.Thompson +441234844048
Macy.Adams
Grace.Robinson    (01234) 538794                      +441234538794
Summer.Stevens    Call me before 11AM 550997
Frederick.Taylor  01234588239                         +441234588239

Very nice. Now to make this permanent we need to push the E164Number property into the telephoneNumber property on each of these users:

Backup first:

$users | Export-Csv C:\Support\MyBackup.csv -NoTypeInformation

Once the blackup task has been completed we can now go ahead and apply the new number. Notice that I used an if statement to check that there actually is a value in the E164Number property first and if there isn’t then it will skip that user.

 $users | ForEach-Object { if ($_.E164Number) {Set-QADUser -Identity $_ -PhoneNumber $_.E164Number}} 

Now to confirm the results:

$users | Get-QADuser | Select-Object Name, telephoneNumber | Format-Table -AutoSize
Name              telephoneNumber
----              ---------------
Georgina.Stewart  +441234554861
Georgina.Stewart1 +441234123456
Eden.Morris       +441234554487
Sarah.Patel       +441234559642
Marley.Adams      +441234550998
Mya.Lewis         +441234127075
Sophia.Baker      +441234552912
Filip.Rogers      +441234558996
Noah.Mason        +441234897740
Isabel.Webb       +441234036428
Steven.Matthews   +441234957823
Courtney.Walker   +441234679860
Rayyan.Mitchell   +447123530656
Mary.Graham       +447123822057
Maisy.Barnes      +447123364461
Arabella.Thompson +441234844048
Macy.Adams
Grace.Robinson    +441234538794
Summer.Stevens    Call me before 11AM 550997
Frederick.Taylor  +441234588239

Excellent, the majority of users now have an E164 formatted phone number.

All that’s left now is to identify users that still do not conform to this format so that they can be contacted, this can be achieved by using a Where-Object with another regular expression like so:

$users | Get-QADUser | Where-Object { $_.telephoneNumber -notmatch "^\+\d{12}" } | Select-Object name, email
Name           Email
----           -----
Macy.Adams     Macy.Adams@jfrmilner.lab
Summer.Stevens Summer.Stevens@jfrmilner.lab

Well that wraps up this post; I think you’ll agree it’s a nice real world example of using PowerShell with regular expressions to solve formatting issues.

Thanks for reading and until next time.

Regards,

jfrmilner


This week I have been tasked with assisting a storage engineer while he replaces a couple of Fibre Channel switches. My task was simple, check the HBAs for any “Dead” paths (See below screen shot for an example) across all the ESX hosts every hour for a weekend. We have a fair few VMHosts so this gave me the opportunity to use PowerCLI (Think PowerShell with a VMware snapin).

It didn’t take long at all to knock up a little script that can report on path states, this is what I came up with:

$VMHosts = Get-VMHost  | ? { $_.ConnectionState -eq "Connected" } | Sort-Object -Property Name
$results= @()

foreach ($VMHost in $VMHosts) {
Get-VMHostStorage -RescanAllHba -VMHost $VMHost | Out-Null
[ARRAY]$HBAs = $VMHost | Get-VMHostHba -Type "FibreChannel"

	foreach ($HBA in $HBAs) {
    $pathState = $HBA | Get-ScsiLun | Get-ScsiLunPath | Group-Object -Property state
    $pathStateActive = $pathState | ? { $_.Name -eq "Active"}
    $pathStateDead = $pathState | ? { $_.Name -eq "Dead"}
    $pathStateStandby = $pathState | ? { $_.Name -eq "Standby"}
    $results += "{0},{1},{2},{3},{4},{5}" -f $VMHost.Name, $HBA.Device, $VMHost.Parent, [INT]$pathStateActive.Count, [INT]$pathStateDead.Count, [INT]$pathStateStandby.Count
    }

}
ConvertFrom-Csv -Header "VMHost","HBA","Cluster","Active","Dead","Standby" -InputObject $results | Ft -AutoSize

The output is pretty simple but does the job:

VMHost                            HBA    Cluster        Active Dead Standby
------                            ---    -------        ------ ---- -------
d1-vmesx-001.*************.uk    vmhba2 Cluster05      40     0    24
d1-vmesx-001.*************.uk    vmhba3 Cluster05      40     0    24
d2-vmesx-001.****************.uk vmhba2 Cluster02      98     0    80
d2-vmesx-001.****************.uk vmhba3 Cluster02      96     0    80
d2-vmesx-011.****************.uk vmhba2 Cluster03      76     0    88
d2-vmesx-011.****************.uk vmhba3 Cluster03      75     0    85
d2-vmesx-012.****************.uk vmhba2 Cluster03      76     0    88
d2-vmesx-012.****************.uk vmhba3 Cluster03      75     0    85
d2-vmesx-013.****************.uk vmhba1 Cluster03      83     0    85
d2-vmesx-013.****************.uk vmhba2 Cluster03      83     0    85
d2-vmesx-014.****************.uk vmhba1 Cluster03      83     0    85
d2-vmesx-014.****************.uk vmhba2 Cluster03      83     0    85
d2-vmesx-015.****************.uk vmhba1 Cluster03      83     0    85
d2-vmesx-015.****************.uk vmhba2 Cluster03      83     0    85
d2-vmesx-016.****************.uk vmhba1 Cluster03      83     0    85
d2-vmesx-016.****************.uk vmhba2 Cluster03      83     0    85
d2-vmesx-017.****************.uk vmhba1 MSCS Cluster01 44     0    308
d2-vmesx-017.****************.uk vmhba2 MSCS Cluster01 44     0    308
d2-vmesx-018.****************.uk vmhba1 MSCS Cluster01 44     0    308
d2-vmesx-018.****************.uk vmhba2 MSCS Cluster01 44     0    308
d2-vmesx-019.****************.uk vmhba1 Cluster04      68     0    52
d2-vmesx-019.****************.uk vmhba2 Cluster04      68     0    52
d2-vmesx-021.****************.uk vmhba1 Cluster04      68     0    52
d2-vmesx-021.****************.uk vmhba2 Cluster04      68     0    52

If you wanted to work with this information further then I would suggest creating a custom object and populating the properties with Add-Member instead of doing the format string method above, I just did that as it’s quick. Well this is my first PowerCLI script, I hope to share some more.

Bye for now.

jfrmilner


I had a situation where I needed to enable the Virtualisation Technology (VT) across a bunch of Dell servers and then install the Hyper-V role. It turned out to be much simpler than I originally thought thanks in part to PowerShell remoting and Dells omconfig.

Dell give you the option to change BIOS configuration from the command line, for example to enable the CPU VT:


omconfig chassis biossetup attribute=cpuvt setting=enabled

In addition to the above I would also need to install the Hyper-V role:

Import-Module ServerManager ; Add-WindowsFeature Hyper-V

This can be combined into a PowerShell remote command like so ($allServers is an array of all the server host names I want to execute the command against):

icm -ComputerName $allServers -ScriptBlock { omconfig chassis biossetup attribute=cpuvt setting=enabled ; Import-Module ServerManager ; Add-WindowsFeature Hyper-V }

Next I needed to create a software virtual switch, for this I used a script from

http://blogs.technet.com/b/virtualization/archive/2008/05/26/hyper-v-wmi-using-powershell-scripts-part-5.aspx :

$VirtualSwitchService = get-wmiobject -class "Msvm_VirtualSwitchManagementService" -namespace "root\virtualization"
$ReturnObject = $VirtualSwitchService.CreateSwitch([guid]::NewGuid().ToString(), "DELL NETWORK TEAM - Virtual Network", "1024","")

#Create New Virtual Switch
$CreatedSwitch = [WMI]$ReturnObject.CreatedVirtualSwitch

#Create Internal Switch Port
$ReturnObject = $VirtualSwitchService.CreateSwitchPort($CreatedSwitch, [guid]::NewGuid().ToString(), "InternalSwitchPort", "")
$InternalSwitchPort = [WMI]$ReturnObject.CreatedSwitchPort

#Create External Switch Port
$ReturnObject = $VirtualSwitchService.CreateSwitchPort($CreatedSwitch, [guid]::NewGuid().ToString(), "ExternalSwitchPort", "")
$ExternalSwitchPort = [WMI]$ReturnObject.CreatedSwitchPort

$ExternalNic = get-wmiobject -namespace "root\virtualization" -Query "Select * From Msvm_ExternalEthernetPort WHERE IsBound=False" | ? { $_.Name -eq 'BASP Virtual Adapter'}

#Call SetupSwitch
$Job = $VirtualSwitchService.SetupSwitch($ExternalSwitchPort, $InternalSwitchPort, $ExternalNic, [guid]::NewGuid().ToString(), "InternalEthernetPort")
while (([WMI]$Job.Job.JobState -eq 2) -or ([WMI]$Job.Job.JobState -eq 3) -or ([WMI]$Job.Job.JobState -eq 4)) {Start-Sleep -m 100}
[WMI]$Job.Job

And finally reboot them all (they actually reboot twice as part of the Hypervisor installtion):

icm -ComputerName $allServers -ScriptBlock { Restart-Computer -Force }

With the above I managed to enable and install Hyper-V across 70 severs simultaneously with less than a couple of hours of effort, nice!

Kind Regards,

jfrmilner


This month I find myself in the need for a quick way to do a simple audit on share permissions on a bunch of files servers. As always I wanted to use PowerShell Remoting (with the code executing on the local server) to accomplish this as enumerating shares is a slow process at the best of times and over the wire this would have been painfully slow.

Before writing a script I always see if anyone has done this already and in this case yes, I stumbled upon http://www.peetersonline.nl/index.php/powershell/listing-share-permissions-for-remote-shares

The only thing missing for my requirements was the need to have both the share name and server name adding to the object, this obviously is very minor and only required a couple of alterations, for example:

function Get-SharePermissions
{
	param([string]$computername,[string]$sharename)
	$ShareSec = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $computername
	ForEach ($ShareS in ($ShareSec | Where {$_.Name -eq $sharename}))
	{
		$SecurityDescriptor = $ShareS.GetSecurityDescriptor()
		$Global:myCol = @()
		ForEach ($DACL in $SecurityDescriptor.Descriptor.DACL)
		{
			$myObj = "" | Select ID, AccessMask, AceType
			$myObj.ID = $DACL.Trustee.Name
			$myObj | Add-Member -MemberType NoteProperty -Name Server -Value $computername
			$myObj | Add-Member -MemberType NoteProperty -Name Share -Value $sharename
			Switch ($DACL.AccessMask)
			{
				2032127 {$AccessMask = "FullControl"}
				1179785 {$AccessMask = "Read"}
				1180063 {$AccessMask = "Read, Write"}
				1179817 {$AccessMask = "ReadAndExecute"}
				-1610612736 {$AccessMask = "ReadAndExecuteExtended"}
				1245631 {$AccessMask = "ReadAndExecute, Modify, Write"}
				1180095 {$AccessMask = "ReadAndExecute, Write"}
				268435456 {$AccessMask = "FullControl (Sub Only)"}
				default {$AccessMask = $DACL.AccessMask}
			}
			$myObj.AccessMask = $AccessMask
			Switch ($DACL.AceType)
			{
				0 {$AceType = "Allow"}
				1 {$AceType = "Deny"}
				2 {$AceType = "Audit"}
			}
			$myObj.AceType = $AceType
			Clear-Variable AccessMask -ErrorAction SilentlyContinue
			Clear-Variable AceType -ErrorAction SilentlyContinue
			$myCol += $myObj
		}
	}
	Return $myCol
}

Get-SharePermissions -computername $ENV:COMPUTERNAME -sharename $args[0]

Like previous post on my blog I will use PowerShell remoting with a variable for the Servers ($allServers) and having saved the above code (C:\Scripts\Get-SharePermissions.ps1):


icm $allServers -FilePath C:\Scripts\Get-SharePermissions.ps1 -ArgumentList Wallpaper$

And the results:

Thanks for reading and I hope you find this useful. Also special thanks to the orginal author of this excellent script Hugo Peeters @ http://www.peetersonline.nl/

Regards,

jfrmilner


One of my clients was experiencing slow logon times after enabling roaming profiles and this was tracked down to large profiles. I needed to write a quick script that would tell me the folder size across a bunch of file servers.

I decided to create a function for this task named Get-FolderSize and this is the code:

function Get-FolderSize {
param ( [Parameter(Mandatory=$true)] [System.String]${Path}	)

$objFSO = New-Object -com  Scripting.FileSystemObject
$folders = (dir $path | ? {$_.PSIsContainer -eq $True})
foreach ($folder in $folders)
    {
    $folder | Add-Member -MemberType NoteProperty -Name "SizeMB" -Value (($objFSO.GetFolder($folder.FullName).Size) / 1MB) -PassThru
    }

}
Get-FolderSize $args[0]

To use this code on a local machine simply execute the above function and call it, for example Get-FolderSize D:\FileData. Now as previously mentioned I wanted to be able to check a large bunch of File Servers and to do that I would first need to create a variable to hold my servers, for example $allServers, then save the above code to the executing server for example C:\Scripts\Get-FolderSize.ps1. This finally allowed me to run the following command:

$folders = icm $allServers -FilePath C:\Scripts\Get-FolderSize.ps1 -ArgumentList "E:\Profiles"
 

Now to see the top 10 worst offenders with a filter to show only two decimal places:

 $folders | sort -Property SizeMB -Descending | select fullname,@{n='SizeMBN2';e={"{0:N2}" -f $_.SizeMB}} | select -First 10
 

Well as you can see from the below screen my client has some profiles to clean up but at least now they know which ones.

Thanks for reading and I hope you find this useful.

Regards,

jfrmilner