1Cv83_InfoBaseManagement.psm1

# Connect-1cCluster; Connect-1cWP
# Connect-1cCluster 10.0.0.31; Connect-1cWP

Function Connect-1cCluster
{
    param(
        [string]$Server = 'localhost',
        [PSCredential]$Credential,
        [string]$ComObject = 'V83.COMConnector'
    )
    
    $Global:1c = [ordered]@{
        'Server' = $Server
        'ComObject' = $Null
        'Cluster' = $Null
        'Agent' = [ordered]@{
            'Connect' = $Null
            'Credential' = [PSCredential]$Null
            'Authenticated' = $false
            'WP' = @()
        }
        'WP' = [ordered]@{
            'Credential' = [PSCredential]$Null
            'Connect' = @()
            'InfoBases' = @()
            'InfoBaseInfo' = @()
        }
    }
    
    
    if(!$Credential) {
        if(!$1c.Agent.Credential) {
            [string]$UserName = $Null
            [string]$Password = $Null
        } else {
            [string]$UserName = $1c.Agent.Credential.UserName
            [string]$Password = $1c.Agent.Credential.GetNetworkCredential().Password
        }
    } else {
        $1c.Agent.Credential = $Credential
        [string]$UserName = $1c.Agent.Credential.UserName
        [string]$Password = $1c.Agent.Credential.GetNetworkCredential().Password
    }
    
    $1c.ComObject = New-Object -COMObject $ComObject
    $1c.Agent.Connect = $1c.ComObject.ConnectAgent($Server)
    $1c.Cluster = @($1c.Agent.Connect.GetClusters())[0]
    
    try {
        $1c.Agent.Authenticated = $true
        $1c.Agent.Connect.Authenticate($1c.Cluster, $UserName, $Password)
    } catch {
        $1c.Agent.Authenticated = $false
        Write-Error 'error[Authenticate]'
    }
    
    [pscustomobject][ordered]@{'Server' = $1c.Server; 'ConnectTo1cCluster' = [bool]$1c.Agent.Authenticated; 'ConnectTo1cWP' = [bool]$1c.WP.Connect}
}

Function Get-1cWorkingServers
{
    if(!$1c.Cluster){
        Write-Error 'use Connect-1cCluster'
        break
    }
    
    $1c.Agent.Connect.GetWorkingServers($1c.Cluster)
}

Function Get-1cCluster
{
    if(!$1c.Cluster){
        Write-Error 'use Connect-1cCluster'
        break
    }
    
    $1c.Cluster
}

Function Get-1cClusterInfoBase
{
    param(
        [string]$infoBaseName = '*'
    )
    if(!$1c.Agent.Authenticated){
        Write-Error 'use Connect-1cCluster'
        break
    }
    $1c.Agent.Connect.GetInfoBases($1c.Cluster) | ? {$_.Name -like $infoBaseName}
}

Function Get-1cClusterConnection
{
<#
.EXAMPLE
Get-1cClusterConnection -ProcessMainPort 1562
#>

    param(
        [string]$infoBaseName = '*',
        [string]$SessionID = '*',
        [string]$ConnID = '*',
        [string]$ProcessMainPort = '*',
        [string]$ProcessPID = '*'
    )
    if(!$1c.Agent.Authenticated){
        Write-Error 'use Connect-1cCluster'
        break
    }
    $1c.Agent.Connect.GetConnections($1c.Cluster) | ? {($_.infoBase.Name -like $infoBaseName) -and ($_.SessionID -like $SessionID) -and ($_.ConnID -like $ConnID) -and ($_.process.MainPort -like $processMainPort) -and ($_.process.PID -like $ProcessPID)}
}

Function Get-1cClusterSession
{
<#
.EXAMPLE
Get-1cClusterSession
#>

    param(
        [string]$infoBaseName = '*',
        [string]$userName = '*',
        [string]$SessionID = '*'
    )
        if(!$1c.Agent.Authenticated){
            Write-Error 'use Connect-1cCluster'
            break
        }
        $1c.Agent.Connect.GetSessions($1c.Cluster) | Select-Object -Property @{'Name'='infoBaseName'; 'Expression'={$_.infoBase.Name}},* | ? {($_.infoBase.Name -like $infoBaseName) -and ($_.userName -like $userName) -and ($_.SessionID -like $SessionID)}
    
}

Function Get-1cClusterInfoBaseSession
{
<#
.EXAMPLE
Get-1cClusterInfoBase DB* | Get-1cClusterInfoBaseSession
#>

    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)][System.__ComObject[]]$InfoBase,
        [string]$infoBaseName = '*',
        [string]$userName = '*',
        [string]$SessionID = '*'
    )
    begin{
        if(!$1c.Agent.Authenticated){
            Write-Error 'use Connect-1cCluster'
            break
        }
    }
    
    process{
        $InfoBase | % {
            $1c.Agent.Connect.GetInfoBaseSessions($1c.Cluster,$_) | ? {($_.infoBase.Name -like $infoBaseName) -and ($_.userName -like $userName) -and ($_.SessionID -like $SessionID)}
        }
        
    }
    
}

Function Stop-1cClusterInfoBaseSession
{
<#
.EXAMPLE
Get-1cClusterInfoBase DB* | Get-1cClusterInfoBaseSession -userName *Smith* | Stop-1cClusterInfoBaseSession
#>

    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)][alias('Name')][System.__ComObject[]]$InfoBaseSession
    )
    begin{
        if(!$1c.Agent.Authenticated){
            Write-Error 'use Connect-1cCluster'
            break
        }
    }
    process{
        $InfoBaseSession | % {
            $1c.Agent.Connect.TerminateSession($1c.Cluster, $_)
            
        }
    }
}

Function Get-1cClusterWP
{
<#
.EXAMPLE
 Get-1cClusterWP -MainPort *1
#>

    param(
        [string]$MainPort = '*',
        [string]$PidWP = '*'
    )
    if(!$1c.Agent.Authenticated){
        Write-Error 'use Connect-1cCluster'
        break
    }
    $1c.Agent.Connect.GetWorkingProcesses($1c.Cluster) | ? {($_.MainPort -like $MainPort) -and ($_.PID -like $PidWP)}
}

Function Connect-1cWP
{
    param(
        [PSCredential]$Credential
    )
    
    if(!$1c.Cluster){
        Write-Error 'use Connect-1cCluster'
        break
    }
    
    if(!$Credential) {
        if(!$1c.WP.Credential) {
            [string]$UserName = $Null
            [string]$Password = $Null
        } else {
            [string]$UserName = $1c.WP.Credential.UserName
            [string]$Password = $1c.WP.Credential.GetNetworkCredential().Password
        }
    } else {
        $1c.WP.Credential = $Credential
        [string]$UserName = $1c.WP.Credential.UserName
        [string]$Password = $1c.WP.Credential.GetNetworkCredential().Password
    }
    
    $1c.Agent.WP = @($1c.Agent.Connect.GetWorkingProcesses($1c.Cluster))
    if($1c.Agent.WP){
        $1c.WP.Connect = @($1c.Agent.WP | ? {$_.MainPort -ge 1} | % { $1c.ComObject.ConnectWorkingProcess( $('tcp://' +$_.HostName+':'+$_.MainPort) ) })
        $1c.WP.Connect | % {$_.AuthenticateAdmin($UserName,$Password)}
        $1c.WP.Connect | % {$_.AddAuthentication($UserName,$Password)}
    } else {Write-Error 'WorkingProcesses not connected'; break}
    
    [pscustomobject][ordered]@{'Server' = $1c.Server; 'ConnectTo1cCluster' = [bool]$1c.Agent.Authenticated; 'ConnectTo1cWP' = [bool]$1c.WP.Connect}
}

Function Get-1cWPInfoBase
{
    param(
        [string]$Name = '*',
        [string]$DBName = '*'
    )
    if(!$1c.WP.Connect){
        Write-Error 'use Connect-1cWP'
        break
    }
    $1c.WP.Connect | % {$_.GetInfoBases()} | ? {($_.Name -like $Name) -and ($_.DBName -like $DBName)} | Group-Object -Property Name | % {$_.Group | Select-Object -Unique}
}

Function Set-1cWPInfoBase
{
<#
.EXAMPLE
 Get-1cWPInfoBase -Name DB | Set-1cWPInfoBase -DeniedFrom (Get-Date).AddDays(-20) -DeniedTo (Get-Date).AddDays(-10) -DeniedMessage 'Test'
#>

    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)][System.__ComObject[]]$InfoBase,
        [string]$DBServerName,
        [string]$DBName,
        [string]$DBUser,
        [string]$DBPassword,
        [bool]$ConnectDenied,
        [datetime]$DeniedFrom,
        [datetime]$DeniedTo,
        [string]$DeniedMessage,
        [string]$PermissionCode,
        [bool]$ScheduledJobsDenied,
        [bool]$SessionsDenied
    )
    
    begin{
        if(!$1c.WP.Connect){
            Write-Error 'use Connect-1cWP'
            break
        }
    }
    
    process{
        $InfoBase | % {
            if($DBServerName){$_.DBServerName = $DBServerName}
            if($DBName){$_.DBName = $DBName}
            if($DBUser){$_.DBUser = $DBUser}
            if($DBPassword){$_.DBPassword = $DBPassword}
            if($MyInvocation.BoundParameters.ContainsKey('ConnectDenied')){$_.ConnectDenied = $ConnectDenied}
            if($DeniedFrom){$_.DeniedFrom = $DeniedFrom}
            if($DeniedTo){$_.DeniedTo = $DeniedTo}
            if($DeniedMessage){$_.DeniedMessage = $DeniedMessage}
            if($PermissionCode){$_.PermissionCode = $PermissionCode}
            if($MyInvocation.BoundParameters.ContainsKey('ScheduledJobsDenied')){$_.ScheduledJobsDenied = $ScheduledJobsDenied}
            if($MyInvocation.BoundParameters.ContainsKey('SessionsDenied')){$_.SessionsDenied = $SessionsDenied}
            
            foreach ($connect in $1c.WP.Connect) {$connect.UpdateInfoBase($_)}
            $_
        }
    }
}

Function Remove-1cWPInfoBase
{
<#
.EXAMPLE
Get-1cWPInfoBase DB* | Remove-1cWPInfoBase -SqlDatabaseAction Delete
#>

    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)][System.__ComObject[]]$InfoBase,
        [ValidateSet('No','Delete','Clean')][string]$SqlDatabaseAction = 'No'
    )
    
    begin{
        if(!$1c.WP.Connect){
            Write-Error 'use Connect-1cWP'
            break
        }
        
        $Action = @{'No' = 0; 'Delete' = 1; 'Clean' = 2;}
    }
    
    process{
        $InfoBase | % {
            $_
            $1c.wp.Connect[0].DropInfoBase($_, $($Action[$SqlDatabaseAction]))
        }
    }
}

Function Add-1cWPInfoBase
{
<#
.EXAMPLE
Add-1cWPInfoBase -Name DB -Descr DB -DBServerName localhost -DBName DB -DBUser sa -DBPassword P@$$w0rd -ScheduledJobsDenied $true -LicenseDistributionAllowed $false -CreateEmptyDB $true
#>

    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Name,
        [string]$Descr = 'PowerShell',
        [ValidateSet('MSSQLServer','PostgreSQL','IBMDB2','OracleDatabase')][string]$DBMS = 'MSSQLServer',
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$DBServerName,
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$DBName,
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$DBUser,
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$DBPassword,
        [datetime]$DeniedFrom,
        [datetime]$DeniedTo,
        [string]$DeniedMessage,
        [string]$PermissionCode,
        [string]$Locale = 'RU',
        [bool]$ConnectDenied = $False,
        [bool]$ScheduledJobsDenied = $False,
        [bool]$SessionsDenied = $False,
        [bool]$LicenseDistributionAllowed = $False,
        [bool]$CreateEmptyDB = $False
    )
    
        if(!$1c.WP.Connect){
            Write-Error 'use Connect-1cWP'
            break
        }
        
        $InfoBaseInfo = $1c.WP.Connect[0].CreateInfoBaseInfo()
        $InfoBaseInfo.Name = $Name
        if($Descr){$InfoBaseInfo.Descr = $Descr}
        $InfoBaseInfo.DBMS = $DBMS
        $InfoBaseInfo.DBServerName = $DBServerName
        $InfoBaseInfo.DBName = $DBName
        $InfoBaseInfo.DBUser = $DBUser
        $InfoBaseInfo.DBPassword = $DBPassword
        if($DeniedFrom){$InfoBaseInfo.DeniedFrom = $DeniedFrom}
        if($DeniedTo){$InfoBaseInfo.DeniedTo = $DeniedTo}
        if($DeniedMessage){$InfoBaseInfo.DeniedMessage = $DeniedMessage}
        if($PermissionCode){$InfoBaseInfo.PermissionCode = $PermissionCode}
        $InfoBaseInfo.Locale = $Locale
        $InfoBaseInfo.ConnectDenied = $ConnectDenied
        $InfoBaseInfo.ScheduledJobsDenied = $ScheduledJobsDenied
        $InfoBaseInfo.SessionsDenied = $SessionsDenied
        $InfoBaseInfo.LicenseDistributionAllowed = [int]$LicenseDistributionAllowed
        
        $InfoBaseInfo
        $1c.wp.Connect[0].CreateInfoBase($InfoBaseInfo,$([int]$CreateEmptyDB))
}

Function Get-1cReportClusterConnection
{
    param(
        [string]$infoBaseName = '*',
        [string]$UserName = '*',
        [string]$processMainPort = '*'
    )
    if(!$1c.WP.Connect){
        Write-Error 'use Connect-1cWP'
        break
    }
    $InfoBaseSessionHash = Get-1cClusterInfoBase  | Get-1cClusterInfoBaseSession | Group-Object -Property SessionID -AsHashTable
    
    Get-1cClusterConnection | ? {($_.infoBase.Name -like $infoBaseName) -and ($_.Process.MainPort -like $ProcessMainPort)} | Select-Object -Property @(
        @{Name='infoBaseName'; Expression={$_.infoBase.Name}}
        @{Name='ProcessPID'; Expression={$_.process.PID}}
        @{Name='UserName'; Expression={$InfoBaseSessionHash[[int]$_.SessionID].userName}}
        @{Name='ProcessMainPort'; Expression={$_.process.MainPort}}
        @{Name='ProcessHostName'; Expression={$_.process.HostName}}
        @{Name='SessionHost'; Expression={$InfoBaseSessionHash[[int]$_.SessionID].Host}}
        @{Name='SessionAppID'; Expression={$InfoBaseSessionHash[[int]$_.SessionID].AppID}}
        @{Name='ProcessConnections'; Expression={$_.process.connections}}
        @{Name='ProcessStartedAt'; Expression={$_.process.StartedAt}}
        @{Name='SessionMemoryAll'; Expression={$InfoBaseSessionHash[[int]$_.SessionID].MemoryAll}}
        @{Name='ProcessMemorySize'; Expression={$_.process.MemorySize}}
        '*'
        
    ) | ? {$_.UserName -like $UserName}
}

Function Get-1cReportClusterInfoBaseSession
{
    param(
        [string]$infoBaseName = '*',
        [string]$UserName = '*'
    )
    
    if(!$1c.WP.Connect){
        Write-Error 'use Connect-1cWP'
        break
    }
    Get-1cClusterInfoBase | Get-1cClusterInfoBaseSession | ? {($_.infoBase.Name -like $infoBaseName) -and ($_.userName -like $UserName)} | Select-Object -Property @(
        @{Name='infoBaseName'; Expression={$_.infoBase.Name}}
        '*'
        @{Name='LicenseFullPresentation'; Expression={$_.License.FullPresentation}}
    ) -ExcludeProperty License
}

Function Reset-1cConnection
{
    if($1c.ComObject){[System.Runtime.Interopservices.Marshal]::ReleaseComObject($1c.ComObject)}
    if($1c.Cluster){[System.Runtime.Interopservices.Marshal]::ReleaseComObject($1c.Cluster)}
    if($1c.Agent.Connect){[System.Runtime.Interopservices.Marshal]::ReleaseComObject($1c.Agent.Connect)}
    if($1c){Remove-Variable -Name 1c -Scope Global -Force -ErrorAction SilentlyContinue}
    
    [System.GC]::Collect()
}