Link to home
Start Free TrialLog in
Avatar of JCIT2009
JCIT2009Flag for United Kingdom of Great Britain and Northern Ireland

asked on

VBScript to Kill print jobs


Hi,

I am trying to get a vbscript to run in the background and delete any print jobs spooled that are over 1hr old (on XP SP3 Machines)

I have this script that will successfully delete files older than 1hr

*******************
sFolder = "c:\windows\system32\spool\printers"
iMaxAge = 1
Set oFSO = CreateObject("Scripting.FileSystemObject")
If oFSO.FolderExists(sFolder) Then
for each oFile in oFSO.GetFolder(sFolder).Files
If DateDiff("h", oFile.DateLastModified, Now) > iMaxAge Then
oFile.Delete
End If
next
End If
**************************

and I have scripts that "should" stop and start the "print spooler" service


**************************

'stop spooler
strServiceName = "print spooler"
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='" & strServiceName & "'")
For Each objService in colListOfServices
    objService.StopService()

**************************
'start spooler
For Each objService in colListOfServices
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colListOfServices = objWMIService.ExecQuery ("Select * from Win32_Service Where Name ='" & strServiceName & "'")
    objService.StartService()
**************************


However I seem unable to stitch this togther so that the print spooler is only stopped if there are files over 1hour old, then the delete kicks in, then restart the service.

I do not want to stop the service unless there are files over 1hr old to delete.

Can anyone point me in the right direction why I cant seem to get this to work?

Thanks


Avatar of Robert Schutt
Robert Schutt
Flag of Netherlands image

sorry to post complete untested but how about this:

blnFound = False
sFolder = "c:\windows\system32\spool\printers"
iMaxAge = 1
Set oFSO = CreateObject("Scripting.FileSystemObject")
If oFSO.FolderExists(sFolder) Then
  for each oFile in oFSO.GetFolder(sFolder).Files
    If DateDiff("h", oFile.DateLastModified, Now) > iMaxAge Then
      If not blnFound then ' first
        blnFound = True
        Call stopSrv
      End If
      oFile.Delete
    End If
  next
End If

If blnFound Then Call startSrv

Sub stopSrv 'stop spooler
  strServiceName = "print spooler"
  Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='" & strServiceName & "'")
  For Each objService in colListOfServices
    objService.StopService()
  Next
End Sub

Sub startSrv 'start spooler
  Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colListOfServices = objWMIService.ExecQuery ("Select * from Win32_Service Where Name ='" & strServiceName & "'")
  For Each objService in colListOfServices
    objService.StartService()
  Next
End Sub

Open in new window

better to move "strServiceName = ..." to the start of the script I see now.
with that last change at least the syntax seems ok but on my system it doesn't find the service so can't stop/start it...
Avatar of JCIT2009

ASKER

hi.... thanks for this.

I will try the script tomorrow and let you know how I get on.  I dont have any XP machines at home to try this on. In hindsight, I think the service should just be "spooler" - sorry I dont normally have to do things like this.
Hi - managed to remote on to an XP box to try this and although the file delete was working on txt files it for some reason doesn't seem to work on the spooled print files. *scratches head*

However - I have taken your script and bodged it with some other script that does seem to delete the right files and have come up with this....

********************
blnFound = False
strServiceName = "spooler"
sdir="c:\windows\system32\spool\printers"
dim dt, fso, odir, f
dt=now
set fso=createobject("scripting.filesystemobject")
if fso.folderexists(sdir) then
set odir=fso.getfolder(sdir)
for each f in odir.files
if (datediff("n",f.datelastmodified,dt)>2) then
    If not blnFound then ' first
        blnFound = True
        Call stopSrv
     End If
End If
next
End If

If blnFound Then Call startSrv

Sub stopSrv 'stop spooler
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='" & strServiceName & "'")
  For Each objService in colListOfServices
    objService.StopService()
  Next
f.delete true 'forced
End Sub

Sub startSrv 'start spooler
  Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colListOfServices = objWMIService.ExecQuery ("Select * from Win32_Service Where Name ='" & strServiceName & "'")
  For Each objService in colListOfServices
    objService.StartService()
  Next
End Sub
set odir=nothing
set fso=nothing
************************

On first attempt, remotely, it seemed to work, but alas I have now been cut off and cant seem to get back on so will not be able to find out until tomorrow PM when I am back in the office (boring site meeting in the morning)
*note

I have set it to 2mins in the above script for speed during testing
In the above script only the first file will be deleted, the command "f.delete true" should be in the main loop, after the "if not found ... end if" block.
With moving the f.delete as you suggest - it now seems to do whats needed.

I would never have got there without your help - Thank you
hmm.... ok. now with further testing. If there are multiple files, but no files that meet the delete criteria I get permission denied error.  If there are file(s) to delete, it works fine.

I knew there was a reason I am not a programmer.


can you post the current code please, just to check there's nothing out of place?
Thanks again for looking at this for me...

The most successful code so far is below...but it only seems to work if there are files to delete, if not or if there are a mix of files to leave and files to delete, it fails with permission error?

**********************************
blnFound = False
strServiceName = "spooler"
sdir="c:\windows\system32\spool\printers"
dim dt, fso, odir, f
dt=now
set fso=createobject("scripting.filesystemobject")
if fso.folderexists(sdir) then
set odir=fso.getfolder(sdir)
for each f in odir.files
if (datediff("n",f.datelastmodified,dt)>2) then
    If not blnFound then ' first
        blnFound = True
        Call stopSrv
     End If
End If
f.delete true 'forced
next
End If

If blnFound Then Call startSrv

Sub stopSrv 'stop spooler
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='" & strServiceName & "'")
  For Each objService in colListOfServices
    objService.StopService()
  Next

End Sub

Sub startSrv 'start spooler
  Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colListOfServices = objWMIService.ExecQuery ("Select * from Win32_Service Where Name ='" & strServiceName & "'")
  For Each objService in colListOfServices
    objService.StartService()
  Next
End Sub
set odir=nothing
set fso=nothing
******************************************

 I have also tried the following, but this does not work at all.

****************************************
blnFound = False
strServiceName = "spooler"
sdir="c:\windows\system32\spool\printers"
dim dt, fso, odir, f
dt=now
set fso=createobject("scripting.filesystemobject")
if fso.folderexists(sdir) then
set odir=fso.getfolder(sdir)
for each f in odir.files
if (datediff("n",f.datelastmodified,dt)>2) then
    If not blnFound then ' first
        blnFound = True
        Call stopSrv
     End If
f.delete true 'forced
End If
next
End If

If blnFound Then Call startSrv

Sub stopSrv 'stop spooler
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='" & strServiceName & "'")
  For Each objService in colListOfServices
    objService.StopService()
  Next

End Sub

Sub startSrv 'start spooler
  Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colListOfServices = objWMIService.ExecQuery ("Select * from Win32_Service Where Name ='" & strServiceName & "'")
  For Each objService in colListOfServices
    objService.StartService()
  Next
End Sub
set odir=nothing
set fso=nothing
Well, the first piece of code would try to delete all files, as the 'delete' is outside of the time checking "if - end if" block. The second piece of code should work, if it finds any files older than the specified time period and the user that's running the script has permission to delete files in the specified folder.

I'm wondering by the way if there wouldn't be a nicer way to do this, maybe a PowerShell script can do it similar to a cancel or delete in the printer queue?
@JCIT2009

Are you still on this? I may have an idea, using a batch file.
I must admit I haven't explored it further, partly because I can't test in the same situation as yours. I don't see the value of a batch file here. Would you like help finding out if there's a better way to do this, like using an API, either from PowerShell or maybe even something like a VB.NET application?
@robert_schutt:
"I don't see the value of a batch file here"
I don't see why not! What if it works?
Anyway, let's first see if JCIT2009 is still on this, and I'll see if I can help.

Cheers
Hi,

Sorry been away. I now have a different, but similar, working VBScript.  I will post it tomorrow in case anyone finds it useful.

Thanks for all the help.

JCIT2009
@ReneGe: sorry, I read your post wrong; thought it was directed at me, from the asker. I read it as: "would a batch file be able to do something different than vbs" and I couldn't see what that would be. Like @JCIT2009, maybe you should just post your idea, it might help somebody who stumbles across this while searching for a solution later.
@Robert:Don't worry :)

My idea was to scan the time of the printer spool files and delete from there.

Inspired by BillPrew's scripts found in:
https://www.experts-exchange.com/questions/27459125/DOS-Command-script-to-delete-files-in-dir-subs-by-date-and-exact-time.html?cid=748&anchorAnswerId=37174758#a37174758

And gerwinjansen:
https://www.experts-exchange.com/questions/27458652/Simple-batch-file-to-move-a-file-from-a-static-location-to-a-directory-named-by-the-system-date.html?cid=748&anchorAnswerId=37173619#a37173619
I have not tested it but here is my idea.


@ECHO OFF
SETLOCAL EnableDelayedExpansion
SET SpoolerFolder=C:\Windows\System32\spool\PRINTERS

FOR /F "tokens=1-4 delims= " %%A IN ('WMIC Path Win32_LocalTime Get Day^,Month^,Year^,Hour ^| findstr /r [0123456789]')  DO (
   IF %%B LEQ 9 (SET hh=09) ELSE (SET hh=9)
   SET Now=%%D%%C%%A!hh!
)

NET STOP SPOOLER

FOR /R "%SpoolerFolder%" %%F in ("*.*") do (
   REM Adjust file name for WMIC call (replace \ with \\)
      SET WmicFile=%%~F
      SET WmicFile=!WmicFile:\=\\!
   REM Do WMIC call to get last modified date/time stamp for this file
      WMIC datafile where "name='!WmicFile!'" get lastmodified | FINDSTR %Now% >NUL || ECHO DEL /f /q %%~F
)

NET START SPOOLER
PAUSE
EXIT

Open in new window

The flaw in my script will be that if a print job is sent at let's say 10:59 and the script runs at 11:00, that print job will also be deleted. I will gladly resolve this issue if it has a value, onless you (robert_schutt) feel like giving it a shot.

Cheers
Great. No, go ahead. I didn't know what was preventing the vb script we got so far to do its job.
@robert_schutt:
I don't know VBScript, so I can't help with this. Let's see what JCIT2009 found in [37184894].
Hi Guys,

OK this is the end result - it works!!

Hope someone else finds this useful at some point as well.

:-)

--------------------------------------------------


Option Explicit

Dim blnFound, strServiceName, sdir, CurrentDateTime, fso, odir, f, GracePeriodMinuteCount

'//////////////////////////////////////////////////////////
'/ Variables
'//////////////////////////////////////////////////////////

strServiceName = "spooler"
sdir="c:\windows\system32\spool\printers"
CurrentDateTime = Now
GracePeriodMinuteCount = 30

blnFound = False

'//////////////////////////////////////////////////////////
'/ Main Code
'//////////////////////////////////////////////////////////


set fso=createobject("scripting.filesystemobject")

If fso.folderexists(sdir) then
Set odir=fso.getfolder(sdir)


On Error Resume Next
Err.Clear
If (odir.Files.Count > 0) Then
For each f in odir.Files

If Err <> 0 Then
MsgBox "Error Fetching Files in: " & sdir & " - " & Err.Description
Err.Clear
End If

On Error Resume Next
If (datediff("n",f.datelastmodified, CurrentDateTime) > GracePeriodMinuteCount) then

If Err <> 0 Then
MsgBox "Error Fetching File Date: " & f.Name & " - " & Err.Description
Err.Clear
End If

If not blnFound then ' first
blnFound = True
SetServiceState strServiceName, False

Err.Clear

f.Delete(True)

If Err <> 0 Then
MsgBox "Error: Deleting File: " & f.Name & " - " & Err.Description
Err.Clear
End If

If blnFound Then
SetServiceState strServiceName, True
End If

End If

End If 'datediff
Next 'f in odir.files
End If 'odir files count
Else
MsgBox "Error: Directory; " & sdir & " Does Not Exist"
WScript.Quit
End If

'//////////////////////////////////////////////////////////
'/ Functions
'//////////////////////////////////////////////////////////


'----------------------------------------------------------------------------------------------------------------------------------

Function SetServiceState( strServiceName, bState ) ' true = Start ; false = Stop

Dim objWMIService, colListOfServices, objService, strServiceState

On Error Resume Next

Err.Clear

Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")

If Err <> 0 Then
MsgBox "Error Getting Wmi Service - " & Err.Description
Err.Clear

Else

Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='" & strServiceName & "'")

If Err <> 0 Then
MsgBox "Error Getting Service Collection - " & Err.Description
Err.Clear
Else

For Each objService in colListOfServices

If bState = False Then
objService.StopService()

Do Until strServiceState = "Stopped"
strServiceState = GetServiceState(strServiceName)

''' You may want to put a timeout here in case the service fails to stop to avoid an endless loop.

WScript.Sleep 200
Loop

Else
objService.StartService()

Do Until strServiceState = "Running"
strServiceState = GetServiceState(strServiceName)

''' You may want to put a timeout here in case the service fails to start to avoid an endless loop.

WScript.Sleep 200
blnFound = False
Loop

End If

Next

End If

End If

Set colListOfServices = Nothing
Set objWMIService = Nothing

End Function

'----------------------------------------------------------------------------------------------------------------------------------

Function GetServiceState( strServiceName )

Dim objWMIService, colListOfServices, objService

GetServiceState = ""

On Error Resume Next

Err.Clear

Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")

If Err <> 0 Then
MsgBox "Error Getting Wmi Service - " & Err.Description
Err.Clear

Else

Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='" & strServiceName & "'")

If Err <> 0 Then
MsgBox "Error Getting Service Collection - " & Err.Description
Err.Clear
Else

For Each objService in colListOfServices

GetServiceState = objService.State

Next
End If

End If

If GetServiceState = "" Then
GetServiceState = "Unknown"
End If

Set colListOfServices = Nothing
Set objWMIService = Nothing

End Function
Great job, thanks for sharing.

Little issue: you've voided the usefulness of the variable "blnFirst", so now the service is stopped and started for each file found. Shouldn't be a real problem though.

But using the Functions and adding error checking is a really good job which will help others looking for a similar solution here.
Hi - no probs for sharing - I wouldnt have got this far without your help. I'll hand out some points soon. ;)

Can you see how I could better this to only stop the service once then? Please feel free to advise.. :)
ASKER CERTIFIED SOLUTION
Avatar of Robert Schutt
Robert Schutt
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
cool - thanks - will try that today.
all seems to work now. Thanks for everyones help! x
I have a question regarding this topic

I have a lot of print server and spool folder is not always at the same place

is there a way through vbs to find spool folder
You should not post comments like this on old questions since the experts will only be alerted about new questions and also they should be able to earn points. That being said, it might be a valuable addition to this particular code, Unfortunately, I'm not able to spend much time on this now so will just give some general info:

1) the spool folder can be found in the registry under: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers

2) code to read the registry in vbscript can be found here for example: http://blogs.msdn.com/b/alejacma/archive/2008/04/11/how-to-read-a-registry-key-and-its-values.aspx