17 January 2016

Low space issue


Again one more script.
I received two requests on two weeks for "Computer have low space". On these machines work many users and open Microsoft Outlook with Exchange accounts. So on computers collected lot off *.ost files (dynamically created for mail program). Easiest decision delete all ost files and receive 30-50 GB. Trouble only we know subnet network but don't know computers name. Ask users every time about computer name or IP when issue come in? Again PowerShell help for this task and protect from future this type of tickets. We need just enter subnet and receive result. After need remotely connect to computer search *.ost files on user directory and remove it. By the way one file we can't delete if user logged on and opened Outlook (profile in use).
For future I'm planning update switch - if computer have less than 5 GB free space start another script that connect remotely to computer and removed *.ost files on Users folder itself.
Param($machine)

function Test-FileLock
{
       param
       (
              [parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
              [Alias("FullName")]
              [string]$Path,
              [switch]$PassThru
       )
       begin {}
       Process
       {
        $oFile = New-Object System.IO.FileInfo $Path

        if ((Test-Path -Path $Path) -eq $false)
        {
               if ($PassThru.IsPresent -eq $false)
               {$false}
              return
        }
               
        try
        {
               $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
               if ($oStream)
               {$oStream.Close()}
               if ($PassThru.IsPresent -eq $false)
               {$false}
               else
               {Get-Item $Path}
        }
        catch
        {
              # file is locked by a process.
               if ($PassThru.IsPresent -eq $false)
               {
                     $true
               }
        }
       }
       end {}
}

function Find-File([string]$folderPath)
{
    if (Test-Path $folderPath)
    {
        try
        {
            [string[]]$childFolderPaths = [System.IO.Directory]::GetDirectories($folderPath)
            foreach($childPath in $childFolderPaths)
            {
                [System.IO.DirectoryInfo]$di = New-Object System.IO.DirectoryInfo($childPath)
                if (($di.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -ne [System.IO.FileAttributes]::ReparsePoint)
                {
                    <#
                    This is the recursive part. That is, this function calls itself in order to process child directories.
                    #>
                   Find-File $childPath
                }
            }
            [string[]]$filePaths = [System.IO.Directory]::GetFiles($folderPath, "*.*", [System.IO.SearchOption]::TopDirectoryOnly)
            foreach($filePath in $filePaths)
            {
                <#
                Here is where you'd take whatever action you want. I'm looking for files named AssemblyInfo.cs and displaying their full paths.
                #>
           
                if (([System.IO.Path]::GetFileName($filePath)) -like "*.ost")
                {
                    #Write-Host $filePath -ForegroundColor DarkGreen
                    Return $filePath
                }
            }
        }
        catch
        {Write-Host ($Error[0]) -ForegroundColor Red}
    }
}

function GetComputerInfo{ #left for future actions
    Param($mc)
    # Ping the machine to see if it is online
    $online=PingMachine $mc
    if ($online -eq $true)
    {
        # Ping Success
        Try { Get-WmiObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ComputerName $mc -ea stop | Format-List -Property Name}
        catch { "Something wrong (not a computer)"; exit}

        # ComputerSystem info
        $CompInfo = Get-WmiObject Win32_ComputerSystem -comp $mc
        # OS info
        $OSInfo = Get-WmiObject Win32_OperatingSystem -comp $mc
        # Serial No
        $BiosInfo = Get-WmiObject Win32_BIOS -comp $mc
        # CPU Info
        $CPUInfo = Get-WmiObject Win32_Processor -comp $mc

        # Create custom Object
        $myobj = "" | Select-Object Name,Domain,Model,MachineSN,OS,ServicePack,WindowsSN,Uptime,RAM,Disk
        $myobj.Name = $CompInfo.Name
        $myobj.Domain = $CompInfo.Domain
        $myobj.Model = $CompInfo.Model
        $myobj.MachineSN = $BiosInfo.SerialNumber
        $myobj.OS = $OSInfo.Caption
        $myobj.ServicePack = $OSInfo.servicepackmajorversion
        $myobj.WindowsSN = $OSInfo.SerialNumber
        $myobj.uptime = (Get-Date) - [System.DateTime]::ParseExact($OSInfo.LastBootUpTime.Split(".")[0],'yyyyMMddHHmmss',$null)
        $myobj.uptime = "$($myobj.uptime.Days) days, $($myobj.uptime.Hours) hours," +`
          " $($myobj.uptime.Minutes) minutes, $($myobj.uptime.Seconds) seconds"

        $myobj.RAM = "{0:n2} GB" -f ($CompInfo.TotalPhysicalMemory/1gb)
        $myobj.Disk = GetDriveInfo $mc

        #Return Custom Object"
        $myobj
    }
    else
    {
        # Ping Failed!
        Write-Host "Error: $mc not Pingable" -fore RED
    }
}

function GetDriveInfo{
    Param($comp)

    # Ping the machine to see if it is online
    $online=PingMachine $comp
    if ($online -eq $true)
    {
        # Ping Success
    Try { $t = Get-WmiObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ComputerName $comp -ea stop | Format-List  -Property Name}
    catch { #Write-Host "Something wrong (not a computer). RPC trouble" -fore RED
            Return}

    # Get disk sizes
    $logicalDisk = Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" -ComputerName $comp
    foreach($disk in $logicalDisk)
    {
        $diskObj = "" | Select-Object Disk,Size,INTFreeSpace,FreeSpace
        $diskObj.Disk = $disk.DeviceID
        $diskObj.Size = "{0:n0} GB" -f (($disk | Measure-Object -Property Size -Sum).sum/1gb)
        $diskObj.INTFreeSpace = (($disk | Measure-Object -Property FreeSpace -Sum).sum/1gb)
        $diskObj.FreeSpace = "{0:n0} GB" -f $diskObj.INTFreeSpace
        #Write-Host $diskObj.FreeSpace[0]
        $text = "{0}  {1}  Free: {2}" -f $diskObj.Disk,$diskObj.size,$diskObj.Freespace
        $msg += $text + [char]13 + [char]10
    }
    $ToDo = [int]$diskObj.INTFreeSpace
    if ($diskObj.INTFreeSpace -le 500){Write-Host "IP: $comp have Free space: $ToDo GB"} #enter control limit
    #Return $msg
    }
    else
    {
        # Ping Failed!
        #Write-Host "Error: $mc not Pingable" -fore RED
    }
}

function PingMachine {
   Param([string]$machinename)
   $pingresult = Get-WmiObject win32_pingstatus -f "address='$machinename'"
   if($pingresult.statuscode -eq 0) {$true} else {$false}
}

# Main - run all the functions
for($counter = 1; $counter -lt 255; $counter++){ # enter your last IP numbers
    $machine = "172.30.222." + $counter # enter your subnet
    GetDriveInfo $machine
    $OST = "\\" + $machine + "\c$\Users"
    Find-File $OST
    #future functions - remove ost files
    if(Test-FileLock $OST) {Write-Host "File locked or in use!" -fore RED}
    }
#Remove OST files
#$OstPath = $Env:LocalAppData + "\Microsoft" + "\Outlook"
#$ost = get-ChildItem $OstPath | where { $_.Extension -eq ".ost"} 
#$ost | remove-Item -WhatIf ## remove -wahtif to remove the files

Pause 0

No comments:

Post a Comment