728x90

Update 2021-12-18 – This looks like a much more competent script for detecting this vulnerability and there is a python version for Linux: https://github.com/CERTCC/CVE-2021-44228_scanner

Updated 2021-12-17 – Script is v1.4 and looks for .war files now too

Original post below

Inspired by the one-liner here: https://gist.github.com/Neo23x0/e4c8b03ff8cdf1fa63b7d15db6e3860b#find-vulnerable-software-windows

gci 'C:\' -rec -force -include *.jar -ea 0 | foreach {select-string "JndiLookup.class" $_} | select -exp Path

I wrote a script to expand on the command, support Windows Server 2008 onward and to be more automated.

This script is basically the one liner with a bit of logic to get all the local fixed disks on a server and iterate through them all looking for Log4j jar file:

<#
.Synopsis
Checks the local system for Log4Shell Vulnerability [CVE-2021-44228]
.DESCRIPTION
Gets a list of all volumes on the server, loops through searching each disk for Log4j stuff
 
Version History
1.0 - Initial release
1.1 - Changed ErrorAction to "Continue" instead of stopping the script
1.2 - Went back to SilentlyContinue, so much noise
Replace attribute -Include by -Filter (prevent unauthorized access exception stopping scan)
Remove duplicate path with Get-Unique cmdlet
.EXAMPLE
.\check_CVE-2021-44228.ps1
.NOTES
Created by Eric Schewe 2021-12-13
Modified by Cedric BARBOTIN 2021-12-14
#>
 
# Get Windows Version string
$windowsVersion = (Get-WmiObject -class Win32_OperatingSystem).Caption
 
# Server 2008 (R2)
if ($windowsVersion -like "*2008*") {
 
$disks = [System.IO.DriveInfo]::getdrives() | Where-Object {$_.DriveType -eq "Fixed"}
 
}
# Everything else
else {
 
$disks = Get-Volume | Where-Object {$_.DriveType -eq "Fixed"}
 
}
 
# I have no idea why I had to write it this way and why .Count didn't just work
$diskCount = $disks | Measure-Object | Select-Object Count -ExpandProperty Count
 
Write-Host -ForegroundColor Green "$(Get-Date -Format "yyyy-MM-dd H:mm:ss") - Starting the search of $($diskCount) disks"
 
foreach ($disk in $disks) {
 
# gci 'C:\' -rec -force -include *.jar -ea 0 | foreach {select-string "JndiLookup.class" $_} | select -exp Path
 
# Server 2008 (R2)
if ($windowsVersion -like "*2008*") {
 
Write-Host -ForegroundColor Yellow " $(Get-Date -Format "yyyy-MM-dd H:mm:ss") - Checking $($disk.Name): - $($disk.VolumeLabel)"
Get-ChildItem "$($disk.Name)" -Recurse -Force -Include @("*.jar","*.war") -ErrorAction SilentlyContinue | ForEach-Object { Select-String "JndiLookup.class" $_ } | Select-Object -ExpandProperty Path | Get-Unique
 
}
# Everything else
else {
 
Write-Host -ForegroundColor Yellow " $(Get-Date -Format "yyyy-MM-dd H:mm:ss") - Checking $($disk.DriveLetter): - $($disk.VolumeLabel)"
Get-ChildItem "$($disk.DriveLetter):\" -Recurse -Force -Include @("*.jar","*.war") -ErrorAction SilentlyContinue | ForEach-Object { Select-String "JndiLookup.class" $_ } | Select-Object -ExpandProperty Path | Get-Unique
 
}
 
}
 
Write-Host -ForegroundColor Green "$(Get-Date -Format "yyyy-MM-dd H:mm:ss") - Done checking all drives"

Sample output with nothing found:

Sample output with something found:

Good luck everyone.

728x90
728x90

We’ve run into a strange problem with our Windows Server 2019 VMs where sometimes when we clone a new VM from our template it works perfectly fine and sometimes it won’t let you install any new Roles and throws a 0x80073701 error. Better still, sometimes it lets you install a new Role and then months later when you go to add something else it fails also with a 0x80073701.

For the longest time the only solution I was able to find online was nuke it and start over which is typically what we did. That or to manually dig through registry keys for packages installed in Windows with a different language than that of your operating system. I never was able to get that suggestion to work because I couldn’t gain the permissions I needed to delete the registry keys. We also had zero luck running DISM with it’s variety of flags.

At some point a co-worker of mine stumbled across a PowerShell script that solved the problem for us and saved us having to rebuild a few more complicated VMs.

I had to use that script tonight on a VM but this time it didn’t work. I tried to see if I could find a new version but I couldn’t even find the original script. With some fiddling I eventually got the script to work but it dawned on me that lots of people might have having this problem and the script to fix it with out wiping/reloading might not be easily found anymore.

Full Disclosure. I did not write this script, I’ve only used it a few times with success. I searched for the authors name to see if they had a Github repo or something out there and found nothing other than a LinkedIn.

Near as I can tell this script does the following:

  1. Elevates its privileges in a very specific looking way. I did not dig much into it since the rest of the script does not appear to do anything malicious and you should run this “As an administrator” anyway I just went with it
  2. It then asks you for the location of your CBS log file, if none is provided it uses the default location
  3. It then parses the CBS log file for any instances of ERROR_SXS_ASSEMBLY_MISSING and then parses those lines to pull out the specific package names that are causing problems
  4. Using it’s elevated privileges it takes ownership of that packages registry keys and changes the ‘Currentstate’ key to ‘0’ which I assume means not installed or ignored
  5. It does some checks to make sure the ‘Currentstate’ was successfully changed and then completes

Once the script has run you do not need to reboot. You should be able to start adding Roles to the server right away.

I have found that running the script against “C:\Windows\Logs\CBS\CBS.log” does not always solve the problem. Tonight I went into “C:\Windows\Logs\CBS\” and had to run it against the second newest log “CbsPersist_20230310065917.log”. After doing that the issue was resolved for me.

In our case it appears the issue is with KB4598230 which has been pulled from the Microsoft Update Catalogue and can no longer be downloaded. I have seen plenty of form posts involving other KBs causing the exact same error though.

Sorry, that was a lot of reading. Here is what you are after:

 
 
 
 
<#
.SYNOPSIS
 
This script will fix the SXS assmbly missing issue while installing feature
 
.DESCRIPTION
 
The script mark the resolved packages absent which are missing manifest.
 
.PARAMETER
 
Provide CBS file path
 
.OUTPUTS
<Outputs if any, otherwise state None - example: Log file stored in current working directory "AssemblyMissingScript-" + [datetime]::Now.ToString("yyyyMMdd-HHmm-ss") + ".log")>
.NOTES
Version: 1.0
Author: Abhinav Joshi
Creation Date: 14/11/2020
Purpose/Change: Initial script development
 
.EXAMPLE
 
Run the script ERROR_SXS_ASSEMBLY_MISSING.ps1
 
Please enter CBS file path (Default Path: c:\windows\logs\cbs\cbs.log): C:\windows\Logs\cbs\cbs2.log
#>
 
 
function enable-privilege {
param(
## The privilege to adjust. This set is taken from
[ValidateSet(
"SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
"SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
"SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
"SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
"SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege",
"SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege",
"SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege",
"SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
"SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege",
"SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege",
"SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
$Privilege,
## The process on which to adjust the privilege. Defaults to the current process.
$ProcessId = $pid,
## Switch to disable the privilege, rather than enable it.
[Switch] $Disable
)
 
## Taken from P/Invoke.NET with minor adjustments.
$definition = @'
using System;
using System.Runtime.InteropServices;
 
public class AdjPriv
{
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
 
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}
 
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public static bool EnablePrivilege(long processHandle, string privilege, bool disable)
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = new IntPtr(processHandle);
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
if(disable)
{
tp.Attr = SE_PRIVILEGE_DISABLED;
}
else
{
tp.Attr = SE_PRIVILEGE_ENABLED;
}
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
}
'@
 
$processHandle = (Get-Process -id $ProcessId).Handle
$type = Add-Type $definition -PassThru
$type[0]::EnablePrivilege($processHandle, $Privilege, $Disable)
}
 
$logfile = [System.IO.Path]::Combine($rootDir, "AssemblyMissingScript-" + [datetime]::Now.ToString("yyyyMMdd-HHmm-ss") + ".log")
if (-not (Test-Path "$PWD\logs")) {
New-Item -Path "$PWD\logs" -ItemType Directory -Verbose
}
Start-Transcript -Path "$PWD\logs\$logfile"
 
$cbspathTEMP = Read-Host -Prompt "Please enter CBS file path (Default Path: c:\windows\logs\cbs\cbs.log)"
 
$cbspath = $cbspathTEMP.Replace('"','')
 
write-host ""
 
write-host -ForegroundColor Yellow $cbspath
 
 
if ($cbspath -eq $null -or $cbspath.Length -eq "0"){
 
Write-Host -ForegroundColor Yellow "No path was entered"
 
Write-Host "Setting up default CBS path"
 
$cbspath = "c:\Windows\Logs\CBS\CBS.log"
 
Write-Host -ForegroundColor Cyan $cbspath
}
 
 
$CheckingpackagesResolving = "Resolving Package:"
 
$checkingFailure = Get-Content $CBSpath | Select-String "ERROR_SXS_ASSEMBLY_MISSING"
 
if ($checkingFailure -ne $null -and $CheckWhichFeature -ne 0) {
 
Write-Host "Checking resolving packages"
 
$CBSlines = Get-Content $CBSpath | Select-String $CheckingpackagesResolving
 
$Result = @()
 
if ($CBSlines) {
 
foreach ($CBSline in $CBSlines) {
 
$packageLine = $CBSline | Out-String
 
$package = $packageLine.Split(":").Trim().Split(',').Trim() | Select-String "Package_"
 
$Result += $package
}
 
Write-host "Found following resolving packages"
 
$Results = $Result | Select-Object -Unique
 
foreach ($regpackage in $Results) {
 
$bb = "SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\$regpackage"
 
$uname = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
 
enable-privilege SeTakeOwnershipPrivilege
 
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($bb, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::takeownership)
# You must get a blank acl for the key b/c you do not currently have access
$acl = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None)
$me = [System.Security.Principal.NTAccount]$uname
$acl.SetOwner($me)
$key.SetAccessControl($acl)
 
# After you have set owner you need to get the acl with the perms so you can modify it.
$acl = $key.GetAccessControl()
$rule = New-Object System.Security.AccessControl.RegistryAccessRule ($uname, "FullControl", "Allow")
$acl.SetAccessRule($rule)
$key.SetAccessControl($acl)
 
$key.Close()
 
Write-Host "Mark this package absent $regpackage"
 
Set-ItemProperty -Path "HKLM:\$bb" -Name Currentstate -Value 0 -Type DWord -Force
}
 
Write-host "Verifying package state"
 
$Verifcationcheckvalue = "1"
 
foreach ($Regpackagecheck in $Results) {
 
$CurrentstateOfpackage = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\$Regpackagecheck").CurrentState
 
if ($CurrentstateOfpackage -eq "0") {
 
Write-host -ForegroundColor Green $CurrentstateOfpackage of $Regpackagecheck
 
$Verifcationcheckvalue += "1"
 
 
}
else {
 
Write-host -ForegroundColor red $CurrentstateOfpackage of $Regpackagecheck
 
$Verifcationcheckvalue += "0"
}
}
 
if ($Verifcationcheckvalue -notmatch "0") {
 
write-host "========================================================================="
 
write-host ""
 
Write-host -f white -BackgroundColor green "Verification passed, Retry Enabled"
 
write-host ""
 
write-host "========================================================================="
 
$Global:try = $true
 
}
else {
 
write-host "========================================================================="
 
write-host ""
 
write-host -f white -BackgroundColor Red "Verification Failed, Can't contiune. Collect $logfile and CBS.log"
 
write-host ""
 
write-host "========================================================================="
 
$Global:try = $false
}
 
}
else {
 
Write-Error "Error while finding resolving packages"
}
}
 
else {
 
Write-Host "Looks like $CBSpath is not right CBS File, check manually. "
 
}
 
 
 
stop-Transcript
 
pause

Abhinav Joshi, whoever you are. Thank you very much for this script. It’s saved us a ton of time and headache.

728x90
728x90

Its been a while with no updates and it's not that I haven't been working hard, it's that I have been doing a lot of stuff directly with the API of systems like WHMCS or NetBox, which have an extremely low appeal to anyone not working in the service provider space, so haven't been adding it all to the blog. If anyone wants me to add this stuff please just get in touch and I will put it on.

I was recently asked to create a function that would allow you to set the IP address of a virtual machine from the host in a Hyper-V environment.

Getting this working for Windows was pretty easy:

function Set-VMIp {
param(
$VMhost,
$VMname,
$Mask,
$GateW,
$IPaddress
)

Invoke-Command -ComputerName $VMhost -ArgumentList $IPaddress, $Mask, $Gatew, $VMname  -ScriptBlock {

[string]$VMname = $args[3]

$VMManServ =  Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_VirtualSystemManagementService

$vm = Get-WmiObject -Namespace 'root\virtualization\v2' -Class 'Msvm_ComputerSystem' | Where-Object { $_.ElementName -eq $VMname }

$vmSettings = $vm.GetRelated('Msvm_VirtualSystemSettingData') | Where-Object { $_.VirtualSystemType -eq 'Microsoft:Hyper-V:System:Realized' } 

$nwAdapters = $vmSettings.GetRelated('Msvm_SyntheticEthernetPortSettingData') 

$ipstuff = $nwAdapters.getrelated('Msvm_GuestNetworkAdapterConfiguration')

$ipstuff.DHCPEnabled = $false
$ipstuff.DNSServers = "8.8.8.8"
$ipstuff.IPAddresses = $args[0]
$ipstuff.Subnets = $args[1]
$ipstuff.DefaultGateways = $args[2]

$setIP = $VMManServ.SetGuestNetworkAdapterConfiguration($VM, $ipstuff.GetText(1))
}
}

I can't really claim this as all being my own work, I used a blog post from a Microsoft employee, head of product dev or something or other. Unfortunately, I can't seem to source the link right now to give proper credit. You dont really need to see it though. His post was pretty hardcore and mine is much easier, I promise.

728x90
728x90

There is nothing more annoying than when people leave ISO's mounted to VM's. It drives me mad.This little script will list machines that have ISO's mounted and then if you like you bulk unmount them. Enjoy

This will just list all your VM's and show you the status od the DVD drive :

$clusternodes = Get-ClusterNode

ForEach ($clusternode in $clusternodes)
{get-VM -ComputerName $clusternode.Name | Get-VMDvdDrive }`

If you want to bulk unmount them its the same command with a little bit at the end

$clusternodes = Get-ClusterNode

ForEach ($clusternode in $clusternodes)
{get-VM -ComputerName $clusternode.Name | Get-VMDvdDrive | Set-VMDvdDrive -Path $null}`

This will recurse through ever node in your cluster, so if you have a large environment, don't panic, it will take a while.

728x90
728x90

Function Copy-WithProgress
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        $Source,
        [Parameter(Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        $Destination
    )

    $Source=$Source.tolower()
#    $Filelist=Get-Childitem "$Source" –Recurse   -- 대상 폴더안의 파일 및 폴더 전체를 리스트함.
    $Filelist=Get-Childitem 파일명
    $Total=$Filelist.count
    $Position=0


    foreach ($File in $Filelist)
    {
        $Filename=$File.Fullname.tolower().replace($Source,'')
        #$Filename= 파일명
        $DestinationFile=($Destination+$Filename)
        Write-Progress -Activity "Copying data from '$source' to '$Destination'" -Status "Copying File $Filename" -PercentComplete (($Position/$total)*100)
        Copy-Item $File.FullName -Destination $DestinationFile
        $Position++
    }
}

$src="c:\temp"
$dest="C:\Temp\download"

Copy-WithProgress -Source $src -Destination $dest

#복사 완료 후 제거 
Remove-Item c:\temp\sw_dvd5_office_professional_plus_2016_64bit_korean_mlf.iso -Force  

728x90
728x90

Column Width

If it’s just a column width problem, the fix is simple enough: just pipe to out-string and add the width parameter.

PS > Get-CsAnalogDevice | ft Identity,RegistrarPool | out-string -Width 160

 

 

Collections / Arrays

… but what if that doesn’t fix it?

It might be that the object you’re looking at is an array (a “collection”), and PowerShell is only showing the first few entries in that array, rather than the lot.

Here, the fix is to change the $FormatEnumerationLimit value. If you type it on its own into PowerShell the current value – probably 3 – will be returned. If you set a new value of -1, it’ll output ALL entries in your collection.

PS > $FormatEnumerationLimit
3
PS > $FormatEnumerationLimit=-1

 

참고 - https://greiginsydney.com/viewing-truncated-powershell-output/

 

Viewing Truncated PowerShell Output | greiginsydney.com

Sometimes PowerShell truncates output, and if you don’t realise what’s going on, you’ll never get it to show. Where you’re expecting potentially lots more text, PowerShell replaces it with a single lousy ellipsis, cruelly taunting you. Column Width If it’s

greiginsydney.com

    

728x90
728x90

Lately, I have found myself in situations where I don’t have full domain admin rights while working on Lync. This isn’t a bad thing but one area that I consistently run into issues with is the Lync Management Shell. If you are on a Lync Front-end and you don’t have Administrator rights, the local Lync Management Shell doesn’t actually do Role Based Access Control (RBAC). Therefore, I’ll try to execute a command (say, set-csuser, grant-csdialplan, etc) and get a permission denied. Yet, I can go into the Lync Control Panel and change a setting on the user just fine.

The way around this is remote PowerShell. Since I work on many different clients, I wrote a nice little script that will prompt me for my credentials and the remote server or pool.

 

############################################
# Connect-LyncRemotePoSH.ps1
# Written By: Adam Ball
# Version History:
# 1.0 - 12/12/2013 - Initial Script
#
############################################

#You can pass a server or pool name with the script (i.e. .\Connect-LyncRemotePoSH.ps1 myserver.mydomain.com )
param ($poolname)

#If no server or pool was passed when the script executed, pop up a box and ask for it.
if ($poolname -eq $null){
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$poolname = [Microsoft.VisualBasic.Interaction]::InputBox("Enter a Pool or Server to connect to", "Remote Lync Pool or Server", "")
}

#Change the server or pool name in to a properly constructed URL
$poolname = "https://" + $poolname + "/OcsPowershell"
$cred = Get-Credential
$session = New-PSSession -ConnectionURI $poolname -Credential $cred
Import-PsSession $session

 

To execute, simply run the script (assuming proper execution policy is set). It will pop-up a box and ask you for the remote server or pool then pop up another box and ask for your credentials. You can also pass the server or pool name to it as part of the script execution (i.e. “.\Connect-LyncRemotePoSH.ps1 mypool.mydomain.com”).

This is also a nice way for being able to do Lync Management from your desktop without having the Lync tools installed.

Just remember, when you are done, remove the session by running “Remove-PsSession $session”.

FYI

https://phyler.wordpress.com/2013/12/12/lync-and-remote-powershell/

https://support.4it.com.au/article/files-cannot-be-loaded-because-running-scripts-is-disabled-on-this-system/

http://blog.insidelync.com/2011/08/remote-lync-powershell-administration/

 

Since you're using a third party firewall im assuming the native firewall is disabled? In any case double check your firewall rules to ensure 5895 and 5986 (if using ssl) inbound are allowed from your ip, on any port.

 

1. 방화벽 상태 확
   opened ports 80, 135, 443, 445, 5985, and 5986, but I am still unable to connect to the remote machine with the firewall enabled.

2. FE 서버와 파워셀을 날릴 서버에서 파워쉘 Policy "RemoteSigned" 설정
get-ExecutionPolicy RemoteSigned

$credential = get-credential
$sessionoption = new-pssessionoption -SkipRevocationCheck -SkipCAcheck -skipCNcheck
$session = New-PSSession -ConnectionUri https://pool01.mani4u.com/ocspowershell -credential $credential -SessionOption $sessionoption
IMport-Pssession $session

 

728x90
728x90

https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-powershell-1.0/ee177028(v=technet.10)

 

Using the Where-Object Cmdlet

Filtering Returned Data

The Where-Object cmdlet provides a way for you to filter data returned by other cmdlets. For example, by default the Get-Process cmdlet returns information about all the processes currently running on your computer. However, suppose you’re interested in only those processes using more than 200 handles. (We’re not sure why you’d be interested in that, but ….) To get back only that subset of processes, call Get-Process and then pipe the results through Where-Object:

Get-Process | Where-Object {$_.handles -gt 200}

Take careful note of the syntax. To begin, the where clause is enclosed within curly braces; in addition, the $_ notation is used to represent the default object (that is, the object being transferred across the pipeline). Last, but surely not least, notice the comparison operator being used to indicate greater than: it’s -gt as opposed to >. Windows PowerShell does not use the standard arithmetic comparison operators; instead, it uses operators such as these:

  • -lt -- Less than

  • -le -- Less than or equal to

  • -gt -- Greater than

  • -ge -- Greater than or equal to

  • -eq -- Equal to

  • -ne -- Not equal to

  • -like - Like; uses wildcards for pattern matching

In other words, if we were looking for processes where handles were greater than or equal to 200 we’d use this command:

Get-Process | Where-Object {$_.handles -ge 200}

You can also use the -and and -or parameters to create even-more finitely targeted datasets. For example, suppose you’d like to return all the instances of the svchost process that are using more than 200 handles. All you have to do is include both criterion in your where clause, separating the two by using -and:

Get-Process | Where-Object {$_.handles -gt 200 -and $_.name -eq "svchost"}

Likewise, suppose you wanted a list of all the process that are using more than 200 handles or that have the name svchost (in other words, all processes using more than 200 handles as well as all the svchost processes, regardless of the number of handles they might be using). In that case, use the -or parameter to join the two parts of your where clause:

Get-Process | Where-Object {$_.handles -gt 200 -or $_.name -eq "svchost"}

Here’s another example; this one (using the Get-ChildItem cmdlet) shows you only the files in the folder C:\Scripts that are larger than 100,000 bytes:

Get-ChildItem c:\scripts | Where-Object {$_.length -gt 100000}

And let’s not forget the -like operator. This command returns all of the files in C:\Scripts that include the string test in the file name. Note the use of the two asterisks as wildcard characters:

Get-ChildItem c:\scripts | Where-Object {$_.name -like "*test*"}

Here’s the kind of data you can expect to get back:

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---          5/6/2006  10:24 PM      34198 test.csv
-a---         5/19/2006   9:11 AM       5918 test.htm
-a---         5/19/2006   8:16 AM      34226 test.log
-a---         5/19/2006   1:20 PM         65 test.ps1
-a---         5/20/2006   9:52 AM        150 test.psc1
-a---         5/20/2006   9:52 AM        150 test.psc1e.psc1
-a---         5/19/2006   1:27 PM        565 test.txt
-a---         4/17/2006   6:41 PM      24064 test.txt.doc
-a---         5/19/2006   1:45 PM       1971 test.vbs
-a---         5/17/2006   1:41 PM       9248 test.xls
-a---         5/19/2006   1:20 PM     628234 Test.xml
-a---          4/6/2006  10:26 PM        205 test_NODUPL.txt
Where-Object Aliases
  • where

728x90
728x90

출처 : https://docs.microsoft.com/ko-kr/powershell/module/skype/get-csmanagementstorereplicationstatus?view=skype-ps




Skype for Business Server 복제 프로세스에 대한 정보를 반환합니다. 여기에는 Skype for Business Server 컴퓨터의 복제본이 최신 상태인지 여부에 대한 정보가 포함됩니다. 이 cmdlet은 Lync Server 2010에 도입되었습니다.

통사론

PowerShell
Get-CsManagementStoreReplicationStatus   [[-ReplicaFqdn] <String>]   [-CentralManagementStoreStatus]   [<CommonParameters>]

기술

관리자가 Skype for Business Server로 변경 한 경우 (예 : 관리자가 새 음성 정책을 만들거나 주소록 서버 구성 설정을 변경 한 경우) 변경 사항은 중앙 관리 저장소에 기록됩니다. 그런 다음 Skype for Business Server 서비스 또는 서버 역할을 실행하는 모든 컴퓨터에 변경 내용을 복제해야합니다.

데이터를 복제하기 위해 Master Replicator (중앙 관리 서버에서 실행)는 수정 된 구성 데이터의 스냅 샷을 생성합니다. 이 스냅 샷의 사본이 Skype for Business Server 서비스 또는 서버 역할을 실행하는 각 컴퓨터로 전송됩니다. 이러한 컴퓨터에서 복제 에이전트는 스냅 샷을 수신하고 수정 된 데이터를 업로드합니다. 에이전트는 최신 복제 상태를보고하는 메시지를 Master Replicator에 전송합니다.

Get-CsManagementStoreReplicationStatus cmdlet를 사용하면 조직의 모든 Skype for Business Server 컴퓨터에 대한 복제 상태를 확인할 수 있습니다.

예제들

-------------------------- 예제 1 ---------------------- ----

PowerShell
Get-CsManagementStoreReplicationStatus

예 1에서 Get-CsManagementStoreReplicationStatus cmdlet은 매개 변수없이 호출됩니다. 모든 Skype for Business Server 컴퓨터의 복제 상태 (최신 상태 또는 최신 상태가 아님)를 반환합니다.

-------------------------- 예제 2 ---------------------- ----

PowerShell
Get-CsManagementStoreReplicationStatus | Where-Object {$_.UpToDate -eq $False}

예제 2는 복제가 최신이 아닌 모든 컴퓨터의 컬렉션을 반환합니다. 이 작업은 먼저 Get-CsManagementStoreReplicationStatus cmdlet를 사용하여 모든 서버의 복제 상태가 포함 된 컬렉션을 검색하여 수행됩니다. 그런 다음이 컬렉션을 Where-Object cmdlet으로 파이프합니다.이 cmdlet은 반환 된 데이터를 UpToDate 속성이 False 인 컴퓨터로 제한하는 필터를 적용합니다.

-------------------------- 예제 3 ---------------------- ----

PowerShell
Get-CsManagementStoreReplicationStatus -ReplicaFqdn atl-cs-001.litwareinc.com

예제 3에서 반환 된 데이터는 한 대의 컴퓨터로 제한됩니다. atl-cs-001.litwareinc.com/

-------------------------- 예제 4 ---------------------- ----

PowerShell
Get-CsManagementStoreReplicationStatus | Where-Object {$_.LastUpdateCreation -lt "8/11/2018 8:00 PM"}

예 4는 2018 년 8 월 11 일 오후 8시 이전에 마지막으로 복제 된 컴퓨터에 대한 정보를 반환합니다. 이렇게하려면 Get-CsManagementStoreReplicationStatus cmdlet가 먼저 호출되어 모든 Skype Business Server 컴퓨터에 대한 복제 정보를 반환합니다. 이 정보는 2018 년 8 월 11 일 (8/11/2018 오후 8:00) LastUpdateCreation 속성이 오후 8:00보다 작은 컴퓨터 만 선택하는 Where-Object cmdlet으로 파이프됩니다. 2018 년 8 월 11 일 8:00 PM 이후에 마지막으로 복제 된 컴퓨터에 대한 정보를 반환하려면 -gt (보다 큼 연산자)를 사용하십시오.

Where-Object {$_.LastUpdateCreation -gt "8/11/2018 8:00 PM"}

이 예제에서 지정된 날짜는 날짜 - 시간 값에 대해 미국 영어 형식을 사용합니다. 날짜는 지역 및 언어 옵션과 호환되는 형식을 사용하여 지정해야합니다.

-------------------------- 예제 5 ---------------------- ----

PowerShell
Get-CsManagementStoreReplicationStatus -CentralManagementStoreStatus

예 5에 표시된 명령은 CentralManagementStoreStatus 매개 변수를 사용하여 중앙 관리 저장소의 현재 상태에 대한 자세한 정보를 반환합니다. 여기에는 Active Master 및 File Transfer Agent 서비스의 정규화 된 도메인 이름과 해당 서비스 각각에 대해 감지 된 마지막 하트 비트의 날짜 및 시간이 포함됩니다.

선택적 매개 변수

-CentralManagementStoreStatus

활성 마스터 및 파일 전송 에이전트 서비스의 위치뿐만 아니라 활성 복제본 및 삭제 된 복제본 목록을 포함하여 중앙 관리 저장소의 현재 상태에 대한 추가 정보를 반환합니다.

유형:SwitchParameter
위치:명명 된
기본값:없음
파이프 라인 입력 허용 :True (ByPropertyName)
와일드 카드 문자 적용 :그릇된
적용 대상 :Lync Server 2010, Lync Server 2013, Skype for Business Server 2015, Skype for Business Server 2019
-ReplicaFqdn

복제 상태를 확인할 컴퓨터의 정규화 된 도메인 이름 (FQDN)입니다. 예 : -ReplicaFqdn "atl-cs-001.litwareinc.com".

이 매개 변수가 포함되어 있지 않으면 모든 Skype for Business Server 컴퓨터의 복제 상태 정보가 반환됩니다.

유형:
위치:2
기본값:없음
파이프 라인 입력 허용 :True (ByPropertyName)
와일드 카드 문자 적용 :그릇된
적용 대상 :Lync Server 2010, Lync Server 2013, Skype for Business Server 2015, Skype for Business Server 2019

투입물

없음

출력

Microsoft.Rtc.Management.Xds.ReplicaState 또는 Microsoft.Rtc.Management.Xds.CentralManagementStoreStatusResult

기본적으로 Get-CsManagementStoreReplicationStatus cmdlet은 Microsoft.Rtc.Management.Xds.ReplicaState 개체의 인스턴스를 반환합니다. CentralManagementStoreStatus 매개 변수가 사용되면 cmdlet는 Microsoft.Rtc.Management.Xds.CentralManagementStoreStatusResult 개체의 인스턴스를 반환합니다.


728x90
728x90

서비스 재시작

#Get List of Microsoft Exchange Services

$services = Get-Service | ? { $_.name -like "MSExchange*" -and $_.Status -eq "Running"}

 

#Restart each service

foreach ($service in $services)

{

Restart-Service $service.name -Force

} 





중지 된 서비스 시작

#Get List of Microsoft Exchange Services

$services = Get-Service | ? { $_.name -like "MSExchange*" -and $_.Status -eq "Stopped"}

 

#Restart each service

foreach ($service in $services)

{

Restart-Service $service.name -Force

} 


728x90

+ Recent posts