Windows PowerShell module added

This commit is contained in:
Dmitry Teselkin 2013-02-25 17:18:44 +04:00
parent 779e61ba72
commit f76f434648
10 changed files with 1283 additions and 0 deletions

View File

@ -0,0 +1,29 @@
<#
Naming convention:
== Normal variables
** Set: $NormalVar = 123
** Get: Write-Host $NormalVar
== Script-scope variables
** Set: $script:__ScriptScopeVar = 123
** Get: Write-Host $__ScriptScopeVar
== Global-scope variables
** Set: $global:__GlobalScopeVar__ = 123
** Get: Write-Host $__GlobalScopeVar__
#>
$script:__ModulePath = $PsScriptRoot
$script:__ModuleName = $PsScriptRoot.Split("\")[-1]
$script:__DefaultLogPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), "PowerShell_$__ModuleName.log")
$script:__RequiredModules = @("ServerManager", "DnsClient")
$script:__ImportModulesExplicitely = $true
$script:__ImportModulesErrorAction = "Stop"
$global:__StopExecutionThrowsExeption__ = $true
$global:__StopExecutionExitsSession__ = $false

View File

@ -0,0 +1,34 @@
# Import config first
. "$PsScriptRoot\Config.ps1"
# Import functions from 'Include' subfolder
Get-ChildItem "$PsScriptRoot\Include" -Filter "*.ps1" |
ForEach-Object {
. "$($_.FullName)"
}
trap { Stop-Execution $_ }
Export-ModuleMember -Function * -Alias *
if ($__ImportModulesExplicitely) {
foreach ($Module in $__RequiredModules) {
Write-Log "Importing module '$Module' ..."
Import-Module -Name "$Module" -ErrorAction "$__ImportModulesErrorAction"
}
}
Write-Log "Module loaded from '$PsScriptRoot'"
#-------------------------------------------------------------------------------
switch ($Args[0]) {
'installTo' {
Install-Module -InstallPath $args[1] -ModulePath $PsScriptRoot
}
'register' {
Register-Module "$PsScriptRoot"
}
default {
}
}

View File

@ -0,0 +1,747 @@
Function Stop-Execution {
<#
.SYNOPSIS
Breaks execution with specified error code.
.DESCRIPTION
Function break script execution with error code provided. Error code may be 0 in case of non-error stop.
It also tries to parse ErrorRecord or Exception object (if provided) and logs this information.
#>
param (
$InputObject = $null,
[String] $ExitString = "",
[Int] $ExitCode = 1,
[Switch] $Success
)
Function Do-ExitFailure {
Write-LogFatal "STOP ($ExitCode): $ExitString"
if ($__StopExecutionThrowsExeption__) {
throw $InputObject
}
elseif ($__StopExecutionExitsSession__) {
exit $ExitCode
}
else {
break
}
}
Function Do-ExitSuccess {
Write-LogInfo "STOP (0): $ExitString"
if ($__StopExecutionThrowsExeption__) {
exit 0
}
elseif ($__StopExecutionExitsSession__) {
exit 0
}
else {
break
}
}
if ($Success -eq $true) {
if ($ExitString -eq "") {
$ExitString = "Script stopped with NO ERROR."
}
Do-ExitSuccess
}
if ($ExitString -ne "") {
Do-ExitFailure
}
if ($InputObject -eq $null) {
$ExitString = "***** SCRIPT INTERRUPTED *****"
Do-ExitFailure
}
if ($ExitString -eq "") {
try {
$ErrorRecord = [System.Management.Automation.ErrorRecord] $InputObject
$ExitString = @"
$($ErrorRecord.ToString())
*** Invocation Info ***
$($ErrorRecord.InvocationInfo.PositionMessage)
*** CategoryInfo ***
$($ErrorRecord.CategoryInfo.ToString())
*** FullyQualifiedErrorId ***
$($ErrorRecord.FullyQualifiedErrorId.ToString())
*** ScriptStackTrace ***
$($ErrorRecord.ScriptStackTrace.ToString())
*** *** ***
"@
}
catch {
$ErrorRecord = $null
Write-LogWarning "Unable to cast InputObject to [System.Management.Automation.ErrorRecord]"
}
}
if ($ExitString -eq "") {
try {
$Exception = [System.Exception] $InputObject
$ExitString = $Exception.ToString()
}
catch {
$Exception = $null
Write-LogWarning "Unable to cast InputObject to [System.Exception]"
}
}
if ($ExitString -eq "") {
try {
$ExitString = [String] $InputObject
}
catch {
Write-LogWarning "Unable to cast InputObject of type [$($InputObject.GetType())] to any of supported types."
}
}
Do-ExitFailure
}
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 {
<#
.SYNOPSIS
Convert to / request password as secure string.
#>
param (
[String] $Password,
[String] $Prompt = "Please enter password"
)
if ($Password -eq "") {
Read-Host -Prompt $Prompt -AsSecureString
}
else {
ConvertTo-SecureString -String "$Password" -AsPlainText -Force
}
}
Function New-Credential {
<#
.SYNOPSIS
Create new creadential object with username and password provided.
#>
param (
[Parameter(Mandatory=$true)]
[String] $UserName,
[String] $Password
)
$SecurePassword = Get-PasswordAsSecureString -Password "$Password"
New-Object System.Management.Automation.PSCredential( "$UserName", $SecurePassword )
}
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 {
if (-not ("win32.nativemethods" -as [type])) {
# Import SendMessageTimeout from Win32
Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"@
}
$HWND_BROADCAST = [IntPtr]0xFFFF
$WM_SETTINGCHANGE = 0x001A
$result = [UIntPtr]::Zero
# Notify all windows of environment block change
Write-Log "Executing 'SendMessageTimeout' ..."
$retval = [Win32.NativeMethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE,
[UIntPtr]::Zero, "Environment", 2, 5000, [ref] $result)
Write-Log "'SendMessageTimeout' returned '$retval' (non-zero is OK)"
}
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 {
param (
[String] $FilePath,
[String[]] $ArgumentList = @(' '),
[Int] $Timeout = 0,
[Switch] $NoWait,
[Switch] $PassThru
)
trap {
Write-LogError $_.Exception.Message
return $null
}
Write-Log "Starting program: $FilePath $ArgumentList"
$ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo
$ProcessStartInfo.FileName = $FilePath
$ProcessStartInfo.Arguments = $ArgumentList
$ProcessStartInfo.CreateNoWindow = $true
$ProcessStartInfo.RedirectStandardOutput = $true
$ProcessStartInfo.RedirectStandardError = $true
$ProcessStartInfo.UseShellExecute = $false
$Process = [System.Diagnostics.Process]::Start($ProcessStartInfo)
if ($NoWait) {
if ($PassThru) {
return $Process
}
else {
return $null
}
}
else {
if ($Timeout -eq 0) {
$Process.WaitForExit()
}
else {
$Process.WaitForExit($Timeout)
}
}
Write-Log ( "STDOUT:`n{0}" -f $Process.StandardOutput.ReadToEnd() )
Write-Log ":STDOUT"
Write-Log ( "STDERR:`n{0}" -f $Process.StandardError.ReadToEnd() )
Write-Log ":STDERR"
Write-Log "Program has finished with exit code ($($Process.ExitCode))"
if ($PassThru) {
return $Process
}
else {
return $null
}
}
New-Alias -Name Exec -Value Start-Program
function Test-ModuleVersion {
<#
.SYNOPSIS
Test module version.
.DESCRIPTION
Function specified module (current module by default), and compares it's version to version provided.
Returned values:
* -2 : error occured
* -1 : module's version is lower than one provided
* 0 : module's version is equal to one provided
* 1 : module's version is greater than one provided
#>
param (
[String] $Name = "$__ModuleName",
[String] $Version
)
$ModuleVersion = (Get-Module -Name $Name -ListAvailable).Version
if ($ModuleVersion -eq $null) {
Write-Log "Module '$Name' not found."
return -2
}
try {
$RequiredVersion = [System.Version]::Parse($Version)
}
catch {
Write-Log "'$Version' is not a correct version string."
return -2
}
$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
}

View File

@ -0,0 +1,139 @@
Function Initialize-Logger {
param (
[String] $ModuleName = $__ModuleName,
[String] $LogPath = $__DefaultLogPath
)
if (-not ("log4net.LogManager" -as [type])) {
$FileStream = ([System.IO.FileInfo] (Get-Item "$__ModulePath\log4net.dll")).OpenRead()
$AssemblyBytes = New-Object Byte[] $FileStream.Length
[Void] $FileStream.Read($AssemblyBytes, 0, $FileStream.Length)
$FileStream.Close()
[Void] [System.Reflection.Assembly]::Load($AssemblyBytes)
}
[log4net.GlobalContext]::Properties["LogPath"] = $LogPath
[log4net.GlobalContext]::Properties["ModuleName"] = $ModuleName
$script:__Logger = [log4net.LogManager]::GetLogger("PowerShell")
$Log4NetConfig = New-Object System.IO.FileInfo("$__ModulePath\log4net.config")
[log4net.Config.XmlConfigurator]::Configure($Log4NetConfig)
$__Logger.info("Logger initialized. Log file: '$LogPath'")
}
Function Write-LogInfo {
param (
[String[]] $Text
)
foreach ($Line in $Text) {
$__Logger.info($Line)
}
}
New-Alias -Name Write-Log -Value Write-LogInfo
Function Out-LogInfo {
param (
[Parameter(ValueFromPipeline=$true)]
[String] $Text
)
$__Logger.info($Text)
}
New-Alias -Name Out-Log -Value Out-LogInfo
Function Write-LogWarning {
param (
[String] $Text
)
foreach ($Line in $Text) {
$__Logger.warn($Line)
}
}
Function Out-LogWarning {
param (
[Parameter(ValueFromPipeline=$true)]
[String] $Text
)
$__Logger__.warn($Text)
}
Function Write-LogError {
param (
[String] $Text
)
foreach ($Line in $Text) {
$__Logger.error($Line)
}
}
Function Out-LogError {
param (
[Parameter(ValueFromPipeline=$true)]
[String] $Text
)
$__Logger.error($Text)
}
Function Write-LogFatal {
param (
[String] $Text
)
foreach ($Line in $Text) {
$__Logger.fatal($Line)
}
}
Function Out-LogFatal {
param (
[Parameter(ValueFromPipeline=$true)]
[String] $Text
)
$__Logger.fatal($Text)
}
Function Write-LogDebug {
param (
[String] $Text
)
foreach ($Line in $Text) {
$__Logger.debug($Line)
}
}
Function Out-LogDebug {
param (
[Parameter(ValueFromPipeline=$true)]
[String] $Text
)
$__Logger.debug($Text)
}
Initialize-Logger

View File

@ -0,0 +1,172 @@
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"
}

View File

@ -0,0 +1,120 @@
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
}

View File

@ -0,0 +1,42 @@
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
<param name="File" type="log4net.Util.PatternString" value="%property{LogPath}" />
<param name="AppendToFile" value="true" />
<param name="RollingStyle" value="Size" />
<param name="MaxSizeRollBackups" value="100" />
<param name="MaximumFileSize" value="1024KB" />
<param name="StaticLogFileName" value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%-5level] [%property{ModuleName}] %message%newline" />
</layout>
</appender>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="error" />
<foreColor value="Red, HighIntensity" />
</mapping>
<mapping>
<level value="warn" />
<foreColor value="Yellow, HighIntensity" />
</mapping>
<mapping>
<level value="info" />
<foreColor value="Green, HighIntensity" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%-5level] [%property{ModuleName}] %message%newline" />
</layout>
</appender>
<!--root>
<level value="info" />
</root-->
<logger name="PowerShell" additivity="false">
<!--level value="info" /-->
<appender-ref ref="ColoredConsoleAppender" />
<appender-ref ref="RollingFileAppender" />
</logger>
</log4net>