Extra functions moved to NotCoreFunctions.ps1 file in order to remove them in the future
This commit is contained in:
parent
cae193a3b3
commit
8dc615b041
@ -11,12 +11,14 @@ trap { Stop-Execution $_ }
|
|||||||
|
|
||||||
Export-ModuleMember -Function * -Alias *
|
Export-ModuleMember -Function * -Alias *
|
||||||
|
|
||||||
|
<#
|
||||||
if ($__ImportModulesExplicitely) {
|
if ($__ImportModulesExplicitely) {
|
||||||
foreach ($Module in $__RequiredModules) {
|
foreach ($Module in $__RequiredModules) {
|
||||||
Write-Log "Importing module '$Module' ..."
|
Write-Log "Importing module '$Module' ..."
|
||||||
Import-Module -Name "$Module" -ErrorAction "$__ImportModulesErrorAction"
|
Import-Module -Name "$Module" -ErrorAction "$__ImportModulesErrorAction"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#>
|
||||||
|
|
||||||
Write-Log "Module loaded from '$PsScriptRoot'"
|
Write-Log "Module loaded from '$PsScriptRoot'"
|
||||||
|
|
||||||
|
@ -140,342 +140,14 @@ $($ErrorRecord.ScriptStackTrace.ToString())
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Set-ComputerName {
|
|
||||||
param (
|
|
||||||
[String] $Name
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Rename the computer
|
|
||||||
if ($Name -ne "") {
|
|
||||||
if (Test-ComputerName -ComputerName $Name) {
|
|
||||||
Stop-Execution -Success -ExitString "Computer name already configured"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Log "Renaming computer to '$Name'"
|
|
||||||
|
|
||||||
Rename-Computer -NewName $NewName -Force -ErrorAction Stop
|
|
||||||
|
|
||||||
Stop-Execution -ExitCode 3010 -ExitString "Please restart the computer now"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Test-ComputerName {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Test if computer name is set, and the computer belongs to specified domain / workgroup.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
Function tests the following conditions:
|
|
||||||
* the computer name is equal to the provided one
|
|
||||||
* the computer is a part of domain
|
|
||||||
* the computer belongs to the specified domain
|
|
||||||
* the computer belongs to the specified workgroup
|
|
||||||
|
|
||||||
Multiple checks are logically ANDed.
|
|
||||||
#>
|
|
||||||
[CmdletBinding()]
|
|
||||||
param (
|
|
||||||
[String] $ComputerName,
|
|
||||||
[String] $DomainName,
|
|
||||||
[String] $WorkgroupName,
|
|
||||||
[Switch] $PartOfDomain
|
|
||||||
)
|
|
||||||
process {
|
|
||||||
$ComputerSystem = Get-WmiObject Win32_ComputerSystem
|
|
||||||
|
|
||||||
if (($ComputerName -ne "") -and ($ComputerSystem.Name -ne "$ComputerName")) {
|
|
||||||
Write-Error "ComputerName is not equal to '$ComputerName'"
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($DomainName -ne "") -and ($ComputerSystem.Domain -ne "$DomainName")) {
|
|
||||||
Write-Error "DomainName is not equal to '$DomainName'"
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($WorkgroupName -ne "") -and ($ComputerSystem.Workgroup -ne "$WorkgroupName")) {
|
|
||||||
Write-Error "WorkgroupName is not equal to '$WorkgroupName'"
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($PartOfDOmain -eq $true) -and ($ComputerSystem.PartOfDomain -eq $false)) {
|
|
||||||
Write-Error "Computer is not the part of any domain."
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
return $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Show-EthernetNetworkAdapters {
|
|
||||||
Get-WmiObject Win32_NetworkAdapter -Filter "PhysicalAdapter = 'True' AND AdapterTypeId = '0'" |
|
|
||||||
Select-Object 'Index','MACAddress','NetConnectionId'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Set-NetworkAdapterConfiguration {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Set network adapter configuration.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
PS> Set-NetworkAdapterConfiguration -MACAddress aa:bb:cc:dd:ee:ff -Auto
|
|
||||||
|
|
||||||
Convert "dynamic" parameters (DHCP) to "static" (manual) for network adapter with MAC address aa:bb:cc:dd:ee:ff
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
PS> Set-NetworkAdapterConfiguration -MACAddress aa:bb:cc:dd:ee:ff -DNSServer "192.168.0.1","192.168.0.2"
|
|
||||||
|
|
||||||
Configure DNS servers list for network adapter with MAC address aa:bb:cc:dd:ee:ff
|
|
||||||
|
|
||||||
#>
|
|
||||||
param (
|
|
||||||
[String] $MACAddress = "",
|
|
||||||
|
|
||||||
[Parameter(ParameterSetName="ManualConfig")]
|
|
||||||
[String] $IPAddress = "",
|
|
||||||
|
|
||||||
[Parameter(ParameterSetName="ManualConfig")]
|
|
||||||
[String] $IPNetmask = "",
|
|
||||||
|
|
||||||
[Parameter(ParameterSetName="ManualConfig")]
|
|
||||||
[String[]] $IPGateway = @(),
|
|
||||||
|
|
||||||
[Parameter(ParameterSetName="ManualConfig")]
|
|
||||||
[String[]] $DNSServer = @(),
|
|
||||||
|
|
||||||
[Parameter(ParameterSetName="ManualConfig")]
|
|
||||||
[Switch] $FirstAvailable,
|
|
||||||
|
|
||||||
[String] $Name = "",
|
|
||||||
|
|
||||||
[Parameter(ParameterSetName="AutoConfig",Mandatory=$true)]
|
|
||||||
[Switch] $Auto,
|
|
||||||
|
|
||||||
[Parameter(ParameterSetName="AutoConfig")]
|
|
||||||
[Switch] $All
|
|
||||||
)
|
|
||||||
|
|
||||||
Write-Log "Configuring network adapter(s) ..."
|
|
||||||
|
|
||||||
:SetIPAddress switch($PSCmdlet.ParameterSetName) {
|
|
||||||
"AutoConfig" {
|
|
||||||
Write-Log "'auto' mode"
|
|
||||||
|
|
||||||
$IPv4RegExp = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
|
|
||||||
|
|
||||||
if ($All -eq $true) {
|
|
||||||
$Filter = { $_.AdapterTypeId -eq 0 }
|
|
||||||
$Name = ""
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$Filter = { $_.MACAddress -eq $MACAddress }
|
|
||||||
}
|
|
||||||
|
|
||||||
Get-WmiObject Win32_NetworkAdapter |
|
|
||||||
Where-Object $Filter |
|
|
||||||
ForEach-Object {
|
|
||||||
$NetworkAdapter = $_
|
|
||||||
$AdapterConfig = Get-WmiObject Win32_NetworkAdapterConfiguration |
|
|
||||||
Where-Object { $_.Index -eq $NetworkAdapter.DeviceId }
|
|
||||||
|
|
||||||
Write-Log "Configuring '$($NetworkAdapter.Name)' ..."
|
|
||||||
|
|
||||||
for ($i = 0; $i -lt $AdapterConfig.IPAddress.Length; $i++) {
|
|
||||||
if ($AdapterConfig.IPAddress[$i] -match $IPv4RegExp) {
|
|
||||||
$IPAddress = $AdapterConfig.IPAddress[$i]
|
|
||||||
$IPNetmask = $AdapterConfig.IPSubnet[$i]
|
|
||||||
$IPGateway = $AdapterConfig.DefaultIPGateway
|
|
||||||
$DNSServer = $AdapterConfig.DNSServerSearchOrder
|
|
||||||
|
|
||||||
Write-Log "Setting IP address ($IPAddress), netmask ($IPNetmask) ..."
|
|
||||||
$AdapterConfig.EnableStatic($IPAddress, $IPNetmask) | Out-Null
|
|
||||||
|
|
||||||
Write-Log "Setting default gateways ($IPGateway) ..."
|
|
||||||
$AdapterConfig.SetGateways($IPGateway) | Out-Null
|
|
||||||
|
|
||||||
Write-Log "Setting DNS servers ($DNSServer) ..."
|
|
||||||
$AdapterConfig.SetDNSServerSearchOrder($DNSServer) | Out-Null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Log "'$($NetworkAdapter.Name)' configured"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"ManualConfig" {
|
|
||||||
Write-Log "'manual' mode"
|
|
||||||
if ( $FirstAvailable ) {
|
|
||||||
Write-Log "Selecting first available network adapter ..."
|
|
||||||
$NetworkAdapter = Get-WmiObject Win32_NetworkAdapter |
|
|
||||||
Where-Object { $_.AdapterTypeId -eq 0 } |
|
|
||||||
Select-Object -First 1
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$NetworkAdapter = Get-WmiObject Win32_NetworkAdapter |
|
|
||||||
Where-Object { $_.MACAddress -eq $MACAddress }
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $NetworkAdapter -eq $null ) {
|
|
||||||
Write-LogError "Network adapter with MAC = '$MACAddress' not found."
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
$AdapterConfig = Get-WmiObject Win32_NetworkAdapterConfiguration |
|
|
||||||
Where-Object { $_.Index -eq $NetworkAdapter.DeviceId }
|
|
||||||
|
|
||||||
if (($IPAddress -ne "") -and ($IPNetmask -ne "")) {
|
|
||||||
Write-Log "Configuring IP address / netmask for '$($NetworkAdapter.Name)' ..."
|
|
||||||
|
|
||||||
<#
|
|
||||||
for ($i = 0; $i -lt $AdapterConfig.IPAddress.Length; $i++)
|
|
||||||
{
|
|
||||||
if (($AdapterConfig.IPAddress[$i] -eq $IPAddress) -and ($AdapterConfig.IPSubnet[$i] -eq $IPNetmask))
|
|
||||||
{
|
|
||||||
Write-Log "There is an adapter with required configuration."
|
|
||||||
break SetIPAddress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#>
|
|
||||||
Write-Log "Setting IP address $IPAddress, netmask $IPNetmask"
|
|
||||||
$AdapterConfig.EnableStatic("$IPAddress", "$IPNetmask") | Out-Null
|
|
||||||
|
|
||||||
Write-Log "IP address configured."
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($IPGateway.Count -gt 0) {
|
|
||||||
Write-Log "Configuring IP gateway for '$($NetworkAdapter.Name)' ..."
|
|
||||||
|
|
||||||
$AdapterConfig.SetGateways($IPGateway) | Out-Null
|
|
||||||
|
|
||||||
Write-Log "IP gateway configured."
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($DNSServer.Count -gt 0) {
|
|
||||||
Write-Log "Configuring DNS server(s) for '$($NetworkAdapter.Name)' ..."
|
|
||||||
|
|
||||||
$AdapterConfig.SetDNSServerSearchOrder($DNSServer) | Out-Null
|
|
||||||
|
|
||||||
Write-Log "DNS configured."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Name -ne "") {
|
|
||||||
Write-Log "Changing adapter name '$($NetworkAdapter.NetConnectionId)' --> '$Name'"
|
|
||||||
$NetworkAdapter.NetConnectionId = "$Name"
|
|
||||||
$NetworkAdapter.Put() | Out-Null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Test-WmiReturnValue {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Check the ReturnValue property of the object provided.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
This funciton checks if ReturnValue property is equal to 0.
|
|
||||||
|
|
||||||
=== TODO ===
|
|
||||||
If it is not, then funtion should try to provide desctiption for the error code based on the WMI object type.
|
|
||||||
WMI object type must be provided explicitely.
|
|
||||||
#>
|
|
||||||
param (
|
|
||||||
[Parameter(ValueFromPipeline=$true,Mandatory=$true)]
|
|
||||||
$InputObject,
|
|
||||||
[String] $Type = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
try {
|
|
||||||
$ReturnValue = $InputObject.ReturnValue
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
throw "Property 'ReturnValue' not found on this object"
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ReturnValue -eq 0) {
|
|
||||||
Write-Log "WMI operation completed successfully"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw "Operation failed with status code = $ReturnValue"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Add-WindowsFeatureWrapper {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Wraps Install-WindowsFeature function.
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
This function adds some logic to multiple feature installation.
|
|
||||||
|
|
||||||
It fails if any of required features fails.
|
|
||||||
|
|
||||||
It reports that reboot required if it is required, or restarts the computer.
|
|
||||||
#>
|
|
||||||
param (
|
|
||||||
[Parameter(Mandatory=$true)]
|
|
||||||
[String[]] $Name,
|
|
||||||
[Switch] $IncludeManagementTools,
|
|
||||||
[Switch] $AllowRestart,
|
|
||||||
[Switch] $NotifyRestart
|
|
||||||
)
|
|
||||||
|
|
||||||
$RestartNeeded = $false
|
|
||||||
|
|
||||||
foreach ($Feature in $Name) {
|
|
||||||
Write-Log "Installing feature '$Feature' ..."
|
|
||||||
$Action = Install-WindowsFeature `
|
|
||||||
-Name $Feature `
|
|
||||||
-IncludeManagementTools:$IncludeManagementTools `
|
|
||||||
-ErrorAction Stop
|
|
||||||
|
|
||||||
if ($Action.Success -eq $true) {
|
|
||||||
if ($Action.FeatureResult.RestartNeeded -eq $true) {
|
|
||||||
Write-LogWarning "Restart required"
|
|
||||||
$RestartNeeded = $true
|
|
||||||
}
|
|
||||||
Write-Log "Feature '$Feature' installed successfully"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Stop-Execution "Failed to install feature '$Feature'"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($RestartNeeded) {
|
|
||||||
Write-Log "Restart required to finish feature(s) installation."
|
|
||||||
if ($AllowRestart) {
|
|
||||||
Write-Log "Restarting computer ..."
|
|
||||||
Restart-Computer -Force
|
|
||||||
}
|
|
||||||
elseif ($NotifyRestart) {
|
|
||||||
Stop-Execution -ExitCode 3010 -ExitString "Please restart the computer now."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Get-PasswordAsSecureString {
|
Function Get-PasswordAsSecureString {
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Convert to / request password as secure string.
|
Convert to / request password as secure string.
|
||||||
#>
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
param (
|
param (
|
||||||
[String] $Password,
|
[String] $Password = "",
|
||||||
[String] $Prompt = "Please enter password"
|
[String] $Prompt = "Please enter password"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -494,6 +166,7 @@ Function New-Credential {
|
|||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Create new creadential object with username and password provided.
|
Create new creadential object with username and password provided.
|
||||||
#>
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
param (
|
param (
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[String] $UserName,
|
[String] $UserName,
|
||||||
@ -507,43 +180,6 @@ Create new creadential object with username and password provided.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Join-Domain {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Executes "Join domain" action.
|
|
||||||
#>
|
|
||||||
param (
|
|
||||||
[String] $DomainName,
|
|
||||||
[String] $UserName,
|
|
||||||
[String] $Password,
|
|
||||||
[Switch] $AllowRestart
|
|
||||||
)
|
|
||||||
|
|
||||||
$Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password
|
|
||||||
|
|
||||||
# Add the computer to the domain
|
|
||||||
if (Test-ComputerName -DomainName $DomainName) {
|
|
||||||
#Stop-Execution -Success -ExitString "Computer already joined to domain '$DomainName'"
|
|
||||||
Write-LogWarning "Computer already joined to domain '$DomainName'"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Log "Joining computer to domain '$DomainName' ..."
|
|
||||||
|
|
||||||
Add-Computer -DomainName $DomainName -Credential $Credential -Force -ErrorAction Stop
|
|
||||||
|
|
||||||
if ($AllowRestart) {
|
|
||||||
Write-Log "Restarting computer ..."
|
|
||||||
Restart-Computer -Force
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#Stop-Execution -ExitCode 3010 -ExitString "Please restart the computer now."
|
|
||||||
Write-Log "Please restart the computer now."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Invoke-WMSettingsChange {
|
Function Invoke-WMSettingsChange {
|
||||||
if (-not ("win32.nativemethods" -as [type])) {
|
if (-not ("win32.nativemethods" -as [type])) {
|
||||||
# Import SendMessageTimeout from Win32
|
# Import SendMessageTimeout from Win32
|
||||||
@ -570,43 +206,14 @@ public static extern IntPtr SendMessageTimeout(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Set-AutoLogonCredentials {
|
|
||||||
param (
|
|
||||||
[String] $DomainName,
|
|
||||||
[String] $UserName,
|
|
||||||
[String] $Password
|
|
||||||
)
|
|
||||||
|
|
||||||
$KeyName = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
|
||||||
|
|
||||||
if ($DomainName -ne "") {
|
|
||||||
$UserName = "$DomainName\$UserName"
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Log "Setting AutoLogon credentials ..."
|
|
||||||
try {
|
|
||||||
[Microsoft.Win32.Registry]::SetValue($KeyName, "DefaultUserName", "$UserName", [Microsoft.Win32.RegistryValueKind]::String)
|
|
||||||
[Microsoft.Win32.Registry]::SetValue($KeyName, "DefaultPassword", "$Password", [Microsoft.Win32.RegistryValueKind]::String)
|
|
||||||
[Microsoft.Win32.Registry]::SetValue($KeyName, "AutoAdminLogon", "1", [Microsoft.Win32.RegistryValueKind]::String)
|
|
||||||
[Microsoft.Win32.Registry]::SetValue($KeyName, "ForceAutoLogon", "1", [Microsoft.Win32.RegistryValueKind]::String)
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-LogError "FAILED"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Log "SUCCESS"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Start-Program {
|
Function Start-Program {
|
||||||
param (
|
param (
|
||||||
[String] $FilePath,
|
[String] $FilePath,
|
||||||
[String[]] $ArgumentList = @(' '),
|
[String[]] $ArgumentList = @(' '),
|
||||||
[Int] $Timeout = 0,
|
[Int] $Timeout = 0,
|
||||||
[Switch] $NoWait,
|
[Switch] $NoWait,
|
||||||
[Switch] $PassThru
|
[Switch] $PassThru,
|
||||||
|
[String] $WorkingDir = (Get-Location).ProviderPath
|
||||||
)
|
)
|
||||||
|
|
||||||
trap {
|
trap {
|
||||||
@ -623,6 +230,7 @@ Function Start-Program {
|
|||||||
$ProcessStartInfo.RedirectStandardOutput = $true
|
$ProcessStartInfo.RedirectStandardOutput = $true
|
||||||
$ProcessStartInfo.RedirectStandardError = $true
|
$ProcessStartInfo.RedirectStandardError = $true
|
||||||
$ProcessStartInfo.UseShellExecute = $false
|
$ProcessStartInfo.UseShellExecute = $false
|
||||||
|
$ProcessStartInfo.WorkingDirectory = $WorkingDir
|
||||||
|
|
||||||
$Process = [System.Diagnostics.Process]::Start($ProcessStartInfo)
|
$Process = [System.Diagnostics.Process]::Start($ProcessStartInfo)
|
||||||
|
|
||||||
@ -643,16 +251,23 @@ Function Start-Program {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Log ( "STDOUT:`n{0}" -f $Process.StandardOutput.ReadToEnd() )
|
$ProcessResult = New-Object PSObject |
|
||||||
|
Add-Member -Name "ExitCode" -MemberType NoteProperty -Value $Process.ExitCode -PassThru |
|
||||||
|
Add-Member -Name "StdOut" -MemberType NoteProperty -Value $Process.StandardOutput.ReadToEnd() -PassThru |
|
||||||
|
Add-Member -Name "StdErr" -MemberType NoteProperty -Value $Process.StandardError.ReadToEnd() -PassThru
|
||||||
|
|
||||||
|
$Process = $null
|
||||||
|
|
||||||
|
Write-Log ( "STDOUT:`n{0}" -f $ProcessResult.StdOut )
|
||||||
Write-Log ":STDOUT"
|
Write-Log ":STDOUT"
|
||||||
|
|
||||||
Write-Log ( "STDERR:`n{0}" -f $Process.StandardError.ReadToEnd() )
|
Write-Log ( "STDERR:`n{0}" -f $ProcessResult.StdErr )
|
||||||
Write-Log ":STDERR"
|
Write-Log ":STDERR"
|
||||||
|
|
||||||
Write-Log "Program has finished with exit code ($($Process.ExitCode))"
|
Write-Log "Program has finished with exit code ($($ProcessResult.ExitCode))"
|
||||||
|
|
||||||
if ($PassThru) {
|
if ($PassThru) {
|
||||||
return $Process
|
return $ProcessResult
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return $null
|
return $null
|
||||||
@ -662,6 +277,80 @@ New-Alias -Name Exec -Value Start-Program
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Backup-File {
|
||||||
|
param (
|
||||||
|
[String] $Path
|
||||||
|
)
|
||||||
|
|
||||||
|
$BackupFile = "$Path.bak"
|
||||||
|
|
||||||
|
if (-not [IO.File]::Exists($Path)) {
|
||||||
|
Write-LogError "Unable to backup file '$Path': file not exists."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([IO.File]::Exists($BackupFile)) {
|
||||||
|
try {
|
||||||
|
[IO.File]::Delete($BackupFile)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-LogError "Unable to delete existing .bak file '$BackupFile'."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Log "Backing up file '$Path' to '$BackupFile'"
|
||||||
|
[IO.File]::Copy($Path, $BackupFile, $true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Install-Module {
|
||||||
|
param (
|
||||||
|
[String] $InstallPath,
|
||||||
|
[String] $ModulePath,
|
||||||
|
[String] $ModuleName
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($ModuleName -eq "") {
|
||||||
|
if ($ModulePath -eq "") {
|
||||||
|
Stop-Execution -ExitString "Don't know which module should be installed."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ModuleName = $ModulePath.Split("\")[-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($InstallPath -eq "") {
|
||||||
|
Stop-Execution -ExitString "To install the module destination path must be provided."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Log "Installing the module to '$InstallPath'"
|
||||||
|
|
||||||
|
$NewModulePath = [IO.Path]::Combine($InstallPath, $ModuleName)
|
||||||
|
if ([IO.Directory]::Exists($NewModulePath)) {
|
||||||
|
[IO.Directory]::Delete($NewModulePath, $true)
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -Path $ModulePath -Destination $InstallPath -Recurse -Force -ErrorAction Stop
|
||||||
|
|
||||||
|
Update-PsModulePath -AddPath "$InstallPath"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Register-Module {
|
||||||
|
param (
|
||||||
|
[String] $ModulePath
|
||||||
|
)
|
||||||
|
$ModuleRoot = Split-Path -Path $ModulePath -Parent
|
||||||
|
Write-Log "Registering the module at '$ModuleRoot'"
|
||||||
|
Update-PsModulePath -AddPath "$ModuleRoot"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function Test-ModuleVersion {
|
function Test-ModuleVersion {
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
@ -697,172 +386,3 @@ Returned values:
|
|||||||
|
|
||||||
$ModuleVersion.CompareTo($RequiredVersion)
|
$ModuleVersion.CompareTo($RequiredVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Set-LocalUserPassword {
|
|
||||||
param (
|
|
||||||
[String] $UserName,
|
|
||||||
[String] $Password,
|
|
||||||
[Switch] $Force
|
|
||||||
)
|
|
||||||
|
|
||||||
trap { Stop-Execution $_ }
|
|
||||||
|
|
||||||
if ((Get-WmiObject Win32_UserAccount -Filter "LocalAccount = 'True' AND Name='$UserName'") -eq $null) {
|
|
||||||
throw "Unable to find local user account '$UserName'"
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Force) {
|
|
||||||
Write-Log "Changing password for user '$UserName' to '*****'" # :)
|
|
||||||
([ADSI] "WinNT://./$UserName").SetPassword($Password) | Out-Null
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-LogWarning "You are trying to change the password for the user '$UserName'. To do this please run the command again with -Force parameter."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Resolve-LdapDnsName {
|
|
||||||
param (
|
|
||||||
[String] $DomainName
|
|
||||||
)
|
|
||||||
|
|
||||||
Resolve-DNSName -Type "SRV" -Name "_ldap._tcp.dc._msdcs.$DomainName" |
|
|
||||||
Where-Object { $_.Type -eq "A" } |
|
|
||||||
Select-Object -Property Name,IPAddress
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Wait-LdapServerAvailable {
|
|
||||||
param (
|
|
||||||
[String] $DomainName,
|
|
||||||
[Int] $PingSeqCountThreshold = 10,
|
|
||||||
[Int] $PingSeqPerHostThreshold = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
$LdapServerList = @( Resolve-LdapDnsName $DomainName )
|
|
||||||
Write-Log @( "Ldap server list:", ( $LdapServerList | Out-String ) )
|
|
||||||
|
|
||||||
:MainLoop foreach ($LdapServer in $LdapServerList) {
|
|
||||||
$PingSeqCount = 0
|
|
||||||
$PingSeqPerHost = 0
|
|
||||||
while ($PingSeqPerHost -lt $PingSeqPerHostThreshold) {
|
|
||||||
if (Test-Connection -ComputerName $LdapServer.IpAddress -Count 1 -Quiet) {
|
|
||||||
Write-Log "Ping '$($LdapServer.Name)' OK"
|
|
||||||
$PingSeqCount++
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Log "Ping '$($LdapServer.Name)' FAILED"
|
|
||||||
$PingSeqCount = 0
|
|
||||||
$PingSeqPerHost++
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($PingSeqCount -ge $PingSeqCountThreshold) {
|
|
||||||
Write-Log "Returning true"
|
|
||||||
return $true
|
|
||||||
}
|
|
||||||
|
|
||||||
Start-Sleep -Seconds 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Log "Returning false"
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Get-ConfigDriveObject {
|
|
||||||
[CmdletBinding()]
|
|
||||||
param (
|
|
||||||
[Parameter(ParameterSetName="MetaData")]
|
|
||||||
[Switch] $MetaData,
|
|
||||||
|
|
||||||
[Parameter(ParameterSetName="UserData")]
|
|
||||||
[Switch] $UserData,
|
|
||||||
|
|
||||||
[Parameter(ParameterSetName="CustomObject")]
|
|
||||||
[String] $CustomObject,
|
|
||||||
|
|
||||||
[String] $Path = "openstack/latest"
|
|
||||||
)
|
|
||||||
|
|
||||||
$ConfigDrivePrefix = "http://169.254.169.154/$Path"
|
|
||||||
|
|
||||||
try {
|
|
||||||
switch($PSCmdlet.ParameterSetName) {
|
|
||||||
"MetaData" {
|
|
||||||
$ConfigDriveObjectUrl = "$ConfigDrivePrefix/meta_data.json"
|
|
||||||
$MetaData = Invoke-WebRequest $ConfigDriveObjectUrl
|
|
||||||
ConvertFrom-Json $MetaData.Content
|
|
||||||
}
|
|
||||||
"UserData" {
|
|
||||||
$ConfigDriveObjectUrl = "$ConfigDrivePrefix/user_data"
|
|
||||||
$UserData = Invoke-WebRequest $ConfigDriveObjectUrl
|
|
||||||
$UserData.Content
|
|
||||||
}
|
|
||||||
"CustomObject" {
|
|
||||||
$ConfigDriveObjectUrl = "$ConfigDrivePrefix/$CustomObject"
|
|
||||||
$CustomObject = Invoke-WebRequest $ConfigDriveObjectUrl
|
|
||||||
$CustomObject.Content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Error "Unable to retrieve object from 'ConfigDriveObjectUrl'"
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Expand-Template {
|
|
||||||
param (
|
|
||||||
[String] $TemplateFile,
|
|
||||||
[String] $OutputFile,
|
|
||||||
[System.Collections.Hashtable] $ReplacementList,
|
|
||||||
[String] $Encoding = "Ascii"
|
|
||||||
)
|
|
||||||
|
|
||||||
if (-not [IO.File]::Exists($TemplateFile)) {
|
|
||||||
Write-Error "File '$TemplateFile' not exists"
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([IO.File]::Exists($OutputFile)) {
|
|
||||||
[IO.File]::Delete($OutputFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
Get-Content $TemplateFile -Encoding $Encoding |
|
|
||||||
ForEach-Object {
|
|
||||||
$Line = $_
|
|
||||||
foreach ($Key in $ReplacementList.Keys) {
|
|
||||||
$Line = $Line.Replace("%_$($Key)_%", $ReplacementList[$Key])
|
|
||||||
}
|
|
||||||
Add-Content -Path $OutputFile -Encoding $Encoding -Value $Line
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Update-AgentConfig {
|
|
||||||
param (
|
|
||||||
[String] $RootPath = "C:\Keero\Agent"
|
|
||||||
)
|
|
||||||
|
|
||||||
try {
|
|
||||||
$MetaData = Get-ConfigDriveObject -MetaData -ErrorAction Stop
|
|
||||||
if ($MetaData.meta -ne $null) {
|
|
||||||
Stop-Service "Keero Agent" -Force
|
|
||||||
Expand-Template -TemplateFile "$RootPath\WindowsAgent.exe.config.template" -OutputFile "$RootPath\WindowsAgent.exe.config" -ReplacementList $MetaData.meta
|
|
||||||
Start-Service "Keero Agent"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-LogError "Failed to update agent configuration"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,172 +0,0 @@
|
|||||||
Function Get-ModuleHelp {
|
|
||||||
param (
|
|
||||||
[String] $ModuleName = $__ModuleName,
|
|
||||||
[String] $Path = "",
|
|
||||||
[Switch] $File,
|
|
||||||
[Int] $Width = 80
|
|
||||||
)
|
|
||||||
|
|
||||||
$sb = {
|
|
||||||
$Module = Get-Module $ModuleName
|
|
||||||
|
|
||||||
"`n"
|
|
||||||
"Module: $($Module.Name)"
|
|
||||||
"Module version: $($Module.Version)"
|
|
||||||
"`n"
|
|
||||||
"{0} Module Description {0}" -f ('=' * 30)
|
|
||||||
"`n"
|
|
||||||
|
|
||||||
Get-Help "about_$($Module.Name)" | Out-String -Width $Width
|
|
||||||
|
|
||||||
"{0} Exported Functions {0}" -f ('=' * 30)
|
|
||||||
"`n"
|
|
||||||
|
|
||||||
foreach ($CommandName in $Module.ExportedCommands.Keys) {
|
|
||||||
'-' * 80
|
|
||||||
Get-Help -Name $CommandName -Detailed | Out-String -Width $Width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($File) -and ($Path -eq "")) {
|
|
||||||
$Path = [IO.Path]::GetTempFileName()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Path -ne "") {
|
|
||||||
& $sb | Out-File -FilePath $Path -Force
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
& $sb | Out-Default
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($File) {
|
|
||||||
notepad.exe "$Path"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function Update-PsModulePath {
|
|
||||||
param (
|
|
||||||
[String] $AddPath = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
$NewPsModulePath = (
|
|
||||||
@([Environment]::GetEnvironmentVariable("PsModulePath", [EnvironmentVariableTarget]::Machine) -split ";") + @($AddPath) `
|
|
||||||
| Select-Object -Unique
|
|
||||||
) -join ';'
|
|
||||||
|
|
||||||
[Environment]::SetEnvironmentVariable("PsModulePath", $NewPsModulePath, [EnvironmentVariableTarget]::Machine)
|
|
||||||
|
|
||||||
Invoke-WMSettingsChange
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Install-Module {
|
|
||||||
param (
|
|
||||||
[String] $InstallPath,
|
|
||||||
[String] $ModulePath,
|
|
||||||
[String] $ModuleName
|
|
||||||
)
|
|
||||||
|
|
||||||
if ($ModuleName -eq "") {
|
|
||||||
if ($ModulePath -eq "") {
|
|
||||||
Stop-Execution -ExitString "Don't know which module should be installed."
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$ModuleName = $ModulePath.Split("\")[-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($InstallPath -eq "") {
|
|
||||||
Stop-Execution -ExitString "To install the module destination path must be provided."
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Log "Installing the module to '$InstallPath'"
|
|
||||||
|
|
||||||
$NewModulePath = [IO.Path]::Combine($InstallPath, $ModuleName)
|
|
||||||
if ([IO.Directory]::Exists($NewModulePath)) {
|
|
||||||
[IO.Directory]::Delete($NewModulePath, $true)
|
|
||||||
}
|
|
||||||
|
|
||||||
Copy-Item -Path $ModulePath -Destination $InstallPath -Recurse -Force -ErrorAction Stop
|
|
||||||
|
|
||||||
Update-PsModulePath -AddPath "$InstallPath"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function Register-Module {
|
|
||||||
param (
|
|
||||||
[String] $ModulePath
|
|
||||||
)
|
|
||||||
$ModuleRoot = Split-Path -Path $ModulePath -Parent
|
|
||||||
Write-Log "Registering the module at '$ModuleRoot'"
|
|
||||||
Update-PsModulePath -AddPath "$ModuleRoot"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function New-ModuleTemplate {
|
|
||||||
param (
|
|
||||||
[Parameter(Mandatory=$true)]
|
|
||||||
[String] $Name,
|
|
||||||
|
|
||||||
[String] $Path = "$($Env:USERPROFILE)\Documents\WindowsPowerShell\Modules",
|
|
||||||
|
|
||||||
[Switch] $Force
|
|
||||||
)
|
|
||||||
if ([IO.Directory]::Exists("$Path\$Name")) {
|
|
||||||
if ($Force) {
|
|
||||||
[IO.Directory]::Delete("$Path\$Name", $true)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Error "Folder '$Path\$Name' already exists. Remove it manually or specify -Force switch."
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[IO.Directory]::CreateDirectory("$Path\$Name")
|
|
||||||
[IO.Directory]::CreateDirectory("$Path\$Name\en-US")
|
|
||||||
[IO.Directory]::CreateDirectory("$Path\$Name\include")
|
|
||||||
|
|
||||||
|
|
||||||
Set-Content -Path "$Path\$Name\en-US\about_$Name.help.txt" -Value @'
|
|
||||||
'@
|
|
||||||
|
|
||||||
|
|
||||||
Set-Content -Path "$Path\$Name\Config.ps1" -Value @'
|
|
||||||
$script:__ModulePath = $PsScriptRoot
|
|
||||||
$script:__ModuleName = $PsScriptRoot.Split("\")[-1]
|
|
||||||
$script:__DefaultLogPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), "PowerShell_$__ModuleName.log")
|
|
||||||
|
|
||||||
$global:__StopExecutionExitsSession__ = $false
|
|
||||||
'@
|
|
||||||
|
|
||||||
|
|
||||||
Set-Content -Path "$Path\$Name\$Name.psm1" -Value @'
|
|
||||||
# Import config first
|
|
||||||
. "$PsScriptRoot\Config.ps1"
|
|
||||||
|
|
||||||
# Import functions from 'Include' subfolder
|
|
||||||
Get-ChildItem "$PsScriptRoot\Include" -Filter "*.ps1" |
|
|
||||||
ForEach-Object {
|
|
||||||
. "$($_.FullName)"
|
|
||||||
}
|
|
||||||
|
|
||||||
Export-ModuleMember -Function * -Alias *
|
|
||||||
|
|
||||||
Initialize-Logger -ModuleName $__ModuleName -LogPath $__DefaultLogPath
|
|
||||||
|
|
||||||
Write-Log "Module loaded from '$PsScriptRoot'"
|
|
||||||
'@
|
|
||||||
|
|
||||||
|
|
||||||
New-ModuleManifest `
|
|
||||||
-Path "$Path\$Name\$Name.psd1" `
|
|
||||||
-ModuleToProcess "$Name.psm1" `
|
|
||||||
-RequiredModules "CoreFunctions"
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,814 @@
|
|||||||
|
Function Set-LocalUserPassword {
|
||||||
|
param (
|
||||||
|
[String] $UserName,
|
||||||
|
[String] $Password,
|
||||||
|
[Switch] $Force
|
||||||
|
)
|
||||||
|
|
||||||
|
trap { Stop-Execution $_ }
|
||||||
|
|
||||||
|
if ((Get-WmiObject Win32_UserAccount -Filter "LocalAccount = 'True' AND Name='$UserName'") -eq $null) {
|
||||||
|
throw "Unable to find local user account '$UserName'"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Force) {
|
||||||
|
Write-Log "Changing password for user '$UserName' to '*****'" # :)
|
||||||
|
([ADSI] "WinNT://./$UserName").SetPassword($Password) | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-LogWarning "You are trying to change the password for the user '$UserName'. To do this please run the command again with -Force parameter."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Set-AutoLogonCredentials {
|
||||||
|
param (
|
||||||
|
[String] $DomainName,
|
||||||
|
[String] $UserName,
|
||||||
|
[String] $Password
|
||||||
|
)
|
||||||
|
|
||||||
|
$KeyName = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
||||||
|
|
||||||
|
if ($DomainName -ne "") {
|
||||||
|
$UserName = "$DomainName\$UserName"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Log "Setting AutoLogon credentials ..."
|
||||||
|
try {
|
||||||
|
[Microsoft.Win32.Registry]::SetValue($KeyName, "DefaultUserName", "$UserName", [Microsoft.Win32.RegistryValueKind]::String)
|
||||||
|
[Microsoft.Win32.Registry]::SetValue($KeyName, "DefaultPassword", "$Password", [Microsoft.Win32.RegistryValueKind]::String)
|
||||||
|
[Microsoft.Win32.Registry]::SetValue($KeyName, "AutoAdminLogon", "1", [Microsoft.Win32.RegistryValueKind]::String)
|
||||||
|
[Microsoft.Win32.Registry]::SetValue($KeyName, "ForceAutoLogon", "1", [Microsoft.Win32.RegistryValueKind]::String)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-LogError "FAILED"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Log "SUCCESS"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Join-Domain {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Executes "Join domain" action.
|
||||||
|
#>
|
||||||
|
param (
|
||||||
|
[String] $DomainName,
|
||||||
|
[String] $UserName,
|
||||||
|
[String] $Password,
|
||||||
|
[Switch] $AllowRestart
|
||||||
|
)
|
||||||
|
|
||||||
|
$Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password
|
||||||
|
|
||||||
|
# Add the computer to the domain
|
||||||
|
if (Test-ComputerName -DomainName $DomainName) {
|
||||||
|
#Stop-Execution -Success -ExitString "Computer already joined to domain '$DomainName'"
|
||||||
|
Write-LogWarning "Computer already joined to domain '$DomainName'"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Log "Joining computer to domain '$DomainName' ..."
|
||||||
|
|
||||||
|
Add-Computer -DomainName $DomainName -Credential $Credential -Force -ErrorAction Stop
|
||||||
|
|
||||||
|
if ($AllowRestart) {
|
||||||
|
Write-Log "Restarting computer ..."
|
||||||
|
Restart-Computer -Force
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#Stop-Execution -ExitCode 3010 -ExitString "Please restart the computer now."
|
||||||
|
Write-Log "Please restart the computer now."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Expand-Template {
|
||||||
|
param (
|
||||||
|
[String] $TemplateFile,
|
||||||
|
[String] $OutputFile,
|
||||||
|
[System.Collections.Hashtable] $ReplacementList,
|
||||||
|
[String] $Encoding = "Ascii"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not [IO.File]::Exists($TemplateFile)) {
|
||||||
|
Write-Error "File '$TemplateFile' not exists"
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([IO.File]::Exists($OutputFile)) {
|
||||||
|
[IO.File]::Delete($OutputFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
Get-Content $TemplateFile -Encoding $Encoding |
|
||||||
|
ForEach-Object {
|
||||||
|
$Line = $_
|
||||||
|
foreach ($Key in $ReplacementList.Keys) {
|
||||||
|
$Line = $Line.Replace("%_$($Key)_%", $ReplacementList[$Key])
|
||||||
|
}
|
||||||
|
Add-Content -Path $OutputFile -Encoding $Encoding -Value $Line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Add-WindowsFeatureWrapper {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Wraps Install-WindowsFeature function.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This function adds some logic to multiple feature installation.
|
||||||
|
|
||||||
|
It fails if any of required features fails.
|
||||||
|
|
||||||
|
It reports that reboot required if it is required, or restarts the computer.
|
||||||
|
#>
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[String[]] $Name,
|
||||||
|
[Switch] $IncludeManagementTools,
|
||||||
|
[Switch] $AllowRestart,
|
||||||
|
[Switch] $NotifyRestart
|
||||||
|
)
|
||||||
|
|
||||||
|
$RestartNeeded = $false
|
||||||
|
|
||||||
|
foreach ($Feature in $Name) {
|
||||||
|
Write-Log "Installing feature '$Feature' ..."
|
||||||
|
$Action = Install-WindowsFeature `
|
||||||
|
-Name $Feature `
|
||||||
|
-IncludeManagementTools:$IncludeManagementTools `
|
||||||
|
-ErrorAction Stop
|
||||||
|
|
||||||
|
if ($Action.Success -eq $true) {
|
||||||
|
if ($Action.FeatureResult.RestartNeeded -eq $true) {
|
||||||
|
Write-LogWarning "Restart required"
|
||||||
|
$RestartNeeded = $true
|
||||||
|
}
|
||||||
|
Write-Log "Feature '$Feature' installed successfully"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Stop-Execution "Failed to install feature '$Feature'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($RestartNeeded) {
|
||||||
|
Write-Log "Restart required to finish feature(s) installation."
|
||||||
|
if ($AllowRestart) {
|
||||||
|
Write-Log "Restarting computer ..."
|
||||||
|
Restart-Computer -Force
|
||||||
|
}
|
||||||
|
elseif ($NotifyRestart) {
|
||||||
|
Stop-Execution -ExitCode 3010 -ExitString "Please restart the computer now."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Test-WmiReturnValue {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Check the ReturnValue property of the object provided.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This funciton checks if ReturnValue property is equal to 0.
|
||||||
|
|
||||||
|
=== TODO ===
|
||||||
|
If it is not, then funtion should try to provide desctiption for the error code based on the WMI object type.
|
||||||
|
WMI object type must be provided explicitely.
|
||||||
|
#>
|
||||||
|
param (
|
||||||
|
[Parameter(ValueFromPipeline=$true,Mandatory=$true)]
|
||||||
|
$InputObject,
|
||||||
|
[String] $Type = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
$ReturnValue = $InputObject.ReturnValue
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
throw "Property 'ReturnValue' not found on this object"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ReturnValue -eq 0) {
|
||||||
|
Write-Log "WMI operation completed successfully"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "Operation failed with status code = $ReturnValue"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Set-NetworkAdapterConfiguration {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Set network adapter configuration.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
PS> Set-NetworkAdapterConfiguration -MACAddress aa:bb:cc:dd:ee:ff -Auto
|
||||||
|
|
||||||
|
Convert "dynamic" parameters (DHCP) to "static" (manual) for network adapter with MAC address aa:bb:cc:dd:ee:ff
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
PS> Set-NetworkAdapterConfiguration -MACAddress aa:bb:cc:dd:ee:ff -DNSServer "192.168.0.1","192.168.0.2"
|
||||||
|
|
||||||
|
Configure DNS servers list for network adapter with MAC address aa:bb:cc:dd:ee:ff
|
||||||
|
|
||||||
|
#>
|
||||||
|
param (
|
||||||
|
[String] $MACAddress = "",
|
||||||
|
|
||||||
|
[Parameter(ParameterSetName="ManualConfig")]
|
||||||
|
[String] $IPAddress = "",
|
||||||
|
|
||||||
|
[Parameter(ParameterSetName="ManualConfig")]
|
||||||
|
[String] $IPNetmask = "",
|
||||||
|
|
||||||
|
[Parameter(ParameterSetName="ManualConfig")]
|
||||||
|
[String[]] $IPGateway = @(),
|
||||||
|
|
||||||
|
[Parameter(ParameterSetName="ManualConfig")]
|
||||||
|
[String[]] $DNSServer = @(),
|
||||||
|
|
||||||
|
[Parameter(ParameterSetName="ManualConfig")]
|
||||||
|
[Switch] $FirstAvailable,
|
||||||
|
|
||||||
|
[String] $Name = "",
|
||||||
|
|
||||||
|
[Parameter(ParameterSetName="AutoConfig",Mandatory=$true)]
|
||||||
|
[Switch] $Auto,
|
||||||
|
|
||||||
|
[Parameter(ParameterSetName="AutoConfig")]
|
||||||
|
[Switch] $All
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Log "Configuring network adapter(s) ..."
|
||||||
|
|
||||||
|
:SetIPAddress switch($PSCmdlet.ParameterSetName) {
|
||||||
|
"AutoConfig" {
|
||||||
|
Write-Log "'auto' mode"
|
||||||
|
|
||||||
|
$IPv4RegExp = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
|
||||||
|
|
||||||
|
if ($All -eq $true) {
|
||||||
|
$Filter = { $_.AdapterTypeId -eq 0 }
|
||||||
|
$Name = ""
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$Filter = { $_.MACAddress -eq $MACAddress }
|
||||||
|
}
|
||||||
|
|
||||||
|
Get-WmiObject Win32_NetworkAdapter |
|
||||||
|
Where-Object $Filter |
|
||||||
|
ForEach-Object {
|
||||||
|
$NetworkAdapter = $_
|
||||||
|
$AdapterConfig = Get-WmiObject Win32_NetworkAdapterConfiguration |
|
||||||
|
Where-Object { $_.Index -eq $NetworkAdapter.DeviceId }
|
||||||
|
|
||||||
|
Write-Log "Configuring '$($NetworkAdapter.Name)' ..."
|
||||||
|
|
||||||
|
for ($i = 0; $i -lt $AdapterConfig.IPAddress.Length; $i++) {
|
||||||
|
if ($AdapterConfig.IPAddress[$i] -match $IPv4RegExp) {
|
||||||
|
$IPAddress = $AdapterConfig.IPAddress[$i]
|
||||||
|
$IPNetmask = $AdapterConfig.IPSubnet[$i]
|
||||||
|
$IPGateway = $AdapterConfig.DefaultIPGateway
|
||||||
|
$DNSServer = $AdapterConfig.DNSServerSearchOrder
|
||||||
|
|
||||||
|
Write-Log "Setting IP address ($IPAddress), netmask ($IPNetmask) ..."
|
||||||
|
$AdapterConfig.EnableStatic($IPAddress, $IPNetmask) | Out-Null
|
||||||
|
|
||||||
|
Write-Log "Setting default gateways ($IPGateway) ..."
|
||||||
|
$AdapterConfig.SetGateways($IPGateway) | Out-Null
|
||||||
|
|
||||||
|
Write-Log "Setting DNS servers ($DNSServer) ..."
|
||||||
|
$AdapterConfig.SetDNSServerSearchOrder($DNSServer) | Out-Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Log "'$($NetworkAdapter.Name)' configured"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"ManualConfig" {
|
||||||
|
Write-Log "'manual' mode"
|
||||||
|
if ( $FirstAvailable ) {
|
||||||
|
Write-Log "Selecting first available network adapter ..."
|
||||||
|
$NetworkAdapter = Get-WmiObject Win32_NetworkAdapter |
|
||||||
|
Where-Object { $_.AdapterTypeId -eq 0 } |
|
||||||
|
Select-Object -First 1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$NetworkAdapter = Get-WmiObject Win32_NetworkAdapter |
|
||||||
|
Where-Object { $_.MACAddress -eq $MACAddress }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $NetworkAdapter -eq $null ) {
|
||||||
|
Write-LogError "Network adapter with MAC = '$MACAddress' not found."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$AdapterConfig = Get-WmiObject Win32_NetworkAdapterConfiguration |
|
||||||
|
Where-Object { $_.Index -eq $NetworkAdapter.DeviceId }
|
||||||
|
|
||||||
|
if (($IPAddress -ne "") -and ($IPNetmask -ne "")) {
|
||||||
|
Write-Log "Configuring IP address / netmask for '$($NetworkAdapter.Name)' ..."
|
||||||
|
|
||||||
|
<#
|
||||||
|
for ($i = 0; $i -lt $AdapterConfig.IPAddress.Length; $i++)
|
||||||
|
{
|
||||||
|
if (($AdapterConfig.IPAddress[$i] -eq $IPAddress) -and ($AdapterConfig.IPSubnet[$i] -eq $IPNetmask))
|
||||||
|
{
|
||||||
|
Write-Log "There is an adapter with required configuration."
|
||||||
|
break SetIPAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#>
|
||||||
|
Write-Log "Setting IP address $IPAddress, netmask $IPNetmask"
|
||||||
|
$AdapterConfig.EnableStatic("$IPAddress", "$IPNetmask") | Out-Null
|
||||||
|
|
||||||
|
Write-Log "IP address configured."
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($IPGateway.Count -gt 0) {
|
||||||
|
Write-Log "Configuring IP gateway for '$($NetworkAdapter.Name)' ..."
|
||||||
|
|
||||||
|
$AdapterConfig.SetGateways($IPGateway) | Out-Null
|
||||||
|
|
||||||
|
Write-Log "IP gateway configured."
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($DNSServer.Count -gt 0) {
|
||||||
|
Write-Log "Configuring DNS server(s) for '$($NetworkAdapter.Name)' ..."
|
||||||
|
|
||||||
|
$AdapterConfig.SetDNSServerSearchOrder($DNSServer) | Out-Null
|
||||||
|
|
||||||
|
Write-Log "DNS configured."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Name -ne "") {
|
||||||
|
Write-Log "Changing adapter name '$($NetworkAdapter.NetConnectionId)' --> '$Name'"
|
||||||
|
$NetworkAdapter.NetConnectionId = "$Name"
|
||||||
|
$NetworkAdapter.Put() | Out-Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Show-EthernetNetworkAdapters {
|
||||||
|
Get-WmiObject Win32_NetworkAdapter -Filter "PhysicalAdapter = 'True' AND AdapterTypeId = '0'" |
|
||||||
|
Select-Object 'Index','MACAddress','NetConnectionId'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Test-ComputerName {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Test if computer name is set, and the computer belongs to specified domain / workgroup.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Function tests the following conditions:
|
||||||
|
* the computer name is equal to the provided one
|
||||||
|
* the computer is a part of domain
|
||||||
|
* the computer belongs to the specified domain
|
||||||
|
* the computer belongs to the specified workgroup
|
||||||
|
|
||||||
|
Multiple checks are logically ANDed.
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[String] $ComputerName,
|
||||||
|
[String] $DomainName,
|
||||||
|
[String] $WorkgroupName,
|
||||||
|
[Switch] $PartOfDomain
|
||||||
|
)
|
||||||
|
process {
|
||||||
|
$ComputerSystem = Get-WmiObject Win32_ComputerSystem
|
||||||
|
|
||||||
|
if (($ComputerName -ne "") -and ($ComputerSystem.Name -ne "$ComputerName")) {
|
||||||
|
Write-Error "ComputerName is not equal to '$ComputerName'"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($DomainName -ne "") -and ($ComputerSystem.Domain -ne "$DomainName")) {
|
||||||
|
Write-Error "DomainName is not equal to '$DomainName'"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($WorkgroupName -ne "") -and ($ComputerSystem.Workgroup -ne "$WorkgroupName")) {
|
||||||
|
Write-Error "WorkgroupName is not equal to '$WorkgroupName'"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($PartOfDOmain -eq $true) -and ($ComputerSystem.PartOfDomain -eq $false)) {
|
||||||
|
Write-Error "Computer is not the part of any domain."
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Set-ComputerName {
|
||||||
|
param (
|
||||||
|
[String] $Name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Rename the computer
|
||||||
|
if ($Name -ne "") {
|
||||||
|
if (Test-ComputerName -ComputerName $Name) {
|
||||||
|
Stop-Execution -Success -ExitString "Computer name already configured"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Log "Renaming computer to '$Name'"
|
||||||
|
|
||||||
|
Rename-Computer -NewName $NewName -Force -ErrorAction Stop
|
||||||
|
|
||||||
|
Stop-Execution -ExitCode 3010 -ExitString "Please restart the computer now"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Resolve-LdapDnsName {
|
||||||
|
param (
|
||||||
|
[String] $DomainName
|
||||||
|
)
|
||||||
|
|
||||||
|
Resolve-DNSName -Type "SRV" -Name "_ldap._tcp.dc._msdcs.$DomainName" |
|
||||||
|
Where-Object { $_.Type -eq "A" } |
|
||||||
|
Select-Object -Property Name,IPAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Wait-LdapServerAvailable {
|
||||||
|
param (
|
||||||
|
[String] $DomainName,
|
||||||
|
[Int] $PingSeqCountThreshold = 10,
|
||||||
|
[Int] $PingSeqPerHostThreshold = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
$LdapServerList = @( Resolve-LdapDnsName $DomainName )
|
||||||
|
Write-Log @( "Ldap server list:", ( $LdapServerList | Out-String ) )
|
||||||
|
|
||||||
|
:MainLoop foreach ($LdapServer in $LdapServerList) {
|
||||||
|
$PingSeqCount = 0
|
||||||
|
$PingSeqPerHost = 0
|
||||||
|
while ($PingSeqPerHost -lt $PingSeqPerHostThreshold) {
|
||||||
|
if (Test-Connection -ComputerName $LdapServer.IpAddress -Count 1 -Quiet) {
|
||||||
|
Write-Log "Ping '$($LdapServer.Name)' OK"
|
||||||
|
$PingSeqCount++
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Log "Ping '$($LdapServer.Name)' FAILED"
|
||||||
|
$PingSeqCount = 0
|
||||||
|
$PingSeqPerHost++
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PingSeqCount -ge $PingSeqCountThreshold) {
|
||||||
|
Write-Log "Returning true"
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Log "Returning false"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Get-ConfigDriveObject {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[Parameter(ParameterSetName="MetaData")]
|
||||||
|
[Switch] $MetaData,
|
||||||
|
|
||||||
|
[Parameter(ParameterSetName="UserData")]
|
||||||
|
[Switch] $UserData,
|
||||||
|
|
||||||
|
[Parameter(ParameterSetName="CustomObject")]
|
||||||
|
[String] $CustomObject,
|
||||||
|
|
||||||
|
[String] $Path = "openstack/latest"
|
||||||
|
)
|
||||||
|
|
||||||
|
$ConfigDrivePrefix = "http://169.254.169.154/$Path"
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch($PSCmdlet.ParameterSetName) {
|
||||||
|
"MetaData" {
|
||||||
|
$ConfigDriveObjectUrl = "$ConfigDrivePrefix/meta_data.json"
|
||||||
|
$MetaData = Invoke-WebRequest $ConfigDriveObjectUrl
|
||||||
|
ConvertFrom-Json $MetaData.Content
|
||||||
|
}
|
||||||
|
"UserData" {
|
||||||
|
$ConfigDriveObjectUrl = "$ConfigDrivePrefix/user_data"
|
||||||
|
$UserData = Invoke-WebRequest $ConfigDriveObjectUrl
|
||||||
|
$UserData.Content
|
||||||
|
}
|
||||||
|
"CustomObject" {
|
||||||
|
$ConfigDriveObjectUrl = "$ConfigDrivePrefix/$CustomObject"
|
||||||
|
$CustomObject = Invoke-WebRequest $ConfigDriveObjectUrl
|
||||||
|
$CustomObject.Content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "Unable to retrieve object from 'ConfigDriveObjectUrl'"
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Update-AgentConfig {
|
||||||
|
param (
|
||||||
|
[String] $RootPath = "C:\Keero\Agent"
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
$MetaData = Get-ConfigDriveObject -MetaData -ErrorAction Stop
|
||||||
|
if ($MetaData.meta -ne $null) {
|
||||||
|
Stop-Service "Keero Agent" -Force
|
||||||
|
Expand-Template -TemplateFile "$RootPath\WindowsAgent.exe.config.template" -OutputFile "$RootPath\WindowsAgent.exe.config" -ReplacementList $MetaData.meta
|
||||||
|
Start-Service "Keero Agent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-LogError "Failed to update agent configuration"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Update-PsModulePath {
|
||||||
|
param (
|
||||||
|
[String] $AddPath = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
$NewPsModulePath = (
|
||||||
|
@([Environment]::GetEnvironmentVariable("PsModulePath", [EnvironmentVariableTarget]::Machine) -split ";") + @($AddPath) `
|
||||||
|
| Select-Object -Unique
|
||||||
|
) -join ';'
|
||||||
|
|
||||||
|
[Environment]::SetEnvironmentVariable("PsModulePath", $NewPsModulePath, [EnvironmentVariableTarget]::Machine)
|
||||||
|
|
||||||
|
Invoke-WMSettingsChange
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function Get-ModuleHelp {
|
||||||
|
param (
|
||||||
|
[String] $ModuleName = $__ModuleName,
|
||||||
|
[String] $Path = "",
|
||||||
|
[Switch] $File,
|
||||||
|
[Int] $Width = 80
|
||||||
|
)
|
||||||
|
|
||||||
|
$sb = {
|
||||||
|
$Module = Get-Module $ModuleName
|
||||||
|
|
||||||
|
"`n"
|
||||||
|
"Module: $($Module.Name)"
|
||||||
|
"Module version: $($Module.Version)"
|
||||||
|
"`n"
|
||||||
|
"{0} Module Description {0}" -f ('=' * 30)
|
||||||
|
"`n"
|
||||||
|
|
||||||
|
Get-Help "about_$($Module.Name)" | Out-String -Width $Width
|
||||||
|
|
||||||
|
"{0} Exported Functions {0}" -f ('=' * 30)
|
||||||
|
"`n"
|
||||||
|
|
||||||
|
foreach ($CommandName in $Module.ExportedCommands.Keys) {
|
||||||
|
'-' * 80
|
||||||
|
Get-Help -Name $CommandName -Detailed | Out-String -Width $Width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($File) -and ($Path -eq "")) {
|
||||||
|
$Path = [IO.Path]::GetTempFileName()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Path -ne "") {
|
||||||
|
& $sb | Out-File -FilePath $Path -Force
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
& $sb | Out-Default
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($File) {
|
||||||
|
notepad.exe "$Path"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Function New-ModuleTemplate {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[String] $Name,
|
||||||
|
|
||||||
|
[String] $Path = "$($Env:USERPROFILE)\Documents\WindowsPowerShell\Modules",
|
||||||
|
|
||||||
|
[Switch] $Force
|
||||||
|
)
|
||||||
|
if ([IO.Directory]::Exists("$Path\$Name")) {
|
||||||
|
if ($Force) {
|
||||||
|
[IO.Directory]::Delete("$Path\$Name", $true)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Error "Folder '$Path\$Name' already exists. Remove it manually or specify -Force switch."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[IO.Directory]::CreateDirectory("$Path\$Name")
|
||||||
|
[IO.Directory]::CreateDirectory("$Path\$Name\en-US")
|
||||||
|
[IO.Directory]::CreateDirectory("$Path\$Name\include")
|
||||||
|
|
||||||
|
|
||||||
|
Set-Content -Path "$Path\$Name\en-US\about_$Name.help.txt" -Value @'
|
||||||
|
'@
|
||||||
|
|
||||||
|
|
||||||
|
Set-Content -Path "$Path\$Name\Config.ps1" -Value @'
|
||||||
|
$script:__ModulePath = $PsScriptRoot
|
||||||
|
$script:__ModuleName = $PsScriptRoot.Split("\")[-1]
|
||||||
|
$script:__DefaultLogPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), "PowerShell_$__ModuleName.log")
|
||||||
|
|
||||||
|
$global:__StopExecutionExitsSession__ = $false
|
||||||
|
'@
|
||||||
|
|
||||||
|
|
||||||
|
Set-Content -Path "$Path\$Name\$Name.psm1" -Value @'
|
||||||
|
# Import config first
|
||||||
|
. "$PsScriptRoot\Config.ps1"
|
||||||
|
|
||||||
|
# Import functions from 'Include' subfolder
|
||||||
|
Get-ChildItem "$PsScriptRoot\Include" -Filter "*.ps1" |
|
||||||
|
ForEach-Object {
|
||||||
|
. "$($_.FullName)"
|
||||||
|
}
|
||||||
|
|
||||||
|
Export-ModuleMember -Function * -Alias *
|
||||||
|
|
||||||
|
Initialize-Logger -ModuleName $__ModuleName -LogPath $__DefaultLogPath
|
||||||
|
|
||||||
|
Write-Log "Module loaded from '$PsScriptRoot'"
|
||||||
|
'@
|
||||||
|
|
||||||
|
|
||||||
|
New-ModuleManifest `
|
||||||
|
-Path "$Path\$Name\$Name.psd1" `
|
||||||
|
-ModuleToProcess "$Name.psm1" `
|
||||||
|
-RequiredModules "CoreFunctions"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function New-SqlServerConnection {
|
||||||
|
param (
|
||||||
|
[String] $ServerName,
|
||||||
|
[String] $UserName = '',
|
||||||
|
[String] $Password = '',
|
||||||
|
$Credentials,
|
||||||
|
[Switch] $SqlAuth
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($Credentials -eq $null) {
|
||||||
|
if ($UserName -eq '') {
|
||||||
|
throw "User name must be provided in order to create credentials object!"
|
||||||
|
}
|
||||||
|
|
||||||
|
$Credentials = New-Credential -UserName $UserName -Password $Password
|
||||||
|
}
|
||||||
|
|
||||||
|
$Server = New-Object `
|
||||||
|
-TypeName Microsoft.SqlServer.Management.Smo.Server `
|
||||||
|
-ArgumentList $ServerName
|
||||||
|
|
||||||
|
$LoginName = $Credentials.UserName -replace("^\\", "")
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($SqlAuth) {
|
||||||
|
$Server.ConnectionContext.set_LoginSecure($false)
|
||||||
|
$Server.ConnectionContext.set_Login($LoginName)
|
||||||
|
$Server.ConnectionContext.set_SecurePassword($Credentials.Password)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "Not implemented!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
$Server
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function Import-SqlServerAssemblies {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Import assemblies required to work with Sql Server instance from PowerShell
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Possible assembly list:
|
||||||
|
"Microsoft.SqlServer.Management.Common"
|
||||||
|
"Microsoft.SqlServer.Smo"
|
||||||
|
"Microsoft.SqlServer.Dmf"
|
||||||
|
"Microsoft.SqlServer.Instapi"
|
||||||
|
"Microsoft.SqlServer.SqlWmiManagement"
|
||||||
|
"Microsoft.SqlServer.ConnectionInfo"
|
||||||
|
"Microsoft.SqlServer.SmoExtended"
|
||||||
|
"Microsoft.SqlServer.SqlTDiagM"
|
||||||
|
"Microsoft.SqlServer.SString"
|
||||||
|
"Microsoft.SqlServer.Management.RegisteredServers"
|
||||||
|
"Microsoft.SqlServer.Management.Sdk.Sfc"
|
||||||
|
"Microsoft.SqlServer.SqlEnum"
|
||||||
|
"Microsoft.SqlServer.RegSvrEnum"
|
||||||
|
"Microsoft.SqlServer.WmiEnum"
|
||||||
|
"Microsoft.SqlServer.ServiceBrokerEnum"
|
||||||
|
"Microsoft.SqlServer.ConnectionInfoExtended"
|
||||||
|
"Microsoft.SqlServer.Management.Collector"
|
||||||
|
"Microsoft.SqlServer.Management.CollectorEnum"
|
||||||
|
"Microsoft.SqlServer.Management.Dac"
|
||||||
|
"Microsoft.SqlServer.Management.DacEnum"
|
||||||
|
"Microsoft.SqlServer.Management.Utility"
|
||||||
|
|
||||||
|
.LINKS
|
||||||
|
http://msdn.microsoft.com/en-us/library/cc281962%28v=sql.105%29.aspx
|
||||||
|
#>
|
||||||
|
$AssemblyList = @(
|
||||||
|
"Microsoft.SqlServer.Smo"
|
||||||
|
"Microsoft.SqlServer.SmoExtended"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($asm in $AssemblyList) {
|
||||||
|
[System.Reflection.Assembly]::LoadWithPartialName($asm) | Out-Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function Import-SqlServerProvider {
|
||||||
|
$SqlPsReg="HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.SqlServer.Management.PowerShell.sqlps"
|
||||||
|
|
||||||
|
if (Get-ChildItem $SqlPsReg -ErrorAction "SilentlyContinue") {
|
||||||
|
throw "SQL Server Provider for Windows PowerShell is not installed."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$Item = Get-ItemProperty $SqlPsReg
|
||||||
|
$SqlPsPath = [System.IO.Path]::GetDirectoryName($Item.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set mandatory variables for the SQL Server provider
|
||||||
|
#
|
||||||
|
$global:SqlServerMaximumChildItems = 0
|
||||||
|
$global:SqlServerConnectionTimeout = 30
|
||||||
|
$global:SqlServerIncludeSystemObjects = $false
|
||||||
|
$global:SqlServerMaximumTabCompletion = 1000
|
||||||
|
|
||||||
|
#
|
||||||
|
# Load the snapins, type data, format data
|
||||||
|
#
|
||||||
|
Push-Location
|
||||||
|
Set-Location $sqlpsPath
|
||||||
|
|
||||||
|
Add-PSSnapin SqlServerCmdletSnapin100
|
||||||
|
Add-PSSnapin SqlServerProviderSnapin100
|
||||||
|
|
||||||
|
Update-TypeData -PrependPath SQLProvider.Types.ps1xml
|
||||||
|
Update-FormatData -PrependPath SQLProvider.Format.ps1xml
|
||||||
|
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
@ -1,120 +1 @@
|
|||||||
function New-SqlServerConnection {
|
|
||||||
param (
|
|
||||||
[String] $ServerName,
|
|
||||||
[String] $UserName = '',
|
|
||||||
[String] $Password = '',
|
|
||||||
$Credentials,
|
|
||||||
[Switch] $SqlAuth
|
|
||||||
)
|
|
||||||
|
|
||||||
if ($Credentials -eq $null) {
|
|
||||||
if ($UserName -eq '') {
|
|
||||||
throw "User name must be provided in order to create credentials object!"
|
|
||||||
}
|
|
||||||
|
|
||||||
$Credentials = New-Credential -UserName $UserName -Password $Password
|
|
||||||
}
|
|
||||||
|
|
||||||
$Server = New-Object `
|
|
||||||
-TypeName Microsoft.SqlServer.Management.Smo.Server `
|
|
||||||
-ArgumentList $ServerName
|
|
||||||
|
|
||||||
$LoginName = $Credentials.UserName -replace("^\\", "")
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ($SqlAuth) {
|
|
||||||
$Server.ConnectionContext.set_LoginSecure($false)
|
|
||||||
$Server.ConnectionContext.set_Login($LoginName)
|
|
||||||
$Server.ConnectionContext.set_SecurePassword($Credentials.Password)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw "Not implemented!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
|
|
||||||
$Server
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function Import-SqlServerAssemblies {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Import assemblies required to work with Sql Server instance from PowerShell
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
Possible assembly list:
|
|
||||||
"Microsoft.SqlServer.Management.Common"
|
|
||||||
"Microsoft.SqlServer.Smo"
|
|
||||||
"Microsoft.SqlServer.Dmf"
|
|
||||||
"Microsoft.SqlServer.Instapi"
|
|
||||||
"Microsoft.SqlServer.SqlWmiManagement"
|
|
||||||
"Microsoft.SqlServer.ConnectionInfo"
|
|
||||||
"Microsoft.SqlServer.SmoExtended"
|
|
||||||
"Microsoft.SqlServer.SqlTDiagM"
|
|
||||||
"Microsoft.SqlServer.SString"
|
|
||||||
"Microsoft.SqlServer.Management.RegisteredServers"
|
|
||||||
"Microsoft.SqlServer.Management.Sdk.Sfc"
|
|
||||||
"Microsoft.SqlServer.SqlEnum"
|
|
||||||
"Microsoft.SqlServer.RegSvrEnum"
|
|
||||||
"Microsoft.SqlServer.WmiEnum"
|
|
||||||
"Microsoft.SqlServer.ServiceBrokerEnum"
|
|
||||||
"Microsoft.SqlServer.ConnectionInfoExtended"
|
|
||||||
"Microsoft.SqlServer.Management.Collector"
|
|
||||||
"Microsoft.SqlServer.Management.CollectorEnum"
|
|
||||||
"Microsoft.SqlServer.Management.Dac"
|
|
||||||
"Microsoft.SqlServer.Management.DacEnum"
|
|
||||||
"Microsoft.SqlServer.Management.Utility"
|
|
||||||
|
|
||||||
.LINKS
|
|
||||||
http://msdn.microsoft.com/en-us/library/cc281962%28v=sql.105%29.aspx
|
|
||||||
#>
|
|
||||||
$AssemblyList = @(
|
|
||||||
"Microsoft.SqlServer.Smo"
|
|
||||||
"Microsoft.SqlServer.SmoExtended"
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach ($asm in $AssemblyList) {
|
|
||||||
[System.Reflection.Assembly]::LoadWithPartialName($asm) | Out-Null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function Import-SqlServerProvider {
|
|
||||||
$SqlPsReg="HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.SqlServer.Management.PowerShell.sqlps"
|
|
||||||
|
|
||||||
if (Get-ChildItem $SqlPsReg -ErrorAction "SilentlyContinue") {
|
|
||||||
throw "SQL Server Provider for Windows PowerShell is not installed."
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$Item = Get-ItemProperty $SqlPsReg
|
|
||||||
$SqlPsPath = [System.IO.Path]::GetDirectoryName($Item.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Set mandatory variables for the SQL Server provider
|
|
||||||
#
|
|
||||||
$global:SqlServerMaximumChildItems = 0
|
|
||||||
$global:SqlServerConnectionTimeout = 30
|
|
||||||
$global:SqlServerIncludeSystemObjects = $false
|
|
||||||
$global:SqlServerMaximumTabCompletion = 1000
|
|
||||||
|
|
||||||
#
|
|
||||||
# Load the snapins, type data, format data
|
|
||||||
#
|
|
||||||
Push-Location
|
|
||||||
Set-Location $sqlpsPath
|
|
||||||
|
|
||||||
Add-PSSnapin SqlServerCmdletSnapin100
|
|
||||||
Add-PSSnapin SqlServerProviderSnapin100
|
|
||||||
|
|
||||||
Update-TypeData -PrependPath SQLProvider.Types.ps1xml
|
|
||||||
Update-FormatData -PrependPath SQLProvider.Format.ps1xml
|
|
||||||
|
|
||||||
Pop-Location
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user