Archive

Posts Tagged ‘Function’

Function: New-BalloonTip – PowerShell Function to Show Balloon Tips

February 21st, 2012 5 comments

Description

Sometimes, we run scripts that may take quite a while to process. Rather than sit idly and watch the script process, we can trigger balloon tips to let us know when it’s done. Something like:

Balloon Tip

Balloon Tip

These are the same type of balloon tips that alert us to outdated or disabled security settings, pending updates, etc.

Windows Update balloon tip

Windows Update balloon tip

This handy little function makes it very easy to use this useful feature. I took the info from PS1 at http://powershell.com/cs/blogs/tips/archive/2011/09/27/displaying-balloon-tip.aspx and put it into a function and optimized it a little. You can specify the icon (none, info, warning, error), the title text, and the tip text.

function New-BalloonTip  {
<#
.SYNOPSIS
  Displays a balloon tip in the lower right corner of the screen.

.DESCRIPTION
  Displays a balloon tip in the lower right corner of the screen. Icon, title, and text can be customized.

.NOTES
  Version                 : 1.3
  Wish List               :
  Rights Required         : Local admin on server
                          : If script is not signed, ExecutionPolicy of RemoteSigned (recommended) or Unrestricted (not recommended)
                          : If script is signed, ExecutionPolicy of AllSigned (recommended), RemoteSigned, 
                            or Unrestricted (not recommended)
  Sched Task Required     : No
  Lync/Skype4B Version    : N/A
  Author/Copyright        : © Pat Richard, Skype for Business MVP - All Rights Reserved
  Email/Blog/Twitter      : pat@innervation.com   https://www.ucunleashed.com @patrichard
  Dedicated Post          : https://www.ucunleashed.com/1038
  Disclaimer              : You running this script means you won't blame me if this breaks your stuff. This script is
                            provided AS IS without warranty of any kind. I disclaim all implied warranties including, 
                            without limitation, any implied warranties of merchantability or of fitness for a particular
                            purpose. The entire risk arising out of the use or performance of the sample scripts and 
                            documentation remains with you. In no event shall I be liable for any damages whatsoever 
                            (including, without limitation, damages for loss of business profits, business interruption,
                            loss of business information, or other pecuniary loss) arising out of the use of or inability
                            to use the script or documentation. 
  Acknowledgements        : 
  Assumptions             : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)
  Limitations             : 
  Known issues            : None yet, but I'm sure you'll find some!                        

.LINK
  
Function: New-BalloonTip – PowerShell Function to Show Balloon Tips
.EXAMPLE New-BalloonTip -icon [none|info|warning|error] -title [title text] -text [text] Description ----------- Creates a balloon tip in the lower right corner. .INPUTS This function does support pipeline input. #> #Requires -Version 2.0 [CmdletBinding(SupportsShouldProcess = $true)] param( # Specifies the type of icon shown in the balloon tip [parameter(Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateSet("None", "Info", "Warning", "Error")] [ValidateNotNullOrEmpty()] [string] $Icon = "Info", # Defines the actual text shown in the balloon tip [parameter(Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true, HelpMessage = "No text specified!")] [ValidateNotNullOrEmpty()] [string] $Text, # Defines the title of the balloon tip [parameter(Position = 2, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true, HelpMessage = "No title specified!")] [ValidateNotNullOrEmpty()] [string] $Title, # Specifies how long to display the balloon tip [parameter(Position = 3, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern("[0-9]")] [int] $Timeout = 10000 ) PROCESS{ [system.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null # Add-Type -AssemblyName System.Windows.Forms #if (! $script:balloon) { #$script:balloon = New-Object System.Windows.Forms.NotifyIcon $balloon = New-Object System.Windows.Forms.NotifyIcon #} $path = Get-Process -Id $pid | Select-Object -ExpandProperty Path $balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path) $balloon.BalloonTipIcon = $Icon $balloon.BalloonTipText = $Text $balloon.BalloonTipTitle = $Title $balloon.Visible = $true $balloon.ShowBalloonTip($Timeout) $balloon.Dispose() } # end PROCESS } # end function New-BalloonTip

And you can call it by either supplying the parameter names:

New-BalloonTip -icon info -text 'PowerShell script has finished processing' -title 'Completed'

or not:

New-BalloonTip info 'PowerShell script has finished processing' 'Completed'

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Categories: PowerShell Tags: ,

Functions: Get-UACStatus Set-UACStatus – PowerShell Functions for Getting and Setting UAC Status

February 20th, 2012 7 comments

Windows-logo-128x128User Account Control, also known as UAC, was designed to reduce vulnerability by requiring confirmation when system settings are being changed. Some people hate it, some don’t mind it. But most understand it’s intent.

In any case, when deploying servers, it’s key to know what state the UAC settings are in, so that we can script accordingly. Normally, I just set the registry value to whatever I need it to be, using a one-liner such as:

To disable UAC:

Set-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -Value 0

To enable UAC:

Set-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -Value 1

UAC changes how a token is assembled when you log on. If we’re making changes to this, remember that a reboot is required before the new setting takes effect.

But what if we just need to programmatically peek at what UAC is set to, so that we can act accordingly? Well, this handy little function should help:

function Get-UACStatus {
	<#
	.SYNOPSIS
	   	Gets the current status of User Account Control (UAC) on a computer.

	.DESCRIPTION
	    Gets the current status of User Account Control (UAC) on a computer. $true indicates UAC is enabled, $false that it is disabled.

	.NOTES
	    Version      			: 1.0
	    Rights Required			: Local admin on server
	    					: ExecutionPolicy of RemoteSigned or Unrestricted
	    Author(s)    			: Pat Richard (pat@innervation.com)
	    Dedicated Post			: https://www.ucunleashed.com/1026
	    Disclaimer   			: You running this script means you won't blame me if this breaks your stuff.

	.EXAMPLE
		Get-UACStatus

		Description
		-----------
		Returns the status of UAC for the local computer. $true if UAC is enabled, $false if disabled.

	.EXAMPLE
		Get-UACStatus -Computer [computer name]

		Description
		-----------
		Returns the status of UAC for the computer specified via -Computer. $true if UAC is enabled, $false if disabled.

	.LINK
	  
Functions: Get-UACStatus Set-UACStatus – PowerShell Functions for Getting and Setting UAC Status
.INPUTS None. You cannot pipe objects to this script. #Requires -Version 2.0 #> [cmdletBinding(SupportsShouldProcess = $true)] param( [parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true, Mandatory = $false)] [string]$Computer ) [string]$RegistryValue = "EnableLUA" [string]$RegistryPath = "Software\Microsoft\Windows\CurrentVersion\Policies\System" [bool]$UACStatus = $false $OpenRegistry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Computer) $Subkey = $OpenRegistry.OpenSubKey($RegistryPath,$false) $Subkey.ToString() | Out-Null $UACStatus = ($Subkey.GetValue($RegistryValue) -eq 1) write-host $Subkey.GetValue($RegistryValue) return $UACStatus } # end function Get-UACStatus

You can call it via

Get-UACStatus

to see the status for the local machine, and

Get-UACStatus -Computer [computer name]

to see the status of a remote machine. Full help is available via

Get-Help Get-UACStatus

And if we need a little function to deal with enabling or disabling, for building into deployment scripts, we have this one, which includes functionality for rebooting:

function Set-UACStatus {
	<#
	.SYNOPSIS
		Enables or disables User Account Control (UAC) on a computer.

	.DESCRIPTION
		Enables or disables User Account Control (UAC) on a computer.

	.NOTES
		Version      			: 1.0
		Rights Required			: Local admin on server
						: ExecutionPolicy of RemoteSigned or Unrestricted
		Author(s)    			: Pat Richard (pat@innervation.com)
		Dedicated Post			: https://www.ucunleashed.com/1026
		Disclaimer   			: You running this script means you won't blame me if this breaks your stuff.

	.EXAMPLE
		Set-UACStatus -Enabled [$true|$false]

		Description
		-----------
		Enables or disables UAC for the local computer.

	.EXAMPLE
		Set-UACStatus -Computer [computer name] -Enabled [$true|$false]

		Description
		-----------
		Enables or disables UAC for the computer specified via -Computer.

	.LINK
	  
Functions: Get-UACStatus Set-UACStatus – PowerShell Functions for Getting and Setting UAC Status
.INPUTS None. You cannot pipe objects to this script. #Requires -Version 2.0 #> param( [cmdletbinding()] [parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true, Mandatory = $false)] [string]$Computer = $env:ComputerName, [parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true, Mandatory = $true)] [bool]$enabled ) [string]$RegistryValue = "EnableLUA" [string]$RegistryPath = "Software\Microsoft\Windows\CurrentVersion\Policies\System" $OpenRegistry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Computer) $Subkey = $OpenRegistry.OpenSubKey($RegistryPath,$true) $Subkey.ToString() | Out-Null if ($enabled -eq $true){ $Subkey.SetValue($RegistryValue, 1) }else{ $Subkey.SetValue($RegistryValue, 0) } $UACStatus = $Subkey.GetValue($RegistryValue) $UACStatus $Restart = Read-Host "`nSetting this requires a reboot of $Computer. Would you like to reboot $Computer [y/n]?" if ($Restart -eq "y"){ Restart-Computer $Computer -force Write-Host "Rebooting $Computer" }else{ Write-Host "Please restart $Computer when convenient" } } # end function Set-UACStatus

Call it via

Set-UACStatus -Computer [computer name] -Enabled [$true|$false]

And, like Get-UACStatus, full help is available via

Get-Help Set-UACStatus

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Function: New-LocalExchangeConnection – Ensure Your PowerShell Script is Connected to Exchange 2010

December 28th, 2011 11 comments

Description

When writing scripts that execute commands on an Exchange server, for Exchange 2010, it’s important to ensure that you’re running within a session connected to an Exchange server, and that all Exchange cmdlets are available. In Exchange 2007, we could load the Exchange snapins. But 2010 doesn’t use snapins. Some people would say that you can simply load the modules, but loading the modules bypasses RBAC, and is thus, not recommended. Mike Pfeiffer wrote a great article Managing Exchange 2010 with Remote PowerShell that sheds some light. It’s worth a read.

A solution around this is to run a PowerShell script that comes built into Exchange 2010. This makes available the Connect-ExchangeServer cmdlet, which will connect via remote PowerShell to Exchange. We can specify a server, or let the -auto option connect to the best server via autodiscover. New-LocalExchangeConnection is a function I wrote to connect:

function New-LocalExchangeConnection	{ 
	[cmdletBinding(SupportsShouldProcess = $true)]
	param(
	)
	Write-Verbose "Checking for Exchange Management Shell"
	$Sessions = Get-PSSession | Where-Object {$_.ConfigurationName -eq "Microsoft.Exchange"}
	if (!($Sessions)){
		if (Test-Path "$env:ExchangeInstallPath\bin\RemoteExchange.ps1"){
			Write-Verbose "Exchange Management Shell not found - Loading..."
			. "$env:ExchangeInstallPath\bin\RemoteExchange.ps1"
			Write-Verbose "Exchange Management Shell loaded"
			Write-Verbose "Connecting to Exchange server"
			Connect-ExchangeServer -auto
			if (Get-PSSession | Where-Object {$_.ConfigurationName -eq "Microsoft.Exchange"}){
				Write-Verbose "Connected to Exchange Server"
			}else{
				Write-Host "An error has occurred" -ForegroundColor red
			}
		}else{
			Write-Warning "Exchange Management Shell is not available on this computer"
		}
	}else{
		Write-Verbose "Exchange Management Shell already loaded"
	}
} # end function New-LocalExchangeConnection

Calling this within your script will make ensuring that your script is running with access to Exchange cmdlets much simpler.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Function: Set-ModuleStatus – PowerShell Function for Loading and Verifying Modules

December 27th, 2011 14 comments

PowerShell-logo-128x84Description

Often in my PowerShell scripts, I need to either load a specific module, or verify it’s loaded. Manually, of course, we can use Get-Module, Import-Module, etc. But in automation scripts, we need to programmatically make sure the module is loaded or load it if it’s not. I wrote this function and it’s worked well for me. introducing Get-ModuleStatus:

function Set-ModuleStatus { 
	[CmdletBinding(SupportsShouldProcess = $True)]
	param	(
		[parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true, HelpMessage = "No module name specified!")] 
		[ValidateNotNullOrEmpty()]
		[string] $name
	)
	PROCESS{
		# Executes once for each pipeline object
		# the $_ variable represents the current input object		
		if (!(Get-Module -name "$name")) { 
			if (Get-Module -ListAvailable | Where-Object Name -eq "$name") { 
				Import-Module -Name "$name"
				# module was imported
				# return $true
			} else {
				# module was not available
				# return $false
			}
		} else {
			# Write-Output "$_ module already imported"
			# return $true
		} 
	} # end PROCESS
} # end function Set-ModuleStatus

Call it supplying the module name, such as

Set-ModuleStatus Lync

You can use logic such as

if (Set-ModuleStatus Lync){Write-Host "Lync module is loaded"}else{Write-Host "Lync module is NOT loaded" -ForegroundColor red}

Simple and effective. You can also pipe module names to it, such as:

“lync”,”activedirectory” | Set-ModuleStatus

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Download

v1.2 – 02-07-2014 – Set-ModuleStatus.v1.2.zip

v1.1 – 09-17-2012 - Set-ModuleStatus.v1.1.zip

v1.0 Get-ModuleStatus.ps1

Categories: PowerShell Tags: ,

Function: New-Password – Creating Passwords with PowerShell

December 26th, 2011 2 comments

Description

When creating new accounts, an admin needs to assign a password. We often then check the box to force a user to change their password when they logon for the first time. Some organizations will use a ‘default’ password for all new accounts. That’s fraught with security implications, and I’ve never recommended it. The downside is that you, as an admin, need to think up a password for each new account. I know how it is – you look around at things on your desk, items on the wall, looking for ideas. Then you have to make sure your super password meets your organizations password requirements, including length and complexity. Well, no more!

Enter New-Password. This function takes one simple input – length. It then spits out a password of said length, using upper and lower case letters, numbers, and punctuation, as well as a phonetic version. If you choose not to use some of the punctuation characters, feel free to just put a ‘#’ in front of that particular line.

function New-Password	{
<#
.SYNOPSIS
  Displays a complex password.

.DESCRIPTION
  Displays a complex password. Output includes password, and phonetic breakdown of the password.

.NOTES
  Version                 : 1.3
  Wish List               :
  Rights Required         : No special rights required
                          : If script is not signed, ExecutionPolicy of RemoteSigned (recommended) or Unrestricted (not recommended)
                          : If script is signed, ExecutionPolicy of AllSigned (recommended), RemoteSigned, 
                            or Unrestricted (not recommended)
  Sched Task Required     : No
  Lync/Skype4B Version    : N/A
  Author/Copyright        : © Pat Richard, Skype for Business MVP - All Rights Reserved
  Email/Blog/Twitter      : pat@innervation.com   https://www.ucunleashed.com @patrichard
  Dedicated Post          : https://www.ucunleashed.com/915
  Disclaimer              : You running this script means you won't blame me if this breaks your stuff. This script is
                            provided AS IS without warranty of any kind. I disclaim all implied warranties including, 
                            without limitation, any implied warranties of merchantability or of fitness for a particular
                            purpose. The entire risk arising out of the use or performance of the sample scripts and 
                            documentation remains with you. In no event shall I be liable for any damages whatsoever 
                            (including, without limitation, damages for loss of business profits, business interruption,
                            loss of business information, or other pecuniary loss) arising out of the use of or inability
                            to use the script or documentation. 
  Acknowledgements        : 
  Assumptions             : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)
  Limitations             : 
  Known issues            : None yet, but I'm sure you'll find some!                        

.LINK
  
Function: New-Password – Creating Passwords with PowerShell
.EXAMPLE New-Password -Length <integer> Description ----------- Creates a password of the defined length .EXAMPLE New-Password -Length <integer> -ExcludeSymbols Description ----------- Creates a password of the defined length, but does not utilize the following characters: !$%^-_:;{}<># &@]~ .INPUTS This function does support pipeline input. #> #Requires -Version 3.0 [CmdletBinding(SupportsShouldProcess = $true)] param( #Defines the length of the desired password [Parameter(ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()] [ValidatePattern("[0-9]")] [int] $Length = 12, #When specified, only uses alphanumeric characters for the password [Parameter(ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True)] [switch] $ExcludeSymbols ) PROCESS { $pw = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" if (!$ExcludeSymbols) { $pw += "!$%^-_:;{}<># &@]~" } $password = -join ([Char[]]$pw | Get-Random -count $length) Write-Output "`nPassword: $password`n" ForEach ($character in [char[]]"$password"){ [string]$ThisLetter = $character switch ($ThisLetter) { a {$ThisWord = "alpha"} b {$ThisWord = "bravo"} c {$ThisWord = "charlie"} d {$ThisWord = "delta"} e {$ThisWord = "echo"} f {$ThisWord = "foxtrot"} g {$ThisWord = "golf"} h {$ThisWord = "hotel"} i {$ThisWord = "india"} j {$ThisWord = "juliett"} k {$ThisWord = "kilo"} l {$ThisWord = "lima"} m {$ThisWord = "mike"} n {$ThisWord = "november"} o {$ThisWord = "oscar"} p {$ThisWord = "papa"} q {$ThisWord = "quebec"} r {$ThisWord = "romeo"} s {$ThisWord = "sierra"} t {$ThisWord = "tango"} u {$ThisWord = "uniform"} v {$ThisWord = "victor"} w {$ThisWord = "whiskey"} x {$ThisWord = "xray"} y {$ThisWord = "yankee"} z {$ThisWord = "zulu"} 1 {$ThisWord = "one"} 2 {$ThisWord = "two"} 3 {$ThisWord = "three"} 4 {$ThisWord = "four"} 5 {$ThisWord = "five"} 6 {$ThisWord = "six"} 7 {$ThisWord = "seven"} 8 {$ThisWord = "eight"} 9 {$ThisWord = "nine"} 0 {$ThisWord = "zero"} ! {$ThisWord = "exclamation"} $ {$ThisWord = "dollar"} % {$ThisWord = "percent"} ^ {$ThisWord = "carat"} - {$ThisWord = "hyphen"} _ {$ThisWord = "underscore"} : {$ThisWord = "colon"} `; {$ThisWord = "semicolon"} `{ {$ThisWord = "left-brace"} `} {$ThisWord = "right-brace"} `/ {$ThisWord = "backslash"} `< {$ThisWord = "less-than"} `> {$ThisWord = "greater-than"} `# {$ThisWord = "pound"} `& {$ThisWord = "ampersand"} `@ {$ThisWord = "at"} `] {$ThisWord = "right-bracket"} `~ {$ThisWord = "tilde"} default {$ThisWord = "space"} } if ($ThisLetter -cmatch $ThisLetter.ToUpper()){ $ThisWord = $ThisWord.ToUpper() } $phonetic = $phonetic+" " +$ThisWord } $phonetic = $phonetic.trim() Write-Output "Phonetic: $phonetic" "Password: $password`nPhonetic: $phonetic" | clip Write-Output "`n`nThis information has been sent to the clipboard" } END{ Remove-Variable ThisWord Remove-Variable ThisLetter Remove-Variable Password Remove-Variable Phonetic Remove-Variable Pw } } # end function New-Password

Now, stick that function in your PowerShell profile. Each time you need a new password, use

New-Password -Length [number]

such as

New-Password -Length 12

And you now have a password to use.

12 character password

You can also specify -ExcludeSymbols to return only an alphanumeric password, bypassing the added complexity of using non-alphanumeric symbols.

New-Password -Length 12 -ExcludeSymbols


12 character alphanumeric password

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Functions: Get-LocalAdminGroupMembership and Set-LocalAdminGroupMembership – Local Admin Group Membership on Remote Machines

December 22nd, 2011 No comments

PowerShell-logo-128x84While writing some PowerShell scripts to automate the installation of Exchange on over 100 servers, I needed to set and then verify that a group (in this case, “Exchange Trusted Subsystem”) was a member of the local admins group on some remote servers.

We start with Get-LocalAdminGroupMembership. This function merely checks the local admins group on a remote server to see if the group to be added is already a member. If it is, it returns $true, if not, $false. We need to pass it two variables: $ComputerName, and $Member. We don’t need to run this function. It’s called from the second function.

function Get-LocalAdminGroupMembership	{
	[CmdletBinding()]
	Param(
		[Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
		$ComputerName = ".",
		[Parameter(Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
		$Member
	)
	if($ComputerName -eq "."){$ComputerName = (get-WmiObject win32_computersystem).Name}
	$computer = [ADSI]("WinNT://" + $ComputerName + ",computer")
	$Group = $computer.psbase.children.find("Administrators")
	$members= $Group.psbase.invoke("Members") | % {$_.GetType().InvokeMember("Name", "GetProperty", $null, $_, $null)}
	if ($members -match $member){return $true}else{return $false}
} # end function Get-LocalAdminGroupMembership

 

The second function does all the heavy lifting.

function Set-LocalAdminGroupMembership {
	[CmdletBinding()]
	Param(
		[Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
		[string]$ComputerName = ".",
		[Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
		[string]$Member,
		[Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
		[string]$Domain = $env:USERDNSDOMAIN
	)

	Process{
		if (!(Get-LocalAdminGroupMembership -ComputerName "$ComputerName" -Member "$Member")){
			if($ComputerName -eq "."){$ComputerName = $env:ComputerName.ToUpper()}    

			if($Domain){
  			$adsi = [ADSI]"WinNT://$ComputerName/administrators,group"
    		$adsi.Add("WinNT://$Domain/$Member,group")
			}else{
	  		Write-Host "Not connected to a domain." -ForegroundColor "red"
			}
		} else {
			Write-Host "`"$Account`" is already a local admin on $ComputerName" -ForegroundColor yellow
		}
		Get-LocalAdminGroupMembership -ComputerComputer "$ComputerName" -Member "$Member"
	}# Process
} # end function Set-LocalAdminGroupMembership

We call Set-LocalAdminGroupMembership and pass it the same parameters, $ComputerName and $Member

Set-LocalAdminGroupMembership -ComputerName mycomputer -Member "Exchange Trusted Subsystem"

The function will add the group to the local admins group, and then do a Get-LocalAdminGroupMembership for that same group and dump the results to the screen.

Function: New-Pause – Pausing PowerShell Scripts

December 21st, 2011 No comments

Yesterday, I wrote about a sleep function to cause a predetermined delay in a script. Today, I give you a short function, New-Pause. New-Pause stops a script and waits for the user to press a key before continuing.

function New-Pause {
 Write-Host "Press any key to continue" -ForegroundColor green
 $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
} # end function New-Pause

We can add some flexibility into it by allowing for the function to be called with alternative values for the text color and the text itself.

function New-Pause {
  [CmdletBinding(SupportsShouldProcess, SupportsPaging, HelpUri = 'https://ucunleashed.com/885')]
  param(
    # Text that is displayed as the prompt when paused.
    [Parameter(ValueFromPipelineByPropertyName)]
    [ValidateNotNullOrEmpty()]
    $PausePrompt = 'Press any key to continue',
    
    # Color of the prompt.
    [Parameter(ValueFromPipelineByPropertyName)]
    [ValidateNotNullOrEmpty()]
    [ValidateSet('Black', 'DarkMagenta', 'DarkRed', 'DarkBlue', 'DarkGreen', 'DarkCyan', 'DarkYellow', 'Red', 'Blue', 'Green', 'Cyan', 'Magenta', 'Yellow', 'DarkGray', 'Gray', 'White')]
    $PauseColor = 'Green'
  )
  Write-Host $PausePrompt -ForegroundColor $PauseColor
  $null = $host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
  Write-Host 'Continuing...'
} # end function New-Pause

Call the function using

New-Pause
New-Pause

New-Pause

Once any key is pressed, your script can continue.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Categories: PowerShell Tags: ,

Function: New-Sleep – When You Need a Delay

December 20th, 2011 6 comments

Description

On a recent project, I needed some PowerShell scripts to wait for a few seconds just to ensure that some other processes were finished and I wasn’t issuing too many commands to some Exchange servers too quickly. I came up with this little function:

function New-Sleep {
	[cmdletbinding()]
	param(
		[parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true, HelpMessage = "No time specified")]
		[int]$s
	)
	for ($i=1; $i -lt $s; $i++) {
	[int]$TimeLeft=$s-$i
	Write-Progress -Activity "Waiting $s seconds..." -PercentComplete (100/$s*$i) -CurrentOperation "$TimeLeft seconds left ($i elapsed)" -Status "Please wait"
	Start-Sleep -Seconds 1
	}
	Write-Progress -Completed $true -Status "Please wait"
} # end function New-Sleep

Call the function like this:

New-Sleep -s 60

Where the value of $s is the number of seconds you want to sleep. The display tells you how long your sleeping for, how much time is left, and how much time has elapsed.

New-Sleep

New-Sleep

Download the function below.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Download

v1.0 New-Sleep.ps1

Categories: PowerShell Tags: ,

Function: New-Share – Creating File Shares Via PowerShell

July 13th, 2011 4 comments

Description

Often we need to create file shares, and this is generally fairly boring. PowerShell can help streamline this process. This function will create the share, but does not set sharing permissions. We’ll cover that later.

This is based partly on How to Use PowerShell to create shared folders in Windows 7. I resolved some minor issues and added the pipeline parameters and some minor error checking, and the description. The script will create the folder if it doesn’t exist, and then share it.

function New-Share {
 param (
  [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No folder name specified")]
  [string]$FolderName,
    [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No share name specified")]
    [string]$ShareName,
    [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false, HelpMessage="No description specified")]
    [string]$Description
 )
 $error.clear()
 # Check for folder; Create it if it doesn't exist
 If (!(Test-Path $FolderName)) {
  New-Item $FolderName -type Directory | Out-Null
 }
 # Check for share; Create it if it doesn't exist
 $Shares=[WMICLASS]"WIN32_Share"
 if (!(Get-WMIObject Win32_share -filter "name='$ShareName'")){
  $Shares.Create($FolderName,$ShareName,0,65535,$Description) | Out-Null
  if (!($error)){
   # the share was created
   return $true
  } else {
   # there was an error
   return $false
  }
 } else {
  # the share already exists
  return $false
  }
} # end function New-Share

And we can then call the function with something like:

New-Share -FolderName "c:\LyncShare" -ShareName "LyncShare" -Description "Used by Lync server to store Address Book files, phone updates, and other important files."

As you can see, it’s pretty straight forward. We’ll cover setting both NTFS and Share permissions soon.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Categories: PowerShell Tags: ,

Function: Remove-ScriptVariables – Cleaning Up Script Variables in PowerShell

July 8th, 2011 3 comments

PowerShell-logo-128x84Description

When writing scripts that use variables, especially those that contain a fair amount of data, it’s best practice to clean up the environment when exiting. This frees up memory for other purposes, and allows you to leave the environment as clean as possible. This is accomplished using the Remove-Variable cmdlet.

As scripts become more complex and evolve over time, it can be tough to keep track of all variables in order to remove them at the end. I created this function to help deal with this. The function takes the path of the script file, inspects the file, compiles a list of variables in the script, and runs them through the Remove-Variable cmdlet. It builds on some of the code from Auto-Documenting Script Variables.

function Remove-ScriptVariables($path) { 
 $result = Get-Content $path | 
 ForEach { if ( $_ -match '(\$.*?)\s*=') {     
   $matches[1]  | ? { $_ -notlike '*.*' -and $_ -notmatch 'result' -and $_ -notmatch 'env:'}  
  } 
 } 
 ForEach ($v in ($result | Sort-Object | Get-Unique)){ 
  Write-Host "Removing" $v.replace("$","")
  Remove-Variable ($v.replace("$","")) -ErrorAction SilentlyContinue
 }
} # end function Get-ScriptVariables

We then call the function, passing the built-in $MyInvocation.MyCommand.Name value, which automatically contains the path and name of the currently running script. Essentially, we tell the function to run against it’s own script file:

Remove-ScriptVariables($MyInvocation.MyCommand.Name)

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Categories: PowerShell Tags: ,