понедельник, 14 марта 2022 г.

Removing Shadow VMs on vCloud

Removing Shadow VMs


##==  ==##

# Removing Shadow VMs on a specific Datastore

# ToDo - Choose Datastore with OGV !


$ErrorActionPreference = "SilentlyContinue" 

$WarningPreference = "SilentlyContinue" 


cls

$User = $env:UserName

$SecurePass = Read-Host -AsSecureString "Please enter password for '$User' and wait..."

$Pass = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePass))

If(-not($Pass)){Write-Host "You must enter a password!" -ForegroundColor Yellow -BackgroundColor DarkRed; Write-Host; Break}

$vCloud = "vCloud"

$vCenter = "VCRD"


##== Connecting to vCloud ==##

Disconnect-CIServer * -Confirm:$false 

$CIServerConnected = ""

$CIServerConnected = Connect-CIServer -Server $vCloud -User $User -Password $Pass # -Org $Org | Out-Null

If(-not($CIServerConnected)){Write-Host "$vCloud is NOT Connected! `nPlease check your password, locked user account or permissions!" -BackgroundColor DarkRed  -ForegroundColor Yellow; Write-Host; Break}

Else{Write-Host "$vCloud is Connected!" -ForegroundColor Yellow -BackgroundColor DarkRed}

Write-Host 


##== Connecting to vCenter ==##

Disconnect-VIServer * -Confirm:$false 

$VIServerConnected = ""

$VIServerConnected = Connect-VIServer -Server $vCenter -User $User -Password $Pass

If(-not($VIServerConnected)){Write-Host "$vCenter is NOT Connected!" -BackgroundColor DarkRed -ForegroundColor Yellow}

Else{Write-Host "vCenter is Connected!" -ForegroundColor Yellow -BackgroundColor DarkRed}

Write-Host 


##== Getting info for four NF400N Datastores from vCenter ==##

$AllDatastoreS = Get-Datastore

$ChosenDatastoreS = $AllDatastoreS | Where{$_.Name -like "Datastore_NF400N_*"} | sort -Property FreeSpaceGB | select -First 5

Write-Host "Five Datastores with the least free space" -BackgroundColor DarkGreen

$ChosenDatastoreS

Write-Host 


##== Searching for Shadow VMs on NF400N Datastores ==##

$ShadowVMs400 = Search-Cloud AdminShadowVM -Filter DatastoreName==Datastore_NF400N_*

$ShadowVMs400Count = $ShadowVMs400.Count

Write-Host "There are $ShadowVMs400Count ShadowVMs in NF400N Cluster" -BackgroundColor DarkGreen


##== Counting Shadow VMs by Datastore ==##

foreach ($Datastore in $ChosenDatastoreS)

    {

    $ShadowVMsDatastore = $ShadowVMs400 | where{$_.DatastoreName -like $Datastore}

    $VMsCount = $ShadowVMsDatastore.Count

    If($VMsCount){Write-Host "$Datastore = $VMsCount VMs" -BackgroundColor Green}

    }

Write-Host 


##== Choosing specific Datastore and creating filter sentence for searching Shadow VMs on this Datastore ==##

$DatastoreNumber = ""

[Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') > $NULL

$DatastoreNumber = [Microsoft.VisualBasic.Interaction]::InputBox("Choose Datastore number for deleting ShadowVMs (or press Enter for exit): ", "Datastore Number")


###=CHOOSE DATASTORE OR EXIT FROM THE SCRIPT IF A NUMBER IS NOT CHOOSEN=###

Write-Host 

$ChosenDatastore = -join("Datastore_NF400N_"+$DatastoreNumber)

$FilterDatastore = "DatastoreName==$ChosenDatastore"

Write-Host 


##== Exit from script by Datastore ==##

If(!$DatastoreNumber){Write-Host "NO Datastore is choosen.`n`nSCRIPT IS FINISHED!" -ForegroundColor Yellow -BackgroundColor DarkCyan; break}

Else{Write-Host "You selected '$ChosenDatastore'" -BackgroundColor Green}


##== Searching Shadow VMs on the specific Datastore ==##

$ShadowVMsOnDatastore = Search-Cloud AdminShadowVM -Filter $FilterDatastore

### $ShadowVMsOnDatastoreCount = $ShadowVMsOnDatastore.name.Count

$ShadowVMsOnDatastoreCount = $ShadowVMsOnDatastore.Count

##== Exit from script if NO ShadowVMs is found/defined on the selected Datastore ==##

If(!$ShadowVMsOnDatastoreCount){Write-Host "Wrong choice, there are NO Shadow VMs on '$ChosenDatastore'. I am exiting!" -BackgroundColor DarkGreen; Break}

Write-Host "There are $ShadowVMsOnDatastoreCount Shadow VMs on '$ChosenDatastore'. Select some or all to kill..." -BackgroundColor DarkGreen

Write-Host 


$VMsNamesBefore = $ShadowVMsOnDatastore.Name

$ShadowVMsDelete = $ShadowVMsOnDatastore | OGV -Title "Shadow VMs On '$ChosenDatastore'" -PassThru

$ShadowVMsNames = ($ShadowVMsDelete).Name

If(!$ShadowVMsNames){Write-Host "Seems you are afraid to kill the Shadow VMs :) `nYou should know it is your choice. I am exiting!" -BackgroundColor DarkGreen; Break}

Write-Host "Shadow VMs selected for deleting:" -BackgroundColor Green

$ShadowVMsNames

Write-Host 


##== Deleting Shadow VMs on the selected Datastore ==##

foreach ($shadowVM in $ShadowVMsDelete)

    {

    $shadowVMName = $shadowVM.Name

    Write-Host "Deleting '$shadowVMName'" -BackgroundColor DarkBlue -ForegroundColor Magenta

    $ShadowDelete = $shadowVM | Get-CIView

    $ShadowDelete.delete()

    }


Write-Host 

$ShadowVMsOnDatastore = Search-Cloud -QueryType AdminShadowVM

$ShadowVMsOnDatastore = $ShadowVMsOnDatastore | where {$_.DatastoreName -like $ChosenDatastore}

$VMsCountAfter = $ShadowVMsOnDatastore.Count

$VMsDifference = $ShadowVMsOnDatastoreCount - $VMsCountAfter


Write-Host $ChosenDatastore -BackgroundColor Black

Write-Host "From $ShadowVMsOnDatastoreCount Shadow VMs you choosed $VMsDifference to delete." -BackgroundColor DarkRed

Write-Host "After deleting there are $VMsCountAfter Shadow VMs left." -BackgroundColor DarkRed

Write-Host 

Write-Host "GREAT JOB '$env:UserName' !" -ForegroundColor Yellow -BackgroundColor DarkRed

Write-Host 


# del $env:TEMP\ShadowDeletedLog.csv

# $VMsDifference | Export-Csv $env:TEMP\ShadowDeletedLog.csv -NoTypeInformation -UseCulture

# ii $env:TEMP\ShadowDeletedLog.csv

##==  ==##




пятница, 11 марта 2022 г.

Unlock AD user with PowerShell

First you need to be Domain Administrator.

To find all locked accounts in Active Directory you may use this simple command:

Search-ADAccount -LockedOut 

To unlock specific user use this command:

Unlock-ADAccount "Username"

To unlock all found accounts you can pipe results of the command to another command:

Search-ADAccount -LockedOut | Unlock-ADAccount

If you want to unlock several users (not only one and not all of them) you may use Out-GridView command which gives the possibility for some sort of GUI menu.

Search-ADAccount -LockedOut | OGV -Title "Choose the accounts for unlocking" -PassThru | Unlock-ADAccount

Put attention to -PassThru  - it gives the possibility to choose one or more objects and then piping them to the next command which is in our case unlocks the chosen users.

In the most of cases these simple commands could be enough, but if you want to be cool you may do some scripting.

##== START ==##

cls

$LockedAcc = ""

$LockedAccCount = ""

$User = $env:UserName


Write-Host "'$User', I am seeking for Locked Accounts....." -BackgroundColor Green

$LockedAcc = Search-ADAccount -LockedOut

$LockedAcc | Select Name, SamAccountName, LockedOut

$LockedAccCount = ($LockedAcc | measure).Count


Write-Host

If(!($LockedAcc)){Write-Host "Great! I cannot find any!" -ForegroundColor Yellow -BackgroundColor DarkRed; Write-Host; Break}

Else{Write-Host "Found $LockedAccCount Locked Account(s)" -BackgroundColor Red}

$LockedAcc | OGV -PassThru | Unlock-ADAccount


##== CHECK ==##

Write-Host "Post-check for Locked Accounts..."

Start-Sleep 5


$LockedAcc2 = ""

$LockedAcc2Count = ""


$LockedAcc2 = Search-ADAccount -LockedOut

$LockedAcc2Count = ($LockedAcc2 | measure).Count


If($LockedAcc2){Write-Host "Still $LockedAcc2Count Account(s) is/are Locked" -BackgroundColor Red}

Else{Write-Host "Great! You successfully unlocked accounts." -BackgroundColor Red}

$LockedAcc2 | Select Name, SamAccountName, LockedOut


##== END ==##




суббота, 5 марта 2022 г.

Useful Links

 How to Allow Multiple RDP Sessions in Windows 10 and 11?

http://woshub.com/how-to-allow-multiple-rdp-sessions-in-windows-10/

Install RSAT on Windows 10 with PowerShell

PowerShell

Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability -Online

понедельник, 14 февраля 2022 г.

Fixing issues with RDP connection when using multiple monitors

If you have two monitors at home and want to connect to your workplace, you might encounter an error when attempting to connect to a server using both monitors.

Luckily, there's a quick and easy solution! First, enter with a single monitor definition on the RDP client. Then, enter with the two-monitor definition without exiting the first session. This will allow the second connection to take the session from the first, preventing the error from occurring.

If you experience this error frequently and want to automate the double-connection process, you can use a small batch script that will do the work for you.

==START OF BATCH==

SET IP=X.X.X.X

SET USERNAME=youruser

SET PASSWORD=yourpassword

SET DOMAIN=yourdodmain.com

start cmdkey /generic:"%IP%" /user:"%USERNAME%" /pass:"%PASSWORD%"

start mstsc /f /v:"%IP%"

TIMEOUT  3

start mstsc -multimon /f /v:"%IP%"

==END OF BATCH==

Using the name of your computer instead of its IP address to connect is possible, but it may result in slower connections and potential DNS issues.



среда, 7 апреля 2021 г.

Delete all computers from WSUS - PowerShell script

# This PowerShell mini-script written by Vladisla2000 is fully ready 

# and should work without any customization to your environment.

cls

$GetWSUS = Get-WsusServer # Get WSUS server as an object

$ComputersObjects = Get-WsusComputer # Gets all computers in WSUS

$ComputersDomainNames = $ComputersObjects.FullDomainName # Extracts Domain names of computers

# Every computer in the loop is deleted

ForEach($Comp in $ComputersDomainNames)

{

Write-Host ""

Write-Host I am deleting "'$Comp'" ... -ForegroundColor Green

($GetWSUS).GetComputerTargetByName("$Comp").Delete() # The main line in the script

Write-Host "'$Comp'" was deleted -ForegroundColor Yellow

}

Write-Host ""

Write-Host FINISHED! -ForegroundColor Green -BackgroundColor Red

понедельник, 22 февраля 2021 г.

PowerShell script to copy groups from one user to another +

There is a useful PowerShell script that is written by friend of mine, talented helpdesk/support person.
He obviously should work in programming field.

I think that the functions of the script are obvious from the picture, 
but the most interesting is by far the possibility to copy groups of one user to another.
It can be useful when creating a new user that should be similar to some existing user.


Here is the script itself.

=START OF SCRIPT=

function form 

    {

    Add-Type -AssemblyName System.Windows.Forms

    Add-Type -AssemblyName System.Drawing

    

     # Build Form

    $form = New-Object System.Windows.Forms.Form

    $form.Text = 'Data Entry Form'

    $form.Size = New-Object System.Drawing.Size(550,300)

    $form.StartPosition = 'CenterScreen'


    #Please enter TZ

    $label = New-Object System.Windows.Forms.Label

    $label.Location = New-Object System.Drawing.Point(10,20)

    $label.Size = New-Object System.Drawing.Size(280,20)

    $label.Text = 'Please enter some value:'

    $form.Controls.Add($label)


    #no coment

    $nf = '

    (\__/)

    (="."=)

    E[:]||||[:]З

    (")_(")'


    #Member of:

    $label2 = New-Object System.Windows.Forms.Label

    $label2.Location = New-Object System.Drawing.Point(340,20)

    $label2.Size = New-Object System.Drawing.Size(280,20)

    $label2.Text = 'Member of:'

    $form.Controls.Add($label2)


    #your username :

    $label2 = New-Object System.Windows.Forms.Label

    $label2.Location = New-Object System.Drawing.Point(10,130)

    $label2.Size = New-Object System.Drawing.Size(280,20)

    $label2.Text = 'uSeRnAmE'

    $form.Controls.Add($label2)


    #search box input

    $inBox = New-Object System.Windows.Forms.TextBox

    $inBox.Location = New-Object System.Drawing.Point(10,40)

    $inBox.Size = New-Object System.Drawing.Size(260,200)

    $form.Controls.Add($inBox)


    #enter user source

    $ussour = New-Object System.Windows.Forms.TextBox

    $ussour.Location = New-Object System.Drawing.Point(320,180)

    $ussour.text="source user"

    $ussour.Size = New-Object System.Drawing.Size(100,10)

    $form.Controls.Add($ussour)


    #enter user target 

    $ustar = New-Object System.Windows.Forms.TextBox

    $ustar.Location = New-Object System.Drawing.Point(320,210)

    $ustar.Text="target user"

    $ustar.Size = New-Object System.Drawing.Size(100,10)

    $form.Controls.Add($ustar)

    

    #box for username output

    $outBox = New-Object System.Windows.Forms.RichTextBox

    $outBox.Location = New-Object System.Drawing.Point(10,155)

    $outbox.font = "arial,10"

    $outBox.Multiline = $true

    $outBox.ScrollBars ="vertical"

    $outBox.Size = New-Object System.Drawing.Size(300,100)

    $outbox.AutoSize = $true

    $form.Controls.Add($outBox)

 

    #box for group 

    $memberofbox = New-Object System.Windows.Forms.TextBox

    $memberofbox.Location = New-Object System.Drawing.Point(320,40)

    $memberofbox.MultiLine = $True

    $memberofbox.ScrollBars = "Vertical"

    $memberofbox.Size = New-Object System.Drawing.Size(200,130)

    $form.Controls.Add($memberofbox)


     # Add search user Button

    $Button = New-Object System.Windows.Forms.Button

    $Button.Location = New-Object System.Drawing.Size(15,75)

    $Button.Size = New-Object System.Drawing.Size(90,23)

    $Button.Text = "search user"

    $Form.Controls.Add($Button)


    # sync groups of users

    $syButton = New-Object System.Windows.Forms.Button

    $syButton.Location = New-Object System.Drawing.Size(440,180)

    $syButton.Size = New-Object System.Drawing.Size(90,53)

    $syButton.Text = "sync groups of users "

    $Form.Controls.Add($syButton)


    # search printer by IP from printer server

    $prButton = New-Object System.Windows.Forms.Button

    $prButton.Location = New-Object System.Drawing.Size(210,75)

    $prButton.Size = New-Object System.Drawing.Size(100,23)

    $prButton.Text = "find printer by IP"

    $Form.Controls.Add($prButton)


    # Add search last log on Button

    $llButton = New-Object System.Windows.Forms.Button

    $llButton.Location = New-Object System.Drawing.Size(115,75)

    $llButton.Size = New-Object System.Drawing.Size(90,53)

    $llButton.Text = "Last logon + -  When Created "

    $Form.Controls.Add($llButton)


    # Add search group Button

    $gButton = New-Object System.Windows.Forms.Button

    $gButton.Location = New-Object System.Drawing.Size(15,105)

    $gButton.Size = New-Object System.Drawing.Size(90,23)

    $gButton.Text = "search group"

    $Form.Controls.Add($gButton)


    #add chekbox

    $chekbox=New-Object System.Windows.Forms.CheckBox

    $chekbox.Location=New-Object System.Drawing.Size(320,20)

    $chekbox.Size=New-Object System.Drawing.Size(15,15)

    $chekbox.Checked = $false

    $form.controls.Add($chekbox)


    #keyboard enter and  esc

    $form.KeyPreview=$True

    #enter

    $form.add_keydown({if ($_.keycode -eq "Enter" ) {$button.PerformClick() } } )


    $form.add_keydown({if ($_.virtualkeycode -eq 38 ) {$gbutton.PerformClick() } } )

    #esc

    $form.add_keydown({if($_.keycode -eq "Escape") {$form.Close() } } )


    $prButton.add_click(

        {

            $ip = $inBox.Text

            $pr=get-WmiObject -class Win32_printer -ComputerName 10.28.28.165,10.28.28.160 | Select-Object -Property  shareName, comment

            foreach($printer in $pr) 

                {

                    if ($printer.comment -eq $ip) 

                        {

                            $outBox.Lines= $printer.shareName

                         }

                }

        }

    )


    #sync group's users 

    $syButton.add_click(

        {

        $usersource = $ussour.Text 

        $usertarget= $ustar.text

        $memof=Get-ADPrincipalGroupMembership $usersource

        $outBox.Forecolor="red"

        $outBox.Lines = "add this groups manauly to user:"

        #set user's group " test123 "

        for ($i=0; $i -le $memof.name.Count-1; $i++)

            {

            #if this NOT Distribution​Group​ and NOT Domain Users

            if ($memof.name[$i] -notmatch "\*" -and $memof.name[$i] -notmatch "Domain Users")

                {

                $q=$memof.name[$i]

                $memberofbox.Appendtext("{0}`n" -f $q)

                Add-ADPrincipalGroupMembership -Identity $usertarget -MemberOf $memof.name[$i]

                }

            else

                {

                $noadd= $memof.name[$i]

                $outBox.Appendtext("{0}`n" -f $noadd)

                }

            }

        }

                        )

    

    #serch last logon date

    $llButton.add_click(

        {

        $x=$inbox.Text

        $x = $x.Trim()

        if($x)             

            {

                $lld = Get-ADUser -LDAPFilter "(sAMAccountName=$x)"

                if($lld)

                    {

                        $out=Get-ADUser -Identity “$x” -Properties “LastLogonDate”,"whenCreated"

                        $outBox.Lines = 'MM/DD/YYYY', $out.LastLogonDate, $out.whenCreated

                    }

                else {$outBox.Lines = "user not found"}

            }

            else {$outBox.Lines = "user not found"}

        }

                        )



    #add group group buton event

    $gButton.add_click(

        {

        $x = $inBox.Text

        if ($x)

            {

                $out=get-adgroup -Filter "name -like '*$x*'" -Properties * | Select-Object name

                $outBox.lines = $out.name

             } 

        else 

            {

                [System.Windows.MessageBox]::Show('Enter something','error')

            }

        }

                        )


    #Add Button event 

    $Button.Add_Click(

        {

        $outbox.Clear()

        $x = $inBox.Text

        if ($x -match '^\d+$')

            {    <#if entering numbers #>

                $out=Get-AdUser -Filter * -Properties postalCode, postOfficeBox, SamAccountName, Enabled | Where-Object {$_.postalCode, $_.postOfficeBox -like $x -or $_.SamAccountName -eq $x }| Select-Object SamAccountName, givenname, surname, Enabled

                chek_out

            }


        elseif ($inBox.TextLength -ne 0) 

            {   <#if entering string #>

                $out = get-ADUser -Filter * -Properties Name, Description, SamAccountName, DisplayName, Enabled, Givenname | where {$_.displayName, $_.Description, $_.FirstName, $_.SamAccountName -like "*$x*"} | Select-Object SamAccountName, Description, Enabled

                chek_out

            }

        else {[System.Windows.MessageBox]::Show('Enter something ','error')}

         }

                    )

     $form.ShowDialog() | Out-Null 

    }

function chek_out

    {

        #if user is  exist then

            if ($out -ne $null )

                {

                    if($out.count -gt 1) #אם נמצא מספר משתמשים 

                        {

                            for ($i=0; $i -le $out.Count-1; $i++)

                                {#הצגת משתמשים לפי כמותם 

                                    if ($out.Enabled[$i] -eq 'true') #user is enable write is green

                                        {$outBox.SelectionColor = 'green'}

                                    else #user is disable write in red

                                         {$outBox.SelectionColor = 'Red'}

                                    $te = $out.SamAccountName[$i] +"    ," + $out.Description[$i] #$te = username + Description

                                    $outBox.Appendtext("{0}`n" -f $te)  #write to outbox

                                }

                         }

                     else #אם נמצא משתמש אחד בלבד

                        { #Description is empty

                            if ($out.Description -eq $null)

                                {

                                    if ($out.Enabled -eq 'true')

                                        {$outBox.Forecolor="green"}

                                    else 

                                        {$outBox.Forecolor="red"}    

                                    $outBox.text= $out.SamAccountName                                    

                                 } 

                             else #Description is NOT empty

                                {

                                    $te = $out.SamAccountName +"     ," + $out.Description

                                    if ($out.Enabled -eq 'true')

                                        {$outBox.Forecolor="green"}

                                    else {$outBox.Forecolor="red"} 

                                    $outBox.Appendtext("{0}`n" -f $te)

                                 }

                             if ($chekbox.Checked -eq $true) 

                                  {

                                   #get member of and put them to memberofbox like text 

                                   $memof=Get-ADPrincipalGroupMembership $out.SamAccountName | select name 

                                   $memberofbox.Text = $memof.name | Out-String

                                   }

                        }

                 }

                #if user not found

            else 

                {

                    [System.Windows.MessageBox]::Show("Not found")

                    #$outBox.Text = "Not found"

                    $memberofbox.text = $nf 

                }        

    }

function Hide-Console

{

    Add-Type -Name Window -Namespace Console -MemberDefinition '

[DllImport("Kernel32.dll")]

public static extern IntPtr GetConsoleWindow();


[DllImport("user32.dll")]

public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);

'

    $consolePtr = [Console.Window]::GetConsoleWindow()

    #0 hide

    [Console.Window]::ShowWindow($consolePtr, 0)

}

Hide-Console

form

#nltest /DSGETDC:domain.local

==END OF SCRIPT==