Блог

  • Мне довелось создать реплику виртуальных машин средствами Veeam B&R. Забавно то что используя GUI это делается за пару кликов, однако задача состояла в том что бы создать реплики на более чем 15 машин при этом каждая машина должна быть отдельной джобой. Что бы не терять большое количество времени, я решил написать небольшой скрипт на Powershell который сделает это за меня. Я постарался максимально унифицировать этот скриптик, но думаю можно будет сделать это еще эффективнее. Тело скрипта под катом.

    Тыкни
    function New-ReplicaJob {
        param (
            [string]$JobName, 
            [string]$TargetServerIP, 
            [string]$VMName, 
            [string]$TargetDatastore,
            [string]$SourceIP, 
            [string]$SourceMask, 
            [string]$ReIpTargetIP, 
            [string]$ReIpTargetMask,
            [string]$ReIpGateway, 
            [string]$ReIpDNS, 
            [string]$SourceNetwork, 
            [string]$TargetNetwork,
            [string]$SourceProxy, 
            [string]$TargetProxy, 
            [string]$Repository = "DefaultRepo"
        )
    
        $Description = "$JobName replication job"
        $RestorePointsToKeep = 7
    
        $TargetServer = Get-VBRServer -Name    $TargetServerIP
        $VMObject = Find-VBRViEntity -Name $VMName
        $Datastore = Find-VBRViDatastore -Name $TargetDatastore -Server $TargetServerIP
        $ReIpRule = New-VBRViReplicaReIpRule -SourceIp $SourceIP -SourceMask $SourceMask -TargetIp $ReIpTargetIP -TargetMask $ReIpTargetMask -TargetGateway $ReIpGateway -DNS $ReIpDNS
    
        $SrcNetwork = Get-VBRViServerNetworkInfo -Server $VMObject.VmHostName | Where-Object { $_.Name -eq $SourceNetwork }
        $TgtNetwork = Get-VBRViServerNetworkInfo -Server $TargetServer.Name | Where-Object { $_.Name -eq $TargetNetwork }
    
        $SrcProxy = Get-VBRViProxy -Name $SourceProxy
        $TgtProxy = Get-VBRViProxy -Name $TargetProxy
    
        Add-VBRViReplicaJob -Name $JobName `
                            -Server $TargetServer `
                            -Entity $VMObject `
                            -Datastore $Datastore `
                            -Suffix "_replica" `
                            -BackupRepository $Repository `
                            -Description $Description `
                            -EnableNetworkMapping `
                            -SourceNetwork $SrcNetwork `
                            -TargetNetwork $TgtNetwork `
                            -SourceProxy $SrcProxy `
                            -TargetProxy $TgtProxy `
                            -RestorePointsToKeep $RestorePointsToKeep `
                            -ReIpRule $ReIpRule `
                            -HighPriority `
                            -Force
    }
    
    Connect-VIServer "$(Read-Host 'Enter vCenter hostname or IP')" -Credential (Get-Credential)
    Connect-VBRServer -Server "$(Read-Host 'Enter Veeam hostname or IP')" -Credential (Get-Credential)
    
    $VMList = @(
    "$(Read-Host 'Enter VM names to replicate, separated by comma (no spaces)')".Split(",") | Where-Object { $_ -ne '' }
    )
    
    foreach ($VM in $VMList) {
        $GuestIP = (Get-VM $VM).Guest.IPAddress[0]
        $GuestNet = (Get-VM $VM).Guest.Nics.NetworkName[0]
        $LastOctet = $GuestIP.Split(".")[-1]
        $NewTargetIP = "192.168.100.$LastOctet"
        $NewGateway = "192.168.100.1"
    
        New-ReplicaJob -JobName $VM `
                       -TargetServerIP "192.168.0.10" `
                       -VMName $VM `
                       -TargetDatastore "TargetDatastore" `
                       -SourceIP $GuestIP `
                       -SourceMask "255.255.255.0" `
                       -ReIpTargetIP $NewTargetIP `
                       -ReIpTargetMask "255.255.255.0" `
                       -ReIpGateway $NewGateway `
                       -ReIpDNS "192.168.100.10" `
                       -SourceNetwork $GuestNet `
                       -TargetNetwork "TargetNetworkName" `
                       -SourceProxy "SourceProxyName" `
                       -TargetProxy "TargetProxyName" `
                       -Repository "DefaultRepo"
    }
    
  • Недавно я столкнулся с острой необходимостью прямой работы с IE на Windows 11. Однако, я столкнулся с тем что просто режим совместимости в EDGE совершенно недостаточно. Немного поразмышляв, я пришел к выводу что ничто так не симулирует стабильную работу IE как сам IE. На просторах Интернета я нашел довольно забавный и рабочий метод открытия IE несмотря на все заявления мелкомягких о том что IE выпилен. Ниже пример скрипта на Powershell. В моем решении я скомпилировал нижеследующий скрипт в EXE файл с помощью Invoke-PS2EXE и использую в своих целях.

    Тыкни
    $vbsFilePath = "$env:APPDATA\ie.vbs"
    $vbsContent = @'
    Set objIE = CreateObject("InternetExplorer.Application")
    objIE.Navigate "https://любой.произвольный.сайт"
    objIE.Visible = 1
    '@
    Set-Content -Path $vbsFilePath -Value $vbsContent
    Start-Process "wscript.exe" -ArgumentList $vbsFilePath
    Start-Sleep -Seconds 10
    Remove-Item $vbsFilePath
    
  • Установка NUPKG файлов в оффлайн режиме при помощи powershell и GUI на Windows Form.
    1 – Окно для выбора файла установки
    2 – Кнопка установить и кнопка закрыть
    3 – Окно лога для возврата статуса установки или ошибки.
    4 – Окно для выбора CodeSign сертификата если в этом есть необходимость

    Тыкни
    <code>Add-Type -AssemblyName System.Windows.Forms  
    Add-Type -AssemblyName System.Drawing 
    
    Function Install-NUPKG {
    param(
    [parameter(Mandatory=$true)]$nupkgFile,
    $Certificate
    )
    try{
        $RenameFrom = $nupkgfile
        $RenameTo = $($nupkgfile.Replace('.nupkg','.zip'))
        Copy-Item $RenameFrom -Destination $RenameTo -Force
        $DestToExpnd = $RenameTo.replace('.zip','')
        Expand-Archive $RenameTo -DestinationPath $DestToExpnd -Force
        Start-Sleep -Seconds 5
        $name = (Get-ChildItem -Path $DestToExpnd `
        |? {($_.name -Like "*.psm1") -or ($_.name -Like "*.psd1")} `
        | select -First 1).Name.split('.')[0]
        $parentpath = ((Get-Item $DestToExpnd).PSParentPath).replace('Microsoft.PowerShell.Core\FileSystem::','')
        $newfoldname = $($parentpath + "\" + $name)
        Rename-Item $DestToExpnd -NewName $newfoldname
        $psmodulefolders = $ENV:PSModulePath.Split(";")[2]
        Copy-Item $newfoldname -Destination $psmodulefolders -Recurse -Force 
        Start-Sleep -Seconds 2
        Remove-Item $newfoldname -Force -Recurse 
        Remove-Item $RenameTo -Force -Recurse
        
        if($Certificate){
        try{
            Get-ChildItem -Path "$psmodulefolders\$name" -Recurse -Attributes !Directory `
            | % {Set-AuthenticodeSignature -Certificate $Certificate -FilePath $_.FullName -ErrorAction SilentlyContinue `
            | ? Status -eq Valid}
            Return Write-Output "$name is installed and signed with cert $($CheckBox.Text.Split('\') `
            | select -Last 1)"
            }
        catch [System.Management.Automation.ParameterBindingException]{
            $opencert = Get-PfxCertificate $Certificate
            Get-ChildItem -Path "$psmodulefolders\$name" -Recurse -Attributes !Directory `
            | % {Set-AuthenticodeSignature -Certificate $Certificate -FilePath $_.FullName -ErrorAction SilentlyContinue `
            | ? Status -eq Valid}
            Return Write-Output "$name is installed and signed with cert $($CheckBox.Text.Split('\') `
            | select -Last 1)"
            }
    
        }
        
        else{
            Return Write-Output "$name is installed"
        }
    }
    Catch{
        Return Write-Output $Error[0].Exception
    }
    }
    
    Function Get-FileName{
     $initialDirectory =  'C:'
     [System.Reflection.Assembly]::LoadWithPartialName(“System.windows.forms”) `
     | Out-Null
    
     $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
     $OpenFileDialog.initialDirectory = $initialDirectory
     $OpenFileDialog.filter = “All files (*.*)| *.*”
     $OpenFileDialog.ShowDialog() | Out-Null
     $OpenFileDialog.filename
    } 
    
    $window_form = New-Object System.Windows.Forms.Form
    $window_form.Text ='Устновка кастомных модулей NUPKG'
    $window_form.Width = 500
    $window_form.Height = 220
    $window_form.AutoSize = $true
    $window_form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog
    ####
    $FormLabel1 = New-Object System.Windows.Forms.Label
    $FormLabel1.Text = "Выберите файл для установки:"
    $FormLabel1.Location = New-Object System.Drawing.Point(0,5)
    $FormLabel1.AutoSize = $true
    $window_form.Controls.Add($FormLabel1)
    $FormLabel3 = New-Object System.Windows.Forms.Label
    
    $FormLabel3.Text = "Результат: "
    $FormLabel3.Location = New-Object System.Drawing.Point(0,100)
    $FormLabel3.AutoSize = $true
    $window_form.Controls.Add($FormLabel3)
    
    $CheckBox = New-Object System.Windows.Forms.CheckBox
    $CheckBox.Text = 'Подписать модуль сертификатом'
    $CheckBox.AutoSize = $true
    $CheckBox.Checked = $False
    $CheckBox.Location  = New-Object System.Drawing.Point(5,55)
    $checkbox.Add_CheckStateChanged({
        If ($Checkbox.Checked) {
            $Certificate = Get-FileName
            $TextBox2.Appendtext("Выбран сертификат: " + $Certificate  + [Environment]::NewLine)
            $CheckBox.Text = $Certificate
        } 
        Else {
            $TextBox2.Appendtext("Выбор отменен" + [Environment]::NewLine)
            $CheckBox.Text = 'Подписать модуль сертификатом'
        }
    })
    $window_form.Controls.Add($CheckBox)
    
    ###
    $TextBox1 = New-Object System.Windows.Forms.TextBox
    $TextBox1.Size = New-Object System.Drawing.Size(390,30)
    $TextBox1.Location  = New-Object System.Drawing.Point(5,25)
    $TextBox1.Text = "Путь к файлу..."
    $window_form.Controls.Add($TextBox1)
    $window_form.Add_Shown({$TextBox1.Select()})
    
    $TextBox2 = New-Object System.Windows.Forms.RichTextBox 
    $TextBox2.ReadOnly = $true 
    $TextBox2.Multiline = $true  
    $TextBox2.Width = 390  
    $TextBox2.Height = 150
    $TextBox2.Multiline = $true
    $TextBox2.Scrollbars = "Vertical"
    $TextBox2.Refresh()
    $TextBox2.ScrollToCaret()
    $TextBox2.ToString()
    $TextBox2.text = ("------------------------------------------------------------" + [Environment]::NewLine)
    $TextBox2.Location = New-Object System.Drawing.Point(5,120)
    $window_form.Controls.Add($TextBox2)
    $window_form.Add_Shown({$TextBox2.Select()})
    ###
    
    $FormButton1 = New-Object System.Windows.Forms.Button
    $FormButton1.Location = New-Object System.Drawing.Size(400,25)
    $FormButton1.Size = New-Object System.Drawing.Size(100,25)
    $FormButton1.Text = "Выбрать"
    $FormButton1.Add_Click({$TextBox1.Text = Get-FileName})
    $window_form.Controls.Add($FormButton1)
    
    $FormButton = New-Object System.Windows.Forms.Button
    $FormButton.Location = New-Object System.Drawing.Size(400,175)
    $FormButton.Size = New-Object System.Drawing.Size(100,25)
    $FormButton.Text = "Поехоли"
    $window_form.Controls.Add($FormButton)
    $FormButton.Add_Click({
    if($CheckBox.Checked -eq $true){
        $info = Install-NUPKG -nupkgFile $TextBox1.Text -Certificate $CheckBox.Text `
        | Out-String
        $TextBox2.Appendtext("$info`r`n")
        $TextBox2.Appendtext("------------------------------------------------------------" + [Environment]::NewLine)
    }
    else{
        $info = Install-NUPKG -nupkgFile $TextBox1.Text `
        | Out-String
        $TextBox2.Appendtext("$info`r`n")
        $TextBox2.Appendtext("------------------------------------------------------------" + [Environment]::NewLine)
    }
    }
    )
    
    $FormButton2 = New-Object System.Windows.Forms.Button
    $FormButton2.Location = New-Object System.Drawing.Size(400,200)
    $FormButton2.Size = New-Object System.Drawing.Size(100,25)
    $FormButton2.Text = "Закрыть"
    $FormButton2.Add_Click({[void]$window_form.Close()})
    $window_form.Controls.Add($FormButton2)
    ###
    [void]$window_form.ShowDialog()
    </code>