I have a piece of code in powershell which I use as an "installation recipe".
I use this script to check that the preparation of the PCs is good and that the various software are installed correctly.
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force
If ((Test-Path "C:\Program Files\7-Zip") -eq $True)
{Write-Host " ~ 7-ZIP : Installation => OK! ~" -ForegroundColor Green}
else{Write-Host " ~ 7-ZIP : Installation => NOK! ~" -ForegroundColor Red}
Sleep 3
If ((Test-Path "C:\Program Files (x86)\Adobe\Acrobat Reader DC") -eq $True)
{Write-Host " ~ Adobe Reader DC : Install => OK! ~" -ForegroundColor Green}
else{Write-Host " ~ Adobe Reader DC : Install => NOK! ~" -ForegroundColor Red}
exit
If the installation is OK (OK), then it generates a value that we store and then export to a .CSV or .XLSX file. Ditto if the installation is not OK (NOK).
How do you do that?
Thanks for your help
One approach is to save each non-installed software's name into an array for later processing.
That being said, testing paths the way in question could be improved. Instead of typing paths here and there, store them in a collection for easy processing. A hashtable works fine. Like so,
$ht = #{
"7-Zip" = "C:\Program Files\7-Zip"
"Adobe Reader DC" = "C:\Program Files (x86)\Adobe\Acrobat Reader DC"
"FooApp" = "C:\Program Files\FooApp"
}
$failedInstalls = #()
foreach($key in $ht.keys){
if(test-path $ht[$key] ) {
Write-Host " ~ $key : Installation => OK! ~" -ForegroundColor Green
} else {
Write-Host " ~ $key : Installation => NOK! ~" -ForegroundColor Red
$failedInstalls += $key
}
}
$failedInstalls
What's done here is that software names and paths are stored in a hash table. So, one central location for all the paths. Then the collection is iterated and each missing software is added to $failedInstalls array. Changing number of software is trivial, it only requires change in the hash table - no need for if(test-path... statement for each piece of software.
As how to export array as an XSLX or CSV is left as an exercise to the reader.
A Hashtable as shown in VonPryz answer to collect the names and paths of the software to test is indeed the easiest way of dealing with this.
From the questions title,you would like a CSV file with the results of the tests; not only colored console output. For that, you need to loop through the list of software and output objects you collect in a variable like below:
# add as many items here as you would like to test
$software = #{
"7-Zip" = "C:\Program Files\7-Zip"
"Adobe Reader DC" = "C:\Program Files (x86)\Adobe\Acrobat Reader DC"
}
# a template line for output to console
$message = ' ~ {0} : Install => {1}! ~'
# loop through the hashtable Keys
$result = $software.Keys | ForEach-Object {
$installed = Test-Path -Path $software[$_]
if ($installed) { $color = 'Green'; $success = 'OK' }
else { $color = 'Red'; $success = 'NOK' }
# output to console
Write-Host ($message -f $_, $success) -ForegroundColor $color
# output an object to save as CSV
[PsCustomObject]#{
'Software' = $_
'Path' = $software[$_]
'IsInstalled' = $installed
}
}
# output result to console as table
$result | Format-Table -AutoSize
# output result as CSV file
$result | Export-Csv -Path 'D:\Test\InstalledSoftware.csv' -NoTypeInformation
Output of $result on screen as Table:
Software Path IsInstalled
-------- ---- -----------
7-Zip C:\Program Files\7-Zip False
Adobe Reader DC C:\Program Files (x86)\Adobe\Acrobat Reader DC True
Related
doing some scripting fun with looking for specific file by input.
i want to search specific file by name for example: "abc*" with the prefix either it will be abc.txt, or abc.doc, or what ever...
search recursively in folders, and print if it exists or not.
here is the script i've got so far:
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
Function Get-ItemName {
$Global:ItemName = [Microsoft.VisualBasic.Interaction]::InputBox('Enter a Filename', 'File Name')
}
Get-ItemName
$itemList = Get-ChildItem "\\path_of_folder_with_many_files" -Recurse
$checkItems = 'true'
foreach ($item in $itemList) {
if ((Test-Path -LiteralPath $item) -eq $true -and (Name -like $ItemName)) {
Write-Host "$item - Found" -ForegroundColor Greed
}
elseif ((Test-Path -LiteralPath $item) -eq $false) {
Write-Host "$item - Not Found" -ForegroundColor Red
$checkItems = 'false'
}
}
if ($checkItems -eq $false){
echo ""
Write-Host "Some files was not found, Build Failed" -ForegroundColor Red
exit 1
}
but all it does is printing list of the files and " - Not Found".
and i do have files named "abc.txt" and "abc.doc" and many many more files.
oh yeah and the reason the "find files" script is so long, its because i want to use this powershell script later on a build, and crush it if files doesnt exists.
any ideas whats wrong here?
Either have your function return what was entered in the box and use that or remove that function completely as I have done below:
Add-Type -AssemblyName Microsoft.VisualBasic
$itemName = [Microsoft.VisualBasic.Interaction]::InputBox('Enter a Filename', 'File Name')
if (![string]::IsNullOrWhiteSpace($itemName)) {
# only search for files if there was anything entered in the box
$itemList = #(Get-ChildItem "\\path_of_folder_with_many_files" -Filter "*$itemName*" -File -Recurse)
# now do something with the array of FileInfo objects
# for demo just show how many files were found using the $itemName
Write-Host "Found $($itemList.Count) files with search name '$itemName'"
}
else {
write-host "Nothing was entered in the inputbox.."
}
As you can see, you don't need to use Test-Path, because all files returned by Get-ChildItem of course do exist.
Parameter -Filter here is used with wildcards to search for files with $itemName in their name
Adding switch -File makes sure only files are searched, not folders aswell
Surrounding Get-ChildItem with #() forces the result to be an array, so you can work with the .Count property
I have a PowerShell 5.1 script that should delete some files. However, when I try to delete them, neither del nor remove-item appear to be working. I have alredy set the execution policy to Unrestricted, and launched the ISE in admin mode. Even moving the file with Move-Item didn't work.
My code:
$startROMFolderPath = "C:\Users\VincentGuttmann\Desktop\retropie-mount\roms" #Pleae enter the path to your current ROM folder here, ending in the roms folder. Note that this script will only work if the ROMs are inside the RetroPie folder.
$deleteROMFolder = $startROMFolderPath + "\delete"
Write-Host #"
Hello!
Welcome to my ROM Sorting program!
There are three main ROM types:
The ROMs that are "known good", which are marked with this tag: [!],
the bad dumps, so "known bad", which are marked [b].
Then there are the ROMs where we don't know.
The ROMs that are known good will be left in the folder.
The bad dumps will be deleted right away, as well as the ROMs which are neither German nor English
If you haven't put in the paths to your current ROM folder,
please exit the program now by pressing enter and then "n" without quotation marks.
"#
$inputted = Read-Host -Prompt 'Have you changed the paths accordingly? Yes: (y), No: anything else than (y)'
$i = 0
if($inputted -eq "y")
{
$foldersOld = #()
Get-ChildItem $startROMFolderPath -Attributes Directory |
foreach {
$foldersOld += $_
}
foreach ($name in $foldersOld) {
$currentROMFolderPath = $StartROMFolderPath + "\" + $name
$ROMList = #()
Get-ChildItem $currentROMFolderPath -File |
foreach {
$currentROMPath = $currentROMFolderPath + "\" + $_
$containsBad = $_ -match "\[b.\]"
$containsGood = $_ -match "\[!\]"
$containsLang = $_ -match ".*(\([UE]+\))|(\(U\).*\(E.*\))|(\(E.*\).*\(U\))|(\(E.*\))|(\([UKNG4A]+\))|(\(Unl\))"
if($containsBad)
{
write-host "====================================="
Write-Host $_
Write-Host "contains bad"
write-host "====================================="
Remove-Item -Path $currentROMPath -Force
}
#Put "!$containsGood -and !$containsLang" into the next bracket if you want to delete all ROMS that are neither good nor in the correct Language.
#For just keeping ROMs in the corect language, plase use "!$containsLang"
elseif(!$containsGood -and !$containsLang)
{
write-host "====================================="
Write-Host $_
Write-Host "Contains no good and no lang"
write-host $currentROMPath
write-host "====================================="
Remove-Item -Path $currentROMPath -Force
}
}
}
}
else
{
exit
}
exit
I am trying to write a script that will remove old queues from users HKLM (will eventually delete from HKCU by mounting ntuser.dat but I am not there yet).
The problem I am having is that I am only iterating through one sid under SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Providers\Client Side Rendering Print Provider\ and I get the following error message:
The term 'else' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is corr
ect and try again.
Has anyone ran into this issue before?
#defining my object that will be used throughout the script. Will be used to log everything
$objQueueData=[pscustomobject]#{
computername=""
computerstatus=""
Registrystatus=""
SID=""
Does_It_Have_2003_Queues=""
User_SID_Status=""
user=""
UNC_2003_Queues=""
}
#$QueueDataCollection=[pscustomobject]#{
#queuecollection=$QueueData
#}
#reading the list of workstations
Get-Content "P:\PowerShell\jm\DeletePrintQueues\Workstations.txt" | ForEach-Object{
$strComputerName = $_
#check if the workstation is up
IF (Test-Connection -ComputerName $strComputerName -count 2 -quiet)
{
#$objUser= Get-ChildItem c:\users
#$strUserName=$objUser.Name
$objQueueData.computername=$strComputerName
$objQueueData.computerstatus="Machine is up"
DeleteHklm $strComputerName
}
else
{
#We are here because the computer could not be reached
Write-Host "Machine down" $strComputerName
$objQueueData.computername =$strComputerName
$objQueueData.computerstatus = "Machine Down"
$objQueueData.Registrystatus ="Machine Down"
$objQueueData.SID = "Machine Down"
$objQueueData.Does_It_Have_2003_Queues="Machine Down"
$objQueueData.User_SID_Status="Machine Down"
$objQueueData.user="Machine Down"
$objQueueData.UNC_2003_Queues="Machine Down"
$objQueueData | Export-Csv P:\powershell\jm\results2.csv -NoTypeInformation -Append
}
}
function DeleteHKLM {
param ([string]$computername)
try{
If($strHklm = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$strcomputername ))
{
#executes when it can open HKLM
$objqueuedata.RegistryStatus = "Was able to open the registry"
#set the path of the registry
$PrinterRegKey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Providers\\Client Side Rendering Print Provider'
#$PrinterRegKey
$regPrinterRef = $strHklm.OpenSubKey($PrinterRegKey)
#debug
Write-Host "regprinterref is: "$regPrinterRef
}
If($regPrinterRef)
{
#This executes if there are Printers present in the registry
#region Loop thru all child keys. These contain the calculable UNC paths to 2003
$regPrinterRef.GetSubKeyNames() | ForEach-Object{
#debug
Write-Host "The sid is: " $_
#concatinating to get to the connections key
#$PrinterRegKey
$strPrinterpath =$PrinterRegKey+"\\"+ $_ + "\\Printers\\Connections"
#debug
Write-Host "The printer keys for SID are located in: "
$strPrinterPath
if ($strPrinterpath -notlike "*servers*")
{
#this value is the sid
# $_ will give us the sids. Here I am storing the SIDs into strUserSID to use later on
$strUserSID = $_
#debug
# $strUserSID
# The logic below will convert SID to username
#pass the SID to the secrity principal SID being struserSID
$objSID = New-Object System.Security.Principal.SecurityIdentifier("$strUserSID")
#using a try catch to filter out deleted SIDs, otherwise powershell will throw an error saying it is null
Try{
$strUser = $objSID.Translate( [System.Security.Principal.NTAccount]).Value
$objQueueData.User_SID_Status ="Valid SID"
$strUser
}
Catch{
#$strUserID = $objSID.Value
$objQueueData.User_SID_Status ="Invalid SID"
$objQueueData.User = "Invalid SID"
$objQueueData.Does_it_Have_2003_Queues ="Invalid SID"
$objQueueData.UNC_2003_Queues = "Invalid SID"
$objQueueData | Export-Csv P:\powershell\jm\results1.csv -NoTypeInformation -Append
#exit
}
$regPrinterDetails = $Strhklm.OpenSubKey($strPrinterPath)
$regPrinterDetails.GetSubKeyNames() |ForEach-Object{
#looping through each key at the connections level to search for the 2003 print server names
if($_ -like "*sarspprt2*")
{
$objQueueData.Does_It_Have_2003_Queues = "Yes"
#this value is the printer if it exists
# $_ will give us the printers. Here I am storing the printers into strUserPrinters to user later on
$strUserPrinters = $_
Write-Host "struserprinters value is " $_
#$strUserPrinters
$blnHasOldQueues = $true
#The code below is to build the printer UNC to make it more legible
$intPrinterLength= $strUserPrinters.Length
$strPrintServer= $strUserPrinters.Substring(2,10)
#Doing the -13 because we have to limit the length of the substring statement to the length minus the starting poistion of the substring
$strPrinterShareName =$strUserPrinters.Substring(13,$intPrinterLength-13)
$strPrintUNC = "\\"+$strPrintServer+"\"+$strPrinterShareName
$objQueueData.UNC_2003_Queues = $strPrintUNC
$objQueueData.User = $strUser
$objQueueData | Export-Csv P:\powershell\jm\results.csv -NoTypeInformation -Append
$strkeytodelete=$strPrinterPath+"\\"+$_
$strkeytodelete
#delete 2003 Key
Remove-Item -Path '$strkeytodelete' -Recurse
}
elseif($_ -notlike "*sarspprt2*")
{
#Write-host "No 2003 Queues Detected"
#Write-host "no 2003 Queues detected" $strUserSID,$strUser,$strPrintUNC
$objQueueData.User = $strUser
$objQueueData.Does_it_Have_2003_Queues = "No 2003 Queues Detected for this user or vsarspprt* queue"
$objQueueData.UNC_2003_Queues = "No 2003 Queues Detected for this user or vsarspprt* queue"
$objQueueData | Export-Csv P:\powershell\jm\results.csv -NoTypeInformation -Append
}
# Write-Host $strServer $blnHasOldQueues $strUserSID $strUserPrinters
}
}
}
else
{
#Write-Host "No Printers in the Registry"
$objQueueData.computername=""
$objQueueData.computerstatus=""
$objQueueData.Registrystatus=""
$objQueueData.SID=""
$objQueueData.Does_It_Have_2003_Queues=""
$objQueueData.User_SID_Status=""
$objQueueData.user=""
$objQueueData.UNC_2003_Queues=""
}
}
}
catch{
# Write-Host "cant read registry"
$_.Exception.Message
}
}
You have an extra curly brace on line 153. If you move that to after line 165 it should work, although I can't test it right now. I got in the habit of systematically collapsing my if-else statements to ensure that they all match up with eachother.
Printers at my job are in constant flux. Because of this I need a script that can automate the process of adding and deleting printers with little intervention. I have here an example of the code that I am using to perform this task. I'd like to condense this code and add 2 new features, unfortunately my ability to code is few an far between as I am but a humble systems janitor.
New Feature idea's:
If the .vbs files 'Last Modified' date has not been altered since the last time this script was ran, the script immediately stops. A comment outlining a method to override this would be good too.
The log file that shows which servers were created, I'd like to know if they were created -successfully- or if they failed.
If the script comes across an error while adding a network printer, it will immediately skip it, but the log will show that the printer has been added created
<#
.SYNOPSIS
Printer Script
1. Archives the working file if it is greater than or equal to 1 MB
2. Starts logging
3. Removes priners which no longer exist on the print server (because of deletion, moves, etc) in a status of 2
4. Compares the Network printer list to the locally installed Network printers and outputs a list of the printers not installed locally
5. Takes the new printer list, and pings each printer, if ping fails, the printer is removed from the install list
6. Builds new printers
7. Ends logging
8. Performs log file maintenance by archiving and removing old log files
.DESCRIPTION
Date: 04/03/2013
Version: 1
PowerShell Version: 2.0
.INPUTS
Network Printer Script \\ShareDrive\Sharefolder\ShareFile.vbs
.OUTPUTS
Log files
Archive files
Temp text files
ShareFile.txt
pl.txt
Localprinters.txt
NewPrinters.txt
ToDelete.txt
working.txt
.EXAMPLE
C:\scripts\PrinterMaint.ps1
.NOTES
Create the following folders before running this script:
C:\PrinterMaint\
C:\temp\
C:\Scripts\
.LINK
#>
###################
####-VARIABLES-####
###################
# Get computer name
$Server = (gc env:computername)
# Specifies Local Printer Properties to be retrieved
$Props = "Name","PrinterStatus"
$GLOBAL:job1 = ""
# Log file naming convention
$Logfile = "C:\PrinterMaint\"+$(gc env:computername)+".log"
# Archive log naming convention
$archive = "C:\PrinterMaint\Archive_"+(gc env:computername)+"_"+$date2+".log"
# Gets todays date and assigns it to a variable
$date = Get-Date
# temp files and path of text file which holds the names of the printers to be deleted
$DelFile = "C:\temp\ToDelete.txt"
# Creates a formatted date which can be used in a file name
$date2 = Get-Date -format "yyyy-MM-ddTHHmmss"
# Error File
$ErrorFile = "C:\PrinterMaint\Errors.log"
# Handle Errors
$ErrorActionPreference = "silentlycontinue"
# Get computer name
$Server = (gc env:computername)
# Local Printer
$GOBAL:LPrinter = #()
$GLOBAL:ltext = #()
$GLOBAL:FinalPrinters = #()
$GLOBAL:Bad = #()
###################
####-FUNCTIONS-####
###################
Function ServiceShutdown #Shuts down High CPU services while this script runs so as to not interfere
{
Set-Service SAVAdminService -StartupType Disabled
Stop-Service SAVAdminService
Set-Service SavService -StartupType Disabled
Stop-Service SavService
}
Function CycleSpooler
{
Write-Host "Cycling Print Spooler"
Stop-Service spooler
Start-Sleep -seconds 10
Start-Service spooler
Write-Host "Print Spooler Cycle is complete"
}
Function ServiceReenable
{
Set-Service SavService -StartupType Automatic
Start-Service SavService
Set-Service SAVAdminService -StartupType Automatic
Start-Service SAVAdminService
}
Function GetLocalPrinters
{
# Start gathering local printer info
$GLOBAL:job1 = gWmi Win32_Printer -computer $Server -Property $props -AsJob
If ($GLOBAL:job1.State -eq "Running")
{
Cls
Write-Host "The local Printer gather may take several minutes to complete" -ForegroundColor Blue -BackgroundColor Yellow
$i = 0
do {Write-Progress -Activity "Gathering Local Printers..." -status "$i seconds";$i+=5; Start-sleep -seconds 5}
while ($GLOBAL:job1.State -eq "Running")
Write-Progress "Done" "Done" -completed
Else
{Write-Host "Local printer gather has completed" -ForegroundColor Yellow}
}
}
Function ArchiveLog # Archives log files if they are greater than or equal to 1MB
{
# Creates the Variable which will hold the archive log naming convention
if (test-path $Logfile) #If the logfile exists then determine if it needs to be archived
{
# Gets the log file if it is greater than oe equal to 1MB
Get-ChildItem $LogFile -recurse | ? {($_.length/1MB) -ge 1} | % {
# Archives the log File
Move-Item $_.Fullname $archive
}
}
else # If the log file does not exist
{New-Item $Logfile -type File} # Create a new log file
}
Function LogI # Function Called to Write actions to the log file
{
# Accepts the parameter
Param ([string]$logstring)
# new line
"`r`n"
# Logs variable to the log file
$logstring >> $LogFile
}
Function StartLog # Function called to format the beginning of each log file
{
LogI "**********Starting Log**********"
LogI "Log Date: $(Get-Date)"
}
Function EndLog # Function called to format the end of each log file
{
LogI "**********End Log**********"
LogI "Log Date: $(Get-Date)"
}
Function CleanupTMP # Function called to cleanup all temp files created by this script
{
# Cleanup of existing build files
$workingfiles = "C:\temp\ShareFile.txt", "C:\temp\pl.txt", "C:\temp\Localprinters.txt", "C:\temp\NewPrinters.txt", "C:\temp\ToDelete.txt", "C:\temp\working.txt"
foreach ($file in $workingfiles) # Gets each file, deletes it
{
# Determines if the file in the path exists
if (test-path $file)
{
echo Test-Path $file
# If the file does exist, it deletes each one
Remove-Item $file
# Writes the name of the deleted file to the log file
LogI "Deleted File: $date $file"
}
}
}
Function CleanupLogs # Removes Log files older than 14 days old
{
# set folder path
$log_path = "C:\PrinterMaint\Archive*.log"
# set min age of files to 14 days
$max_days = "-14"
# determine how far back we go based on current date
$del_date = $date.AddDays($max_days)
# Gets log files older than the $max_days defiled and Removes them
Get-ChildItem $log_path -Recurse | Where-Object { $_.LastWriteTime -lt $del_date } | Remove-Item
}
Function BadPrinter # Function checks for indtalled printers with a status of 2, "Printer not Found on Server, unable to connect"
{
# Handle Bad Printers
# Gathers Printers with status of 2 - Not Found on Server
$GLOBAL:Bad = $GLOBAL:LPrinters | where {$_.printerstatus -eq 2} | select name | sort name
#$GLOBAL:Bad2 = $GLOBAL:LPrinters | where {$_.printerstatus -eq 3 -and $_.name -ne "Microsoft XPS Document Writer"} | select name | sort name
#$GLOBAL:Bad = $GLOBAL:Bad1 + $GLOBAL:Bad2
if ($GLOBAL:Bad.count -gt 0) # If the array is greater than 0 then call the function to delete the printers
{DelPrinter}
Else
{Write-Host "No printers will be deleted" -ForegroundColor Yellow
LogI "$date No printers were deleted"}
}
Function DelPrinter # Function is called to delete printers if the array tests to be greater than 0
{
# Outputs the printers to a text file
$GLOBAL:Bad | Out-File $DelFile
# Assigns the text file contents to an array
$btext = gc $DelFile
# Removes the text file
#remove-item $DelFile
##########################-Formatting-##########################################
# Remove first four lines from the text file, spaces and blank lines
$btext[0],$btext[3..($btext.length-1)] | out-file $DelFile -encoding ascii
(gc $DelFile) | ? {$_.trim() -ne "" } | sc $DelFile -encoding ascii
(gc $DelFile) | Foreach {$_.TrimEnd()} | sc $DelFile -encoding ascii
(gc $DelFile) | where {$_ -ne ""} | sc $DelFile -encoding ascii
##########################-Formatting-###########################################
# Removing a Network Printer Connection
# Get the contents of the delete text file
$GLOBAL:Bad = (gc $DelFile)
# Reviews each item in the array and processes them seperately
foreach ($B in $Bad)
{
# Reinitializes date for more accurate reporting
$date2 = Get-Date
# Assigns the date and time to the printer being deleted to a variable
$LogDel = "$date2 $B"
# Logs the deletion of the printer
LogI "Deleted: $LogDel"
# Networked printer is now deleted
Write-Host "Deleting printer $B"
(New-Object -ComObject WScript.Network).RemovePrinterConnection("$B")
}
}
Function GNP # Function to Get Network Printers (GNP)
{
# Copies the printer map script to the local computer
Copy-Item \\ShareDrive\Sharefolder\ShareFile.vbs C:\temp\ShareFile.txt
}
Function FNP
{
# Assign the contents of the Network printer list to a variable
$NPrinters = Get-Content C:\temp\ShareFile.txt
##########################-Formatting-##########################################
#removes all text and formatting from the network printer list then assigns the contents to a new array
foreach ($NPrinter in $NPrinters)
{
$NPrinter1 = $NPrinter.split(" ")
$Printers = $NPrinter1[1]
$Printers1 = $($Printers -split '"')
$PL = $Printers1[1]|Where-Object {$_.length -gt 2}
$PL >> C:\temp\pl.txt
}
##########################-Formatting-##########################################
}
Function GIP
{
# Get the installed printers and write to a file
$GLOBAL:LPrinters | select name | sort name | Out-File C:\temp\LocalPrinters.txt
# Get the contents of the file and load into an array
$GLOBAL:ltext = gc C:\temp\Localprinters.txt
# Remove the old file
remove-item C:\temp\Localprinters.txt
}
Function FIP
{
# Format the data in the array by removing the first four lines and spaces from the array and output to the file
$GLOBAL:ltext[0],$GLOBAL:ltext[3..($GLOBAL:ltext.length-1)] | out-file C:\temp\Localprinters.txt -encoding ascii
# Removes blanks from the file and sets the contents with the new formatting
(gc C:\temp\Localprinters.txt) | ? {$_.trim() -ne "" } | sc C:\temp\Localprinters.txt -encoding ascii
# Removes the blank lines from the end of the file and sets the contents with the new formatting
(gc C:\temp\Localprinters.txt) | ForEach {$_.trimEnd()} | sc C:\temp\Localprinters.txt -encoding ascii
# Assigns the nice neat contents of the file back to the array
$GLOBAL:ltext = (gc C:\temp\Localprinters.txt)
}
Function COMP
{
# Begins comparing the two printer files
# Compares the files and outputs non-built printers to the NewPrinters.txt file
$FinalGroups = Compare-Object (gc C:\temp\pl.txt) (gc C:\temp\LocalPrinters.txt) |
where {$_.SideIndicator -eq "<="} |
select -ExpandProperty inputObject |
sort
#Removes duplicate printers from the list using the -uniq
$FinalGroups | select -uniq | Out-File C:\temp\NewPrinters.txt
$GLOBAL:FinalPrinters = gc C:\temp\NewPrinters.txt
}
Function PNP
{
# Test new printer connectivity
$PingFile = "C:\temp\NewPrinters.txt"
$PingFile
$Pings = gc $PingFile
# Get just the printer names from the New Print File and appends them to a new file called Working
foreach ($p in $Pings)
{
$np = $p.split("\\")
$to = $np[3]
$to >> C:\temp\working.txt
}
# Assigns the contents of the working file (new printers) to an array
$to = gc C:\temp\working.txt
foreach ($t in $to)
{
# Tests the printers connection
write-host "testing printer $t"
$ok = Test-Connection $t -Count 2 -Quiet
#Takes the connectivity results and determines to remove the printer from the file prior to build starting.
if ($ok -ne "TRUE")
{
write-host "$t Communication Failed" -ForegroundColor Red
# If the printer communication fails, the entry is removed from the NewPrinters.txt file
(gc "C:\temp\NewPrinters.txt") -notmatch "$t" | Out-file "C:\temp\NewPrinters.txt"
# Logs the removal of the printer and why it is being removed
#Reinitializes date for more accurate times in the log file
$date11 = Get-Date
$remprt = "$date11 - printer $t will not be built - communication failed"
LogI $remprt
}
else
{
Write-Host "$t Communication Successful" -ForegroundColor Yellow
}
}
}
Function BUILD
{
# Build each new printer found in the NewPrinters text file
$ToBuild = gc C:\temp\NewPrinters.txt
foreach ($item in $ToBuild)
{
# Reinitialized date to get more accurate reporting
$date4 = Get-Date
# Creates Logging info
$LogIt = "Created: $date4 $item"
# Calls function to write information to a log file
LogI $LogIt
Write-Host -NoNewLine "Creating printer $item" -ForegroundColor green
# Printer Build now occurs
(New-Object -ComObject WScript.Network).AddWindowsPrinterConnection("$item")
}
}
##############
####-MAIN-####
##############
# Cleanup High CPU and long running services which interfere with this script
ServiceShutdown
# Cycle the print spooler service
CycleSpooler
# Get Local Printers
GetLocalPrinters
# Archive log maintenance
ArchiveLog
# Starts logging
StartLog
# Get the completed job
`enter code here` $GLOBAL:LPrinters = Receive-Job -job $GLOBAL:job1 -keep | select $props
# Handles Bad pritners in a status of 2 "Printer not Found on Server, unable to connect"
BadPrinter
# Get Network printer list
GNP
# Format Network printer list
FNP
# Get installed/existing printers
GIP
# Format installed/existing printer file
FIP
# Compare existing printers with new printers only keep network printers needing to be built
COMP
# Check if New Printer File is NULL
if ($GLOBAL:FinalPrinters.count -gt 0)
{
# Ping new printer connection and remove printers with failed connections
PNP
# Build new printers
BUILD
}
Else
{
$date6 = Get-Date
LogI "$date6 No new printers were built"
}
# Cleanup temp text files
CleanupTMP
# Stops Logging
EndLog
# Cleanup Archive log files older than the specified ## of days
CleanupLogs
# Restarts Services
ServiceReenable
# Cycle the print spooler service
CycleSpooler
# Printer Maintenance is Complete
Write-Host "Printer Maintenance is complete" -ForegroundColor Red -BackgroundColor Yellow
Example of what is inside the VBS:
Set objNetwork = CreateObject("WScript.Network")
objNetwork.AddWindowsPrinterConnection "\\PrintServer\Printer1"
I do not control nor maintain this file. I am only allowed to run it. This script copies the .vbs to a local text file which is then edited as needed.
I have written a script which checks a service status, tests two paths and also tests a registry value. Currently I am getting output on the power shell console (that could be because I am using write-output command).
Is there any way to write the single one page output to a file?
I am struggling to find a way to out-file entire output to a file.
Below is the script.
$testpath = Test-Path "C:\test"
$testpath2 = test-path "C:\test"
$mcshieldk = Get-Service -Name mcshield | select Name
$internet = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\internet explorer").MkEnabled $hostname = hostname Write-Host "hostname of comuter is" $hostname if (Test-Path $Machinetype)
{}
else { Write-Host "internet is" $internet }
if ($testpath -eq $true -and $testpath2 -eq $true)
{ Write-Host "test and test1 folder exists" -ForegroundColor Green }
else{ Write-Host "folder does not exists" -ForegroundColor Red } if($mcshield.Name -eq "mcshield") { Write-Host "mcshield service exists" }
else { Write-Host "mcshield does not exists" }
Below is the console output
hostname of comuter is Server1
internet is Yes
test and test1 folder exists
mcshield does not exists
Swap out your Write-Host cmdlets or add in another line with the following:
"Your output text $YourVariable" | Out-File -FilePath "C:\Log.txt" -Append -Encoding utf8
This will append a string to the end of the log file C:\Log.txt. Note, missing the -Append parameter will cause the file to be overwritten.
You can also use the follow to give the same affect:
"Your output text $YourVariable" >> "C:\Log.txt"
But be carefully not to mix the two methods as you might get encoding errors in the text file. If you wish to overwrite the file with the second method use > instead of >>.