I am stuck on this little project I've been working on.
My out put is blank, not sure how to call the info right. I keep getting on one line in my excel
#Output Hash Table as CSV
$IPAddressHash.GetEnumerator()
I also think I have some missing info here...
$IPAddressHash.Add($IPAddressToPing)
Thanks in advance
#Place holder
$InputText1 = #unused
$InputText2 = "TestSite" ##Popup input box
$DateTime = $(get-date -Format yyyyddmm_hhmmtt)
#Set Output File
$OutputCSVFilePath = "C:\MSP_PingLogs\ $($InputText2) $($DateTime).csv"
#Set Information
$IPAddress = "192.168.0.147"
$SecondsToRun = 5
#Hash Table to hold results
$IPAddressHash = #(
$IPAddress)
$outList = foreach ($IPAddress in $IPAddressToPing){
}
#Test Ping
for ($i = 0; $i -lt $SecondsToRun; $i++){
$Pingable = Test-Connection -ComputerName $IPAddressToPing -Count 1 -Quiet
if ($Pingable)
{
Write-Host "Seccess" $($IPAddressToPing) at $(Get-Date), $responseTime -ForegroundColor Green
#$IPAddressHash.($IPAddressToPing.("IPAddressToPing"),1)
}
else {
Write-Host "FAILED PING " $($IPAddressToPing) at $(Get-Date), $responseTime -ForegroundColor Red
#$IPAddressHash.($IPAddressToPing.("IPAddressToPing"),0)
}
Start-Sleep -Seconds 1
}
$outList = #(
[pscustomobject]#{
Address= $IPAddressToPing
Date= $DateTime
Pingable = $Pingable
}
)
$outList | Export-Csv -path $OutputCSVFilePath -NoTypeInformation
#Show where file is
Write-Host "Output can be found at: $($OutputCSVFilePath)"
here is how i would do what i think you are trying to do ... [grin]
what it does ...
creates a list of systems to ping
replace the entire #region/#endregion stuff with a Get-Content call, or some other way to load your list as plain text system names.
sets the various constants
iterates thru the system list
iterates thru the test count
gets a $False/$True response from Test-Connection
writes the "pingable" info to the screen
creates a [PSCustomObject] with the desired properties
sends that to the $Results collection
displays the collection on screen
saves the collection to a CSV file
here's the code ...
#region >>> fake reading in a text file
# in real life, use Get-Content
$ComputerList = #(
'LocalHost'
'10.0.0.1'
'127.0.0.1'
'BetterNotBeThere'
)
#endregion >>> fake reading in a text file
$TestCount = 3
$DateTimeFormat = 'yyyy-MM-dd HH:mm:ss.ff'
$LogDir = $env:TEMP
$PingLog = 'PingLog_-_{0}.csv' -f (Get-Date).Date.ToString('yyyy-MM-dd')
$FullPingLog = Join-Path -Path $LogDir -ChildPath $PingLog
$Results = foreach ($CL_Item in $ComputerList)
{
foreach ($TC_Item in 1..$TestCount)
{
$Pingable = Test-Connection -ComputerName $CL_Item -Count 1 -Quiet
if ($Pingable)
{
Write-Host ('Ping of {0} was successful.' -f $CL_Item) -ForegroundColor 'Green'
}
else
{
Write-Warning (' Unable to Ping {0} ...' -f $CL_Item)
}
}
[PSCustomObject]#{
ComputerName = $CL_Item
Pingable = $Pingable
TimeStamp = Get-Date -Format $DateTimeFormat
}
}
# show on screen
$Results |
# this forces things to show immediately
# otherwise the "Write-*" calls might interleave with the output stream
Out-Host
# send to CSV
$Results |
Export-Csv -LiteralPath $FullPingLog -NoTypeInformation
output to screen ...
Ping of LocalHost was successful.
Ping of LocalHost was successful.
Ping of LocalHost was successful.
WARNING: Unable to Ping 10.0.0.1 ...
WARNING: Unable to Ping 10.0.0.1 ...
WARNING: Unable to Ping 10.0.0.1 ...
Ping of 127.0.0.1 was successful.
Ping of 127.0.0.1 was successful.
Ping of 127.0.0.1 was successful.
WARNING: Unable to Ping BetterNotBeThere ...
WARNING: Unable to Ping BetterNotBeThere ...
WARNING: Unable to Ping BetterNotBeThere ...
ComputerName Pingable TimeStamp
------------ -------- ---------
LocalHost True 2020-04-10 19:47:33.98
10.0.0.1 False 2020-04-10 19:47:45.62
127.0.0.1 True 2020-04-10 19:47:45.65
BetterNotBeThere False 2020-04-10 19:47:45.68
content of the PingLog_-_2020-04-10.csv file ...
"ComputerName","Pingable","TimeStamp"
"LocalHost","True","2020-04-10 19:47:33.98"
"10.0.0.1","False","2020-04-10 19:47:45.62"
"127.0.0.1","True","2020-04-10 19:47:45.65"
"BetterNotBeThere","False","2020-04-10 19:47:45.68"
Related
I need to ping a list of machines and have the results split between up and down into two different .txt files.
$PingPCs = Get-Content "C:\Temp\Cache Cleanup Project\Computerlist.txt
foreach ($PC in $PingPCs) {
$up = Test-Connection $PC -Count 1 -Quiet
if($up) {
$Response = Test-Connection $PC -Count 1 | Select-Object Name
$Response ## Need help figuring out the outfile process to write to .txt ##
}
else {
$Failed = "$PC is not reachable"
$Failed ### Need help figuring out the outfile process to write to .txt ###
}
}
The two places I need help with is just writing the results to separate text files. One file named Online.txt and the other Offline.txt.
You can do something like this, instead of exporting the results on each iteration and appending to a file, it's a better idea to first perform your test and save the results in memory. Once all is complete, export the results:
$PingPCs = Get-Content "C:\Temp\Cache Cleanup Project\Computerlist.txt"
$result = foreach ($PC in $PingPCs)
{
$testConnection = Test-Connection $PC -Count 1 -Quiet
[pscustomobject]#{
ComputerName = $PC
TestConnection = $testConnection
}
}
$result.where({$_.TestConnection}) | Out-File "x:\path\to\online.txt"
$result.where({-not $_.TestConnection}) | Out-File "x:\path\to\offline.txt"
Edit
Adding nice optimization to export the results. Thanks #mklement0
$online, $offline = $result.where({$_.TestConnection},'Split')
$online | Out-File "x:\path\to\online.txt"
$offline | Out-File "x:\path\to\offline.txt"
i have this script , that take IP Address and ping them , and then it save the result to TXT file or EXCEL file.
and the issue is that - > If i will change the name output name file and even change the IP address from the original ( or new ) file i will get in the end file with all the previous test connections.
The Script :
$IPs = Get-Content "C:\IPs.txt"
foreach($name in $Ips){
if(Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){
Write-Host "$name is up" -ForegroundColor Green
$output+="$name is up,"+"`n"
}
else{
Write-Host "$name is down" -ForegroundColor Red
$output+="$name is down,"+"`n"
}
}
$output | Out-File "C:\IP_Result"
TXT file with the IP Address :
8.8.8.8
192.168.33.2
10.10.10.10
192.168.33.4
1.1.1.1
so when i run the script for the first time i receive :
8.8.8.8 is up,
192.168.33.2 is up,
10.10.10.10 is down,
192.168.33.4 is up,
1.1.1.1 is up,
now if i will change the $output | Out-File to another file name ( so i can get new file with results )
i will receive new file name but will the previous results
for example
New IP Address ( inserted in new file with new name in $IPs = Get-Content )
2.2.2.2
3.3.3.3
4.4.4.4
now i run the script and the result :
8.8.8.8 is up,
192.168.33.2 is up,
10.10.10.10 is down,
192.168.33.4 is up,
1.1.1.1 is up,
1.1.1.1 is up,
2.2.2.2 is down,
3.3.3.3 is down,
4.4.4.4 is down,
why i see the old results ?
You use the same variable $output and keep appending to it ($output +=). If you ran the script in a completly new window, you would get single results.
To prevent that behavior initiate the variable $output in the beginning of the script:
$output = $null # = empty
or
$output = #() # = array
or
$output = "" # = string
Another way would be to remove the variable when you are done using it:
Remove-Variable output
Here is an additional tipp:
Using += will recreate the collection with every iteration. For a few dozen values thats ok but for multiple hundred it's much faster to collect the output of the foreach itself:
$output = foreach($name in $Ips){
if(Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){
Write-Host "$name is up" -ForegroundColor Green
"$name is up,"
}
else{
Write-Host "$name is down" -ForegroundColor Red
"$name is down,"
}
}
And you wont have to reinitiate the variable by yourself.
Trying to set up a loop that will run test_netconnection to each line in the text file and then output the response into a different file
I have tried different ways of writing it, just not sure where my loop breaks
$file = 'Z:\servers.txt'
$addresses = Get-Content $file
$reader = New-Object IO.Streamreader $file
while ($reader.ReadLine() -ne $null) { }
foreach ($address in $addresses) {
try {
$Test = Test-NetConnection -ComputerName $addresses -Port xxxx -InformationLevel Quiet
Write-Host "$Test"
}
catch {
Out-File z:/output.txt
}
}
Not getting any output sent to my Out-File, I suspect that my loop is broken
If servers.txt contains the following:
www.google.com
www.microsoft.com
www.stackoverflow.com
...
...then you can loop through it, use Test-NetConnection to see if entries are pingable (ICMP), and export the results as a *.CSV file with the following code:
$servers = Get-Content C:\path\to\servers.txt
$servers | % {
Test-NetConnection $_ | Select ComputerName, PingSucceeded | Export-Csv C:\path\to\results.csv -NoTypeInformation -Append
}
You can extend the exported result properties by adjusting the Select portion of the code.
here's a rather overdone version of the idea. [grin] it uses Tet-Connection instead of the newer Test-NetConnection since win7ps5.1 does not have that cmdlet.
if you nave never seen it used before, the #region comments are code folding markers. that lets one fold away the parts that are not currently of interest.
#region - save default prefs
# the Verbose default is screen display OFF
$AllowVerboseOutput = $True
# the Warning default is screen display ON
$AllowWarningOutput = $True
# save the VerbosePref
$OldVPref = $VerbosePreference
if ($AllowVerboseOutput)
{
# enable screen display of Write-Verbose [it's OFF by default]
$VerbosePreference = 'Continue'
}
# save the WarningPref
$OldWPref = $WarningPreference
if (-not $AllowWarningOutput)
{
# DISABLE Write-Warning screen output [it's ON by default]
$WarningPreference = 'SilentlyContinue'
}
#endregion - save default prefs
# if you want _fewer_ reports, use a larger final time unit
# minutes, hours, whatever suits your needs [*grin*]
$TimeStamp = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss'
$SystemListDir = $env:TEMP
$SystemListFile = 'ServerList.txt'
$FullSystemListFile = Join-Path -Path $SystemListDir -ChildPath $SystemListFile
$ReportDir = $env:TEMP
# if you don't want multiple report files, comment OUT this line & UN-comment the line after it
$ReportFile = -join ('ConnectionRemport', '_-_', $TimeStamp, '.csv')
#$ReportFile = -join ('ConnectionRemport', '.csv')
$FullReportFile = Join-Path -Path $ReportDir -ChildPath $ReportFile
$NoResponse = '-- No Response --'
#region - sample data import
# fake reading in a file
# in real life, use the Get-Content line below
# remove the leading "#" on the next line when you are ready to use a real file
#<#
$SystemList = #'
LocalHost
127.0.0.1
10.0.0.1
'#.Split("`n").Trim()
#>
#endregion - sample data import
# remove the leading "#" on the next line when you are ready to use a real file
#$SystemList = Get-Content -Path $FullSystemListFile
$Results = foreach ($SL_Item in $SystemList)
{
Write-Verbose "Connecting to $SL_Item ..."
if (Test-Connection -ComputerName $SL_Item -Count 1 -Quiet)
{
Write-Verbose " System $SL_Item reached successfully."
$TempObject = [PSCustomObject]#{
MachineName = $SL_Item
Status = 'Online'
# the resulting "sortable" date string is yyyy-MM-ddTHH:mm:ss
TimeStamp = (Get-Date).ToString("s")
}
}
else
{
Write-Warning " Unable to reach $SL_Item."
$TempObject = [PSCustomObject]#{
MachineName = $SL_Item
Status = $NoResponse
# the resulting "sortable" date string is yyyy-MM-ddTHH:mm:ss
TimeStamp = (Get-Date).ToString("s")
}
}
$TempObject
} # end = foreach ($SL_Item in $SystemList)
# display $Results on screen
$Results
# save $Results to CSV file
$Results |
Export-Csv -LiteralPath $FullReportFile -NoTypeInformation
#region - restore default prefs
# restore previuos VerbosePref
$VerbosePreference = $OldVPref
# restore previous WarningPref
$WarningPreference = $OldWPref
#endregion - restore default prefs
on-screen output while running ...
VERBOSE: Connecting to LocalHost ...
VERBOSE: System LocalHost reached successfully.
VERBOSE: Connecting to 127.0.0.1 ...
VERBOSE: System 127.0.0.1 reached successfully.
VERBOSE: Connecting to 10.0.0.1 ...
WARNING: Unable to reach 10.0.0.1.
final onscreen output from the $Results collection ...
MachineName Status TimeStamp
----------- ------ ---------
LocalHost Online 2019-08-02T12:16:43
127.0.0.1 Online 2019-08-02T12:16:43
10.0.0.1 -- No Response -- 2019-08-02T12:16:47
CSV file content ...
"MachineName","Status","TimeStamp"
"LocalHost","Online","2019-08-02T12:16:43"
"127.0.0.1","Online","2019-08-02T12:16:43"
"10.0.0.1","-- No Response --","2019-08-02T12:16:47"
How can I apply 1 IP address in a list to 1 server in another list?
Then move onto the next IP and apply it to the next server.
servers.txt looks like:
server1
server2
server3
ip.txt looks like:
10.1.140.80
10.1.140.81
10.1.140.83
I just want to go through the list and apply
10.1.140.80 to server1
10.1.140.81 to server2
10.1.140.83 to server3
Instead, my script is applying all 3 IP addresses to each server.
I dont want to cycle through all IP addresses over and over.
How can I iterate through the lists properly and correct this?
$computers = "$PSScriptRoot\servers.txt"
$iplist = gc "$PSScriptRoot\ip.txt"
function changeip {
get-content $computers | % {
ForEach($ip in $iplist) {
# Set IP address
$remotecmd1 = 'New-NetIPAddress -InterfaceIndex 2 -IPAddress $ip -PrefixLength 24 -DefaultGateway 10.1.140.1'
# Set DNS Servers - Make sure you specify the server's network adapter name at -InterfaceAlias
$remotecmd2 = 'Set-DnsClientServerAddress -InterfaceAlias "EthernetName" -ServerAddresses 10.1.140.5, 10.1.140.6'
Invoke-VMScript -VM $_ -ScriptText $remotecmd1 -GuestUser Administrator -GuestPassword PASSWORD -ScriptType PowerShell
Invoke-VMScript -VM $_ -ScriptText $remotecmd2 -GuestUser Administrator -GuestPassword PASSWORD -ScriptType PowerShell
}
}
}
changeip
Use your the Get-Content cmdlt to place both file contents into an array then pull the individual values by array position. You'll probably want some logic to check if the array size matches and custom handling if it does not. In your above example, you are basically putting a for each loop inside another foreach loop which is giving you the behavior you are seeing.
$computers = GC "C:\server.txt"
$iplist = GC "C:\ip.txt"
for ($i = 0; $i -lt $iplist.Count ; $i++) {
Write-host ("{0} - {1}" -f $computers[$i],$iplist[$i])
}
Or if you are married to using the foreach logic for one list to be all fancy like instead of basic iterating with a for loop then you can add a counter in your foreach loop. Then you can look up your array index of your already parsed iplist array. It's basically doing the same thing though..
$computers = "C:\server.txt"
$iplist = GC "C:\ip.txt"
get-content $computers | % {$counter = 0} {
Write-host ("{0} - {1}" -f $_,$iplist[$counter])
$counter++
}
Just for clarity purposes as well, please note in this line:
"get-content $computers | %"
The % is actually an alias for ForEach-Object which is why you are getting the foreach inside a foreach output that you are seeing.
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.