Print Thread
Page 2 of 2 1 2
Re: PLS-Recovery Directory has "Monitor" subfolders - no files recovered at startup
James B #54124 10/12/16 04:04 PM
Joined: Jul 2016
Posts: 20
J
Member
Offline
Member
J
Joined: Jul 2016
Posts: 20
Wow, you said creating a recursive folder structure is a "really, really bad idea" and then you went ahead and documented it for me! eek

When you tried it yourself, did you leave it that way? How long?

Any application, utility or system service which tries to scan the folder hierarchy (for instance to do a virus scan or recursive copy) is likely to get stuck in an infinite loop, which sounds like a great way to cause myself all kinds of future pain.

My company uses Roaming User profiles, and my understanding is that the \AppData\Roaming directory gets copied up to the server and then down to any machine I log into. This could potentially break my ability to log in, to my machine or any others -- NO THANKS!

(Why isn't Allround addressing this???)

Re: PLS-Recovery Directory has "Monitor" subfolders - no files recovered at startup
Jeff Kandt #55172 12/31/16 05:22 PM
Joined: Jun 2010
Posts: 35
J
James B Offline OP
Member
OP Offline
Member
J
Joined: Jun 2010
Posts: 35
Believe it or not, I haven't had any issues - and it's been six months, now? Most apps (e.g. our antivirus software) are smart enough not to follow junctions, as they know the underlying directory is controlled/monitored elsewhere. I don't know if my company keeps a roaming profile or not, so I can't say for sure it wouldn't break, but if this directory had been left in its original location in \AppData\Local, the question would be moot **hem**Marco**hem**. While I'm dreaming, I'd also like a pony.

But in any case, it's worked fine for me. I still hate it mad

Re: PLS-Recovery Directory has "Monitor" subfolders - no files recovered at startup
James B #57755 03/27/18 08:17 PM
Joined: Mar 2018
Posts: 2
P
Member
Offline
Member
P
Joined: Mar 2018
Posts: 2
I have been encountering this issue for years, and am finally beginning to understand exactly what creates it. Thank you, all. I have been able to witness how starting a remote desktop suddenly causes my sessions to start saving in a different folder. I can see, from people describing the same problem, how any access with a different monitor configuration must be doing the same.

The Link Shell solution made me nervous, so I have created an AHK script as an alternate solution. (AHK, or AutoHotKey, is a Windows scripting language. If you have it on your system, you can double-click any AHK script to run it.) What this one does is keep the root and all "Monitors" folders in sync. It copies the newest .cfg files, overwriting old ones. It also attempts to detect when "window" files (e.g. desktop.common.001 if you have an unsaved window in your desktop=common session) are no longer in use, and delete them.

This script needs to be located in your PLS-Recovery directly, and I HIGHLY recommend backing up the directory before running it. You also have to run multiple times until you get no output, because files are moving around as it operates. I can simplify that, but I am eager for the possibility of having other testers, so here is version 1.0. (At the moment it also does a poor job of handing "crash" files because it cannot detect when they are consumed (recovered or ignored) versus not yet having been backed up, so it just keeps copying them around forever. I'm sure there are other things I could be doing better, too. I will probably put a new version up within a month.)


Code
#NoEnv                       ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn                      ; Enable warnings to assist with detecting common errors.
SendMode Input               ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force

; ==================== IMPORTANT NOTES =============================================================

; PL/SQL Developer has an amazing "desktop=" feature which allows you to autosave your workspace(s) and re-load all open windows on startup.
; However, this feature breaks when you have multiple monitor configurations, e.g. when remoting in from a laptop, or possibly saving the workspaces on a shared drive.
; In this situation, PL/SQL Developer puts single-monitor setups in the root folder, and multi-monitor setups in a folder named for the resolution of those desktops.
; So if you have a workspace open on one machine and then remote in, suddenly the autosave is happening to a different folder.

; Given that this is happening, but that I would prefer my workspaces to operate seamlessly regardless of how I am accessing them,
; I want something that can automatically detect when any ".cfg" file is created or updated in any of the folders and keep the others at the newest version.

; Also, PL/SQL Developer, when working in a single directory, will delete temporary files that are no longer in use.  This script *would* keep those deleted files alive
; by continually copying them into other directories and back again.  This won't really harm anything, since they won't be connected to any workspaces.  So, to reduce
; clutter I have also added a check to detect when they are not in use.  So for the root directory and each Monitors directory, this script will loop through non-cfg
; files, then parse the corresponding "desktop.*.cfg" file to see whether the filename appears in any of them.  If not, it will delete it.  Note that this means ANY FILE
; in this folder starting with "desktop." (and not ending in ".cfg" or ".ini") or ending in ".0xx" will be deleted if it does not belong to a PL/SQL Developer workspace.

; Sometimes we get "crash" files which are handled poorly by this script.  I don't know how to detect when these ones are no longer necessary.

; EXTRA-IMPORTANT NOTE: This script is not very thoroughly vetted yet, and it deletes/overwrites files.  Thus, *back up* the entire PLS-Recovery directory before *each* use.
; At some point, I'd love to have this run automatically, maybe several times per hour.  As it stands, it should be run prior to opening workspaces and probably only then.
; Also, it needs to be run several times until there is no output, since it's moving and deleting files in a very specific order. Probably best to do this while no
; PL/SQL Developer windows are open so that files aren't being modified by both at the same time.

; ==================== GLOBAL VARIABLES ============================================================

; Turn on or off the copy/delete functions (this was useful during testing, but I might as well leave it in)
global do_copy = true
global do_delete = true

; Turn on or off detailed debug messages for the copy/delete functions
global msg_copy = false
global msg_delete = false

; ==================== MAIN PROGRAM ================================================================

file1 =
file2 =
file2dir =
cfgfile =
parsestr =
FileList = ; List files first to prevent errors as we operate on the files we're checking
FileList2 =
DirList =

Loop, Files, *, D
DirList = %DirList%%A_LoopFileName%`n
Loop, Parse, DirList, `n
{
	if (InStr(A_LoopField, "Monitors") = 1)
	{
		file2dir = %A_LoopField%
		if msg_copy or msg_delete
			MsgBox, Found directory: %file2dir%
	}
}

; For each .cfg in the root directory, check each folder and check if the file exists.  If it doesn't, copy it.  If it does, compare the dates.
Loop, Files, *
FileList = %FileList%%A_LoopFileName%`n
Loop, Parse, FileList, `n
{
	file1 = %A_LoopField%
	if (InStr(A_LoopField, ".cfg") >= 1)
	{
		if msg_copy
			MsgBox Found config file: %file1%
		Loop, Parse, DirList, `n
		{
			FileList2 =
			if (InStr(A_LoopField, "Monitors") = 1)
			{
				if msg_copy
					MsgBox Checking folder: %A_LoopField%
				file2dir = %A_LoopField%
				file2 = %file2dir%/%file1%
				CompareFiles(file1, file2)
			}
		}
		
	} else {
		if (InStr(A_LoopField, "desktop.") = 1 and InStr(A_LoopField, ".ini") = 0)
		{
			if msg_delete
				MsgBox, Found non-config %file1%
			cfgfile := Substr(file1, 1, Instr(file1, ".", false, -1)) . "cfg"
			ParseFile(cfgfile, file1, file1)
		}
	}
	
}

; Then, for each file in each of the folders, check if it exists in the root.
Loop, Parse, DirList, `n
{
	FileList2 =
	if (InStr(A_LoopField, "Monitors") = 1)
	{
		file2dir = %A_LoopField%
		;MsgBox, Found dir %file2dir%
		Loop, Files, %A_LoopField%\*
		FileList2 = %FileList2%%A_LoopFileName%`n
		Loop, Parse, FileList2, `n
		{
			FileList =
			file2 = %A_LoopField%
			if (InStr(A_LoopField, ".cfg") >= 1)
			{
				if msg_copy
					MsgBox Found config file: %file2dir%/%file2%.  Checking root.
				CompareFiles(file2dir . "/" . file2, file2)
			} else {
				if (InStr(A_LoopField, "desktop.") = 1 and InStr(A_LoopField, ".ini") = 0) or (RegExMatch(A_LoopField, "[.][0-9][0-9][0-9]$") > 0)
				{
					if msg_delete
						MsgBox, Found non-config %file2%
					cfgfile := file2dir . "/" . Substr(file2, 1, Instr(file2, ".", false, -1)) . "cfg"
					did_delete := ParseFile(cfgfile, file2, file2dir . "/" . file2)
					if not %did_delete%
					{
						if msg_delete
							MsgBox, Kept %file2%; comparing to root
						CompareFiles(file2dir . "/" . file2, file2)
					}
					
				}
			}
		}
	}
}
return

; ==================== FUNCTIONS ===================================================================

ParseFile(file, str, delfile)
{
	did_delete = false
	FileRead, filestr, %A_ScriptDir%/%file%
	if ErrorLevel
		MsgBox, Could not open file %file%: %A_LastError%
	else
	{
		if msg_delete
			MsgBox, Parsing %file% for string "%str%"
		if (InStr(filestr, str) < 1)
		{
			MsgBox, Deleting %delfile%
			if do_delete
			{
				FileDelete, %delfile%
				did_delete = true
			}
		}
		else
		{
			if msg_delete
				MsgBox, File is in use by a workspace.  Keeping.
		}
	}
	return did_delete
}

OverwriteFile(srcFile, destFile)
{
	MsgBox, Copying %srcFile% to %destFile%
	if do_copy
		FileCopy, %srcFile%, %destFile%, 1
}

CompareFiles(file1, file2)
{
	; Compares the system date on file1 and file2 and updates the older with the most recent version
	if msg_copy
		MsgBox, Comparing %file1% with %file2%
	IfNotExist, %file2%
		OverwriteFile(file1, file2)
	else
	{
		FileGetTime, time1, %file1%
		FileGetTime, time2, %file2%
		if time1 - time2 > 0
			OverwriteFile(file1, file2)
		if time2 - time1
			OverwriteFile(file2, file1)
	}
}

Last edited by parmeisan; 03/27/18 08:31 PM. Reason: Better explanation of the script and AHK.
Page 2 of 2 1 2

Moderated by  support 

Link Copied to Clipboard
Powered by UBB.threads™ PHP Forum Software 7.7.4
(Release build 20200307)
Responsive Width:

PHP: 7.1.33 Page Time: 0.037s Queries: 15 (0.012s) Memory: 2.5499 MB (Peak: 3.0430 MB) Data Comp: Off Server Time: 2024-05-20 04:15:55 UTC
Valid HTML 5 and Valid CSS