|
Each contribution is licensed to you under a License Agreement by its owner, not Microsoft. Microsoft does not guarantee the contribution or purport to grant rights to it.
|
Categories |
Update RD Connection Broker cluster configuration(Microsoft)
Script Code
Windows PowerShell
<#
.Synopsis
Copies the RD Connection Broker role service configuration settings from the 'ReferenceNode' and applies them to all the nodes in the cluster.
.Description
Copies the RD Connection Broker role service configuration settings from the 'ReferenceNode' and applies them to all the nodes in the cluster.
The script configures all RD Connection Broker servers in the Fail-Over cluster by taking the settings from already an configured RD Connection Broker server.
Prerequisites for script execution:
1. All nodes in the cluster should be configured for High-Availability of Connection Broker service as per the guidelines. 'Set-ConnectionBrokerCluster.ps1' can be used to create such a RD Connection Broker server Fail-Over cluster.
2. Script is expected to be executed on the OwnerNode of Fail-Over cluster.
3. The 'ReferenceNode' is configured appropriately. The script does not check the sanity of configuration settings of the ReferenceNode.
NOTE:
The following settings are replicated/applied across nodes:
1. The RD Virtualization Host Servers added to the 'ReferenceNode' are added to all the servers that are part of the Connection Broker Fail-Over cluster.
2. The 'WebAccessComputers' that are added to the 'ReferenceNode' are added to all the servers that are part of the Connection Broker Fail-Over cluster.
3. The 'RemoteAppSources' that are added to the 'ReferenceNode' are added to all the servers that are part of the Connection Broker Fail-Over cluster.
4. The 'Pools' thats are created in the 'ReferenceNode' are created on all the servers that are part of the Connection Broker Fail-Over cluster.
5. Apart from the 'Certificate' related settings, all other settings RD Connection Broker role service configuration settings on 'ReferenceNode' and are applied on all nodes in the cluster.
The script uses 'RemoteDesktopServices' provider for PowerShell to enumerate the RD Connection Broker role service configuration settings. For further details on the RDS PowerShell provider please refer to the blog: 'http://blogs.msdn.com/rds/archive/2009/01/28/managing-remote-desktop-services-aka-terminal-services-using-windows-powershell.aspx'
.Parameter ReferenceNode
Name of the RD Connection Broker server that is configured as per the need of the deployment. The RD Connection Broker role service configuration settings from this server will be copied to all the other servers in the Fail-Over cluster
.Parameter Credential
Credentials that has administrative privileges on all nodes of the Fail-Over cluster and has AD rights to add new computers.
.Example
PS C:\> Replicate-CBSettingsAcrossNodesInCluster.ps1 -ReferenceNode CB1 -Credential (Get-Credential)
Configures all servers added to the Connection Broker Fail-Over cluster by copying RD Connection Broker role service configuration settings from CB1.
.Notes
Name : Replicate-CBSettingsAcrossNodesInCluster.ps1
#>
param(
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$TRUE, HelpMessage="Configured Node from which the settings are read and applied to the list specified under 'Node'.")]
[System.String]$ReferenceNode,
[Parameter(Mandatory=$TRUE, HelpMessage="The credentials of a user that has administrative privileges on all nodes in the cluster and also active directory account creation rights.")]
[System.Management.Automation.PSCredential]$Credential
)
function Print-Error([System.String]$Msg)
{
Write-Host -ForegroundColor Red -BackgroundColor White $Msg
Exit(1)
}
function WMIPing-Comp([System.String]$Computer)
{
$RetVal = $null
if($Credential)
{
$RetVal = Get-WmiObject -Class Win32_ComputerSystem -Property Name,Domain -ComputerName $Computer -Credential $Credential
}
else
{
$RetVal = Get-WmiObject -Class Win32_ComputerSystem -Property Name,Domain -ComputerName $Computer
}
return $RetVal
}
function Invoke-MyCommand([System.String]$Computer, [System.Management.Automation.ScriptBlock]$ScriptBlock, [System.Object[]]$ArgumentList)
{
$RetVal = @()
if($Credential)
{
$RetVal = [System.Object[]](Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -Credential $Credential -ArgumentList $ArgumentList)
}
else
{
$RetVal = [System.Object[]](Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList)
}
return $RetVal
}
function Ping-Comp([System.String]$Computer)
{
$RetVal = $null
$RetVal = Invoke-MyCommand $Computer {"Ping"}
if($RetVal)
{
return $TRUE
}
else
{
return $FALSE
}
}
function Get-HostName([Bool]$IsFqdn)
{
$WmiObj = Get-WmiObject -Class Win32_ComputerSystem -Property Name,Domain
if($IsFqdn)
{
return $WmiObj.Name + "." + $WmiObj.Domain
}
else
{
return $WmiObj.Name
}
}
function Get-HostDomain()
{
$WmiObj = Get-WmiObject -Class Win32_ComputerSystem -Property Name,Domain
return $WmiObj.Domain
}
function Set-RDVHostsSBName([String]$CB, [String[]]$RDVHS)
{
foreach($RDVH in $RDVHS) {
$sdSetting = Get-WmiObject -ComputerName $RDVH -Namespace root\cimv2\terminalservices -Class win32_TSVirtualDesktopServerSettings –Authentication PacketPrivacy -Credential $Credential
$sdSetting.SessionBrokerName = $CB
$putopt = New-Object System.Management.PutOptions
$putopt.Type = [System.Management.PutType]::UpdateOnly
$sdSetting.Put($putopt) |Out-Null
}
}
#Check if there are proper privileges to run the script
$LoggedInUser = New-Object -TypeName System.Security.Principal.WindowsPrincipal -ArgumentList ([System.Security.Principal.WindowsIdentity]::GetCurrent())
if(!($LoggedInUser.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)))
{
Print-Error "Please execute the script with administrative privileges."
}
Import-Module -Name FailOverClusters -ErrorAction Stop
$ClientAccessNameWmiObj = Get-WmiObject -Class Win32_SessionBrokerServiceProperties -Property SBNetworkName -ErrorAction SilentlyContinue
if(!$ClientAccessNameWmiObj)
{
Print-Error "Unable to fetch 'ClientAccessName'. Please ensure that the script is executed on the OwnerNode of the Connection Broker Fail-Over-Cluster."
}
$ClientAccessName = $ClientAccessNameWmiObj.SBNetworkName
Write-Verbose "ClientAccessName: $ClientAccessName"
$NonFqdnClientAccessName = ($ClientAccessName.Split("."))[0]
$ClusterGroup = Get-ClusterGroup -Name $NonFqdnClientAccessName
if($ClusterGroup)
{
$script:ClusterName = $ClusterGroup.Cluster.Name
}
else
{
Print-Error "Unable to fetch cluster information from the provided 'ClientAccessName'. Please provided a valid 'ClientAccessName'."
}
$Node = [String[]](Get-ClusterNode -Cluster $ClusterName | %{$_.Name})
if(!$Node)
{
Print-Error "Either the 'ClusterName' is invalid or there are no nodes in cluster!"
}
$ReferenceNodeNonFQDN = $ReferenceNode.Split(".")[0]
$LocalHostName = Get-HostName $FALSE
if( $ReferenceNodeNonFQDN -ne $LocalHostName )
{
foreach( $N1 in $Node )
{
if( $N1 -eq $ReferenceNodeNonFQDN )
{
$script:ClusterReferenceNode = $N1
}
}
}
if($ClusterReferenceNode)
{
(Move-ClusterGroup -Name $NonFqdnClientAccessName -Node $ClusterReferenceNode -ErrorAction Stop) > $null
}
Write-Host "Nodes in cluster: $Node"
#Check to see if all computers are accessible for remote PowerShell script execution.
$AllComputers = [String[]]($Node) + [String[]]($ReferenceNode)
foreach($Comp in $AllComputers)
{
if( !(Ping-Comp $Comp) )
{
Print-Error "Unable to ping $Comp. Exiting..!"
}
}
#Read settings from configured node and build a data base.
$ScriptBlock = {
function IsNotNull([String]$Path)
{
if( ((Get-Item -Path $Path).CurrentValue -eq "NULL") -or ( (Get-Item -Path $Path).CurrentValue.Trim() -eq [String]::Empty ) )
{
return $null
}
else
{
return (Get-Item -Path $Path).CurrentValue
}
}
$Dict = @{}
Import-Module -Name RemoteDesktopServices -ErrorAction Stop
$ScriptBlockLines = @()
#Add computers to SessionBrokerComputers
$RDSAssembly = [System.Reflection.Assembly]::LoadFrom("$pshome\modules\remotedesktopservices\tspsengine.dll")
$ConnBrokerComps = [Microsoft.TerminalServices.PSEngine.UserGroupHelper]::ListMembers("Session Broker Computers")
if($ConnBrokerComps)
{
$ScriptBlockLines += @"
`$RDSAssembly = [System.Reflection.Assembly]::LoadFrom("`$pshome\modules\remotedesktopservices\tspsengine.dll")
"@
foreach($comp in $ConnBrokerComps)
{
$ScriptBlockLines += "[Microsoft.TerminalServices.PSEngine.UserGroupHelper]::AddMember('Session Broker Computers', '$comp') | Out-Null"
}
}
$RDVHostServers = [String[]]( Get-ChildItem -Path "RDS:\ConnectionBroker\VirtualDesktops\RDVHostServers" | %{$_.Name} )
if($RDVHostServers)
{
$Dict.Add("RDVHostServers",$RDVHostServers)
foreach($HostServ in $RDVHostServers)
{
$ScriptBlockLines += "New-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\RDVHostServers' -Name '$HostServ' -Credential `$args[0]"
}
}
$WebAccessComputers = [String[]]( Get-ChildItem -Path "RDS:\ConnectionBroker\WebAccessComputers" | %{$_.Name} )
if($WebAccessComputers)
{
foreach($WebAcComp in $WebAccessComputers)
{
$ScriptBlockLines += "New-Item -Path 'RDS:\ConnectionBroker\WebAccessComputers' -Name '$WebAcComp'"
}
}
$RemoteAppSources = [String[]]( Get-ChildItem -Path "RDS:\ConnectionBroker\RemoteAppSources" | %{$_.Name} )
if($RemoteAppSources)
{
foreach($RemAppSource in $RemoteAppSources)
{
$ScriptBlockLines += "New-Item -Path 'RDS:\ConnectionBroker\RemoteAppSources' -Name '$RemAppSource' -Force"
}
}
$Pools = [String[]]( Get-ChildItem -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools" | Where-Object -FilterScript {$_.Name -ne "PersonalVirtualDesktops"} | %{$_.Name} )
if($Pools)
{
foreach($Farm in $Pools)
{
$ScriptBlockLines += "New-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools' -Name '$Farm' -DisplayName '$Farm'"
$VirtualMachines = [String[]](Get-ChildItem -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\VirtualMachines" | %{$_.Name})
if($VirtualMachines)
{
foreach($VM in $VirtualMachines)
{
$ScriptBlockLines += "New-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$Farm\VirtualMachines' -Name '$VM'"
}
}
}
}
$Val = IsNotNull "RDS:\ConnectionBroker\VirtualDesktops\RedirectionServer"
if($Val)
{
#$ScriptBlockLines += "net localgroup 'Session Broker Computers' /add '$Val`$'"
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\RedirectionServer' -Value '$Val' -Force"
#Add the server to the dictionary
$Dict.Add("Redirector" , $Val)
}
$Val = IsNotNull "RDS:\ConnectionBroker\DisplayName"
if($Val)
{
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\DisplayName' -Value '$Val'"
}
$Val = IsNotNull "RDS:\ConnectionBroker\ConnectionID"
if($Val)
{
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\ConnectionID' -Value '$Val'"
}
if((Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\DownlevelSupport").CurrentValue -eq "1")
{
$AlternateServer = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\AlternativeServerName").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\DownlevelSupport' -Value '1' -AlternateServerName '$AlternateServer'"
}
else
{
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\DownlevelSupport' -Value '0'"
}
$GatewayUsage = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\GatewaySettings\GatewayUsage").CurrentValue
$GatewayName = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\GatewaySettings\GatewayName").CurrentValue
$GatewayAuthMode = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\GatewaySettings\GatewayAuthMode").CurrentValue
$GatewayUseCachedCreds = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\GatewaySettings\GatewayUseCachedCreds").CurrentValue
switch($GatewayUsage)
{
"0" { $ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\GatewaySettings\GatewayUsage' -Value '0'"}
"1" { $ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\GatewaySettings\GatewayUsage' -Value '1' -GatewayName '$GatewayName' -GatewayAuthMode '$GatewayAuthMode' -GatewayUseCachedCreds '$GatewayUseCachedCreds'"}
"2" { $ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\GatewaySettings\GatewayUsage' -Value '2' -GatewayName '$GatewayName' -GatewayAuthMode '$GatewayAuthMode' -GatewayUseCachedCreds '$GatewayUseCachedCreds'"}
"3" { $ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\GatewaySettings\GatewayUsage' -Value '3'"}
}
$Pools = [String[]]($Pools) + [String[]]("PersonalVirtualDesktops")
foreach($Farm in $Pools)
{
if($Farm -ne "PersonalVirtualDesktops")
{
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\DisplayName").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$Farm\DisplayName' -Value '$Val'"
}
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\ShowInWebAccess").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$Farm\ShowInWebAccess' -Value '$Val'"
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\EnableSaveDelay").CurrentValue
if($Val -eq "1")
{
$SaveDelay = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\SaveDelay").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$Farm\EnableSaveDelay' -Value '1' -SaveDelay '$SaveDelay'"
}
else
{
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$Farm\EnableSaveDelay' -Value '0'"
}
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\ColorDepth").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\ColorDepth' -Value '$Val'"
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\AllowFontSmoothing").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\AllowFontSmoothing' -Value '$Val'"
$Val = IsNotNull "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\CustomRDPSettings"
if($Val)
{
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\CustomRDPSettings' -Value '$Val'"
}
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\UseAllMonitors").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\UseAllMonitors' -Value '$Val'"
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\DeviceRedirectionSettings\DiskdriveRedirection").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\DeviceRedirectionSettings\DiskdriveRedirection' -Value '$Val'"
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\DeviceRedirectionSettings\PrinterRedirection").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\DeviceRedirectionSettings\PrinterRedirection' -Value '$Val'"
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\DeviceRedirectionSettings\ClipboardRedirection").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\DeviceRedirectionSettings\ClipboardRedirection' -Value '$Val'"
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\DeviceRedirectionSettings\PnPDeviceRedirection").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$Farm\RDPSettings\DeviceRedirectionSettings\PnPDeviceRedirection' -Value '$Val'"
$Val = (Get-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($Farm)\RDPSettings\DeviceRedirectionSettings\SmartCardRedirection").CurrentValue
$ScriptBlockLines += "Set-Item -Path 'RDS:\ConnectionBroker\VirtualDesktops\Pools\$Farm\RDPSettings\DeviceRedirectionSettings\SmartCardRedirection' -Value '$Val'"
}
$Dict.Add("ScriptBlock" , $ScriptBlockLines)
$Dict
}
#$ScriptBlockLines = [String[]](Invoke-MyCommand $ReferenceNode $ScriptBlock)
$RetunDictionary = [Object[]](Invoke-MyCommand $ReferenceNode $ScriptBlock)
$ScriptBlockLines = $null
$RDVHostServers = $null
if( $RetunDictionary )
{
$RetunDictionary = $RetunDictionary[0]
if($RetunDictionary.ContainsKey("ScriptBlock"))
{
$ScriptBlockLines = [String[]]($RetunDictionary["ScriptBlock"])
}
if($RetunDictionary.ContainsKey("RDVHostServers"))
{
$RDVHostServers = [String[]]($RetunDictionary["RDVHostServers"])
}
}
if(!$ScriptBlockLines)
{
Print-Error "Could not fetch data from 'ReferenceNode: $ReferenceNode'! Exiting..!!"
}
if($RDVHostServers)
{
foreach($HServer in $RDVHostServers)
{
if( -not (WMIPing-Comp $HServer) )
{
Print-Error "Could not connect to the RDVHostServer '$HServer'.Exiting..!!"
}
}
}
$ConfiguredRedirector = $null
if( $RetunDictionary.ContainsKey("Redirector") )
{
$ConfiguredRedirector = [String]($RetunDictionary["Redirector"])
}
$ScriptBlock = {
#Use RDS provider to remove the existing entries if any.
Import-Module -Name RemoteDesktopServices -ErrorAction Stop
Remove-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\RDVHostServers\*" -Credential $args[2] -Recurse -Force
Remove-Item -Path "RDS:\ConnectionBroker\WebAccessComputers\*" -Recurse -Force
Remove-Item -Path "RDS:\ConnectionBroker\RemoteAppSources\*" -Recurse -Force
foreach( $Pool in (Get-ChildItem -Path RDS:\ConnectionBroker\VirtualDesktops\Pools) )
{
$PoolName = $Pool.Name
if($PoolName -ne "PersonalVirtualDesktops")
{
Remove-Item -Path "RDS:\ConnectionBroker\VirtualDesktops\Pools\$($PoolName)" -Recurse -Force
}
}
$RDSAssembly = [System.Reflection.Assembly]::LoadFrom("$pshome\modules\remotedesktopservices\tspsengine.dll")
$ConnBrokerComps = [Microsoft.TerminalServices.PSEngine.UserGroupHelper]::ListMembers("Session Broker Computers")
if($ConnBrokerComps)
{
foreach($comp in $ConnBrokerComps)
{
[Microsoft.TerminalServices.PSEngine.UserGroupHelper]::RemoveMember("Session Broker Computers",$comp) | Out-Null
}
}
#Return 'True' if all the operations succeed!
$TRUE
}
$ScriptBlockLines = [String[]]("Import-Module -Name RemoteDesktopServices -ErrorAction Stop") + $ScriptBlockLines
$ScriptBlockLinesJoined = [String]::Join( [Environment]::NewLine,$ScriptBlockLines )
$ScriptBlockImported = [System.Management.Automation.ScriptBlock]::Create($ScriptBlockLinesJoined)
Write-Verbose "The following script would be run on all nodes: $([Environment]::NewLine)$ScriptBlockImported"
Write-Verbose "Redirector: $ConfiguredRedirector"
Import-Module -Name FailOverClusters -ErrorAction Stop
foreach($Comp in $Node)
{
#Make the Cb cluster service active on the current node
(Move-ClusterGroup -Name $NonFqdnClientAccessName -Node $Comp -ErrorAction Stop) > $null
$ArgsList = @($NonFqdnClientAccessName, $Comp, $Credential)
$RetValue = Invoke-MyCommand $Comp $ScriptBlock $ArgsList
if($RetValue)
{
$ArgsList = @($Credential)
Invoke-MyCommand $Comp $ScriptBlockImported $ArgsList
Start-Sleep 30
}
else
{
Write-Error "Could not apply the desired settings on node '$Comp'"
}
}
if($RDVHostServers)
{
Set-RDVHostsSBName $ClientAccessName $RDVHostServers
}
(Move-ClusterGroup -Name $NonFqdnClientAccessName -Node (Get-HostName $FALSE) -ErrorAction Stop) > $null
Write-Host "The settings are succefully replicated across nodes of the Connection Broker Fail-Over cluster."
Platforms
For online peer support, join
The Official Scripting Guys Forum!
To provide feedback or report bugs in sample scripts, please start a new discussion on the Discussions tab for this script.
Disclaimer
The sample scripts are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims 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 Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts 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 sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.
Be the first to create a discussion.
|