PowerShell Puzzles and Challenges

Here are my solutions to the posted challenges:

  1. How many stopped services are on your computer?
(Get-Service | where status -eq 'Stopped').count

2. list services set to autostart but are NOT running?

$AutoStrtType = (Get-Service | where{$_.StartType -eq "Automatic"})
foreach($srv in $autoStrtType){if($srv.status -ne 'Running'){$srv.DisplayName}}

3. List ONLY the property names of the Win32_BIOS WMI class.

Get-CimInstance "Win32_BIOS" -KeyOnly

4. List all loaded functions displaying the name, number of parameter sets, and total number of lines in the function.

$LoadedFunctions = gcm (Get-ChildItem function:\ -Name)
foreach($Function in $LoadedFunctions){
$numberOfPSets =($Function.ParameterSets).count
$FunctionName = $Function.Name
$NumberOfLines = (((Get-Command $FunctionName).ScriptBlock) | Measure-Object -Line).Lines
Write-Output "Function: $FunctionName has $numberOfPSets Parameter Sets and $NumberOfLines number of lines in the function"
}#FE Function

5. Create a formatted report of Processes grouped by UserName. Skip processes with no user name.

$output = Get-Process -IncludeUserName  | Group-Object UserName
foreach($out in $output){
if(($out.Name | Measure-Object -Character).Characters -eq 0){
}#If Name is empty then skip
}#Else output groups
}#FE output

6. Using your previous code, display the username, the number of processes, the total workingset size. Set no username to NONE.

function CalculateProcess {
    param (
    $WorkingSetsize = $
    foreach($Wset in $WorkingSetsize){
        $TotalWorkingSetSize += $Wset
    $NumberOfProcesses = $
        $UserName = $userNameChange
    }#If UserName Change is True
    $UserName = $out.Name 
    Write-Output "UserName: $UserName has $NumberOfProcesses processes using total workingSet size: $TotalWorkingSetSize"
}#Function CalculateProcess
$output = Get-Process -IncludeUserName  | Group-Object UserName
foreach($out in $output){
    $TotalWorkingSetSize = $null
if(($out.Name | Measure-Object -Character).Characters -eq 0){
    CalculateProcess -userNameChange "None"
}#If Name is empty then skip
}#Else output groups
}#FE output

7. Create a report that shows files in %TEMP% by extension. Include Count,total size, % of total directory size.

$FolderToCheck = $env:temp
$Groups = get-childitem $FolderToCheck -recurse -file | Group-Object Extension ###Gets files by extension and count
$FolderSize = (get-childItem $FolderToCheck -recurse -file -force | Measure-Object -Property length -sum).sum 
$FolderREport = foreach($grp in $Groups){
    $TypeTotal   = $null
    $GroupList   = $null
    $PercentUsed = $null
$GroupList = $ | Out-String
foreach ($file in (get-childitem -path ${
    $TypeTotal += $file.length

    }#FE File in list
$PercentUsed = ($TypeTotal/$FolderSize).ToString("P")

New-Object psobject -Property @{
    "Extension Type"            = $
    "Count"                     = $grp.count
    "Total Size in MB"          = $TypeTotal/1MB
    "Group"                     = $GroupList
    "% of Total Directory size" = $PercentUsed
}#FE Group

#####Extra - export to Excel
try{Install-Module PSExcel -ErrorAction stop
}#Try to install PSExcel module
Import-Module PSExcel
$Filename = "TempFolder_Report" + ".xlsx"
$FolderREport | Export-XLSX -Path ".\$Filename" -Table -Autofit

8. Find the total % of WS memory a process is using. Show top 10 processes,count,total workingset and PctUsedMemory.

$WS = (Get-Counter "\Process(*)\Working Set").CounterSamples
foreach($value in $WS){
    $TotalWSValue =+ $value.CookedValue
   }#FE Counter
$TotalWSValue #/1MB
$Top10Unique = (Get-Process | Sort-Object -Property ws -Descending | Select-Object -first 10 Name -Unique).name
foreach($Proc in $Top10Unique){
    $WSTotal = $null
    $ProcTotal = $null
    $TotalArrayValue = $Null

     $WSTotal = (Get-Process -Name $Proc).WorkingSet
     if($WSTotal.GetType().BaseType.Name -eq 'Array'){
        foreach($arr in $WSTotal){
            $TotalArrayValue += $arr
        }#FE Array Element
        $WSTotal = $TotalArrayValue
     }#If array
     }#Else out Int
     $WSTotalMB = $WSTotal /1MB
    $ProcTotal = (Get-Process -Name $Proc).count
    $PercentUsed = ($WSTotal/$TotalWSValue).ToString("P")
    Write-Output "Process name: $Proc total Working set in use is: $WSTotalMB MB's with count of $ProcTotal procesess. Percent of WS used is $PercentUsed"
}#FE top 10MB

Bonus #1

Write PowerShell code to achieve the following goals:

  1. Create a directory called C:\DataFiles
  2. Create 25 files of varying sizes between 1KB and 1MB with your own naming convention.
    But don’t use something as simple as Test-1. Files should have a .dat extension.
  3. Modify the creation and last write times to “age” the files between 10 and 100 days.
$Path = 'C:\DataFiles'
$NumberOfFilesToCreate = 25
New-Item -Path $Path  -ItemType Directory -ErrorAction Ignore
#Get list of 25 Random unique strings to use for file names
$ListOfRandomNames = (Get-command | Get-Member).Name | Select-Object -unique

$Number = 0
while($Number -lt $NumberOfFilesToCreate){
    $RandomNumber = Get-Random -Maximum 1000
    $RandomName = $ListOfRandomNames[$Number]
    fsutil file createNew $Path\$RandomName.dat $RandomNumber

$Number ++
}#While Number is less than $NumberOfFilesToCreate

###age last write and creation time by random 10 - 100 days 
$ListOfFiles = (Get-ChildItem -Path $Path).FullName
foreach($File in $ListOfFiles){

$CreationTime = (Get-Item $File).CreationTime
$LastWriteTime = (Get-Item $File).LastWriteTime
(Get-Item $File).LastWriteTime = (Get-date).AddDays((Get-Random -Minimum 10 -Maximum 101))
(Get-Item $File).CreationTime = (Get-date).AddDays((Get-Random -Minimum 10 -Maximum 101))
$CreationTimeNew = (Get-Item $File).CreationTime
$LastWriteTimeNew = (Get-Item $File).LastWriteTime
Write-Output "$File original creationTime: $CreationTime changed to $CreationTimeNew"
Write-Output "$File original LastWriteTime: $LastWriteTIme changed to $LastWriteTimeNew"
}#FE file change last write and creation time

Bonus #2

Create a formatted HTML report that shows each module location from %PSModulePath%, the number of modules in each location and their total size, and then a listing of each module which shows the most recent version and the total size of all module files.

Extra bonus points if you can make it pretty with CSS formatting.

#Create a formatted HTML report that shows each module location from %PSModulePath%, the number of modules
#in each location and their total size, and then a listing of each module which shows the most recent version
# and the total size of all module files.
$ModuleReport = $Null
$ModulePaths = $env:PSModulePath
$ModuleReport = foreach($ModulePath in ($ModulePaths.Split(';'))){
    $ModuleCount = $Null
    $ListingOfModules = $Null
          try{ $ModuleFolders = (get-childitem -Path $ModulePath -Directory -ErrorAction stop).FullName

       foreach ($Module in $ModuleFolders){
              if((Get-ChildItem -Path $Module\*.psm1 -Recurse).name){
                   $ModuleCount ++
                #try with uppercase M  
                $ModuleShortName = $Module.Split("Modules\")[1]
               if($ModuleShortName.count -eq 0){
                  #Try with lowercase m
                   $ModuleShortName = $Module.Split("modules\")[1]

                    }#If count is 0 then Try lowercase modules
              #   Write-Host "$ModuleShortName" -ForegroundColor blue
                   $IndividualModuleSize = ((get-childItem $Module -recurse -force | Measure-Object -Property length -sum).sum) 
                   $ModulesTotalSize =+ $IndividualModuleSize
                   #Try to get Module Version
                   $ModVer =  (Get-InstalledModule $ModuleShortName -ErrorAction stop)[0].Version
                   }#try to get module version
                    $ModVer = ((Get-Module $ModuleShortName -ListAvailable).Version)[0].ToString()
                  # Write-Host "$ModuleShortName version is $Modver" -ForegroundColor Yellow -BackgroundColor Red
                   $ListingOfModules  += " "
                   $NameAndVer = $ModuleShortName + " " +"v" + $ModVer + " Module Size:" + $IndividualModuleSize/1MB + " MB"
                   $ListingOfModules += $NameAndVer
                   $ListingOfModules  += " "

                }#If there are .psm1 files then proceed and create new PS objects

}#FE Module Folder

New-Object psobject -Property @{
    "M Location"     = $ModulePath
    "M  Number"        = $ModuleCount
    "M Size"         = $ModulesTotalSize/1MB
    "List"    = $ListingOfModules
     }#try and get folder contents for folder from module path list

  }#catch folders that do not exist
}#FE Module PAth

##Export to HTML using module from:
Import-Module PSWriteHTML -Force
New-HTML -TitleText 'Bonus 2 HTML' -UseCssLinks:$true -UseJavaScriptLinks:$true -FilePath $PSScriptRoot\Example01.html -ShowHTML {
  New-HTMLPanel {
      New-HTMLTable -DataTable $ModuleReport -HideFooter -ScrollCollapse {
      New-HTMLTableHeader -BackGroundColor Green -Color White -Title 'Bonus 2 Powershell Puzzles output'

By Peter Charleston

Powershell, automation enthusiast.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s