I have windows service written in vb.net that deletes the contents of a folder (meaning all files, subfolders, and files) in that folder every few minutes.
I need to change the service so that it now deletes the contents of the C:\Windows\Temp folder.
When I edit the path in the service, then recompile, and re-install, the service does not delete the contents of C:\Windows\Temp
I even added code to handle any open/locked files so that the deletion process would just continue, but still nothing.
Sub ClearWinTempDirectory(folder As String)
'Loop over the subdirectories and remove them with their contents
For Each d In Directory.GetDirectories(folder)
Directory.Delete(d, True)
Next
' Finish removing also the files in the root folder
For Each f In Directory.GetFiles(folder)
Try
File.Delete(f)
Catch e As System.IO.IOException
Console.WriteLine(e.Message)
End Try
Next
COBWtl.WriteEntry("All files and folders in the " & folder & " directory that
are not currently locked by applications or processes Have been deleted",
EventLogEntryType.Information, eventID:=9995)
End Sub
I am hoping someone can help me identify why this service does not work when pointed to C:\Windows\Temp but it works without incident when deleting files and folders in C:\MyTestFolder.
My service runs as LocalSystem and SYSTEM has full control on C:\Windows\Temp
I also changed it to run as an administrator account, but that doesn't work either.
I can put the same code into a non-service exe and double click it, and it works and deletes the contents of C:\Windows\Temp -- so I am at a complete loss and hope someone can point me in the right direction on how to figure out what is wrong.
I provided process monitor results, which appear to show the service is accessing C:\windows\temp which is confusing because I put some test files out there that are not open or held up in a process, and those are not being deleted.
Native Process Monitor PML Results File
Process Monitor Extended Results XML File
I was able to fix my own problem. Here is what I found:
The service was successfully accessing C:\Windows\Temp but it was failing due to two exceptions:
1) Permissions Exception where it was denied access to a subfolder or file as a result of permissions
2) IO Problem because the file was open or in use.
In my code, I was only checking for System.IO.Exceptions so when it encountered an Access Failure exception it would break.
Once I discovered this, I modified the exception handling on the catch so that it would check for all exceptions.
Hence the code changed from what it was as listed above to this.
Sub ClearWinTempDirectory(folder As String)
'Loop over the subdirectories and remove them with their contents
For Each d In Directory.GetDirectories(folder)
Try
Directory.Delete(d, True)
Catch e As System.Exception
COBWtl.WriteEntry("The directory " & d & " is
currently locked or is inaccessable and will not be deleted.",
EventLogEntryType.Information, eventID:=9997)
End Try
Next
' Finish the files in the root folder
For Each f In Directory.GetFiles(folder)
Try
File.Delete(f)
Catch e As System.Exception
COBWtl.WriteEntry("The file " & f & " in directory " & folder
& " is currently locked or is inaccessable and will not be
deleted.", EventLogEntryType.Information, eventID:=9997)
End Try
Next
COBWtl.WriteEntry("All files and folders in the " & folder & "
directory that are not currently locked by applications or processes
Have been deleted", EventLogEntryType.Information, eventID:=9995)
End Sub
Problem solved.
Related
I am working on vbscript to unzip the multiple files one after another.
I am using below code
Dim folder(3)
folder(0) = "UBO90R1"
folder(1) = "UBO90R2"
folder(2) = "UBO100R1"
folder(3) = "UBO100R2"
For i = 0 To 3
unzip_Source = "D:\Autobackup\" & folder(i) & ".zip"
unzip_destination = "D:\Autobackup_unzip\" & folder(i) &"\"
Call ExtractFilesFromZip(unzip_Source,unzip_destination)
WScript.Echo "unzip Finished"
Next
Sub ExtractFilesFromZip(pathToZipFile, dirToExtractFiles)
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
pathToZipFile = fso.GetAbsolutePathName(pathToZipFile)
dirToExtractFiles = fso.GetAbsolutePathName(dirToExtractFiles)
If (Not fso.FileExists(pathToZipFile)) Then
WScript.Echo "Zip file does not exist: " & pathToZipFile
Exit Sub
End If
If Not fso.FolderExists(dirToExtractFiles) Then
WScript.Echo "Directory does not exist: " & dirToExtractFiles
Exit Sub
End If
dim sa : Set sa = CreateObject("Shell.Application")
Dim zip : Set zip = sa.NameSpace(pathToZipFile)
Dim d : Set d = sa.NameSpace(dirToExtractFiles)
d.CopyHere zip.items, 4
Do Until zip.Items.Count <= d.Items.Count
WScript.Sleep(200)
Loop
End Sub
The Problem currently I have that if the folder or file is already exist than it open the dialog to the user to select any option Overwrite, keep both file etc.
If I change the following line from the code
d.CopyHere zip.items, 4
'Integer 4 didn't show the progress bar
to
d.CopyHere zip.items, 16
'Integer 16 overwrite the existing file but it shows the progress bar.
I would like to overwrite the existing file without any dialog box and without any progress bar.
PS: Code to unzip copied from here.
Looking at help we would find the follwing.
Type: FILEOP_FLAGS
Flags that control the file operation. This member can take a combination of the following flags.
FOF_ALLOWUNDO
Preserve undo information, if possible.
Prior to Windows Vista, operations could be undone only from the same process that performed the original operation.
In Windows Vista and later systems, the scope of the undo is a user session. Any process running in the user session can undo another operation. The undo state is held in the Explorer.exe process, and as long as that process is running, it can coordinate the undo functions.
If the source file parameter does not contain fully qualified path and file names, this flag is ignored.
FOF_CONFIRMMOUSE
Not used.
FOF_FILESONLY
Perform the operation only on files (not on folders) if a wildcard file name (.) is specified.
FOF_MULTIDESTFILES
The pTo member specifies multiple destination files (one for each source file in pFrom) rather than one directory where all source files are to be deposited.
FOF_NOCONFIRMATION
Respond with Yes to All for any dialog box that is displayed.
FOF_NOCONFIRMMKDIR
Do not ask the user to confirm the creation of a new directory if the operation requires one to be created.
FOF_NO_CONNECTED_ELEMENTS
Version 5.0. Do not move connected files as a group. Only move the specified files.
FOF_NOCOPYSECURITYATTRIBS
Version 4.71. Do not copy the security attributes of the file. The destination file receives the security attributes of its new folder.
FOF_NOERRORUI
Do not display a dialog to the user if an error occurs.
FOF_NORECURSEREPARSE
Not used.
FOF_NORECURSION
Only perform the operation in the local directory. Do not operate recursively into subdirectories, which is the default behavior.
FOF_NO_UI
Windows Vista. Perform the operation silently, presenting no UI to the user. This is equivalent to FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR.
FOF_RENAMEONCOLLISION
Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists at the destination.
FOF_SILENT
Do not display a progress dialog box.
FOF_SIMPLEPROGRESS
Display a progress dialog box but do not show individual file names as they are operated on.
FOF_WANTMAPPINGHANDLE
If FOF_RENAMEONCOLLISION is specified and any files were renamed, assign a name mapping object that contains their old and new names to the hNameMappings member. This object must be freed using SHFreeNameMappings when it is no longer needed.
FOF_WANTNUKEWARNING
Version 5.0. Send a warning if a file is being permanently destroyed during a delete operation rather than recycled. This flag partially overrides FOF_NOCONFIRMATION.
Option Explicit
dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FolderExists("C:\Users\michal\Desktop\mv_files_backup") then
fso.MoveFolder "C:\Users\michal.glowacki\Desktop\mv_files_backup\*.*", "\\192.168.10.245\backup\servers\backup_server"
Else
wscript.echo "doesn't exist"
End If
When I try run this script I have error:
Permission denied 800A0046
but when I change MoveFolder to CopyFolder script works correctly. Why I can't use function MoveFolder ?
From MSDN:
If source contains wildcards or destination ends with a path separator
( \ ), it is assumed that destination specifies an existing folder in
which to move the matching files. Otherwise, destination is assumed to
be the name of a destination folder to create. In either case, three
things can happen when an individual folder is moved:
If destination does not exist, the folder gets moved. This is the
usual case.
If destination is an existing file, an error occurs.
If destination is a directory, an error occurs.
An error also occurs if a wildcard character that is used in source
doesn't match any folders. The MoveFolder method stops on the first
error it encounters. No attempt is made to roll back any changes made
before the error occurs.
I've marked in bold the parts that explain your problem. Because your destination doesn't end with a trailing backslash, your script is attempting to create the folder, and failing. Try it with a \ added to the end of the destination and report back if it still doesn't work.
Try this:
fso.MoveFolder "C:\Users\michal.glowacki\Desktop\mv_files_backup", "\\192.168.10.245\backup\servers\backup_server\"
I'm trying to automate pushing a file into my users' home directories, but am stuck on a "Permission Denied" error — is thrown on line 6 here, with the CopyFile call.
There are other parts of the script (not shown) that create and copy folder contents using the same source and destination directories, and they work perfectly. It's only when I use CopyFile that it fails.
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FileExists("H:\Minecraft\.minecraft\options.txt") Then
fso.CopyFile "C:\Minecraft\options.txt", "H:\Minecraft\.minecraft\"
End If
Set fso = Nothing
H: is a network home directory, to which the current user has full read/write privs.
I've tried adding/removing trailing slashes from the paths, adding "options.txt" to the destination path, removing the false argument... Not sure what else to try. Any thoughts?
FYI, this chunk of code, which comes immediately before the error-prone bit above, executes perfectly every time:
If Not fso.FolderExists("H:\Minecraft\.minecraft\bin\") Then
If Not fso.FolderExists("H:\Minecraft\.minecraft\") Then
fso.CreateFolder("H:\Minecraft\.minecraft\")
End If
fso.GetFolder("C:\Minecraft\bin\").Copy "H:\Minecraft\.minecraft\"
End If
I've only ever seen CopyFile fail with a "permission denied" error in one of these 3 scenarios:
An actual permission problem with either source or destination.
Destination path is a folder, but does not have a trailing backslash.
Source file is locked by an application.
for me adding / worked at the end of location of folder.
Hence, if you are copying into folder, don't forget to put /
Based upon your source variable (sourcePath = "C:\Minecraft\bin\") I suspect your hard code is pointing at the wrong place
fso.CopyFile "C:\Minecraft\options.txt", destinationPath, false
should be
fso.CopyFile "C:\Minecraft\bin\options.txt", destinationPath
or
fso.CopyFile sourcePath & "options.txt", destinationPath
Another thing to check is if any applications still have a hold on the file.
Had some issues with MoveFile. Part of my permissions problem was that my script opens the file (in this case in Excel), makes a modification, closes it, then moves it to a "processed" folder.
In debugging a couple things, the script crashed a few times. Digging into the permission denied error I found that I had 4 instances of Excel running in the background because the script was never able to properly terminate the application due to said crashes. Apparently one of them still had a hold on the file and, thusly, "permission denied."
I have read your problem, And i had the same problem. But af ter i changed some, my problem "Permission Denied" is solved.
Private Sub Addi_Click()
'On Error Resume Next
'call ds
browsers ("false")
Call makeAdir
ffgg = "C:\Users\Backups\user\" & User & "1\data\"
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.Getfolder("c:\users\Backups\user\" & User & "1\data")
f.Attributes = 0
Set fso = VBA.CreateObject("Scripting.FileSystemObject")
Call fso.Copyfile(filetarget, ffgg, True)
Look at ffgg = "C:\Users\Backups\user\" & User & "1\data\", Before I changed it was ffgg = "C:\Users\Backups\user\" & User & "1\data" When i add backslash after "\data\", my problem is solved. Try to add back slash. Maybe solved your problem. Good luck.
You can do this:
fso.CopyFile "C:\Minecraft\options.txt", "H:\Minecraft\.minecraft\options.txt"
Include the filename in the folder that you copy to.
It's worth checking task manager for any stray wscript.exe tasks that are stuck.
It could be one of those that's blocking access to the file.
It is possible that your Antivirus software may be preventing the activity of the script. I encountered this with AVG Antivirus running in silent mode (which means it does not alert you to every protection step it takes, so you get a permission error without realising that AVG is preventing the action).
In my case, I invoked verbose mode (switched off silent mode), executed the script and AVG came up with an interception warning, allowing me to train AVG to permit this script to run.
A friend and I started building a VBScript that with the goal to copy any opened files/some specific format of docs (like pdf, pptx) when we insert an external hard disk or USB on the computer. We got our script as far as only copying all docs of a specific format from one the external hard disk/USB to my computer, but we must manually execute the script after inserting the external hard disk/USB.
What we would like the script to do:
Start automatically when an external hard disk/USB is inserted
Don't show a pop up after the copy
Possibily only copy the files (pdf,jpeg,pptx) that are opened by the user
Here is what we've done so far:
' foreach.vbs
' Testing the for each function on files
'
' BEGIN
' Create a File System Object to handle files and folders
Set fso = CreateObject("Scripting.FileSystemObject")
' Some vars
src = "C:\" ' The source of search, should be changed before use
dest = "c:\temp\1\" ' destination where we will copy files to
' It would be a bright idead to force and/or create dest before
' starting copy
fso.CreateFolder(dest)
Set ofolder = fso.GetFolder(src) ' set as object
' get all files inside the specified folder
Set allfiles = ofolder.Files
' Enter a For Each Loop that will process each of the files
For Each sfile in allfiles
' Better get all extensions in lower case
If LCASE(fso.GetExtensionName(sfile.Name)) = "bat" then
' Print out what we find
wscript.echo sfile.Name
fso.CopyFile sfile, dest
End If
Next
If I get it right, your actual question is How to detect a USB drive has been plugged in?
You'll need some event driven language to do this, not VBScript unfortunately.
But if you don't want to go with programming, why not using Task Scheduler.
P.S. Actually, this topic (I not like the infinite cycle, but) is a possible answer.
Ok, this is my problem.
I'm doing a logonscript that basically copies Microsoft Word templates from a serverpath on to a local path of each computer. This is done using a check for group membership.
If MemberOf(ObjGroupDict, "g_group1") Then
oShell.Run "%comspec% /c %LOGONSERVER%\SYSVOL\mydomain.com\scripts\ROBOCOPY \\server\Templates\Group1\OFFICE2003\ " & TemplateFolder & "\" & " * /E /XO", 0, True
End If
Previously I used the /MIR switch of robocopy, which is exellent.
But, if a user is member of more than one group, the /MIR switch removes the content from the first group, since it's mirroring the content from the second group. Meaning, I can't have both contents.
This is "solved" by not using the /MIR switch and just let the content get copied anyway.
BUT the whole idea of having the templates on a server is so that I can control the content the users receive through the script. So if I delete a file or folder from the server path, this doesn't replicate on the local computer. Since I don't use the /MIR switch anymore. Comprende?
So, what do I do?
I did a small script that basically checks the folders and files and then removes them accordingly, but this actually ended up being the same functionality as the /MIR switch anyway. How do I solve this problem?
Edit: I've found that what I actually need is a routine that scans my local template folder for files and folders and checks if the same structure exists in any of the source template folders.
The server template folders are set up like this:
\\fileserver\templates\group1\
\\fileserver\templates\group2\
\\fileserver\templates\group3\
\\fileserver\templates\group4\
\\fileserver\templates\group5\
\\fileserver\templates\group6\
And the script that does the copying is structures like this (pseudo):
If User is MemberOf (group1) Then
RoboCopy.exe \\fileserver\templates\group1\ c:\templates\workgroup *.* /E /XO
End if
If User is MemberOf (group2) Then
RoboCopy.exe \\fileserver\templates\group2\ c:\templates\workgroup *.* /E /XO
End if
If User is MemberOf (group3) Then
RoboCopy.exe \\fileserver\templates\group3\ c:\templates\workgroup *.* /E /XO
End if
Etc etc
With the /E switch, I make sure it copies subfolders as well. And the /XO switch only copies files and folders that are newer than those in my local path.
But it doesn't consider if the local path contains files or folders that doesn't exist on the server template path.
So after the copying is done, I would like to check if any of the files or folders on my c:\templates\workgroup actually exists in either of the sources. And if they don't, delete them from my local path. Something that could be combined in these memberchecks perhaps?
Using a lookup table
I'd suggest an approach that puts all templates into one common file server directory and use a lookup table to assign templates to groups.
The benefit would be that your templates would be guaranteed to be in sync; i.e. you don't have to worry that a template for group A, B, and C is really the same in all group specific folders on your file server.
Another bonus is a maintainable configuration table which allows you to assign templates to groups without the need to make changes to your logon script.
The lookup table config file would look something like
group1;\templateA.dot;\templateA.dot
group2;\B\templateB.dot;\B\templateB.dot
group3;\B\C\templateC.dot;\templateC.dot
with column 1 listing your AD group names; column 2 the source path and column 3 the target path.
This would also allow for flattening your template folder on the client side.
In any case you can avoid having to maintain multiple copies of all your templates on your file server and adding more groups or templates doesn't require to touch your logon script but just the config file.
In your logon script you can iterate over all lines and copy the ones with matching groups
Logon script code
open lookup table config file
For Each line In lookup table
If MemberOf(ObjGroupDict, groupname_column_value) Then
execute Robocopy templatename_column_value local_target
End If
Next
Removing old files on the client
Here's a script that removes files in the template directory the user's machine not present in one of the file groups copied. For clarity, the code is at the end of this answer. Here's how to use the script in your current solution that doesn't use /MIR.
In the code for each group copied, add one additional method call to 'ListFiles' - this tracks the files copied from the server:
If User is MemberOf (group3) Then
RoboCopy.exe \\fileserver\templates\group3\ c:\templates\workgroup *.* /E /XO
ListFiles("\\fileserver\templates\group3\", userTemplates)
End if
Do this for each group copied. (It is ok if the same template appears in more than one group.)
After all groups have been copied, you add this code block:
ListFiles "c:\templates\workgroup", toDelete
removeAllFrom toDelete, userTemplates
This lists all files in the user's local templates folder to toDelete. All the files just copied are then removed from that set, leaving just the files that were not copied from the server. We can then print the files to delete, and then actually delete them.
echoDictionary "deleting old user templates", toDelete
' deleteFiles c:\templates\workgroup", toDelete
The call to deleteFiles commented out - probably wise to do a trial run first! The first argument to deleteFiles is the user's template directory - it should not have a trailing slash.
With these changes in place, any files in the templates folder on the users machine that were not copied from the server will be deleted, providing effectively multi-directory synchronization.
Now comes the script. The first block can be pasted to the top of your file, and the remainder at the bottom, to help avoid clutter.
// script to remove files not present on one of the group folders on the fileserver
Set fs = CreateObject("Scripting.FileSystemObject")
Set userTemplates = CreateObject("Scripting.Dictionary")
userTemplates.CompareMode = 1
Set toDelete = CreateObject("Scripting.Dictionary")
toDelete.CompareMode = 1
-- under here are just procedures so they can go at
-- the bottom of your script if desired
Sub deleteFiles(basedir, dictionary)
for each key in dictionary.Keys
fs.DeleteFile(basedir+"\"+key)
next
End Sub
Sub echoDictionary(msg, dictionary)
for each key in dictionary.Keys
Wscript.Echo msg & ": " & key
next
End Sub
Sub removeAllFrom(target, toRemove)
for each key in toRemove.Keys
if target.Exists(key) then
target.remove key
end if
next
End Sub
Sub ListFiles(folderName, dictionary)
Set folder = fs.GetFolder(folderName)
ListSubFolders folder, "", dictionary
End Sub
Sub ListSubFolders(folder, prefix, dictionary)
Set files = folder.Files
For Each file in files
qualifiedName = prefix & file.Name
dictionary.add qualifiedName, file
Next
For Each Subfolder in Folder.SubFolders
qualifiedName = prefix+Subfolder.Name & "\"
ListSubFolders Subfolder, qualifiedName, dictionary
dictionary.add qualifiedName, Subfolder
Next
End Sub