PowerShell: Search Windows Event Logs

# searchWindowsEventsLog.ps1

$computername=$env:computername
$logType='Security'
$eventId=4732
$daysBack=365
$limit=9999
$messageLike="*Remote Desktop Users*"

function searchWindowsEvents{
    param(
        $computername=$env:computername
        $logType='Security'
        $eventId=4732
        $daysBack=365
        $limit=9999
        $messageLike="*Remote Desktop Users*"    
    )    

    $filter=@{
        LogName=$logType
        ID=$eventId
        StartTime=[datetime]::Now.AddDays(-$daysBack)
    }
    
    $events=Get-WinEvent -FilterHashTable $filter -ComputerName $computername -EA Ignore|select -first $limit
    $events|?{$_.Message -like $messageLike}
}

searchWindowsEvents $computername $logType $eventId $daysBack $limit $messageLike

Changing User Password Using Command Lines or PowerShell

# Command-line method
net user usernamehere newpasswordhere

# Powershell Method 1 - via ActiveDirectory module
$username="USERNAMEHERE"
$newPassword="NEWPASSWORDHERE"
$encryptedPass= ConvertTo-SecureString $newPassword -AsPlainText -Force 
Set-ADAccountPassword -Identity $username -NewPassword $encryptedPass -Reset

# Powershell method 2 - via ASDI
$userid = [ADSI]"LDAP://CN=USERNAME,OU=Users,DC=DOMAIN,DC=Local"
$userid.psbase.invoke("SetPassword",'NEWPASSWORDHERE')
$userid.psbase.CommitChanges()

PowerShell: Increase CPU Count or Memory of VMs via Virtual Machine Manager

# IncreaseCpuandRamViaVMM.ps1

# User Input Variables
$vmNames=@(
    'TESTWINDOWS',
    'TESTWINDOWS2'
)
$vmmServer=$env:computername
$setCpuCount=8
$setDynamicMemory=$false
$dynamicMemoryMinimumGB='2GB'
$dynamicMemoryMaximumGB='16GB'

# Get all VMs beloging to specific cloud(s) - this is to dynamically configure all VMs within a virtual cloud
# $vms=Get-SCVirtualMachine -VMMServer $vmmServer|?{$_.Cloud.Name -in $cloudNames}
$dynamicMemoryMinimumMB=$dynamicMemoryMinimumGB/1MB
$dynamicMemoryMaximumMB=$dynamicMemoryMaximumGB/1MB
$results=@()
foreach ($vm in $vms){
    $vmName=$vm.Name
    $previousCpuCount=$vm.CPUCount
    write-host "Upgrading $vmName..."
    if($vm.Status -eq 'Running'){
        Stop-SCVirtualMachine -VM $vm -Shutdown
    }    
    if($setCpuCount -and !$setDynamicMemory){
        if($vm.CPUCount -lt $setCpuCount){
            Set-SCVirtualMachine -VM $vm -RunAsSystem -CPUCount $setCpuCount -CPUExpectedUtilizationPercent 20
        }else{
            write-host "$($vm.Name) CPU Count is $previousCpuCount, which is already equal or higher than $setCpuCount"
        }
        $results+=@{
            vmName=$vmName;
            previousCpuCount=$previousCpuCount;
            currentCpuCount=$setCpuCount
            }
    }elseif($setCpuCount -and $setDynamicMemory){
        Set-SCVirtualMachine -VM $vm -RunAsSystem `
        -CPUCount $setCpuCount -CPUExpectedUtilizationPercent 20 `
        -DynamicMemoryEnabled $setDynamicMemory -DynamicMemoryBufferPercentage 20 -MemoryWeight 5000 `
        -MemoryMB $dynamicMemoryMinimumMB -DynamicMemoryMinimumMB $dynamicMemoryMinimumMB -DynamicMemoryMaximumMB $dynamicMemoryMaximumMB        
        $results+=@{
            vmName=$vmName;
            previousCpuCount=$previousCpuCount;
            currentCpuCount=$setCpuCount;
            StartupMemory=$dynamicMemoryMinimumMB;
            DynamicMemoryMinimumMB=$dynamicMemoryMinimumMB;
            DynamicMemoryMaximumMB=$dynamicMemoryMaximumMB
            }
    }elseif(!$setCpuCount -and $setDynamicMemory){
        Set-SCVirtualMachine -VM $vm -RunAsSystem `
                -DynamicMemoryEnabled $setDynamicMemory -DynamicMemoryBufferPercentage 20 -MemoryWeight 5000 `
                -MemoryMB $dynamicMemoryMinimumMB -DynamicMemoryMinimumMB $dynamicMemoryMinimumMB -DynamicMemoryMaximumMB $dynamicMemoryMaximumMB        
                $results+=@{
                    vmName=$vmName;
                    StartupMemory=$dynamicMemoryMinimumMB;
                    DynamicMemoryMinimumMB=$dynamicMemoryMinimumMB;
                    DynamicMemoryMaximumMB=$dynamicMemoryMaximumMB
                    }
    }else{    
        write-warning "User must input the `$setDynamicMemory and/or `$setCpuCount variables"
        break
    }
    if($vm.Status -eq 'PowerOff'){
        Start-SCVirtualMachine -VM $vm
    }    
}
write-host $($results|out-string).trim()

PowerShell: Virtual Machine Snapshots Report from VMM Servers

# vmSnapshotReport.ps1
# Requirements:
# - Credentials to access VMM Servers with Administrator role
# - Firewall open WinRM ports from jump host to VMM Servers

# Variables
$vmmServers=@(
    @{servername='LAX-VMM01.kimconnect.com';adminname='intranet\clusterReport';password=$env:kimconnectcom}
    @{servername='PHX-VMM01.kimconnect.net';adminname='intranet\clusterReport';password=$env:kimconnectnet}
)

# Email relay parameters
$emailFrom='admins@kimconnect.com'
$emailTo='admins@kimconnect.com'
$subject='Hyper-V Snapshots Report'
$smtpRelayServer='email-relay.kimconnect.com'
$emailDay='Monday'
$css="
    <style>
    .h1 {
        font-size: 18px;
        height: 40px;
        padding-top: 80px;
        margin: auto;
        text-align: center;
    }
    .h5 {
        font-size: 22px;
        text-align: center;
    }
    .th {text-align: center;}
    .table {
        padding:7px;
        border:#4e95f4 1px solid;
        background-color: white;
        margin-left: auto;
        margin-right: auto;
        width: 100%
        }
    .colgroup {}
    .th { background: #0046c3; color: #fff; padding: 5px 10px; }
    .td { font-size: 11px; padding: 5px 20px; color: #000;
            width: 1px;
            white-space: pre;
        }
    .tr { background: #b8d1f3;}
    .tr:nth-child(even) {
        background: #dae5f4;
        width: 1%;
        white-space: nowrap
    }
    .tr:nth-child(odd) {
        background: #b8d1f3;
        width: 1%;
        white-space: nowrap
    }
    </style>
"

$results=$null
foreach($vmmServer in $vmmServers){
    $servername=$vmmServer.servername
    $username=$vmmServer.adminName
    $password=convertto-securestring $vmmServer.password -AsPlainText -Force
    $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password
    $pssession=new-pssession -computername $servername -credential $credential
    if($pssession.State -eq 'Opened'){
        $results+=invoke-command -session $pssession {Get-SCVMCheckpoint -vmmserver localhost}
        remove-pssession $pssession
    }else{
        write-warning "Unable to connect to $servername"
        break
    }
}
$report=$results|select @{name='VMMServer';e={$_.PSComputername}},VM,Name
if($null -ne $report){
    $currentReport=$report | ConvertTo-Html -Fragment | Out-String
    $currentReportHtml=$currentReport -replace '\<(?<item>\w+)\>', '<${item} class=''${item}''>'
    $emailContent='<html><head>'+$css+"</head><body><h5 class='h5'>$subject</h5>"+$currentReportHtml+'</body></html>'
    write-host "####################################################################################################`r`nVM Snapshots Report:`r`n####################################################################################################`r`n$(($report|out-string).trim())"
    $today=(get-date).DayOfWeek
    if ($today -eq $emailDay){
        Send-MailMessage -From $emailFrom `
        -To $emailTo `
        -Subject $subject `
        -Body $emailContent `
        -BodyAsHtml `
        -SmtpServer $smtpRelayServer
        write-host "$subject email has been sent to $emailTo with time stamp $((get-date|out-string).trim())"
    }
}

PowerShell: Set VM Dynamic Memory in Virtual Machine Manager

# setVmDynamicMemoryInVmm.ps1

# Optimize Dynamic RAM
$minGb='16GB'
$maxGb='32GB'
$startupGb='2GB'
$buffer=20
$memoryWeight=5000
$forcedRestart=$false
$vmmServer='localhost'

function getUnoptimizedMemoryVms{
    param(
        $minGb='16GB',
        $maxGb='1024GB',
        $vmmServer='localhost'
    )
    Import-Module -Name "virtualmachinemanager"
    $vms=Get-VM -vmmserver $vmmServer
    $targetVms=$vms|?{$($_.MemoryAssignedMB -ge $minGb/1MB -and $_.MemoryAssignedMB -le $maxGb/1MB) -and $($_.DynamicMemoryDemandMB -ne $_.MemoryAssignedMB)} # -and !$_.DynamicMemoryEnabled
    # Memory = startup memory
    # DynamicMemoryDemandMB = memory demand
    # MemoryAssignedMB = memory currently assigned
    # DynamicMemoryMaximumMB = Maximum Memory (non-zero value only if Dynamic Memory is enabled)
    return $($targetVMs|select-object Name,Version,DynamicMemoryEnabled,DynamicMemoryDemandMB,MemoryAssignedMB|sort-object -Property Name)
}

function setVmDynamicMemoryInVmm{
    param(
        $vmName,
        $setMinMb,
        $setMaxMb,
        $setStartupMb,
        $forcedRestart=$false,
        $buffer=20,
        $memoryWeight=5000,
        $vmmServer='localhost'
    )
    
    Import-Module -Name "virtualmachinemanager"
    $vm=get-scvirtualmachine -name $vmName -vmmserver $vmmServer
    $staticMemory=!$vm.DynamicMemoryEnabled # if Dynamic Memory is enabled and VM generation is 9.0 or higher, then Dynamic RAM can be configured while VM remains online
    $maximumMB=if($setMaxMb -gt $vm.MemoryAssignedMB){$setMaxMb}elseif($vm.MemoryAssignedMB -gt $vm.DynamicMemoryDemandMB){$vm.MemoryAssignedMB}elseif($vm.DynamicMemoryDemandMB -gt $vm.Memory){$vm.DynamicMemoryDemandMB}else{4096}
    $startupMb=if($startupMb){$startupMb}elseif($vm.DynamicMemoryDemandMB -lt $maximumMB/2){$vm.DynamicMemoryDemandMB}else{2048}
    $minimumMB=if($setMinMb){$setMinMb}elseif($vm.DynamicMemoryDemandMB -lt $maximumMB/2){$vm.DynamicMemoryDemandMB}else{$startupMb}

    if(!$vm -or $vm.count -gt 1){
        write-warning "VM Name $vmName cannot be queried"
        return $false
    }
    
    $vmHasFailed=$vm.Status -eq 'Failed'
    if($vmHasFailed){
        try{
            # Manually repair virtual machine in a failed state
            Repair-SCVirtualMachine $vm -Dismiss 
        }catch{
            write-warning $_
            return $false
        }
    }

    $vmIsOnline=$vm.VirtualMachineState -eq 'Running'
    if($vmIsOnline -and $forceRestart -and $staticMemory){
        Stop-SCVirtualMachine -VM $vm
        write-host "$vmName has been stopped temporarily"
    }elseif($vmIsOnline -and !$forceRestart -and $staticMemory){
        write-warning "VM Name $vmName status is 'Running' and the `$forceRestart flag has been set to `$false"
        return $false
    }elseif(!$staticMemory){
        write-host "VM name $vmName memory config is detected as dynamic"
    }
    # Hyper-V Commands - will not work in VMM
    # $startupBytes=$startupGb/1
    # $minBytes=$minGb/1
    # $maxBytes=$maxGb/1
    # Set-VMMemory $vmName -DynamicMemoryEnabled $true -MinimumBytes $minBytes -StartupBytes $startupBytes -MaximumBytes $maxBytes -Priority $priority -Buffer $buffer
    
    # VMM Command
    try{
        Set-SCVirtualMachine -VM $vm -DynamicMemoryEnabled $true `
            -MemoryMB $startupMb -DynamicMemoryMinimumMB $minimumMB -DynamicMemoryMaximumMB $maximumMB `
            -DynamicMemoryBufferPercentage $buffer -MemoryWeight $memoryWeight
        if($vmIsOnline -and $forceRestart){        
            Start-SCVirtualMachine -VM $vm
            if($vm.Status -eq 'Running'){
                write-host "$vmName has started"
            }else{
                write-host "$vmName has NOT started successfully"
                return $false
            }
        }
        write-host "VM name $vmname memory has been set to dynamic with min of $minGb GB and $maxGb GB"
        return $true
    }catch{
        write-warning $_ 
        return $false
    }

    # Set Static RAM
    # Set-VM -StaticMemory -Name $vmName -MemoryStartupBytes $($startupGb/1)
}

# setVmDynamicMemoryInVmm $vmName $setMinMb $setMaxMb $forceRestart $buffer $memoryWeight $vmmServer
function optimizeMemoryVms{
    param(
        $minGb='16GB',
        $maxGb='64GB',
        $startupGb='2GB',
        $forcedRestart=$false,
        $buffer=20,
        $memoryWeight=5000,
        $vmmServer='localhost'
    )
    $targetVMs=getUnoptimizedMemoryVms $minGb $maxGb $vmmServer
    if($targetVMs.count){
        $results=[hashtable]@{}
        foreach($vm in $targetVMs){
            $vmName=$vm.Name
            $setMaxMb=if($vm.DynamicMemoryDemandMB -gt $vm.MemoryAssignedMB){$vm.DynamicMemoryDemandMB}else{$vm.MemoryAssignedMB}
            $setStartupMb=if($startupGb){$startupGb/1MB}elseif($vm.DynamicMemoryDemandMB -lt $setMaxMb/2){$vm.DynamicMemoryDemandMB}else{2048}
            $setMinMb=if($($vm.MemoryAssignedMB/2) -lt $setStartupMb){$vm.MemoryAssignedMB/2}else{$setStartupMb}
            $result=setVmDynamicMemoryInVmm $vmName $setMinMb $setMaxMb $setStartupMb $forceRestart $buffer $memoryWeight $vmmServer
            write-host "$vmName Memory config as been set to Dynamic with Min $setMinMb MB and Max $setMaxMb MB"
            $results+=@{$vmName=$result}
        }
        return $results
    }
}

optimizeMemoryVms $minGb $maxGb $startupGb $forcedRestart $buffer $memoryWeight $vmmServer



# Set-SCVirtualMachine -Name TESTWINDOWS -DynamicMemoryEnabled $true -DynamicMemoryMinimumMB $(8*1024)

# Set-VMMemory TESTWINDOWS -StartupBytes $(8GB/1)

# PS C:\Windows\system32> Set-VMMemory $vmName -StartupBytes $($startupGb/1)
# Set-VMMemory : Failed to modify device 'Memory'.
# 'TESTWINDOWS' failed to modify device 'Memory'. (Virtual machine ID
# 0A1E6930)
# Changing memory size of running virtual machine 'TESTWINDOWS' failed. VM version must be at least 6.0.
# At line:1 char:1
# + Set-VMMemory $vmName -StartupBytes $($startupGb/1)
# + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#     + CategoryInfo          : NotSpecified: (:) [Set-VMMemory], VirtualizationException
#     + FullyQualifiedErrorId : OperationFailed,Microsoft.HyperV.PowerShell.Commands.SetVMMemory

# Install-WindowsFeature -Name Hyper-V-PowerShell
# Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell

PowerShell: Set DNS Records on Remote Computers

# setDnsEntries.ps1

$computernames=@(
    "$env:computername"
)
$dnsServers=@(
    "8.8.8.8",
    "4.4.2.2"
)

$results=[hashtable]@{}
foreach ($computername in $computernames){
    $psSession=new-pssession $computername
    if($psSession.State -eq 'Opened'){
        $result=invoke-command -session $pssession {
            param($dnsServers)
            try{
                $defaultInterfaceIndex=(Get-NetRoute -DestinationPrefix "0.0.0.0/0").IfIndex
                Set-DnsClientServerAddress -InterfaceIndex $defaultInterfaceIndex -ServerAddresses $dnsServers
                write-host "$env:computername`:`r`n$((Get-DnsClientServerAddress -interfaceindex $defaultInterfaceIndex|?{$_.AddressFamily -eq 'IPv4'}|out-string).trim())"
                return $true
            }catch{
                write-warning $_ 
                return $false
            }            
        } -ArgumentList (,$dnsServers)
        $results+=[hashtable]@{$computername=$result}
        remove-pssession $psSession
    }else{
        write-warning "Unable to connect to $computername"
        $results+=[hashtable]@{$computername='unableToConnect'}
    }
    pause
}

Windows Event ID 2017: Unable to collect NUMA physical memory utilization data

Issue:
Log Name: Application
Source: Microsoft-Windows-PerfOS
Date: 9/12/2018 7:47:38 AM
Event ID: 2017
Task Category: None
Level: Warning
Keywords: Classic
User: N/A
Computer: TESTWINDOWS
Description:
Unable to collect NUMA physical memory utilization data. The first four bytes (DWORD) of the Data section contains the status code.
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-PerfOS" Guid="{F82FB576-E941-4956-A2C7-A0CF83F6450A}" EventSourceName="PerfOS" />
<EventID Qualifiers="32768">2017</EventID>
<Version>0</Version>
<Level>3</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2018-09-12T14:47:38.788262000Z" />
<EventRecordID>118276</EventRecordID>
<Correlation />
<Execution ProcessID="0" ThreadID="0" />
<Channel>Application</Channel>
<Computer>TESTWINDOWS</Computer>
<Security />
</System>
<EventData>
<Binary>05000080</Binary>
</EventData>
</Event>
Resolution:
[TESTWINDOWS]: PS C:\windows\system32> lodctr /R

Info: Successfully rebuilt performance counter setting from system backup store

PowerShell: How To Append to Windows Environmental Paths Permanently

Often, when we install applications such as Python, its bin directory may not automatically be added to the OS environmental paths. Most of us would use the command $env:path+=”;$appendPath” to work around this issue; however, such command only works for that single user or session.

How do we make a permanent change to the System Environmental paths? Here’s a function for that.

*** WARNING: this is only for educational purposes. Please DO NOT apply this to PRODUCTION systems without knowing what you’re doing as misuse can lead to system failures! Please consult a professional. Caveat Emptor! ***

$appendPath='C:\Python38\Scripts'

function appendEnvironmentPaths($appendPath){
    $appendPath=if($appendPath -match '\\$'){$appendPath.Substring(0,$appendPath.Length-1)}else{$appendPath}
    $regEnvironmentPaths='Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment'
    $regKeyname='PATH'
    $systemPaths=(Get-ItemProperty -Path $regEnvironmentPaths -Name $regKeyname)."$regKeyname"
    $systemPathsArray=$systemPaths -split ';'
    $pathExists=.{
        $systemPathsArray|%{
            $path=if($_ -match '\\$'){$_.Substring(0,$_.Length-1)}else{$_}
            if($path -eq $appendPath){
                return $true
            }
        }
    }
    if(!$pathExists){
        $systemPaths+=";$appendPath"
        Set-Itemproperty -path $regEnvironmentPaths -Name $regKeyname -value $systemPaths
        write-host "$appendPath has been appended:`r`n$systemPaths"
$env:Path=[System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
    }else{
        write-host "$appendPath already exists in System Paths:`r`n$systemPaths"
    }
}

appendEnvironmentPaths $appendPath

PowerShell: Grant SMB Access

# grantSmbAccess.ps1

$computername='fileserver'
$shareName='TEST'
$account='domain\groupOrUsername'
$accessType='read' # also change or full

invoke-command -computername $computername -scriptblock{
    param($shareName,$account,$accessType)
    try{
        Grant-SmbShareAccess -Name $shareName -AccountName $account -AccessRight $accessType -force
        # Get-SmbShareAccess $shareName
        $object=(Get-SmbShare $shareName).Path
        # Translating SMB to NTFS equivalent: Full, Modify, ReadAndExecute
        $permission=switch($accessType.tolower()){
            'full' {'full'}
            'change' {'modify'}
            'read' {'ReadAndExecute'}
            Default {'ReadAndExecute'}
        }
        $acl=Get-Acl $object
        $grantAccess=New-Object System.Security.AccessControl.FileSystemAccessRule($account,$permission,'Allow')
        $acl.AddAccessRule($grantAccess)
        Set-Acl $object $acl
        return $true
    }catch{
        write-warning $_
        return $false
    }

} -Args $shareName,$account,$accessType

Issue: A-Host Records Disappear in an Active Directory Integrated DNS Environment with Windows DHCP Server

Issue:

Certain virtual machines would loose their a-host records after a period of time. That would lead to such machines being inaccessible by users by computer names.

Investigation:

DHCP Server Settings:

DNS Server Settings:

DNS Zone Settings

A-host record settings

Analysis:

According to the screenshots above, we can derive at this generalization:

 – No-refresh interval = 7 days
 – Refresh interval = 7 days
 – Scavenge stale records = enabled at [domain name] zone
 – Scavenge period = not enabled at server level

Hence, the DNS server does not have a default policy to delete stale records. However, the domain zone level settings have this effect (by having a check mark next to ‘scavenge stale resource records’). Furthermore, since the record is set as ‘dynamic’, it would automatically delete itself after a refresh interval + no refresh interval or 7 + 7 = 14 days have expired.

More importantly, the DHCP server option to ‘discard A and PTR records when lease is deleted’ would also trigger an automatic deletion. Hence, any machine that has a DHCP lease would be at risk of its associated DNS records being purged if its lease doesn’t get renewed. Therefore, if a machine leases an IP, then subsequently sets that IP as static in its TCP/IP settings, would run the risk of its a-host record being pruned due to it no longer sending out DHCP renew packets to the DHCP server.

There may be other factors, such as network layer 1-3 issues preventing packets from leaving the clients or reaching the servers. In such scenarios, that would have a similar effect of the client not renewing its lease toward the DHCP servers and performing refreshes toward DNS servers. Thus, such client machines and their associated DNS records would also be cleared automatically.

How To Use CredSSP to Move Virtual Machines In a Hyper-V Cluster

# Prep on Client
$domain='intranet.kimconnect.com'
Enable-WSManCredSSP -Role "Client" -DelegateComputer "*.$domain"

# Prep on Server
Enable-WSManCredSSP -Role "Server"

# Test a command the requires CredSSP
$adminUsername='intranet\brucelee'
$plaintextPassword='SOMEPASSWORD'
$encryptedPassword=ConvertTo-securestring $plaintextPassword -AsPlainText -Force
$adminCredential=New-Object -TypeName System.Management.Automation.PSCredential -Args $adminUsername,$encryptedPassword

$vmName='testWindows'
$currentNode='lax-node002'
$newOwnerNode='lax-node008'

invoke-command -computername $currentNode -credential $adminCredential -scriptblock {
		param($vmName,$newOwnerNode)
		Move-ClusterVirtualMachineRole -Name $vmName -MigrationType Live -Node $newOwnerNode
	} -Args $vmName,$newOwnerNode

Incomplete VM Configuration

Symptom:

refresh-vm : VMM could not find the specified path C:\win10iso\KMS
SW_DVD9_Win_Pro_10_20H2.2_64BIT_English_Pro_Ent_EDU_N_MLF_-2_X22-46651.ISO on the HYPERV-NODE25 server.
(Error ID: 2904, Detailed Error: The system cannot find the path specified (0x80070003))

Ensure that you have specified a valid file name parameter, and then try the operation again.

To restart the job, run the following command:
PS> Restart-Job -Job (Get-VMMServer localhost | Get-Job | where { $_.ID -eq "{fce569ca-bd01-4493-b27c-e3a433cee5f4}"})
At line:1 char:38
+ $incompleteVmConfigs|select -first 1|refresh-vm -force
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : ReadError: (:) [Read-SCVirtualMachine], CarmineException
+ FullyQualifiedErrorId : 2904,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.RefreshVmCmdlet

Resolution:

Remove the virtual DVD ISO that is being attached to the guest VM. 

Installing DotNet 3.5 on Windows with Restricted Internet Access

# Set Windows Source files
# Assuming that a Windows ISO / DVD Rom have been mounted as F:\ volume
$windowsSources='F:\sources\sxs'
dism /online /enable-feature /featurename:NetFX3 /All /Source:$windowsSources /LimitAccess

# Sample output
# [TESTWINDOWS]: PS f:\> dism /online /enable-feature /featurename:NetFX3 /all /Source:$windowsSources /LimitAccess

# Deployment Image Servicing and Management tool
# Version: 10.0.20348.681
# Image Version: 10.0.20348.707
# Enabling feature(s)
# [===========================61.0%===                       ]
# [==========================100.0%==========================]
# The operation completed successfully.

Windows: How To Expand Disk Volumes That Are Not Adjacent the Intended Volume

Problem:

Here’s a scenario when a virtualized disk has been expanded in Hyper-V, Vmware, AWS, Azure, Google Cloud, etc. The intended disk to be expanded is C:\, but E:\ is blocking C:\ from being expanded using the Windows diskmgmt.msc. What to do?

Resolution:

Option 1: Windows 7/10/11 (Client OS)

Install AOMEI Partition Assistant Standard

Option 2: Windows Servers

Pay the licensing fee to be able to use the partitioning wizard on a Windows Server OS

Option 3: Change vDisk bus type

  • Clone the existing Guest VM as a full backup
  • While having target Guest VM powered off, edit its VHD file > change ddb.adapterType = “ide” to ddb.adapterType = “lsilogic”
  • Remove the drive from the Guest VM with the “DO NOT remove from virtual machine and delete files from disk” option
  • Add a new hard disk > choose the “Use an existing virtual disk” option > select the targeted hard disk

Option 4: Windows Server 2012 / 2016 / 2019 / 2022 as a Guest VM

Caveat: this have proven to work on volumes with files that are NOT constantly changing (e.g. NOT databases, OS, real-time applications with transient items)

  • Add a new volume
  • Take a VSS Snapshot of the volume to be moved
$targetVolume="E:\"
$vssAccessLink="C:\shadowcopy"

function createVssSnapshot{
[cmdletbinding()]
param(
[string]$targetVolume="C:\",
$vssAccessLink="C:\shadowcopy"
)
# Sanitation
if (!($targetVolume -like "*\")){$targetVolume+="\"}
if(Test-Path $vssAccessLink){(Get-Item $vssAccessLink).Delete()}

write-host "Initiating VSS snapshot..."
$shadowCopyClass=[WMICLASS]"root\cimv2:win32_shadowcopy"
$thisSnapshot = $shadowCopyClass.Create($targetVolume, "ClientAccessible")
$thisShadow = Get-WmiObject Win32_ShadowCopy | Where-Object { $_.ID -eq $thisSnapshot.ShadowID }
$thisShadowPath = $thisShadow.DeviceObject + "\"

# Creating symlink
$null=cd C:
$null=cmd /c mklink /d $vssAccessLink $thisShadowPath
write-host "Vss Snapshot of $targetVolume has been made and it's accessible at this local file system (LFS): $vssAccessLink."

# Validation
if(Test-Path $vssAccessLink){
$snapshotId=$thisShadow.ID;
write-host "Snapshot $snapshotId has been created.";
return $snapshotId;
}else{
write-host "Failed to create client accessible VSS Snapshot.";
return $false;
}
}

createVssSnapshot $targetVolume $vssAccessLink
  • Copy data from snapshot to new volume
$vssAccessLink="C:\shadowcopy"
$newVolume='X:\'
robocopy $vssAccessLink $newVolume /e /R:0 /NP
  • Change the drive letter of the new volume as the original volume’s drive letter

 

Disable and Enable Trace Logging for Dynamics CRM

# Set common variables
$serverTracingRegistry='Registry::HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\MSCRM'

# Enable CRM Tracing
Add-PSSnapin Microsoft.Crm.PowerShell
$setting = Get-CrmSetting TraceSettings
$setting.Enabled = $True
$setting.Directory = "D:\crmTraceLogs"
Set-CrmSetting $setting
$traceRefreshCurrentValue=(Get-ItemProperty -path $serverTracingRegistry).'TraceRefresh'
Set-Itemproperty -path $serverTracingRegistry -Name 'TraceRefresh' -value $($traceRefreshCurrentValue++)

# Disable Tracing
Add-PSSnapin Microsoft.Crm.PowerShell
$setting = Get-CrmSetting TraceSettings
$setting.Enabled = $False
Set-CrmSetting $setting
Set-Itemproperty -path $serverTracingRegistry -Name 'TraceRefresh' -value 0

 
# Check current settings
Get-CrmSetting TraceSettings
Get-ItemProperty -path $serverTracingRegistry -Name 'TraceRefresh'

PowerShell: Find Locking PID of a File

$filePath="C:\Program Files\Google\Chrome\Application\chrome.exe"

function findPidOfFile($filepath){    
    try{
        if (!(Get-Command handle.exe -ErrorAction SilentlyContinue)) {
            if (!(Get-Command choco.exe -ErrorAction SilentlyContinue)) {
            [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
            Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))    
            }
            choco install sysinternals -y --ignore-checksums
        }
        $handles=handle.exe
        $matchedLines=$handles|?{$_ -like "*$filepath*"}
        $lockingPids=@();
        $lastKnownPid="";
        if($null -ne $matchedLines){
            foreach ($line in $matchedLines) {
            $lastKnownPid=.{
                [void]($line -match "pid:\s(.*)\s");
                if ($matches[1]){return $matches[1]}
                }
            if ($line -like "*$filepath*") {
                return $lastKnownPid;
                }
            }
        }else{
            write-host "$filepath does NOT currently have a locking pid"
        }
    }catch{
        write-warning $_
    }
}

findPidOfFile $filePath

PowerShell: Enable TLS 1.2 on Windows

function enableTls12{
	try{
		$null=New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Force
		$null=New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Force
		$null=New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'Enabled' -value '1' –PropertyType 'DWORD'
		$null=New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'DisabledByDefault' -value '0' –PropertyType 'DWORD'
		$null=New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'Enabled' -value '1' –PropertyType 'DWORD'
		$null=New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'DisabledByDefault' -value '0' –PropertyType 'DWORD'
		Write-Host "TLSv1.2 has been enabled on $env:computername"
	}catch{
		write-warning $_
	}
}

enableTls12
Other project: DragonCoin.com