DSCResources/MSFT_xComputer/MSFT_xComputer.psm1
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope = 'Function')] param ( ) Import-Module -Name (Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) ` -ChildPath 'CommonResourceHelper.psm1') $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_xComputer' <# .SYNOPSIS Gets the current state of the computer. .PARAMETER Name The desired computer name. .PARAMETER DomainName The name of the domain to join. .PARAMETER JoinOU The distinguished name of the organizational unit that the computer account will be created in. .PARAMETER Credential Credential to be used to join a domain. .PARAMETER UnjoinCredential Credential to be used to leave a domain. .PARAMETER WorkGroupName The name of the workgroup. .PARAMETER Description The value assigned here will be set as the local computer description. #> function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [ValidateLength(1, 15)] [ValidateScript( {$_ -inotmatch '[\/\\:*?"<>|]' })] [System.String] $Name, [Parameter()] [System.String] $DomainName, [Parameter()] [System.String] $JoinOU, [Parameter()] [System.Management.Automation.PSCredential] $Credential, [Parameter()] [System.Management.Automation.PSCredential] $UnjoinCredential, [Parameter()] [System.String] $WorkGroupName, [Parameter()] [System.String] $Description ) Write-Verbose -Message ($script:localizedData.GettingComputerStateMessage -f $Name) $convertToCimCredential = New-CimInstance ` -ClassName MSFT_Credential ` -Property @{ Username = [System.String] $Credential.UserName Password = [System.String] $null } ` -Namespace root/microsoft/windows/desiredstateconfiguration ` -ClientOnly $convertToCimUnjoinCredential = New-CimInstance ` -ClassName MSFT_Credential ` -Property @{ Username = [System.String] $UnjoinCredential.UserName Password = [System.String] $null } ` -Namespace root/microsoft/windows/desiredstateconfiguration ` -ClientOnly $returnValue = @{ Name = $env:COMPUTERNAME DomainName = Get-ComputerDomain JoinOU = $JoinOU CurrentOU = Get-ComputerOU Credential = [ciminstance] $convertToCimCredential UnjoinCredential = [ciminstance] $convertToCimUnjoinCredential WorkGroupName = (Get-CimInstance -Class 'Win32_ComputerSystem').Workgroup Description = (Get-CimInstance -Class 'Win32_OperatingSystem').Description } return $returnValue } <# .SYNOPSIS Sets the current state of the computer. .PARAMETER Name The desired computer name. .PARAMETER DomainName The name of the domain to join. .PARAMETER JoinOU The distinguished name of the organizational unit that the computer account will be created in. .PARAMETER Credential Credential to be used to join a domain. .PARAMETER UnjoinCredential Credential to be used to leave a domain. .PARAMETER WorkGroupName The name of the workgroup. .PARAMETER Description The value assigned here will be set as the local computer description. #> function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateLength(1, 15)] [ValidateScript( {$_ -inotmatch '[\/\\:*?"<>|]' })] [System.String] $Name, [Parameter()] [System.String] $DomainName, [Parameter()] [System.String] $JoinOU, [Parameter()] [System.Management.Automation.PSCredential] $Credential, [Parameter()] [System.Management.Automation.PSCredential] $UnjoinCredential, [Parameter()] [System.String] $WorkGroupName, [Parameter()] [System.String] $Description ) Write-Verbose -Message ($script:localizedData.SettingComputerStateMessage -f $Name) Assert-DomainOrWorkGroup -DomainName $DomainName -WorkGroupName $WorkGroupName if ($Name -eq 'localhost') { $Name = $env:COMPUTERNAME } if ($PSBoundParameters.ContainsKey('Description')) { Write-Verbose -Message ($script:localizedData.SettingComputerDescriptionMessage -f $Description) $win32OperatingSystemCimInstance = Get-CimInstance -ClassName Win32_OperatingSystem $win32OperatingSystemCimInstance.Description = $Description Set-CimInstance -InputObject $win32OperatingSystemCimInstance } if ($Credential) { if ($DomainName) { if ($DomainName -eq (Get-ComputerDomain)) { # Rename the computer, but stay joined to the domain. Rename-Computer -NewName $Name -DomainCredential $Credential -Force Write-Verbose -Message ($script:localizedData.RenamedComputerMessage -f $Name) } else { if ($Name -ne $env:COMPUTERNAME) { # Rename the computer, and join it to the domain. if ($UnjoinCredential) { Add-Computer ` -DomainName $DomainName ` -Credential $Credential ` -NewName $Name ` -UnjoinDomainCredential $UnjoinCredential ` -Force } else { if ($JoinOU) { Add-Computer ` -DomainName $DomainName ` -Credential $Credential ` -NewName $Name ` -OUPath $JoinOU ` -Force } else { Add-Computer ` -DomainName $DomainName ` -Credential $Credential ` -NewName $Name ` -Force } } Write-Verbose -Message ($script:localizedData.RenamedComputerAndJoinedDomainMessage -f $Name,$DomainName) } else { # Same computer name, and join it to the domain. if ($UnjoinCredential) { Add-Computer ` -DomainName $DomainName ` -Credential $Credential ` -UnjoinDomainCredential $UnjoinCredential ` -Force } else { if ($JoinOU) { Add-Computer ` -DomainName $DomainName ` -Credential $Credential ` -OUPath $JoinOU ` -Force } else { Add-Computer ` -DomainName $DomainName ` -Credential $Credential ` -Force } } Write-Verbose -Message ($script:localizedData.JoinedDomainMessage -f $DomainName) } } } elseif ($WorkGroupName) { if ($WorkGroupName -eq (Get-CimInstance -Class 'Win32_ComputerSystem').Workgroup) { # Rename the computer, but stay in the same workgroup. Rename-Computer ` -NewName $Name Write-Verbose -Message ($script:localizedData.RenamedComputerMessage -f $Name) } else { if ($Name -ne $env:COMPUTERNAME) { # Rename the computer, and join it to the workgroup. Add-Computer ` -NewName $Name ` -Credential $Credential ` -WorkgroupName $WorkGroupName ` -Force Write-Verbose -Message ($script:localizedData.RenamedComputerAndJoinedWorkgroupMessage -f $Name,$WorkGroupName) } else { # Same computer name, and join it to the workgroup. Add-Computer ` -WorkGroupName $WorkGroupName ` -Credential $Credential ` -Force Write-Verbose -Message ($script:localizedData.JoinedWorkgroupMessage -f $WorkGroupName) } } } elseif ($Name -ne $env:COMPUTERNAME) { if (Get-ComputerDomain) { Rename-Computer ` -NewName $Name ` -DomainCredential $Credential ` -Force Write-Verbose -Message ($script:localizedData.RenamedComputerMessage -f $Name) } else { Rename-Computer ` -NewName $Name ` -Force Write-Verbose -Message ($script:localizedData.RenamedComputerMessage -f $Name) } } } else { if ($DomainName) { New-InvalidArgumentException ` -Message ($script:localizedData.CredentialsNotSpecifiedError) ` -ArgumentName 'Credentials' } if ($WorkGroupName) { if ($WorkGroupName -eq (Get-CimInstance -Class 'Win32_ComputerSystem').Workgroup) { # Same workgroup, new computer name Rename-Computer ` -NewName $Name ` -Force Write-Verbose -Message ($script:localizedData.RenamedComputerMessage -f $Name) } else { if ($name -ne $env:COMPUTERNAME) { # New workgroup, new computer name Add-Computer ` -WorkgroupName $WorkGroupName ` -NewName $Name Write-Verbose -Message ($script:localizedData.RenamedComputerAndJoinedWorkgroupMessage -f $Name,$WorkGroupName) } else { # New workgroup, same computer name Add-Computer ` -WorkgroupName $WorkGroupName Write-Verbose -Message ($script:localizedData.JoinedWorkgroupMessage -f $WorkGroupName) } } } else { if ($Name -ne $env:COMPUTERNAME) { Rename-Computer ` -NewName $Name Write-Verbose -Message ($script:localizedData.RenamedComputerMessage -f $Name) } } } $global:DSCMachineStatus = 1 } <# .SYNOPSIS Tests the current state of the computer. .PARAMETER Name The desired computer name. .PARAMETER DomainName The name of the domain to join. .PARAMETER JoinOU The distinguished name of the organizational unit that the computer account will be created in. .PARAMETER Credential Credential to be used to join a domain. .PARAMETER UnjoinCredential Credential to be used to leave a domain. .PARAMETER WorkGroupName The name of the workgroup. .PARAMETER Description The value assigned here will be set as the local computer description. #> function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateLength(1, 15)] [ValidateScript( {$_ -inotmatch '[\/\\:*?"<>|]' })] [System.String] $Name, [Parameter()] [System.String] $JoinOU, [Parameter()] [System.Management.Automation.PSCredential] $Credential, [Parameter()] [System.Management.Automation.PSCredential] $UnjoinCredential, [Parameter()] [System.String] $DomainName, [Parameter()] [System.String] $WorkGroupName, [Parameter()] [System.String] $Description ) Write-Verbose -Message ($script:localizedData.TestingComputerStateMessage -f $Name) if (($Name -ne 'localhost') -and ($Name -ne $env:COMPUTERNAME)) { return $false } if ($PSBoundParameters.ContainsKey('Description')) { Write-Verbose -Message ($script:localizedData.CheckingComputerDescriptionMessage -f $Description) if ($Description -ne (Get-CimInstance -Class 'Win32_OperatingSystem').Description) { return $false } } Assert-DomainOrWorkGroup -DomainName $DomainName -WorkGroupName $WorkGroupName if ($DomainName) { if (-not ($Credential)) { New-InvalidArgumentException ` -Message ($script:localizedData.CredentialsNotSpecifiedError) ` -ArgumentName 'Credentials' } try { Write-Verbose -Message ($script:localizedData.CheckingDomainMemberMessage -f $DomainName) if ($DomainName.Contains('.')) { $getComputerDomainParameters = @{ netbios = $false } } else { $getComputerDomainParameters = @{ netbios = $true } } return ($DomainName -eq (Get-ComputerDomain @getComputerDomainParameters)) } catch { Write-Verbose -Message ($script:localizedData.CheckingNotDomainMemberMessage) return $false } } elseif ($WorkGroupName) { Write-Verbose -Message ($script:localizedData.CheckingWorkgroupMemberMessage -f $WorkGroupName) return ($WorkGroupName -eq (Get-CimInstance -Class 'Win32_ComputerSystem').Workgroup) } else { # No Domain or Workgroup specified and computer name is correct return $true } } <# .SYNOPSIS Throws an exception if both the domain name and workgroup name is set. .PARAMETER DomainName The name of the domain to join. .PARAMETER WorkGroupName The name of the workgroup. #> function Assert-DomainOrWorkGroup { [CmdletBinding()] param ( [Parameter()] [System.String] $DomainName, [Parameter()] [System.String] $WorkGroupName ) if ($DomainName -and $WorkGroupName) { New-InvalidOperationException ` -Message ($script:localizedData.DomainNameAndWorkgroupNameError) } } <# .SYNOPSIS Returns the domain the computer is joined to. .PARAMETER NetBios Specifies if the NetBIOS name is returned instead of the fully qualified domain name. #> function Get-ComputerDomain { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter()] [Switch] $NetBios ) try { if ($NetBios) { $domainName = $ENV:USERDOMAIN } else { $domainName = ([System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain()).Name } return $domainName } catch [System.Management.Automation.MethodInvocationException] { Write-Verbose -Message ($script:localizedData.ComputerNotInDomainMessage) } } <# .SYNOPSIS Gets the organisation unit in the domain that the computer account exists in. #> function Get-ComputerOU { [CmdletBinding()] param ( ) $ou = $null if (Get-ComputerDomain) { $dn = $null $dn = ([adsisearcher]"(&(objectCategory=computer)(objectClass=computer)(cn=$env:COMPUTERNAME))").FindOne().Properties.distinguishedname $ou = $dn -replace '^(CN=.*?(?<=,))', '' } return $ou } Export-ModuleMember -Function *-TargetResource |