# killService.ps1
$serviceName='vmms'
function killService($serviceName='Spooler',$restart=$false){
$processId=Get-WmiObject -Class Win32_Service -Filter "Name LIKE '$serviceName'"|Select-Object -ExpandProperty ProcessId
if($processId.count -eq 1 -and $processId -ne 0){
try{
$taskkill=taskkill /f /pid $processid
write-host $taskkill
if($restart){
start-service $serviceName
$result=get-service $serviceName
if($result.Status -eq 'Running'){
$processId=Get-WmiObject -Class Win32_Service -Filter "Name LIKE '$serviceName'"|Select-Object -ExpandProperty ProcessId
write-host "$serviceName has successfully restarted with pid $processId" -foregroundcolor GREEN
return $true
}else{
write-host "$serviceName has NOT successfully restarted" -foregroundcolor RED
return $false
}
}else{
$result=get-service $serviceName
if($result.Status -eq 'Stopped'){
$processId=Get-WmiObject -Class Win32_Service -Filter "Name LIKE '$serviceName'"|Select-Object -ExpandProperty ProcessId
write-host "$serviceName has successfully stopped" -foregroundcolor GREEN
return $true
}else{
write-host "$serviceName has NOT successfully stopped" -foregroundcolor RED
return $false
}
}
}catch{
write-warning $_
return $false
}
}else{
try{
start-service $serviceName
}catch{
write-warning $_
# write-warning "$serviceName is not found on $env:computername"
return $null
}
}
}
killService $serviceName
Category: Microsoft Windows
How to Install PowerShell Module on An Offlined Computer
# Download the desired module onto a 'jump host' (an intermediary computer that has access to the Internet)
PS C:\WINDOWS\system32> Save-Module -Name SqlServer -Path C:\Temp
PS C:\WINDOWS\system32> ls C:\temp
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 1/30/2023 5:04 PM SqlServer
# Add files into remote computer from the jump host
robocopy c:\temp\sqlserver \\SERVERNAME\C$\Program Files\WindowsPowerShell\Modules /E /NP
PS C:\Windows\system32> Enter-PSSession SERVERNAME
[SERVERNAME]: PS C:\Users\kimconnect\Documents> Get-Module -Name SQLServer -ListAvailable
Directory: C:\Program Files\WindowsPowerShell\Modules
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 21.1.18256 SqlServer {Add-RoleMember, Add-SqlAvailabilityDatabase, Add-SqlAvail...
# Check SqlServer module's path
[SERVERNAME]: PS C:\Users\kimconnect\Documents> (Get-Module -ListAvailable SQLServer).path
C:\Program Files\WindowsPowerShell\Modules\SqlServer\21.1.18256\SqlServer.psd1
# Import sqlserver powershell module into current session
[SERVERNAME]: PS C:\Users\kimconnect\Documents> Import-Module -Name SqlServer
[SERVERNAME]: PS C:\Users\kimconnect\Documents> get-module
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Manifest 3.1.0.0 Microsoft.PowerShell.Management {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Con...
Manifest 3.1.0.0 Microsoft.PowerShell.Utility {Add-Member, Add-Type, Clear-Variable, Compare-Object...}
Script 21.1.18256 SqlServer {Add-RoleMember, Add-SqlAvailabilityDatabase, Add-SqlAvail...
PowerShell: Uninstall Program Using Its Name
# uninstallProgramUsingId.ps1
$appName='Virtual Machine Manager Agent'
$uninstallStringRegPaths='HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall','HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall'
$uninstallStrings=Get-ChildItem -Path $uninstallStringRegPaths
$uninstallString=($uninstallStrings|Get-ItemProperty|Where-Object {$_.DisplayName -match $appName}).UninstallString
if($uninstallString.count -eq 1){
$appCode=[regex]::match($uninstallString,'\{(.*)\}').Value
$uninstallCommand="& msiexec.exe /x $appCode /quiet /norestart"
write-host "Invoking uninstall Command: $uninstallCommand"
Invoke-Expression $uninstallCommand
$appStillExists=Get-WmiObject -Class Win32_Product -Filter "Name='$appName'"
if($appStillExists){
write-warning "Uninstall has been unsuccessful at removing $appName"
return $false
}else{
return $true
}
}else{
write-warning "Please check this/these uninstall string(s):`r`n$uninstallString"
return $false
}
PowerShell: Get Connected Port by Process Name
# getProcessConnectionPort.ps1
$computerlist=@'
SQL1
SQL2
'@
$computernames=@($computerList -split "`n")|%{$_.Trim()}
$processname='sqlservr'
$state='Established'
$results=@()
foreach ($computername in $computernames){
$result=invoke-command -computername $computername{
param($processName,$state='Established')
try{
$processid=(get-process $processName).Id
$ports=Get-NetTcpConnection -OwningProcess $processid -State $state|Group-Object -Property LocalPort
write-host "$env:computername`: $processName PID is found as $processid running on port(s) $($ports.Name)"
return $ports
}catch{
write-warning $_
return $false
}
} -Args $processName,$state
$results+=$result
}
$results
PowerShell: Quickly Test Connectivity from a List of Sources toward a Destination on a Specific Port
# testRemotePort.ps1
$connectFrom=@'
windows1
windows2
'@
$connectTo=@'
\\servername\sharename
'@
$testPort=445
$sources=@($connectFrom -split "`n")|%{$_.Trim()}
$destinations=@($connectTo -split "`n")|%{$_.Trim()}
$results=@()
foreach($source in $sources){
foreach($destination in $destinations){
$result=invoke-command -computername $source {
param($destination,$testPort)
write-host "$env:computername to $destination`:$testPort => " -nonewline
$result=try{if(test-netconnection $destination -port $testPort -informationLevel Quiet){'Open'}else{'Closed'}}catch{write-warning $_;'Unknown'}
write-host "$result"
return $result
} -Args $destination,$testPort
$results+=[pscustomobject]@{
source=$source
destination=$destination
port=$testPort
status=$result
}
}
}
How To Recover SQLSERVER Service from Being Unable to Start
# startSqlService.ps1
# special provision to deal with SQL Server not starting up due to various reasons
$sqlServerService='mssqlserver'
$sqlWaitSeconds=120
$desiredState='Running'
$sqlWaitTimespan=[timespan]::fromseconds($sqlWaitSeconds)
if($sqlServerService -in $originalStoppedServices.Name){
try{
$sqlService=get-service $sqlServerService -EA Ignore
if($sqlService.Status -ne $desiredState -and $null -ne $sqlService){
$stopped=try{$sqlService.waitforstatus('Stopped',$sqlWaitTimespan);$true}catch{$false}
if($stopped){
$attempt=net start $sqlServerService /T902 2>&1
$running=(get-service $sqlServerService).Status -eq 'Running'
$running=if(!$running){try{$sqlService.waitforstatus('Running',$sqlWaitTimespan);$true}catch{$false}}else{$running}
if($attempt -match 'started' -and $running){
write-host "$sqlServerService has been started with trace flag /T902" -foregroundcolor Green
}else{
write-host "$sqlServerService has NOT been started with trace flag /T902" -foregroundcolor Red
}
}else{
write-warning "$sqlServerService has current state is $((get-service $sqlServerService).Status)"
}
}
}catch{
write-warning $_
}
}
Resume All Guest VMs in a Clustered Hyper-V Environment
# resumeAllVms.ps1
# Significance: this script is useful in a Clustered Hyper-V environment
# where storage was down for over 60 seconds, causing Hyper-V to put all guest VM's into 'paused-critical' statuses.
# During such event, the cluster would be unreachable as well. Hence, knowing node names prior to pasting this script
# would be necessary.
$computerlist=@'
hyperVServer1
hyperVServer2
hyperVServer100
'@
$computernames=@($computerlist -split "`n")|%{$_.Trim()}
foreach ($computername in $computernames){
invoke-command $computername {
write-host "Connected to $env:computername..."
#Get list of all VMs on this host
#$vmNames=(get-vm).Name
#write-host "$env:computername`:`r`n$($vmNames|out-string)"
# Unpausing all VMs
$pausedVms=get-vm | where state -eq 'paused'
foreach($vm in $pausedVMs){
write-host $vm.Name -nonewline
try{
$vm|resume-vm -ea stop
write-host ": resumed" -foregroundcolor Green
}catch{
write-warning $_
continue
}
}
}
}
PowerShell: Command to Retrieve Windows Applications List
The following the the PoSH equivalent of appwiz.cpl in Windows:
PS> invoke-command TestWindows {Get-Package -Provider Programs -IncludeWindowsInstaller|select-object Name,Version|sort -property Name}|select -property * -ExcludeProperty runspaceid,pscomputername
Name Version
---- -------
7-Zip 18.06 (x64 edition) 18.06.00.0
DRAC Command Line Tools 9.2.0
Notepad++ (64-bit x64) 7.5.9
NSClient++ (x64) 0.5.2039
PuTTY release 0.71 (64-bit) 0.71.0.0
How to Search for Installed Application by Name in PowerShell
One can search using the known Vendor or application Name as illustrated below:
[testwindows]: PS C:\Users\user1\Documents> Get-WmiObject -Class Win32_Product | ?{$_.Name -like '*exporter*'}
IdentifyingNumber : {EDD0CDE3-4519-4C1A-9FB4-C8C067615698}
Name : windows_exporter
Vendor : prometheus-community
Version : 0.20.0
Caption : windows_exporter
[btestwindows]: PS C:\Users\user1\Documents> Get-WmiObject -Class Win32_Product | ?{$_.Vendor -like '*prometheus*'}
IdentifyingNumber : {EDD0CDE3-4519-4C1A-9FB4-C8C067615698}
Name : windows_exporter
Vendor : prometheus-community
Version : 0.20.0
Caption : windows_exporter
PowerShell: Create Registry Keys within Windows Localhost
# createRegKey.ps1
$regKeys=@(
@{
hive='REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome';
name='ChromeCleanupEnabled';
value=0
}
@{
hive='REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome';
name='ChromeCleanupReportingEnabled';
value=0
}
)
function createRegKey{
param(
$regHive,
$keyName,
$value
)
try{
$keyValue=(Get-ItemProperty -Path $regHive -Name $keyName -ErrorAction Stop).$keyName
if($keyValue -ne $value){
New-ItemProperty -Path $regHive -Name $keyName -Value $value -Type String -Force
}else{
write-host "$regHive $keyName already has a value of $value"
}
}catch [System.Management.Automation.ItemNotFoundException],[System.Management.Automation.PSArgumentException] {
New-Item -Path $regHive -Force
New-ItemProperty -Path $regHive -Name $keyName -Value $value -Force
write-host "$regHive $keyName value has been set to $value"
}catch {
write-warning $_
New-ItemProperty -Path $regHive -Name $keyName -Value $value -Type String -Force
write-host "$regHive $keyName value has been set to $value"
}
}
$regKeys|%{createRegKey $_.hive $_.name $_.value}
Windows: How to Map Network Drive for All Users of a Local Machine
# Mapping file share using legacy commands (more effective than newer PowerShell equivalents in certain scenarios)
$textContent=@'
net use m: /delete
net use m: \\FILESERVER\SHARENAME
'@
Set-Content "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\mountShares.bat" $textContent
How to Set PowerShell Window and Prompt Title or Label
Have you ever wondered about changing the boring PS C:\Windows\system32> whenever a new window is opened in PowerShell? You’re in luck by finding this quick note. Here’s how you’d do it:
# Set Window title to match current machine name
$host.UI.RawUI.WindowTitle="PS $env:computername $env:username"
# Set Window prompt to match current machine name
function prompt {"PS $env:computername $env:username> "}
# Set color of label
function prompt{
Write-Host ("PS $env:computername $env:username> ") -nonewline -foregroundcolor Yellow
return " "
}
Use DISM To Install Windows Features
# dismInstallFeatures.ps1
$featuresToInstall = ('FileAndStorage-Services','Storage-Services','Web-Server','Web-WebServer','Web-Common-Http','Web-Default-Doc','Web-Dir-Browsing','Web-Http-Errors',
'Web-Static-Content','Web-Http-Redirect','Web-Health','Web-Http-Logging','Web-Log-Libraries','Web-ODBC-Logging','Web-Request-Monitor',
'Web-Http-Tracing','Web-Performance','Web-Stat-Compression','Web-Dyn-Compression','Web-Security','Web-Filtering','Web-Basic-Auth',
'Web-Client-Auth','Web-Digest-Auth','Web-Cert-Auth','Web-IP-Security','Web-Url-Auth','Web-Windows-Auth','Web-App-Dev','Web-Net-Ext',
'Web-Net-Ext45','Web-ASP','Web-Asp-Net','Web-Asp-Net45','Web-CGI','Web-ISAPI-Ext','Web-ISAPI-Filter','Web-Includes','Web-WebSockets',
'Web-Ftp-Server','Web-Ftp-Service','Web-Mgmt-Tools','Web-Mgmt-Console','Web-Mgmt-Compat','Web-Metabase','Web-Lgcy-Mgmt-Console','Web-Lgcy-Scripting',
'Web-WMI','Web-Scripting-Tools','Web-Mgmt-Service','NET-Framework-Features','NET-Framework-Core','NET-Framework-45-Features','NET-Framework-45-Core',
'NET-Framework-45-ASPNET','NET-WCF-Services45','NET-WCF-HTTP-Activation45','NET-WCF-TCP-PortSharing45','RSAT','RSAT-Feature-Tools','RSAT-SMTP',
'RSAT-SNMP','FS-SMB1','SMTP-Server','SNMP-Service','User-Interfaces-Infra','Server-Gui-Mgmt-Infra','Server-Gui-Shell','PowerShellRoot','PowerShell',
'PowerShell-V2','PowerShell-ISE','WAS','WAS-Process-Model','WAS-Config-APIs','WoW64-Support')
# Remove any feature that is not available to prevent dism failures. MSMQ-Container for example is only available
# on Windows 7 but not on Windows Server 2008 R2.
$availableFeatures = dism /online /Get-Features
$featuresToRemove = @()
$featuresToInstall | % { if (-not ($availableFeatures | Select-String ('{0}$' -f $_) -Quiet)) { $featuresToRemove += $_} }
$featuresToInstall = Compare-Object -ReferenceObject $featuresToInstall -DifferenceObject $featuresToRemove | select -ExpandProperty InputObject
$dismParameter = @('/online', '/Enable-Feature', ($featuresToInstall | % { '/FeatureName:{0}' -f $_ }), '/NoRestart', '/all')
$output = dism @dismParameter
# throw an error if dism wasn't successful
if ($global:LastExitCode -ne 0){
throw 'Error while installing Windows Features. {0}' -f ($output | Select-String '\.log$')
}
# dismCheckWindowsFeature.ps1
$featuresToCheck = ('RDS-RD-Server')
$availableFeatures = dism /online /Get-Features
$featuresToRemove = @()
$featuresToInstall | % { if (-not ($availableFeatures | Select-String ('{0}$' -f $_) -Quiet)) { $featuresToRemove += $_} }
$featuresToInstall = Compare-Object -ReferenceObject $featuresToInstall -DifferenceObject $featuresToRemove | select -ExpandProperty InputObject
$dismParameter = @('/online', '/Get-Features', ($featuresToCheck | % { '/FeatureName:{0}' -f $_ }), '/NoRestart', '/all')
$output = dism @dismParameter
# throw an error if dism wasn't successful
if ($global:LastExitCode -ne 0)
{
throw 'Error while installing Windows Features. {0}' -f ($output | Select-String '\.log$')
}
dism /online /get-Features 'RDS-RD-Server'
PowerShell: Get Available RAM Slots
# getRamSlotsAvailable.ps1
$computername=$env:computername
function getRamSlotsAvailable{
param($computername=$env:computername)
write-host "Computer name: $computerName"
$slots = Get-WmiObject -Class "win32_PhysicalMemoryArray" -namespace "root\CIMV2" -computerName $computerName
$ramModules = Get-WmiObject -Class "win32_PhysicalMemory" -namespace "root\CIMV2" -computerName $computerName
$ramSum=0
$ramModules.Capacity|%{$ramSum+=$_}
$slotsSum=0
$slots.MemoryDevices|%{$slotsSum+=$_}
write-host "Total slots: $slotsSum"
write-host "Total RAM: $([math]::round($ramSum/1GB,2)) GB"
Foreach ($module In $ramModules) {
write-host "Memory Installed: $($module.DeviceLocator)"
write-host "Memory Size: $($module.Capacity/1GB) GB"
}
return $slotsSum
}
getRamSlotsAvailable $computername
# Sample output
# PS C:\Windows\system32> getRamSlotsAvailable $computername
# Computer name: TEST-SERVER
# Total slots: 24
# Total RAM: 256 GB
# Memory Installed: DIMM_A1
# Memory Size: 16 GB
# Memory Installed: DIMM_A2
# Memory Size: 16 GB
# Memory Installed: DIMM_A3
# Memory Size: 16 GB
# Memory Installed: DIMM_A4
# Memory Size: 16 GB
# Memory Installed: DIMM_A5
# Memory Size: 16 GB
# Memory Installed: DIMM_A6
# Memory Size: 16 GB
# Memory Installed: DIMM_A7
# Memory Size: 16 GB
# Memory Installed: DIMM_A8
# Memory Size: 16 GB
# Memory Installed: DIMM_B1
# Memory Size: 16 GB
# Memory Installed: DIMM_B2
# Memory Size: 16 GB
# Memory Installed: DIMM_B3
# Memory Size: 16 GB
# Memory Installed: DIMM_B4
# Memory Size: 16 GB
# Memory Installed: DIMM_B5
# Memory Size: 16 GB
# Memory Installed: DIMM_B6
# Memory Size: 16 GB
# Memory Installed: DIMM_B7
# Memory Size: 16 GB
# Memory Installed: DIMM_B8
# Memory Size: 16 GB
How To Add or Remove a Path in Windows Environmental Paths
There are 2 functions to Add and Remove, at your convenience:
# addEnvironmentalPath.ps1
$pathToAdd='C:\Scripts'
$pathToRemove='C:\Scripts'
function addEnvironmentalPath($pathToAdd){
$registryEnvironment='Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment'
$pathToAdd=if($pathToAdd -match '\\$'){$pathToAdd -replace '.$'}else{$pathToAdd}
try{
$originalPaths=(Get-ItemProperty -Path $registryEnvironment -Name PATH).path
$pathsArray=$originalPaths -split ';'|?{$_.trim() -ne ''}|%{if($_ -match '\\$'){$_ -replace '.$'}else{$_}}|Sort-Object -Unique
if($pathToAdd -in $pathsArray){
write-host "$pathToAdd is already included in the environmental paths: '$originalPaths'"
return $true
}else{
$newPathsArray=$pathsArray+$pathToAdd
$newPaths=$newPathsArray -join ';'
Set-ItemProperty -Path $registryEnvironment -Name PATH -Value $newPaths
$newRegistryEnvironment=(Get-ItemProperty -Path $registryEnvironment -Name PATH).Path
write-host "Environmental paths have been changed:`r`nFrom: $originalPaths`r`nTo: $newPaths"
return $true
}
}catch{
write-warning $_
return $false
}
}
function removeEnvironmentalPath($pathToRemove){
$registryEnvironment='Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment'
$pathToRemove=if($pathToRemove -match '\\$'){$pathToRemove -replace '.$'}else{$pathToRemove}
try{
$originalPaths=(Get-ItemProperty -Path $registryEnvironment -Name PATH).path
$pathsArray=$originalPaths -split ';'|?{$_.trim() -ne ''}|%{if($_ -match '\\$'){$_ -replace '.$'}else{$_}}|Sort-Object -Unique
if($pathToRemove -notin $pathsArray){
write-host "$pathToRemove does not exist in the environmental paths: '$originalPaths'"
return $true
}else{
$itemIndex=[array]::indexof($pathsArray,$pathToRemove)
[System.Collections.ArrayList]$newPathsArrayList=$pathsArray
$newPathsArrayList.RemoveAt($itemIndex)
$newPaths=$newPathsArrayList -join ';'
Set-ItemProperty -Path $registryEnvironment -Name PATH -Value $newPaths
$newRegistryEnvironment=(Get-ItemProperty -Path $registryEnvironment -Name PATH).Path
write-host "Environmental paths have been changed:`r`nFrom: $originalPaths`r`nTo: $newPaths"
return $true
}
}catch{
write-warning $_
return $false
}
}
addEnvironmentalPath $pathToAdd
removeEnvironmentalPath $pathToRemove
PowerShell: Find Windows RDS Roles and Their Licensing Servers
# Get TS Licensing Servers (Enterprise or AD Registered)
$termLicenseServers=Get-ADGroupMember -Identity "Terminal Server License Servers"
$termLicenseServers|Select-Object -Property @{label='computername';expression={[regex]::match($_.DistinguishedName,'([\w\d-]+)(?=,OU=)').Value}}
# Get TS Connection Points with Licensing Role Installed (may or may not be registered on the domain)
$termServers=Get-ADObject -Filter {objectClass -eq 'serviceConnectionPoint' -and Name -eq 'TermServLicensing'}
$termServers|Select-Object -Property @{label='computername';expression={[regex]::match($_.DistinguishedName,'([\w\d-]+)(?=,OU=)').Value}}
# Check localhost for TS Licensing Servers
$tsSettings=gwmi -namespace "Root/CIMV2/TerminalServices" Win32_TerminalServiceSetting
$tsSettings.GetSpecifiedLicenseServerList().SpecifiedLSList
# Find RDS Servers and their Licensing Configs
$servers=Get-ADComputer -Filter {OperatingSystem -Like '*Windows Server*' -and Enabled -eq $true}
$results=@()
$noResults=@()
$initCount=0
$serversCount=$servers.Count
write-host "There are $serversCount servers to check..."
foreach($server in $servers.DNSHostName){
$initCount++
write-host "$initCount of $serversCount`: $server"
$rdsRole=try{Get-WindowsFeature RDS-RD-Server -ComputerName $server -EA Ignore}catch{$null}
if($rdsRole){
$rdsRoleInstalled=$rdsRole.InstallState -eq 'Installed'
if($rdsRoleInstalled){
$rdsLicenseServer=try{
$tsSettings=gwmi -namespace "Root/CIMV2/TerminalServices" Win32_TerminalServiceSetting -computername $server
$tsSettings.GetSpecifiedLicenseServerList().SpecifiedLSList
}catch{
'not configured'
}
$result=@{
computername=$server
rdsLicenseServer=$rdsLicenseServer
licensingType=$tsSettings.LicensingName
}
write-host "$server has RDS-RD-Server role installed with licensing server(s) $rdsLicenseServer"
$results+=$result
}else{
write-host "$server doesn't have RDS-RD-Server role installed"
}
}else{
write-warning "$env:computername cannot connect to $server"
$noResults+=@{
computername=$server
connectionProblem=$True
}
}
#pause
}
$results|%{write-host "$($_.computername)`: $($_.rdsLicenseServer) | $($_.LicensingType)"}
$noResults|%{write-host "$($_.computername)"}
Issue:
Log Name: System
Source: Microsoft-Windows-DNS-Client
Date: 8/1/2018 2:11:47 AM
Event ID: 8019
Task Category: (1028)
Level: Warning
Keywords:
User: NETWORK SERVICE
Computer:
Description:
The system failed to register host (A or AAAA) resource records (RRs) for network adapter
with settings:
Adapter Name : {2F85D40D-4BEB}
Host Name : testwindows
Primary Domain Suffix : intranet.kimconnect.com
DNS server list : x.x.x.x
Sent update to server : <?>
IP Address(es) : y.y.y.y
The reason the system could not register these RRs was because of a security related problem. The cause of this could be (a) your computer does not have permissions to register and update the specific DNS domain name set for this adapter, or (b) there might have been a problem negotiating valid credentials with the DNS server during the processing of the update request.
You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig /registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems administrator. See event details for specific error code information.
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-DNS-Client" Guid="{1C95126E}" />
<EventID>8019</EventID>
<Version>0</Version>
<Level>3</Level>
<Task>1028</Task>
<Opcode>0</Opcode>
<Keywords>0x4000000000000000</Keywords>
<TimeCreated SystemTime="2018-08-01T06:11:47.524646900Z" />
<EventRecordID>285426</EventRecordID>
<Correlation />
<Execution ProcessID="484" ThreadID="2104" />
<Channel>System</Channel>
<Computer>testwindows.intranet.kimconnect.com</Computer>
<Security UserID="S-1-5-20" />
</System>
<EventData>
<Data Name="AdapterName">{2F85D40D}</Data>
<Data Name="HostName">dbmon01l-ops-23</Data>
<Data Name="AdapterSuffixName">intranet.kimconnect.com</Data>
<Data Name="DnsServerList"> x.x.x.x</Data>
<Data Name="Sent UpdateServer"><?></Data>
<Data Name="Ipaddress">y.y.y.y</Data>
<Data Name="ErrorCode">9017</Data>
</EventData>
</Event>
Resolution:
List available NIC’s to pick the correct one
[testwindows]: PS C:\Users\brucelee\Documents> Get-NetAdapter
Name InterfaceDescription ifIndex Status MacAddress LinkSpeed
---- -------------------- ------- ------ ---------- ---------
Ethernet Microsoft Hyper-V Network Adapter 2 Up AA-6C-B8-00-00-00 20 Gbps
Ethernet 2 Cisco AnyConnect Secure Mobility Cli... 6 Not Present 00-05-00-00-00-00 0 bps
Remove the GUI check mark next to ‘Register this connection’s addresses with DNS’
[testwindows]: PS C:\Users\brucelee\Documents> Get-NetAdapter Ethernet|Set-DNSClient -RegisterThisConnectionsAddress $F
alse
Verify the result:
[testwindows]: PS C:\Users\brucelee\Documents> Get-NetAdapter Ethernet | Get-DNSClient
InterfaceAlias Interface ConnectionSpecificSuffix ConnectionSpecificSuffix RegisterThisConn UseSuffixWhen
Index SearchList ectionsAddress Registering
-------------- --------- ------------------------ ------------------------ ---------------- -------------
Ethernet 2 {} False True
How to Install Windows Dot Net 3.5 & 4.5
Run these commands to check dot net 3.5:
PS C:\Windows\system32> import-module servermanager
PS C:\Windows\system32> get-windowsfeature web-asp-net
Display Name Name Install State
------------ ---- -------------
[ ] ASP.NET 3.5 Web-Asp-Net Available
Install ASP.NET 3.5:
PS C:\Windows\system32> install-windowsfeature web-asp-net
Success Restart Needed Exit Code Feature Result
------- -------------- --------- --------------
True No Success {ASP.NET 4.8, Application Development, ASP...
Run this command to check dot net 4.5:
PS C:\Windows\system32> get-windowsfeature Net-Framework-45-Core
Display Name Name Install State
------------ ---- -------------
[X] .NET Framework 4.8 NET-Framework-45-Core Installed
If necessary, install DotNet 4.5:
add-windowsfeature Net-Framework-45-Core
PowerShell: Install App Using MSI on Remote Computers Via WinRM
# installMSiRemoteComputers.ps1
# version 0.0.1
$computernames='REMOTEPC001','REMOTEPC002'
$thisMsiFile='C:\Temp\something.msi'
$appName='testapp'
$desiredVersion='1.0'
$maxWaitSeconds=120
function installMsiOnRemoteComputers($computernames,$msiFile,$appName,$desiredVersion,$maxWaitSeconds){
function installMsiOnRemoteComputer{
param(
$computernames=$env:computername,
$msiFile,
$destinationLocalTempFolder='C:\Temp',
$testFileName='testfile.txt'
)
function translateLocalPathToSmbPath($computername,$localPath,$testFileName){
$adminDriveLetter=[regex]::match($localPath,'^([\w\W])\:').captures.groups[1].value
$partialPath=[regex]::match($localPath,'^([\w\W])\:(.*)').captures.groups[2].value
$testPath=join-path "\\$computername\$adminDriveLetter`$" "$partialPath"
if(!(test-path $testPath)){
try{
New-Item -Path $testPath -ItemType "directory" -force
}catch{
write-warning "Unable to create $testPath"
return $false
}
}
try{
$null=New-Item -Path $testPath -Name $testFileName -ItemType "file" -force
Remove-Item "$testPath\$testFileName" -force
return $testPath
}catch{
write-warning "Unable to read or write to $testPath"
return $false
}
}
$results=[hashtable]@{}
$msiLocalFilePath=join-path $destinationLocalTempFolder $(split-path $msiFile -leaf)
foreach ($computername in $computernames){
$translatedDestination=translateLocalPathToSmbPath $computername $destinationLocalTempFolder $testFileName
if($translatedDestination){
copy-item $msiFile $translatedDestination
}else{
write-warning "Unable to copy $msiFile to $translatedDestination"
$results+=[hashtable]@{$computername=$false}
continue
}
$psSession=new-psSession $computername
if($psSession.State -eq 'Opened'){
$result=invoke-command -session $pssession -scriptblock{
param($filePath)
$file=gi $filePath
$DataStamp = get-date -Format yyyyMMddTHHmmss
$logFile ="C:\" + '{0}-{1}.log' -f $file.name,$DataStamp
$MSIArguments = @(
"/i"
('"{0}"' -f $file.fullname)
"/qn"
"/norestart"
"/L*v"
$logFile
)
try{
[diagnostics.process]::start("msiexec.exe", $MSIArguments).WaitForExit()
write-host "MSIEXEC has been called for file $filePath on $env:computername"
return $true
}catch{
write-warning $_
return $false
}
} -Args $msiLocalFilePath
# Note Error:
# Resolved by not using -wait switch and calling [diagnostics.process] instead of Start-Process "msiexec.exe"
# Although, this error would still being thrown with the [diagnostics.process] result of success
# Processing data for a remote command failed with the following error message: The I/O operation has been aborted
# because of either a thread exit or an application request. For more information, see the about_Remote_Troubleshooting
# Help topic.
# + CategoryInfo : OperationStopped: (:String) [], PSRemotingTransportException
# + FullyQualifiedErrorId : JobFailure
# + PSComputerName :
$results+=[hashtable]@{$computername=$result}
remove-psSession $psSession
}else{
write-warning "Unable to connect to $computername"
$results+=[hashtable]@{$computername="Unable to connect to $computername"}
}
}
return $results
}
$results=[hashtable]@{}
foreach($computername in $computernames){
try{
installMsiOnRemoteComputer $computername $msiFile
write-host "Now waiting up to $maxWaitSeconds seconds before checking on the install result"
$timer=[System.Diagnostics.Stopwatch]::StartNew()
do{
start-sleep -seconds 5
$appVersionPassed=invoke-command -computername $computername {
param($appName,$desiredVersion)
$matchedApp=Get-WmiObject -Class Win32_Product -Filter "Name='$appName'"
if($matchedApp.Version -eq $desiredVersion){
return $true
}else{
return $false
}
} -Args $appName,$desiredVersion
if($appVersionPassed){
write-host "$appName $desiredVersion installed on $computername successfully"
$results+=[hashtable]@{$computername='$appName $desiredVersion installed'}
}
$exitCondition=$timer.elapsed.totalseconds -ge $maxWaitSeconds
}until($appVersionPassed -or $exitCondition)
if(!$appVersionPassed){
write-host "$appName $desiredVersion has NOT been installed successfully on $computername"
$results+=[hashtable]@{$computername="$appName $desiredVersion NOT installed"}
}
$timer.stop()
}catch{
write-warning $_
$results+=[hashtable]@{$computername="$_"}
exit 1
}
}
return $results
}
installMsiOnRemoteComputers $computernames $thisMsiFile $appName $desiredVersion $maxWaitSeconds
PowerShell: Add Local Group Members Onto a Server List
Sometimes, the GUI method of accomplishing tasks is too arduous and error prone. Thus, these quick cmdlets would get the job done in matter of seconds, assuming that WinRM and firewall allows the jump host to reach its targets.
# addLocalGroupMemberOnServerList.ps1
$computernames=@(
'testserver1',
'testserver2'
)
$localAdmins=@(
'domain\backupadmin'
)
$remoteDesktopUsers=@(
'domain\testuser'
)
invoke-command -computername $computernames -scriptblock{
param($localAdmins,$remoteDesktopUsers)
$localAdmins=$localAdmins.ToArray() # converting ArrayList datatype to Array [of objects]
$remoteDesktopUsers=$remoteDesktopUsers.ToArray()
try{
$remoteDesktopUsers|%{add-localgroupmember -group 'Remote Desktop Users' -Member $_}
$localAdmins|%{add-localgroupmember -group 'Administrators' -Member $_}
return $true
}catch{
write-warning $_
return $false
}
} -Args (,$localAdmins),(,$remoteDesktopUsers)
# Use legacy cmdlets to preemt this error
# Failed to compare two elements in the array.
# + CategoryInfo : NotSpecified: (:) [Get-LocalGroupMember], InvalidOperationException
# + FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand
# + PSComputerName : testserver.kimconnect.com
invoke-command -computername $computernames {net localgroup 'Administrators'; net localgroup 'Remote Desktop Users'}