func_Start-AlocVMM2DVLSSync.ps1

<#
 .Synopsis
  Syncs data from System Center Virtual Machine Manger to Remote Desktop Manager
 
 .Description
  This function gets the information of all VM's in SC VMM an sync over to RDM
  If the entry isn't found in RDM the entry will be created in the specified folder.
 
 .Parameter DataSourceName
  Name of the RDM Datasource to connect to.
  Only required if you run this headless and there is 2 or more data sources, as the script then prompt to as which data source to connect to.
 
 .Parameter VMMFQDN
  Full dns name of the VMMServer to get VM's from
 
 .Parameter VMGroup
  The path to the folder where new VM's wil be created
 
 .Example
   Sync-VMM2DVLS -VMMFQDN "SCVMM01.domain.com" -VMGroup "SCVMM\NewVMs"
#>

function Start-AlocVMM2DVLSSync {
    [CmdletBinding()]
    param (
        # Name of the RDM Datasource
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "ReuseInjectAppKey",
            HelpMessage = "Name of the RDM Datasource"
        )]
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "CreateDataSource",
            HelpMessage = "Name of the RDM Datasource"
        )]
        [Alias("DataSourceName")]
        [String]
        $DSName,

        # Full dns name of the VMMServer to get VM's from
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "Reuse",
            HelpMessage = "Full dns name of the VMMServer to get VM's from"
        )]
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "ReuseInjectAppKey",
            HelpMessage = "Full dns name of the VMMServer to get VM's from"
        )]
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "CreateDataSource",
            HelpMessage = "Full dns name of the VMMServer to get VM's from"
        )]
        [Alias("VMMFQDN")]
        [String]
        $VMMServerName,

        # The path to the folder where new VM's wil be created
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "Reuse",
            HelpMessage = "The path to the folder where new VM's wil be created"
        )]
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "ReuseInjectAppKey",
            HelpMessage = "The path to the folder where new VM's wil be created"
        )]
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "CreateDataSource",
            HelpMessage = "The path to the folder where new VM's wil be created"
        )]
        [Alias("VMGroup")]
        [String]
        $BaseGroup,

        # Application key from Devolutions server
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "ReuseInjectAppKey",
            HelpMessage = "Application key from Devolutions server"
        )]
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "CreateDataSource",
            HelpMessage = "Application key from Devolutions server"
        )]
        [String]
        $AppKey,

        # Application Secret from Devolutions server
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "ReuseInjectAppKey",
            HelpMessage = "Application Secret from Devolutions server"
        )]
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "CreateDataSource",
            HelpMessage = "Application Secret from Devolutions server"
        )]
        [String]
        $AppSecret,

        # If set, a datasource will be created instead of using an existing
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "CreateDataSource",
            HelpMessage = "If set, a datasource will be created instead of using an existing"
        )]
        [Switch]
        $CreateDS,

        # Name of the DVLS server
        [Parameter(
            Mandatory = $True,
            ParameterSetName = "CreateDataSource",
            HelpMessage = "Name of the DVLS server"
        )]
        [Alias("Hostname")]
        [string]
        $DVLSHostname,
        # Tries to get extended inofrmation from the VMs
        [Parameter(
            Mandatory = $False,
            ParameterSetName = "Reuse",
            HelpMessage = "If specified, extra information is tried to be collected."
        )]
        [Parameter(
            Mandatory = $False,
            ParameterSetName = "ReuseInjectAppKey",
            HelpMessage = "If specified, extra information is tried to be collected."
        )]
        [Parameter(
            Mandatory = $False,
            ParameterSetName = "CreateDataSource",
            HelpMessage = "If specified, extra information is tried to be collected."
        )]
        [Switch]
        $ExtendedInfo
    )

    if ($CreateDS) {
        $DSAction = "CreateDataSource"
    }elseif ($DSName -ne "") {
        $DSAction = "ReuseInjectAppKey"
    }else {
        $DSAction = "Reuse"
    }

    $PrevErrorActionPreference = $ErrorActionPreference
    $ErrorActionPreference = "Stop"
    
    $PrePadding = "
     
----VMM-Desc----
"

    $PostPadding = "
----VMM-End----
"

    $VerbosePref = $VerbosePreference
    $VerbosePreference = "SilentlyContinue"
    if ((Get-Module).Name -notcontains "RemoteDesktopManager") {
        if ((Get-Module -ListAvailable).Name -contains "RemoteDesktopManager") {
                try {
                    Write-Verbose "Importing RemoteDesktopManager"
                    Import-Module RemoteDeskTopManager 
                }
                catch {
                    Write-Error "Failed to import RemoteDesktopManager"
                }
        }else{
            try {
                Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Scope CurrentUser -Force
                Install-Module RemoteDesktopManager -Scope CurrentUser -Force
            }
            catch {
                Write-Error "RemoteDesktopManager Module not installed, and installation failed."
            }
            
        }
    }
    $VerbosePreference = $VerbosePref
    Write-Verbose "Connecting to Devolutions Server"
    $DataSources = Get-RDMDataSource
    switch ($DSAction) {
        "Reuse" {
            if ($DataSources.Count -gt 1) {
                Write-Host "Select the data source to connect to:"
                $i = 0
                foreach ($DataSource in $DataSources) {
                    Write-Host "$($i): $($DataSource.Name)"
                    $i++
                }
                [int]$Selection = Read-Host "Enter Number"
                Set-RDMCurrentDataSource -DataSource $DataSources[$Selection]
            }else {
                Set-RDMCurrentDataSource -DataSource $DataSources[0]
            }
        }
        "ReuseInjectAppKey" {
            try {
                Write-Verbose "Using datasource $DSName and specified Key/Secret"
                $Currentds = Get-RDMDataSource $DSName
                Set-RDMCurrentDataSource $Currentds
                Set-RDMDatasourceProperty $Currentds -Property "ScriptingTenantID" -Value $AppKey
                Set-RDMDatasourceProperty $Currentds -Property "ScriptingApplicationPassword" -Value $AppSecret
                if ($VerbosePreference = "Continue") {
                    Get-RDMDatasourceProperty $Currentds -Property "ScriptingTenantID"
                    Get-RDMDatasourceProperty $Currentds -Property "ScriptingApplicationPassword"
                }
                Set-RDMCurrentDataSource $Currentds
            }
            catch {
                Write-Error "The datasource supplied could not be found."
            }
        }
        "CreateDataSource" {
            Write-Verbose "Creating datasource $DSName"
            if ($DataSources.Name.Contains($DSName)) {
                Remove-RDMDataSource $DSName
            }
            if ($DVLSHostname.Substring(0,8).ToLower() -ne "https://"){
                $DVLSHostname = "https://$DVLSHostname"
            }
            $ds = New-RDMDataSource -DVLS -Server $DVLSHostname -Name $DSName -ScriptingTenantID $AppKey -ScriptingApplicationPassword $AppSecret
            if ($VerbosePreference = "Continue") {
                Get-RDMDatasourceProperty $ds -Property "ScriptingTenantID"
                Get-RDMDatasourceProperty $ds -Property "ScriptingApplicationPassword"
            }
            Set-RDMCurrentDataSource $ds
        }
    }

    if ($Currentds.IsConnected -eq $True -and $Currentds.IsOffline -eq $false) {
        Write-Verbose "Connected to RDM, datasource $($Currentds.Name)"
        $RDMHosts = Get-RDMSession
    }else{
        try {
            $RDMHosts = Get-RDMSession
        }
        catch {
            Get-RDMCurrentDataSource
            Write-Error "Connection ot RDM, datasource $($Currentds.Name) not ready, script exits"
            exit
        }
    }

    Try {
        # Expecting Domain, so trying default connection to VMM Server
        Write-Verbose "Connecting to VMM server..."
        $PSSession = New-PSSession -ComputerName $VMMServerName
    }
    Catch {
        # Domain login failed, trying negotiate
        try {
            if (Test-Path .\vmmcred.clixml) {
                $Creds = Import-Clixml .\vmmcred.clixml
                $PSSession = New-PSSession -ComputerName $VMMServerName -Credential $Creds
            }else {
                Write-Warning "Kerberos autentication failed, and no .\vmmcred.clixml file exists
             Please create a vmmcred.clixml file with credenetials to access to VMM Server by running, in the same directory at this script
             Get-Credential | Export-Clixml .\vmmcred.clixml"

             exit
            }
        }
        catch {
            $Message = 'Cannot connect to VMM Server: {0}
            Possible solution is to run, in an Elevated Powershell winodws:
            "Set-Item WSMan:\localhost\Client\TrustedHosts\ -Value {0}"
             
            The script will now end.'
 -f $VMMServerName
            Write-Error -Message $Message
            Exit
        }
    }
    Write-Verbose "Connected to VMM"
    Write-Verbose "Getting list of VMs from VMM"
    $VMs = Invoke-Command -Session $PSSession -ArgumentList $VMMServerName -ScriptBlock {Get-SCVirtualMachine -VMMServer $Args[0]}
    Remove-PSSession -Session $PSSession
    Write-Verbose "List Retrieved"

    #$VMs = @(@{Name = "Server1"; Description = "This is the first server"; ComputerName = "Server1.aloc.com"},@{Name = "Server2"; Description = "This is server two"; ComputerName = "Server1.aloc.com"})

    
    ForEach ($VM in $VMs | Where-Object {$_.name -notlike "SLOT-[0-9][0-9][0-9]" -or $_.Name -notlike "VM-[0-9][0-9]" -or $_.name -notlike "NP-[0-9][0-9]" -or $_.name -notlike "SP-[0-9][0-9]"}){
        if ($null -eq $VM.ComputerName -or $VM.ComputerName -eq "") {
            Write-Debug "Skipping $($VM.Name) No hostname"
            Continue
        }elseif (($VMs | Where-Object {$_.Name -eq $VM.Name}).count -gt 1) {
            Write-Debug "Skipping $($VM.Name) Multiple VM instances"
            Continue
        }
        $RDMHost = $RDMHosts | Where-Object {$_.Host -eq $VM.ComputerName -and $_.ConnectionType -eq "Group" -and $_.GroupDetails.GroupType -eq "Server"}
        $RDMName = $RDMHosts | Where-Object {$_.Name -eq $VM.Name -and $_.ConnectionType -eq "Group" -and $_.GroupDetails.GroupType -eq "Server"}
        if ($RDMHost.Count -eq 1) {
            $Action = "Edit"
        }elseif ($RDMName.Count -eq 1) {
            $RDMHost = $RDMName
            $Action = "Edit"
        }elseif ($RDMHost.Count -gt 1 -and $RDMName.Count -gt 1) {
            Write-Debug "Skipping $($VM.Name)/$($VM.ComputerName), multiple RDM entries found"
        }elseif ($RDMHost.Count -eq 0 -and $RDMName.Count -eq 0){
            $Action = "NewEntry"
        }else{
            Write-Debug "Cant choose action for $($VM.Name)/$($VM.ComputerName)"
            $Action = "None"
        }
        if ($Action -eq "Edit") {
            if ($($RDMHost.Description -match ("----VMM-Desc----") -and $RDMHost.Description -match ("----VMM-End----"))){
                $Action = "Edit"
            }else {
                $Action = "FirstEdit"
            }
        }
        Write-Verbose "Action selected: $Action"
        if ($Action -eq "Edit" -or $Action -eq "FirstEdit") {
            Write-Verbose "Updating host: $($VM.Name)"
            try {
                $N = ([regex]::Matches($RDMHost.Description, "----VMM-Desc----" )).count
                if ($N -gt 1) {
                    $Start = $($RDMHost.Description).IndexOf("----VMM-Desc----")
                    $End = $($RDMHost.Description).LastIndexOf("----VMM-End----")
                    $Begining = $RDMHost.Description.Substring(0,$Start).trim()
                    $Last = $RDMHost.Description.Substring($End+15).Trim()
                    $RDMHost.Description = "
$Begining
 
----VMM-Desc----
----VMM-End----
$Last"
.Trim()
                    $RDMHost.Description = $RDMHost.Description -replace (" ","")
                    $Action = "Edit"
                }
                if ($Action -eq "FirstEdit") { 
                    $RDMHost.Description = $RDMHost.Description + $PrePadding + $VM.Description + $PostPadding
                }else{
                    $HostDesc = $RDMHost.Description
                    $NewDesc = $HostDesc.Substring(0,$HostDesc.IndexOf("----VMM-Desc----")+18)
                    $NewDesc += $VM.Description
                    $NewDesc += $HostDesc.Substring(($HostDesc.IndexOf("----VMM-End----"))-2,$HostDesc.Length-($HostDesc.IndexOf("----VMM-End----")-2))
                    $RDMHost.Description = $NewDesc
                }
                Write-Verbose "Updating variable"
                
                $RDMHost.Group = $RDMHost.Group -replace ($RDMHost.name,$VM.Name)
                $RDMHost.Name = $VM.name
                $RDMHost.Host = $VM.ComputerName
            }
            catch {
                Write-Error "Failed to update variables $_"
            }
            try {
                Write-Verbose "Saving to RDM"
                Set-RDMSession $RDMHost -Refresh
            }
            catch {
                Write-Error "Failed to save entry $_"
            }
        }Elseif ($Action = "NewEntry") {
            if ($VM.name -like "SLOT-[0-9][0-9][0-9]" -or $VM.Name -like "VM-[0-9][0-9]" -or $VM.name -like "NP-[0-9][0-9]" -or $VM.name -like "SP-[0-9][0-9]") {
                Write-Verbose "Booking slot, skipping"
                Continue
            }
            Write-Verbose "Entry not found, creating: $($VM.Name)"

            try {
                $DefaultInfo = 'HOST: $HOST$
                IP: $COMPUTER_IP$'

                $NewSession = New-RDMSession -Type Group -Name $VM.Name -Host $VM.ComputerName -Group $BaseGroup
                $NewSession.GroupDetails.GroupType = "Server"
                $NewSession.CredentialConnectionID = "1310CF82-6FAB-4B7A-9EEA-3E2E451CA2CF"
                $NewSession.Description = $DefaultInfo + $PrePadding + $VM.Description + $PostPadding
                if ($ExtendedInfo) {
                    #$ExtendedInfomation | fl -Property *
                    $ExtendedInfomation = Start-AlocExtendedScan $vm.ComputerName
                    $NewSession.MetaInformation = $ExtendedInfomation.OperatingSystem
                }
            }
            catch {
                Write-Error "Failed to create varible $_"
            }
            try {
                Write-Verbose "Saving Host entry"
                Set-RDMSession $NewSession
            }
            catch {
                Write-Error "Failed to save to RDM $_
                $($NewSession.Group)"

            }
            try {
                Write-Verbose "Create RDP Connection"
                $NewRDP = New-RDMSession -Type RDPConfigured -Name "RDP" -TemplateID "157fc699-d152-4c8b-a944-19be44c736e7" -Host "" -Group $NewSession.Group
            }
            catch {
                Write-Error "Failed to create RDP Connection"
            }
            try {
                Write-Verbose "Saving RDP Connection"
                Set-RDMSession $NewRDP
            }
            catch {
                Write-Error "Failed to save RDP Connection"
            }
            Write-Debug "Creation done."
        }
    }
    
    # Setting back system variables
    $VerbosePreference = $PrevVerbosePreference
    $ErrorActionPreference = $PrevErrorActionPreference
    
}
function Start-AlocExtendedScan {
    param (
        # The Server FQDN to look up
        [Parameter(Mandatory = $true, Position = 0)]
        [String]
        $FQDN
    )
    # $FQDN = "dvls.aloc.com"
        try {
            $CimS = New-CimSession -ComputerName $FQDN -Credential $Cred
            $Information = Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $CimS
            Remove-CimSession $CimS
            Return $Information
        }
        catch {
            Write-Warning "Extended information could not be retrieved"
            return $null
        }
}