by David | Dec 23, 2020 | Information Technology, PowerShell
Today, I needed to convert a mac address to a CIDR. The lesson I learned about this is to go back to the basics instead of looking around for a quick answer. So, to the basics first.
A mac address is a 4 octet number that represents a binary position. It ranges between 1 and 255. This means something like 255.255.255.0 is represented in binary as: 1111 1111 1111 1111 1111 1111 0000 0000
It’s easier to remember the 255 number instead of all those ones and zeros. However, what’s that CIDR? Well, what’s a CIDR? A CIDR represents the mac address and how many positions there are. If you count the number above, it turns into 24 1s and 8 0s. Thus the CIDR is 24. Very simple.
Now, how do you change 240.0.0.0 to a cidr? You can go to a chart and look or we can use PowerShell. The first thing we need to do is split up this string.
We split the string up with a split command and tell it to split it up by the . item. We use an exit \ because the . is a special character for regex. Next, we loop through this list of octets with a foreach-object loop.
$Mask -split '\.' | ForEach-Object {
}
Then we break down each octet into a binary number. We do this with a system.convert and tell it the number we bytes we want which is 2.
[System.Convert]::ToString($_, 2)
We then pad that information because sometimes 0s will produce more useless items.
([System.Convert]::ToString($_, 2).PadLeft(8, '0'))
The code above will give us the 1s and 0s of the binary number. Now we need to count the ones. We do this by converting the string to a char array with at .toochararray(). We search the string with a where-object for the number 1 and finally count it.
(([System.Convert]::ToString($_, 2).PadLeft(8, '0')).tochararray() | where-object { $_ -eq '1' } | measure-object).count
Now we need to add each item up. We do this by adding a variable before the loop set to 0 and then add the variable to the variable and the count. Finally, after the loop, display the information.
$Cidr = 0
$Mask -split '\.' | ForEach-Object {
$Cidr = $Cidr + (([System.Convert]::ToString($_, 2).PadLeft(8, '0')).tochararray() | where-object { $_ -eq '1' } | measure-object).count
}
$Cidr
That’s it yall! We count the number of 1s. That will give us our cidr count.
Script
Have fun with the script!
function ConvertFrom-SHDIPv4MaskToCidr {
param (
[string]$Mask
)
$Cidr = 0
$Mask -split '\.' | ForEach-Object {
$Cidr = $Cidr + (([System.Convert]::ToString($_, 2).PadLeft(8, '0')).tochararray() | where-object { $_ -eq '1' } | measure-object).count
}
$Cidr
}
by David | Dec 6, 2020 | PowerShell
Need 1000 or unique user photos for your lab? There is a great website for just such a thing. https://thispersondoesnotexist.com/image. Let’s break down some code to see how we can pull a few hundred pictures.
The first thing we need to know is how many we want. We are going to get 1000 faces for this example. Next, we need a safe location. Finally, we need an sleep time for the site to regenerate an image. Lets get started.
$StartCount..$FinishCount
the two . in this code allows you to loop through two values. Next we need to pipe this command into a foreach object loop.
$StartCount..$FinishCount | foreach-object {}
Inside the for each loop we start the real work. We are going to use the Invoke-WebRequest. Our URI is the site “https://thispersondoesnotexist.com/image” We will select where we want to save the file using the -outfile location. We are going to save it in the save location we choose earlier. We will put the name as the number you are currently using. Finally we will add a -disablekeepalive flag to stop the system from keeping the connection alive. We do this out of respect for the site.
Invoke-WebRequest -Uri $URL -OutFile "$SaveFolder\$_.jpg" -DisableKeepAlive
Next we need to do a sleep cycle. We do this because if we do a request after another request, we will get the same image. 7 Seconds seems to be the magic number. We do this with Start-Sleep -Seconds 7.
That’s it, It’s a simple process. The Invoke-WebRequest will get the needed image and save it to your computer. The site will generate a new picture each time you reach out.
The Scripts
Here is the script below.
function Get-Faces {
param (
[int]$StartCount = 1,
[int]$FinishCount = 1000,
[int]$SecondsToSleep = 7,
[string]$SaveFolder = "C:\Dpb\100000 Faces"
)
$URL = 'https://thispersondoesnotexist.com/image'
$StartCount..$FinishCount | foreach-object {
Invoke-WebRequest -Uri $URL -OutFile "$SaveFolder\$_.jpg" -DisableKeepAlive
Start-Sleep -Seconds $SecondsToSleep
}
}
Have fun with this little guy, just remember to be respectful of the sites you are pulling information from.
by David | Nov 22, 2020 | Help Desk, Information Technology, PowerShell
Do you have an admin account that needs to be hidden? Setting up this account among 2000 machines at different sites and different clients? Sounds like a nightmare right? Well, you can easily hide a user’s account from the login. This is done through the registry.
HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList
Inside here, we create a Dword with the username that we want to hide from the start menu and set it to 0 to hide the user and 1 to make it visible. So the code is a single liner. We create the Userlist, if it doesn’t exist, and make the new item property.
This code will make the user visable.
New-Item 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList' -Force | New-ItemProperty -Name $Param1 -Value 1 -PropertyType DWord -Force
This code will make the user hidden.
New-Item 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList' -Force | New-ItemProperty -Name $Param1 -Value 0 -PropertyType DWord -Force
Make sure to replace the Param1 with the username accordingly. After that you will need to reboot and should be good to go.
by David | Nov 22, 2020 | Help Desk, Information Technology, PowerShell
I hate it when I start up my PC and my number lock is turned off. Did you know you can set this to be automatic. Yep that’s right, automatic. Start up powershell as administrator and run the single line of code below. Then you should be set to go.
Set-Itemproperty -Path 'HKU:\.DEFAULT\Control Panel\Keyboard\' -Name 'InitialKeyboardIndicators' -Value '2'
Use wisely fellow admins.
by David | Oct 21, 2020 | Information Technology, PowerShell, Resources
Ever need a service that copies a single folder to multiple locations at once? This script will do just that. It will copy a single location to more than one location and even log the outcomes accordingly. Thus, you will be able to set this one up as a task and run it every so often.
Invoke-SHDMoveFiles {
<#
.SYNOPSIS
Copy files from target source folders to a set of target folders.
.DESCRIPTION
Copys from multiple source folders to a select target folders. This allows archiving to occur.
The folders are not auto created. Thus, the folders must exists. The script also adds a log file of any error
messages you see. See notes for more details.
.PARAMETER SourceFolder
[String[]] SourceFolder is an Array of Strings of target folders to move the files from.
.PARAMETER TargetFolder
[String[]] TargetFolder is an Array of strings where the files will be copied to. This is not a one for one ratio. Thus all files will exist inside the targetfolder.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\','C:\tbc\tmp\Source Folder 2\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\'
Moves all files from the source folder 1 and 2 to target folders 1 and 2.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\'
Moves all files from the source folder 1 to target folders 1 and 2.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder 1\','C:\tbc\Tmp\Source Folder 2\','C:\tbc\Tmp\Source Folder 3\' -TargetFolder 'C:\tbc\tmp\Target Folder\'
Moves all files from the source folder 1, 2, and 3 to the target folder
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\','C:\tbc\tmp\Source Folder 2\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\' -Recurse
Moves all files under Source folder 1 and 2 to target folders 1 and 2.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\' -Recurse
Moves all files under source folder 1 to target folders 1 and 2.
.EXAMPLE
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder 1\','C:\tbc\Tmp\Source Folder 2\','C:\tbc\Tmp\Source Folder 3\' -TargetFolder 'C:\tbc\tmp\Target Folder\' -Recurse
Moves all files under source folder 1, 2, and 3 to the target folder
.INPUTS
[String] Folder Paths
.OUTPUTS
No Output
.NOTES
Author: David Bolding
Date: 8/16/2020
Purpose: Moving files around and making archives
Min Powershell Version: 4
This command generates error logs located c:\tbc\SHDMoveFileLog.txt. The error logs structure is broken up in 4 sections seperated with by ;
1;$((Get-Date).tostring());Catch;$($_.Exception)
1 - The placement of the error physically inside the script.
2 - The date and time of the error
3 - What type of error
4 - Information about the error
Run this command inside a scheduled task every 5 minutes to copy files needed to required locations. Make sure the
tasks running user has full access right to the file locations provided.
.LINK
https://bolding.us
#>
[cmdletbinding()]
param (
[Parameter(HelpMessage = "Source Folder", Mandatory = $True)][string[]]$SourceFolder,
[Parameter(HelpMessage = "Target Folders", Mandatory = $True)][string[]]$TargetFolder,
[parameter(HelpMessage = "Recurse the Source Folder")][switch]$Recruse
[parameter(HelpMessage = "Log Location")][string]$Logs = "C:\tmp\SHDMoveFileLog.txt"
)
#Tests to see if local c:\tbc exists, if it doesn't, it will create the path.
if (Test-Path (Split-Path $logs)) { "" >> $logs } else { mkdir (Split-Path $logs) }
#Start with the first source
foreach ($Source in $SourceFolder) {
#Tests to see if the source path exists.
if (Test-Path -Path $Source) {
#Grabs the required files from the first source path. It only grabs files.
#Also checks if there is a recruse flag. If so, recurses accordingly.
if ($Recruse) { $files = Get-childitem -Path $Source -File -Recurse } else { $files = Get-childitem -Path $Source -File }
#Next we sort through the files in question
foreach ($File in $files) {
#Create a test bool.
$success = $false
#Starts the target folder sorting
foreach ($Target in $TargetFolder) {
#Tests to see if target folder exists. If not, logs.
if (Test-Path -Path $target) {
#Enter a try catch to copy the files
try {
#Copys a single file to target folder. Overwrites any other there without confirmation
#No Confiramtion due to the lack of human Interaction.
Copy-Item -Path $file.fullname -Destination $Target -Force -Confirm:$false
#If no error so far, sets the success bool to true
$success = $true
}
catch {
#a failure occured, thus we set the success bool to false
$success = $false
#We log the error. This is the first log that shows up in the system.
#We date it.
#We state it's a catch
#Then we give the reason the try catch gives.
"1;$((Get-Date).tostring());Catch;$($_.Exception)" >> $logs
}
}
else {
#We log the fact that we can't reach the target location
"2;$((Get-Date).tostring());CanNotFind;$Target" >> $logs
}
}
#We test the bool for success.
if ($success -eq $true) {
try {
#if successful we remove the file.
Remove-Item -Path $file.FullName -Force -Confirm:$false
}
catch {
#If we can't remove the file we log the reason why.
"3;$((Get-Date).tostring());Catch;$($_.Exception)" >> $logs
}
}
}
}
else {
#We log the fact we can't reach the source location.
"4;$((Get-Date).tostring());CanNotFind;$Source" >> $logs
}
}
}
Examples
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder\' -TargetFolder 'C:\tbc\tmp\Target Folder\','C:\tbc\tmp\Target Folder 2\'
Moves all files from the source folder 1 to target folders 1 and 2. This is good for a backup of files. What I use this for is a custom software at work. It other products drop to location 1. Then it has a backup folder and the system folder. There we go, good as gold.
./Invoke-SHDMoveFiles -SourceFolder 'C:\tbc\Tmp\Source Folder 1\','C:\tbc\Tmp\Source Folder 2\','C:\tbc\Tmp\Source Folder 3\' -TargetFolder 'C:\tbc\tmp\Target Folder\' -Logs c:\tmp\Combiner.txt
Moves all files from the source folder 1, 2, and 3 to the target folder. It also logs any errors. This is useful when trying to come folders together.
Notes
- This script was designed to be ran as a task. If it doesn’t grab a file the first time around, it will grab it the second time around. It does this by using the try catch. It trys to move a file. if it doesn’t, it logs it and leaves it. We do that because a lot of times these files are being created and have a lock state. It’s best not to move them during that state.
- This script auto logs into the c:\tmp location if you don’t state otherwise when things go wrong.
by David | Oct 16, 2020 | Information Technology, PowerShell, Resources
This little script will allow you to check a folder location, if that folder location has x number of files, it will restart the service of your choice on a target computer. Then it will log that information and finally it will email someone this information.
function Invoke-FileServiceIntegrityCheck {
<#
.SYNOPSIS
Checks a file path for number of files. If greater, restarts a service and emails a message and logs a log.
.DESCRIPTION
Checks a file path for a set number of files that are predefined by the end user. If the file count is greater, it will restart a service. It will log the results and email a person stated by the end user.
.PARAMETER SearchPath
Target Path to scan for file count.
.PARAMETER FileCount
File count that will be used to determine the request size.
.PARAMETER ComputerName
Target Computer Name that the service lives on.
.PARAMETER ServiceName
Name of the service to restart.
.PARAMETER SendReportTo
The email address to which the email report will be sent to.
.PARAMETER EmailDomain
The domain name. For example, example.local
.PARAMETER MailServer
The mail server to send the email from.
.PARAMETER Recurse
Recurses the file search path.
.PARAMETER Credential
The Credentials, if needed for the email server.
.EXAMPLE
Invoke-FileServiceIntegrityCheck -SearchPath \\server1\share -FileCount 25 -ComputerName server2 -ServiceName intergrator -SendReportTo bob@example.com -EmailDomain example.com -Mailserver mail.example.com -Credential (Get-Credential)
Checks the folder \\server1\share to see if there is 25 or more files. If it does, it will restart the service named intergrator on server 2.
Then it will send an bob@example.com from watcheye@example.com using mail.example.com and the credentials provided.
.EXAMPLE
Invoke-FileServiceIntegrityCheck -SearchPath \\server1\share -FileCount 25 -ComputerName server2 -ServiceName intergrator -SendReportTo bob@example.com -EmailDomain example.com -Mailserver mail.example.com
Checks the folder \\server1\share to see if there is 25 or more files. If it does, it will restart the service named intergrator on server 2.
Then it will send an bob@example.com from watcheye@example.com using mail.example.com. Email will be sent from the server. If no relay is setup, the server will reject the email.
.INPUTS
[none]
.OUTPUTS
email and log
.NOTES
Author: David Bolding
Date: 10/14/2020
.LINK
https://github.com/rndadhdman/PS_Super_Helpdesk
#>
[cmdletbinding()]
param (
[parameter(HelpMessage = "Folder Search Path", Mandatory = $True)][string]$SearchPath,
[parameter(HelpMessage = "File Count", Mandatory = $True)][int]$FileCount,
[parameter(HelpMessage = "Computer That the server Lives", Mandatory = $True)][String]$ComputerName,
[parameter(HelpMessage = "Service Name", Mandatory = $True)][String]$ServiceName,
[parameter(HelpMessage = "Service Name", Mandatory = $True)][String]$SendReportTo,
[parameter(HelpMessage = "Service Name", Mandatory = $True)][String]$EmailDomain,
[parameter(HelpMessage = "Service Name", Mandatory = $True)][String]$Mailserver,
[parameter(HelpMessage = "Recurse the Search")][switch]$Recurse
[Parameter(HelpMessage = "Allows for custom Credential.")][System.Management.Automation.PSCredential]$Credential
)
#Checks Files
if ($Recurse) { $Files = Get-ChildItem "$SearchPath" -Recurse } else { $Files = Get-ChildItem "$SearchPath" }
if ($Files.Count -ge $FileCount) {
$StopTime = Get-date
Get-Service -ComputerName mtxs-lifetecapp -Name "Interlink" | Stop-Service
sleep 30
Get-Service -ComputerName mtxs-lifetecapp -Name "Interlink" | Start-Service
$StartTime = Get-date
sleep 30
if ($Recurse) { $Files2 = Get-ChildItem "$SearchPath" -Recurse } else { $Files2 = Get-ChildItem "$SearchPath" }
if (!(Test-Path c:\logs)) {mkdir c:\logs}
#Gathers Log Info
$Log = [pscustomobject]@{
ComputerName = $ComputerName
ServiceName = $ServiceName
SearchPath = $SearchPath
StopFileCount = $Files.count
ServiceStopTime = $StopTime.ToString()
ServiceStartTime = $StartTime.tostring()
StartFileCount = $Files2.count
CallingComputer = $env:COMPUTERNAME
}
$Log | Export-csv c:\temp\Invoke_FileServiceIntegrityCheck_log.csv -Append
#Builds EMail
$ErrorHtmlbody = @"
<html>
<head>
<style>
body {
Color: #252525;
font-family: Verdana,Arial;
font-size:11pt;
}
h1 {
text-align: center;
color:#C8102E;
Font-size: 34pt;
font-family: Verdana, Arial;
}
</style>
</head>
<body>
<h1>$ServiceName Restarted</h1>
<hr>
<br>
Dear Watcher,<br>
<br>
During my last check there were <b>$($Files.Count)</b> files inside <i>$SearchPath</i>. The Integrator was stopped on <b>$($StopTime.tostring())</b> and started on <b>$($StartTime.tostring())</b>. There are now <b>$($files2.count)</b> in <i>$SearchPath</i>. Please investigate on why the $ServiceName failed on $ComputerName.<br>
<br>
<br>
Thank you,<br>
<i>$ServiceName WatchEye</i><br>
<br>
<hr>
</body>
</html>
"@
if ($PSBoundParameters.ContainsKey('Credential')) {
Send-MailMessage -To $SendReportTo -From "Service Watch Eye <WatchEye@$EmailDomain>" -Subject "$ServiceName Failure" -BodyAsHtml $ErrorHtmlbody -SmtpServer $Mailserver -Credential $Credential
} else {
Send-MailMessage -To $SendReportTo -From "Service Watch Eye <WatchEye@$EmailDomain>" -Subject "$ServiceName Failure" -BodyAsHtml $ErrorHtmlbody -SmtpServer $Mailserver
}
}
}
Example
Invoke-FileServiceIntegrityCheck -SearchPath \\server1\share -FileCount 25 -ComputerName server2 -ServiceName integrator -SendReportTo bob@example.com -EmailDomain example.com -Mailserver mail.example.com
In this example, we will search for the share on server1 if it has more than 25 files. If it does, then we will restart the integrator on server2. Finally, we will email bob@example.com with an email from watcher@example.com using the mail server mail.example.com.