Archive

Posts Tagged ‘Windows Server 2008 R2’

Function: Set-TimeZone – Configure Time Zone via PowerShell

March 4th, 2013 1 comment

Powershell_logo-137x137Note: This functionality was added into PowerShell version 3.1.For more information, see https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.management/set-timezone

It’s easy to just double-click on the time in the system tray and set the time and time zone when building a new server. You may even have a GPO that does this for you. That’s all fine and dandy. But GPOs don’t work for member servers, and if you build a lot of servers, like I do, it’s a repetitive task – something perfectly suited for PowerShell.

With this function, we do nothing more than call tzutil.exe with the timezone name. Nothing fancy. I added some validation to make sure that the timezone specified is truly one of the 100 valid time zones that tzutile.exe should recognize and accept.

So, now, in your server provisioning script, merely call the function, Set-TimeZone, with the desired timezone. For example:

Set-TimeZone "Pacific Standard Time"

The script defaults to “Eastern Standard Time” if you don’t supply a timezone. That’s it. There is no screen output for this function. Here’s the function:

function Set-TimeZone {
  [CmdletBinding(SupportsShouldProcess = $True)]
  param( 
    [Parameter(ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True, Mandatory = $False)]
    [ValidateSet("Dateline Standard Time","UTC-11","Hawaiian Standard Time","Alaskan Standard Time","Pacific Standard Time (Mexico)","Pacific Standard Time","US Mountain Standard Time","Mountain Standard Time (Mexico)","Mountain Standard Time","Central America Standard Time","Central Standard Time","Central Standard Time (Mexico)","Canada Central Standard Time","SA Pacific Standard Time","Eastern Standard Time","US Eastern Standard Time","Venezuela Standard Time","Paraguay Standard Time","Atlantic Standard Time","Central Brazilian Standard Time","SA Western Standard Time","Pacific SA Standard Time","Newfoundland Standard Time","E. South America Standard Time","Argentina Standard Time","SA Eastern Standard Time","Greenland Standard Time","Montevideo Standard Time","Bahia Standard Time","UTC-02","Mid-Atlantic Standard Time","Azores Standard Time","Cape Verde Standard Time","Morocco Standard Time","UTC","GMT Standard Time","Greenwich Standard Time","W. Europe Standard Time","Central Europe Standard Time","Romance Standard Time","Central European Standard Time","W. Central Africa Standard Time","Namibia Standard Time","Jordan Standard Time","GTB Standard Time","Middle East Standard Time","Egypt Standard Time","Syria Standard Time","E. Europe Standard Time","South Africa Standard Time","FLE Standard Time","Turkey Standard Time","Israel Standard Time","Arabic Standard Time","Kaliningrad Standard Time","Arab Standard Time","E. Africa Standard Time","Iran Standard Time","Arabian Standard Time","Azerbaijan Standard Time","Russian Standard Time","Mauritius Standard Time","Georgian Standard Time","Caucasus Standard Time","Afghanistan Standard Time","Pakistan Standard Time","West Asia Standard Time","India Standard Time","Sri Lanka Standard Time","Nepal Standard Time","Central Asia Standard Time","Bangladesh Standard Time","Ekaterinburg Standard Time","Myanmar Standard Time","SE Asia Standard Time","N. Central Asia Standard Time","China Standard Time","North Asia Standard Time","Singapore Standard Time","W. Australia Standard Time","Taipei Standard Time","Ulaanbaatar Standard Time","North Asia East Standard Time","Tokyo Standard Time","Korea Standard Time","Cen. Australia Standard Time","AUS Central Standard Time","E. Australia Standard Time","AUS Eastern Standard Time","West Pacific Standard Time","Tasmania Standard Time","Yakutsk Standard Time","Central Pacific Standard Time","Vladivostok Standard Time","New Zealand Standard Time","UTC+12","Fiji Standard Time","Magadan Standard Time","Tonga Standard Time","Samoa Standard Time")]
    [ValidateNotNullOrEmpty()]
    [string]$TimeZone = "Eastern Standard Time"
  ) 

  $process = New-Object System.Diagnostics.Process 
  $process.StartInfo.WindowStyle = "Hidden" 
  $process.StartInfo.FileName = "tzutil.exe" 
  $process.StartInfo.Arguments = "/s `"$TimeZone`"" 
  $process.Start() | Out-Null 
} # end function Set-TimeZone

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-PSUpdateHelpScheduledTask – Auto Update PowerShell Help

March 1st, 2013 2 comments

Powershell_logo-137x137Probably not of much value to people unless you build a fair amount of servers and have it scripted, but…

One thing you want to do with servers running PowerShell v3.0, such as Windows Server 2012, is to regularly run Update-Help from a PowerShell session to update the help files PowerShell uses for various modules. But this is something that can be easily forgotten, and, who wants to manually do a recurring task, anyways?

Here is a function you can toss in your server build script to create a scheduled task that will automatically update PowerShell help every day at 7pm. The task runs as ‘system’, so we don’t have to worry about storing credentials. Here’s the function

function New-PSUpdateHelpScheduledTask {
	[CmdletBinding(SupportsShouldProcess = $true)]
	param()
	BEGIN{
		[string] $TaskArguments = '-NoProfile -Command "& {Update-Help -Force; Start-Sleep -Seconds 5; Get-ChildItem $env:temp -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.PSIsContainer -eq $True -and $_.GetFiles() -match ''.cab''} | Remove-Item -Recurse -Force}"'
		[string] $TaskProgram =  "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe"
	}
	PROCESS{	
		$TaskAction = New-ScheduledTaskAction -Execute $TaskProgram -Argument $TaskArguments
		$TaskTrigger = New-ScheduledTaskTrigger -Daily -At 19:00
		Register-ScheduledTask -TaskName "Update PowerShell Help" -Action $TaskAction -Trigger $TaskTrigger -RunLevel Highest -User "system" -Description "Automatically updates PowerShell help." | Out-Null
	}
	END {
		Remove-Variable TaskAction
		Remove-Variable TaskTrigger
	}
} # end function New-PSUpdateHelpTask

and merely call it using

New-PsUpdateHelpScheduledTask

You’ll notice a new scheduled task in Task Scheduler, and we see that it completed successfully.
Update PowerShell Help
Just a couple of lines of code and we’ve removed the need to manually run Update-Help on a server.

Hope this helps!

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-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			: http://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			: http://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.

[Redirect] Automated Prerequisite Installation via PowerShell for Lync Server 2010 on Windows Server 2008 R2

April 27th, 2011 No comments

Update: A newer version of this script has been released, and is available at Set-Lync2010Features.ps1 v5.0 – automated prereq PowerShell script for Lync Server 2010 released

If you’ve followed this blog for a while, you may remember one of the more popular posts, Automated prerequisite installation via PowerShell for Exchange Server 2010 on Windows Server 2008 R2. In that script, I used some simple techniques to help take some of the boring tasks out of installing Exchange 2010 servers. It was updated several times, and a new update is coming soon.

Well, Lync Server MVP Stale Hansen took that script and adapted it to installing the prerequisites for Lync Server 2010 and posted the results online. He did some neat things like installing the Best Practice Analyzer and the Resource Kit.

I got tasked with Lync responsibilities on my current project, so I took a closer look at the Stale’s version of the script, and decided to add some more code. Here are some of the changes:

  1. The script now prompts you about installing the telnet client. The telnet client isn’t REQUIRED, but is often recommended. Since my current project is in a high security environment, installing anything that isn’t absolutely required is generally frowned upon. So I made it optional.
  2. I added the option to disable IPv6. Lync Server 2010 doesn’t make use of IPv6 at all, so this option might prove handy.
  3. I added the option to install the Lync Server 2010 Stress and Performance Tool, the Visual C++ 2008 Redistributable that the Lync installer complains about, and options to install the recently released IM and Expert feature as well as starting Windows Update. Note that the IM an Expert piece is still early in testing. Note also that the Visual C++ install should be done after rebooting the server, otherwise it throws errors.
  4. Behind the scenes, I cleaned up a LOT of code – something I’ve been meaning to do to the Exchange prereq script as well. The script now looks to see if something is installed before trying to install it. The Resource Kit and BPA both have documentation that is MS Word based, so the script will ask you if you want to automatically install the free MS Word viewer and related filters.
  5. The OS detection method was cleaned up, and now supports any version of 2008 R2, including RTM and various service packs.

I’ve built 6 production servers and haven’t noticed any issues yet. But, as always, use at your own risk.

The code can be downloaded at Set-Lync2010Windows2008R2Features.zip. Rights required are local server admin. Also, set your execution policy to unrestricted in order to be able to run this unsigned script.

I welcome any comments, suggestions, concerns.