Clear Google Cache with Powershell

Clear Google Cache with Powershell

Yesterday I had to clear out a few users’ google chrome cache. It was a little aggravating going computer by computer. We were doing this because recently a core web app was updated. The application left traces of itself in the Google Chrome Cache and it caused all kinds of problems. So the last few I looked for a way to do it with PowerShell. Long and behold you can Clear Google Cache with Powershell.

The Script

We are starting with the script, to begin with. We are doing this because the core of this script is wrapped around a remote template I use. I will cover the template later down the road.

Function Clear-SHDGoogleCache {
    param (
        [parameter(
            ValueFromPipeline = $True,
            ValueFromPipelineByPropertyName = $True,    
            HelpMessage = "Hostname of target computer", 
            Mandatory = $true)][alias('ComputerName')][String[]]$Computer,
        [Parameter(
            HelpMessage = "Allows for custom Credential.")][string[]]$username,
        [Parameter(
            HelpMessage = "Allows for custom Credential.")][System.Management.Automation.PSCredential]$Credential
    )
    begin {
        if ($null -eq $username) { $username = "*" }
    }
    process {
        foreach ($PC in $Computer) {
            foreach ($user in $username) {
                $Parameters = @{
                    Computername = $PC
                    ScriptBlock  = {
                        if ($username -ne "*") {
                            if (Test-Path C:\Users\$user) {
                                Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\default\cache\*" -Recurse -Force -ErrorAction SilentlyContinue 
                                Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\default\code cache\js\*" -Recurse -Force -ErrorAction SilentlyContinue 
                                Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\default\media cache\*" -Recurse -Force -ErrorAction SilentlyContinue 
                                Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\Default\Service Worker\CacheStorage\*" -Recurse -Force -ErrorAction SilentlyContinue 
                                Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\Default\Service Worker\ScriptCache\*" -Recurse -Force -ErrorAction SilentlyContinue 
                            }
                            else {
                                Write-Error "$user is not present."
                            }
                        }
                        else {
                            Remove-Item "c:\users\*\appdata\local\google\chrome\user data\default\cache\*" -Recurse -Force -ErrorAction SilentlyContinue 
                            Remove-Item "c:\users\*\appdata\local\google\chrome\user data\default\code cache\js\*" -Recurse -Force -ErrorAction SilentlyContinue 
                            Remove-Item "c:\users\*\appdata\local\google\chrome\user data\default\media cache\*" -Recurse -Force -ErrorAction SilentlyContinue 
                            Remove-Item "c:\users\*\appdata\local\google\chrome\user data\Default\Service Worker\CacheStorage\*" -Recurse -Force -ErrorAction SilentlyContinue 
                            Remove-Item "c:\users\*\appdata\local\google\chrome\user data\Default\Service Worker\ScriptCache\*" -Recurse -Force -ErrorAction SilentlyContinue   
                        }
                    }
                    Asjob        = $true
                    JobName      = $PC
                }
                if ($PSBoundParameters.ContainsKey('Credential')) {
                    $Parameters | Add-Member -MemberType NoteProperty -Name Credential -Value $Credential
                }
                if (Test-Connection -ComputerName $PC -Count 1 -Quiet) {
                    try {
                        Invoke-Command @Parameters
                    }
                    catch {
                        Write-Warning "$PC Invoke Command Failed"
                    }
                }
                else {
                    Write-Warning -Message "$PC is offline"
                }
            }
        }
    }
    end {}
}

The Breakdown

Let’s break down the script and see what is needed and how it is needed. The first thing you will notice is the computer and the user are both lists of strings. [String[]]. This means I will have to loop through each one. This is important because this means you can target a single user on multiple machines or multiple users on a single machine or both. The second thing I want to point out is the credentials. So, if you are not in admin mode, you can deploy the script with your admin creds, or with the local admin creds.

The Username is not a required item. Why did I do this? The simple answer is, if you don’t put a username, then it will clear every user’s google chrome cache. Notice in the “begin” area, we have if null is equal to username, then we want the username to be *. Later we ask, if the username is not equal to *, then we use the user. If not, we use the * which will go through all the users at once. Also notice in the do the user, we test if the user exists. If it doesn’t we deploy an error, if it does, we do our work.

if ($null -eq $username) { $username = "*" }
if ($user-ne "*") { do the user
    if (Test-Path C:\Users\$user) { Its there, lets go for it.} else { Error will robison.}
} else {do everyone}

The Core

At the core of this script is the remove-item blurp. We are going through each user data area and clearing out the different types of cache. There is the default cache, code, media, storage, and script caches. Each of these folders will have folders inside of them. So we need to recurse. We want to force it and we don’t care about the errors as some cache will not delete while chrome is active. Could I have added a kill chrome, yes, but why? if the end-user is working in chrome, this is going to be disruptive and force them to restart chrome. Lets look at the code.

Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\default\cache\*" -Recurse -Force -ErrorAction SilentlyContinue 
                                Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\default\code cache\js\*" -Recurse -Force -ErrorAction SilentlyContinue 
                                Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\default\media cache\*" -Recurse -Force -ErrorAction SilentlyContinue 
                                Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\Default\Service Worker\CacheStorage\*" -Recurse -Force -ErrorAction SilentlyContinue 
                                Remove-Item "c:\users\$user\appdata\local\google\chrome\user data\Default\Service Worker\ScriptCache\*" -Recurse -Force -ErrorAction SilentlyContinue 

That’s all the code you will need. If you selected not to use username the $user will turn into * which will do every user, including default. if you have something like sccm, pdq, intune, ninja, pulse, etc, then just user this part of the code with * instead of user. This will clear the cache as needed.

We close it all up and send it as a job to the machine in question. This way we are not stuck on each computer. It speeds things up. With Powershell 7, you can loop with a number of objects that you want which would speed this up even more.

Additional Reading

SSH with Powershell

SSH with Powershell

Recently I went over how to get information from the Unifi Controller. Now I want to show you how to grab information from the unifi device itself. In this example, we are going to use SSH with Powershell to pull some basic information from an unifi AP.

SSH with Powershell

The first thing you will need is to make an ssh connection. Most computers have open ssh installed and you can type in ssh username@ipaddress and access it after inputting passwords and such. However, I want to work with powershell and not whatever shell the unifi will present me. Thus, we will run through a module called POSH-SSH by darkoperator.

Install Posh-ssh

The first thing you will need to do, if you haven’t already, is installing the module. This module lives in the standard repos, which makes life so much easier. Here is the command:

Install-Module -Name Posh-SSH

Once you have the command installed, that’s when we import with the import module command.

Making a connection

The next step is to make the connection. The feel of this command is just the same as that of enter-pssession. We call the computer name, normally an IP address, and we add the credentials. The biggest difference is we add an acceptkey flag. You can also give your session an ID number, this is good if you are doing more than one at a time. Today we are only focusing on one connection. So it’s not needed, but it becomes very useful with loops. Like always, these sessions start at 0.

New-SSHSession -ComputerName 10.0.0.8 -AcceptKey -Credential (Get-Credential)

This creates a session of 0 which we can send commands to later. Remember, each session connection adds another session number. So the next one will be 1 and so on so forth. if you need more information or become lost with which sessions you are using, get-sshsession will help resolve this question.

Invoking SSH commands with Powershell

The next thing we need to do is invoke commands. What is the point of just connecting when we have the power of ssh and powershell? The command we can use is called invoke-sshcommand. When working with any system, you need to be mindful of that system’s shell. Ssh gives you the connection, and that system determines what you can use. This took me a while to figure out. One of the commands inside the unifi devices is info. This gives you useful information. So when you are connected, typing info will telling you IP addresses, mac address, inform statuses, and more. However, with the SSHcommand, it produces nothing useful. As the image below shows.

So, what is needed to do from here is adding a flag to let it know you are coming from somewhere else. This flag is “mca-cli-op” followed by the command you want. However, as the image below suggests, it parses the output as a single object. We need to go deeper by selecting the output.

$Output = (Invoke-SSHCommand -Command "mca-cli-op info" -SessionId 0).output

This is nice to know, however… It’s a string. You will need to parse this data out accordingly. I do this by using select-string then from there working each item. When I select the string, for example, model. I take the output and select-string model. Then i convert that to a string as select string make it into an match info object. Which isn’t as helpful as you would think. Then from there, I replace any spaces and split from the : to get the information I need. Below is the code.

$Return = [PSCustomObject]@{
        model = ($output | select-string model).tostring().replace(' ','').split(":")[1]
        version = ($output | select-string version).tostring().replace(' ','').split(":")[1]
        MacAddress = ($output | select-string mac).tostring().split(' ')[-1]
        IPaddress = ($output | select-string ip).tostring().replace(' ','').split(":")[1]
        Hostname = ($output | select-string hostname).tostring().replace(' ','').split(":")[1]
        UptimeSeconds = ($output | select-string uptime).tostring().replace(' ','').split(":")[1] -replace("\D",'')
        Status = ($output | select-string status).tostring().split(':').split('(').replace(' ','')[1]
        Inform = ($output | select-string status).tostring().split(' ')[-1] -replace('[()]','')
    }

From here you can change the inform, or other items using the flag and the command accordingly. Once you are finished with your session, make sure to remove it with the Remove-SSHSession command.

The Script

Here is the script. This script allows you to do more than one IP address.

function Get-UnifiSSHDeviceInformation {
    param (
        [parameter(
            ValueFromPipeline = $True,
            ValueFromPipelineByPropertyName = $True,    
            HelpMessage = "Unifi Username and Password", 
            Mandatory = $true)][alias('IP')][ipaddress[]]$IPaddress,
        [parameter( 
            HelpMessage = "Unifi Username and Password", 
            Mandatory = $true)][alias('UserNamePassword')][System.Management.Automation.PSCredential]$Credential
    )
    $return = @()
    foreach ($IP in $IPaddress) {
        New-SSHSession -ComputerName $IP -AcceptKey -Credential $Credential
        $Output = (Invoke-SSHCommand -Command "mca-cli-op info" -SessionId 0).output
        Remove-SSHSession -SessionId 0
        $Return += [PSCustomObject]@{
            model = ($output | select-string model).tostring().replace(' ','').split(":")[1]
            version = ($output | select-string version).tostring().replace(' ','').split(":")[1]
            MacAddress = ($output | select-string mac).tostring().split(' ')[-1]
            IPaddress = ($output | select-string ip).tostring().replace(' ','').split(":")[1]
            Hostname = ($output | select-string hostname).tostring().replace(' ','').split(":")[1]
            UptimeSeconds = ($output | select-string uptime).tostring().replace(' ','').split(":")[1] -replace("\D",'')
            Status = ($output | select-string status).tostring().split(':').split('(').replace(' ','')[1]
            Inform = ($output | select-string status).tostring().split(' ')[-1] -replace('[()]','')
        }
    }
    $Return
}

Additional Reading

Auto 365 Licensing with Groups

Auto 365 Licensing with Groups

I was working with a client a few months ago, and they needed me to set up auto licensing. The idea is that the helpdesk right-clicks on a user and clicks copy. That user will get all the groups inside the template user. This also includes licensing for O365. Believe it or not, this is super easy to do.

The client’s structure was as such, They had a local active directory that uses ad connect to sync all the user information. The ad sync occurred every 30 minutes.

Local AD

The first step is to create the licensing groups in local AD. In this case, I named them “Microsoft Office 365 E3” and “Microsoft Office 365 F3”. This way it’s super clear. These will be security groups. I have them in an OU that is synced with AD Connect.

Only users that will get E3 will be in the E3 group and the ones getting F3 will be in the F3 group. Once again, very clear.

Now I have created the groups, I complete an AD sync or I wait for the ADSync to be completed. To force an ad sync, you will need to log into the AD sync server. Normally this is a DC, it doesn’t have to be, but normally from my experience, it is.

Start-ADSyncSyncCycle -PolicyType Initial

You can view your sync by loading the Synchronization Service Manager and watching the sync. Once the sync is complete, move to the next step, Azure AD.

Azure AD Licensing Assignments.

Log into azure ad at https://entra.microsoft.com. On the left side, You will see Groups. Expand Groups and Click all Groups. Then search for the group you are looking for. In this case we want the Microsoft Office 365 E3 Group.

Now its time to add the license for anyone who joins this group.

  • Click on the Group
  • Under Manage click Licenses
  • In The middle Click Assignment
  • Add the desired licenses and applications associated with the licenses, See the image below.
  • Click Save.

The final step is to add users accordingly. After they sync, they will receive the licensing accordingly. Now you have a fully automated method of assigning licenses.

Additional Reading

It’s Ok to be you

It’s Ok to be you

Our American society is driven to force people to mask up and be something else. This is very true in IT. In IT, we are told we need to have a decade of rust experience, even though it isn’t a decade old. Impossible standards are always around us, forcing us to believe that we must match those standards to be a valid person or employee.

This is not the case. You are valid. No one can do everything. It’s not possible. I wouldn’t trust brain surgery to my fellow coworkers. I wouldn’t trust grandpa to build a complex security structure with the latest ai technology. It’s just not logical. We are a more powerful group together than apart.

When you try to do everything yourself, you push others away. There is a ton of reasons why we do this. It can range from past trauma, shame, upbringing, pride, and more. By pushing people away, you will face burnout. Thus letting people in is the only way to avoid burnout.

Lets take a look at why it’s ok to be you.

How do I be myself?

Spend time with yourself. We humans, especially us IT people, oftentimes fill our schedule with everything but time for us. We think sleep is time for us. Sleep is a basic requirement, not dedicated time for yourself. Set priorities for your own time. This is a requirement. There is no option. Boredom is good. It forces you to sit with yourself.

Try new hobbies. Once again, it’s ok to branch out and discover new things. If you always enjoyed being outside and playing with the dirt as a child, try out gardening. I always, loved water as a child, so why not swim? The key is to look at what you enjoyed as a child and translate that as an adult. I always enjoyed building new things and making new things. So, I take scraps and try to make something. Most of the time it’s a failure, but sometimes it’s something cool. I personally like “chasing” the dopamine. I like getting my hands on many different things. My joy of teaching is the reason this blog exists. That’s why I blog. It is relaxing for me.

Spend time with Old Friends

If it is safe, spend time with old friends. These memories will show you who you are under that layer of “Worker.” Often times when I am with my friends we talk about goofy stuff our kids are doing or about an anime we just watched. Sometimes we break out the mtg cards and play an old-style game. This brings me back to my core self, my authentic self. Also often times being around others, even though I’m an introvert, helps me see others as they are and not as I want them to be. This is very important for us in IT because of the impossible standards. When the standards are higher than reality, this fosters an attitude that we can be better than others. So being around others will show us, we are equal.

It’s Ok to be you

Being you is not a bad thing. Being someone else is a bad thing. Accepting who you are is the first step of true and lasting growth. Don’t deny yourself of yourself. That’s painful. It’s like a wond of the self. Over time, it will destroy you. So, be ok with being you.

Have a wonderful month.

Additional Readings

WordPress for Free

WordPress for Free

Today’s post is a formula that you can use to get a decent server and install WordPress on it. This is the setup for this site, and it works like magic. This is a self-hosted WordPress for free.

Oracle Always Free Teir

Oracle offers an always free tier for servers. This is an arm server and it does wonders. 8 Cores and 24 gb of ram with up to 200 GB of storage. This thing is a beast for a free server. For more information, you can visit their site: https://docs.oracle.com/en/learn/cloud_free_tier/index.html

When you create your compute, make sure you stay within the always free unless you are willing to pay for more. Also, select the Ubuntu server as this is the easiest way to build your server.

Make sure to download your SSL cert or you will not be able to later.

LAMP stack

The next phase for your Free WordPress site is building out a lamp stack. Lamp means Linux, Apache, Mysql, and PHP. With this stack, you can run almost any site. I’m going to refer you to digital oceans for this part, as they have an amazing tutorial for just this. https://www.digitalocean.com/community/tutorials/how-to-install-linux-apache-mysql-php-lamp-stack-on-ubuntu-22-04.

Quick Catch

The Oracle always free tier users iptables. Here is a good forum post on how to disable iptables. https://serverfault.com/questions/129086/how-to-start-stop-iptables-on-ubuntu.

Another Quick catch is you must open the ports in the firewall of your compute on the main page. Once you do this, then you are free to do more.

WordPress For Free

Now it’s time to install WordPress for Free. Digital Oceans offers a free tutorial for this process as well. I suggest reading over it. https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-on-ubuntu-22-04-with-a-lamp-stack. Once you have your website installed, it’s all about the setup from here. You have the basic setup. Now it’s time to work on logos, placement, content, SEO, and more. This is a learning curve within itself.

I suggest getting a udmey account and searching for the SEO beginner to hero courses as these will change how you build out your site. I always suggest a few plugins for beginners.

  • Loginizer – This plugin prevents people from brute forcing into your site.
  • W3 Total Cache – This plugin keeps your site moving quickly and you can set it to do some crazy stuff.
  • Health Check and Troubleshooting – This will help keep you up to date. This includes things like PHP upgrades and such.
  • WP Statistics – this one is very simple, it gives you a visit and visitor lists. This way you can see your returning traffic vs new traffic.
  • Yoast SEO – SEO allows your site to be found. Yoast makes, making sites easier. It helps with blog posts and more. I personally can’t write without it. The readability helped me see some of my language issues.
  • Shortcodes Ultimate – The paid version of this is amazing, the free is amazing as well. I am able to do quotes and more with the free version. Which is why I use it.

Other Reading