Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem with SET DEFAULT TO 2

Status
Not open for further replies.

Bryan - Gendev

Programmer
Jan 9, 2011
408
AU
In my app ( written 10+ years ago and now being revised and checked) I have a need to change the default folder on a number of occasions. I use SET DEFAULT TO (cNewfolder) and this works on every occasion except one which I am now trying to resolve. I need to be placed in a certain folder in this instance to make a backup of an ini file before changing the current ini in a certain way - allowing the current ini to be restored later.
I don't know if this is the problem but the path required is like
C:\Users\username\AppData\Roaming\the_target_ini_appnameI am unable to set my default to this folder to backup the ini file which resides there using COPY FILE (file1) to backupfile1.txt.
Can anyone advise me on this?

GenDev
Adelaide
South Australia
 
Just to prove the point you can copy files with full path, try out this:

Code:
lcSourceFile = AddBS(Home())+"redist.txt"
lcDestFile = AddBS(GetEnv("TEMP"))+"redist.txt"
? File(lcSourceFile)
? File(lcDestFile)
COPY FILE (lcSourceFile) to (lcDestFile)
? File(lcDestFile)

This obviously only runs within VFP, where HOME() is pointing the the installation directory of VFP containing the redist.txt, but shouldn't be a problem, should it?
Expected output is
[pre].T. (redist.txt exists in Home())
.F. (redist.txt is not in TEMP)
.T. (redist.txt was copied to TEMP)[/pre]


Chriss
 
Hi Gendev,

I was wondering about the length of the entire copy command, not just the filename.

Regards Gerrit
 
Just a thought:

The pu8rpose of a roaming profile is, that it roams with a user. What would it be worth a profile roams, if you (or any application using profile specific files) would need to know whether the user roams or uses his usual workstation? Shouldn't Windows mirror the usual profile into the roaming folder and after it was travelling via storage on a domain controller to another workstation mirror it back into the "normal" location of user profile, the local profile?

Maybe it was never necessary to write directly into the roaming subfolder, as the only use for it is to let the profile files roam from one to any workstation, not to be used, so the roaming folder is just the mirrored local profile and not meant to be used. If you do so, your changes obviously also roam, so no harm is done by what you did earlier - but from what I read so far I think it's true Microsoft decided to reduce permissions of that, so you're nudged towards using the usual profile files as a developer.

Well, if my thought bears any meaning, I think you would find a copy of the INI of TMG.exe somewhere outside the roaming folder and the EXE likely reads that in.

Chriss
 
Chriss,
1.
I added
SET DEFAULT TO AddBS(GetEnv("TEMP"))
success=File(lcDestFile)
and success = .T.
2
C>the EXE likely reads that in.

That was why I was asking about the utility to investigate exactly that.
However, both TMG and my program 'use' roaming profiles as do many other programs I have installed on my PC.
TMG does have an ini in the program files folder along with its exe but the one in the roaming folder contains the details of the latest usage of the TMG program ( which is why I want to access it).
So at the moment it looks like I will not be able to modify the TMG ini file. <sigh>

3
Both TMG and my program are designed to run on a users home PC (Genealogists who in the main know little of the 'innards' of a PC.
GenDev
 
Gerrit
G> I was wondering about the length of the entire copy command, not just the filename.
Sorry, I don't follow?

GenDev
 
gendev said:
Both TMG and my program are designed to run on a users home PC

Well, that's not necessarily natural, good that you say so.

In your first post you mentioned
C:\Users\username\AppData\[highlight #FCE94F]Roaming[/highlight]\
Roaming profiles are only a thing in a network of a company, where a user can roam from onw workstation to another and still have his user profile, his personal settings and many more user specific files available no matter where he logs in.

So it is very questionable that you ever needed access to a Roaming subfolder of the user profile.

It could be very handy to know where TMG.exe actually reads its own INI from. Even if one exists in [tt]C:\Users\username\AppData\Roaming\[/tt] for whatever reason, it may not even be used. Not in a standalone PC that doesn't have anything like roaming profiles.

So the idea you had in your other thread to determine which files a process accesses is not bad. I and others told you Sysinternal procmon can show that, did you investigate in that direction to see whicdh INI TMG.exe loads?

Chriss

PS: To relativate what's available and what not. On a standalone notebook I use my local user profile folder in C:\Users\profilename also has C:\Users\profilename\AppData\Roaming and there are some folders of companies (Microsoft, for example) and applications (Notepad++) for example. I can read and write in these third party application folders both as a user using Windows Explorer and with VFP. I'm on Windows 10, though.

So either Windows 11 changed this to become private to users and applications or its soimething that the TMG.exe does to it's own files, perhaps you also can read/write the INI as long as TMG.exe runs and not, if it is started, when it perhaps opens its own INI file with exclusive access.

For Notepad++ I don't see a corresponding appdata folder in the Local and LocalLow subdirectories. So this application decides to use the Roaming subdirectory only. Why does it even exist on a standalone PC? I can't really tell you what's on the mind of MS about this, but I guess that's for simplyfying the roaming feature once the PC would join a network. Anyway, it is indeed not only existing for networked computers, that's right.

The last thing I read your code didn't manage here or in your other thread is even just reading the INI file and copying it elsewhere. If that also didn't cause any error I'm quite stumped, so the last direction we can go for is finding out whether TMG.exe reads its INI from there or elsewhere.

If you're then locked out of the directory or file, your last chance still is providing an EXE, maybe a separate module, that requires the user to have adminstrative permissions so you can try to access the folder that's protected. Unless there's really a simple reason like a typo in the path or file name that sneaked in with any recent edit, unintended.
 
Chriss,

AS I mentioned in the other thread it is clear/certain that TMG uses the ini in the roaming folder.
I'm not sure the definition of roaming folders as used on a network is what I am describing here.

As a second evidence both TMG and my app install with roaming folders under users/username/appdata/roaming on my notebook so I am convinced this is the normal case thus valid in my thoughts of wanting to access the tmg app.ini there.

I have process monitor installed but haven't yet been able to see what additional files an exe uses. I did do this before so i will probably get there soon

GenDev.
 
Okay, it's still more appropriate for a non networked and thus local application to use {localappdata} instead of {userappdata} - speaking in terms of Inno Setup constants, no matter what other Software does.

It's not a showstopper usualy, it seems - see my edited previous post. But all your test results indicate either Windows 11 or TMG are protecting their application data folder from access of other applications, doesn't it? If not by default and since you installed them but just recently. Anything that's not your code can change at any time, can't it?

So focus on the current situation, not the fact "it worked before", it's just not getting you forward, is it?

From the pure perspective of coding things you do what you did, you set variables to the fully qulified names (path+filename) or path only and then either
Code:
COPY FILE (lcSourceFile) TO (lcDestinationfile)
or using separation of paths and file names:
Code:
SET DEFAULT TO (lcPath)
COPY FILE (lcSourceFile) TO (lcDestinationfile)
This time only the file names in lcSourceFile and lcDestinationfile - "your.ini" and "backupyour.ini", for example.

The brackets indicate to VFP that you don't literally mean files named like the variables - that's what VFP would interpret and do if you leave off the brackets, it also makes it possible to use paths and filenames with spaces. So from that perspective everything is fine with your code. But something is wrong and it's hard to tell from here without having hands on your computer and full code.

Since the code is okay, it can only fail on wrong values, permisssions, non existing directories, protected/hidden directories, files in exclusive use, and maybe more reasons, just because code once ran, that's not putting you in a futureproof situation, when influences from outside have an effect. So you could make code much more cautious in checking assumptions:

Code:
*assumed: lcPath, lcSourceFile and lcDestinationfile are set as wanted/needed
IF DIRECTORY(lcPath)
   SET DEFAULT TO (lcPath)
   IF ADIR(laDummy,lcSourceFile)=1
      IF ADIR(laDummy,lcDestinationfile)=0 OR Set('Safety')=='OFF' && important, upercase OFF.
         * Copy file with local error handling
         TRY
            COPY FILE (lcSourceFile) TO (lcDestinationfile)
         CATCH TO loException
            Messagebox("Copying file failed due to Error:"+CHR(13)+CHR(10)+loException.Message)
         ENDTRY
      ELSE
         Messagebox("Destination File "+lcDestinationfile+" already exists. Copy File would fail to overwrite it as SAFETY is ON.")
      ENDIF
   ELSE
      Messagebox("Source File "+lcSourceFile+" not found.")
   ENDIF
Else
   Messagebox(lcPath+' does not exist or is a hidden or system directory.')
Endif

You can see from this how a centralized error handler shortens code as you (usually) will be informed about what's not working with path or filenames when you just do SET PATH and COPY FILE instead. But something is ill with your situation, if this code yields some messages that should have triggered your error handling, or your error handling is not yet initialized when you do this in an early application state, whatever. But you could try this code to see what it brings up.

Chriss
 
One detail aspect, notice the help topic about DIRECTORY() and its second parameter, that can be used optionally, set to 1:

Code:
? Directory(GetEnv("USERPROFILE")+'\AppData') && results in .F., usually, as AppData is a hidden folder
? Directory(GetEnv("USERPROFILE")+'\AppData',1) && results in .T., as this disregards the hidden status.
? Directory(GetEnv("USERPROFILE")+'\AppData\Local') && .T. - works regardless of AppData being hidden, as the Local folder isn't hidden.
? Directory(GetEnv("USERPROFILE")+'\AppData\Roaming') && .T. - dito for Roaming.

So it's not just better to use Directory(lcDir,1) always, because if you would want to copy from or into the hidden directoy itself, VFP would respect the hidden status and decidedly fail, even if files and directories exist just hidden. Therefore the longwinded code does check Directory(lcPath), not Directory(lcPath,1). It makes no sense if the hidden attribute wouldn't have any effect. The way Windows handles its hidden folders is not as strict as they could be, you can configure the options for Windows Explorer to show hidden folders with a fainter yellow color´and allow navigating into them, too. So the hidden status is mainly a guidance of the normal user that doesn't set this up for himself, but once you know a non hidden subfolder within a hidden folder you're in safe territory again and (usually) don't need special permissions, unless a folder like Program Files is write protected anyway, no matter that it's not hidden.

Chriss
 
Chriss,
So the result of your code is
lcPath+' does not exist or is a hidden or system directory.'

I substituteg

IF DIRECTORY(lcPath,1)
SET DEFAULT TO (lcPath)

and the command is ignored with no error msg and path remains as it was before the command. ( as before)

Investigating the roaming folder itself with TMG loaded and pathwiz the same and I get the following screens
TMG_Roaming_Fldr_j6bmpc.png

TMG_Roaming_Fldr2_nnqwtj.png

TMG_Roaming_Fldr3_p7zirr.png

The access 'ticks' show exactly the same density as a folder on my 'spare' SSD that pathwiz operates from.

I changed the read only check box to clear and tried again - same result.
So- 'up a creek without a paddle' I guess, unless I've misunderstood some of your wonderful comments.

GenDev
 
Chriss,

Just to clean up the query about TMG app.ini

TMGapp.ini_kbf9gh.png


and PathWiz being able to write to its roaming folder

paths_y7ygcz.png


and my ini file

pathwizini_hkn3k9.png


GenDev
 
gendev said:
So the result of your code is
lcPath+' does not exist or is a hidden or system directory.'

For which lcPath?

This does not help, gendev. It would be easier to post the screenshot of the Messgebox.

gendev said:
I substituteg

IF DIRECTORY(lcPath,1)
SET DEFAULT TO (lcPath)

Have you read what I wrote?
quote myself said:
So it's not just better to use Directory(lcDir,1) always, because if you would want to copy from or into the hidden directoy itself, VFP would respect the hidden status and decidedly fail, even if files and directories exist just hidden

Seems to me, the path you want to change to is hidden and thus even though it exists, VFP wouldn't write into it, maybe not even re<d from it. Your change to DIRECTORY(lcPath[highlight #FCE94F],1)[/highlight] does only change that DIRECTORY will report the path as existing. For VFP to work within that folder it would need to be unhidden, and you can't change by changing permissions.

Chriss
 
I tested what in detail happens in a hidden folder.

SET DEFAULT TO (hiddenfolder) works without error.
COPY FILE (fileinhiddenfolder) to (backupfilename) also works without error.
And also, both do their job.

So VFP does only respect the hidden attribute in terms of denying the existence of the folder, not working within it.
So what's really the problem with your case, then?

Is it perhaps just your way to verify the existence of the backup file, that's wrong?

Chriss
 
Chriss,

Your results are disheartening on one hand and pleasing in another.
I just can't replicate your results so I'm not sure where to from here.
No matter what I do I cannot get DEFA To - to curdir() to the required folder ( although my folders have the hidden
attribute removed.
I do not see the backup file either so it's not working for me as shown by your code I cut into my program.
Maybe someone else can confirm your results.

Cheers
GenDev
 
The one thing that makes me question now is - of course, how else could it be - about the unknonw lcPath.

If the change of DIRECTORY(lcPath) to DIRECTORY(lcPath,1) did help to go on with my code, then lcPath must be a hidden or system path the DIRECTORY function reports as non existing, unless you force it with ...,1).

I wonder why that would be the case as you want to change directory to the folder that has the INI within it, and that seems to be [tt]C:\Users\bryan\AppData\Roaming\pathwiz11[/tt], not [tt]C:\Users\bryan\AppData\Roaming[/tt].

Why are you showing all details about [tt]C:\Users\bryan\AppData\Roaming[/tt], as it is [tt]C:\Users\bryan\AppData\Roaming\pathwiz11[/tt] that is of interest, isn't it?

Chriss
 
gendev said:
I do not see the backup file eithe
Do you look at the right place? I know, that's assuming you don't knopw what you're doing, but coming back to UAC, a file you write into a system folder can be redirected into somewhere within

Making the backup copy also is just the first step before you change the INI and thereby influence the TMG9.exe

What about verifying the copy by code?
Code:
SET DEFAULT TO (lcPath)
COPY FILE (lcSourceFile) TO (lcTargetFile)
IF FILETOSTR(lcSourceFile) == FILETOSTR(lcTargetFile) 
   MESSAGEBOX("COPY succeeded.")
ELSE
   MESSAGEBOX("COPY didn't succeed.")
ENDIF

Besides that, you still owe some answers to questions.

Chriss
 
Chriss,
As a start today
C> 1 Why are you showing all details about C:\Users\bryan\AppData\Roaming,
2 as it is C:\Users\bryan\AppData\Roaming\pathwiz11 that is of interest, isn't it?

1 Showing PathWiz accessing its own ini file

2 The ini I am wanting to modify is in my fist image above
C:\Users\bryan\AppData\Roaming\The Master Genealogist v9
At the monent I am not sure what other answers you need. I'll look back today and see if I can locate anything.

Cutting your new code into my app I get
Store .T. To lTableError
at the SET DEFAULT TO (lcPath) command.
Where lcPath is the TMG one shown above

GenDev
 
This afternoon I no longer get the error on SET DEFAULT TO (lcPath) command.
tcFilename1 = app.ini
savedfile1 = oldappini.txt
The debugger (see image)passes through with the claimed result as shown. Note the curdir() on the Watch window.
Using wizfile it is clear despite the vfp message no file was created.

error1_sch54x.png

nofile_ly6obd.png


GenDev
 
I'd trust FILETOSTR(lcSourceFile) == FILETOSTR(lcTargetFile) much more than any third party tool.

What are you searching with wizfile - and where are you searching?

Get real, open up Windows Explorer, look into the directoy C:\Users\bryan\AppData\Roaming\pathwiz11
And see if you find the app.ini and the oldappini.txt

Or add this code:
Code:
SET DEFAULT TO (lcPath)
COPY FILE (lcSourceFile) TO (lcTargetFile)
IF FILETOSTR(lcSourceFile) == FILETOSTR(lcTargetFile) 
   MESSAGEBOX("COPY succeeded.")
  [highlight #FCE94F] _dummy = GETFILE('*.txt*)[/highlight]
ELSE
   MESSAGEBOX("COPY didn't succeed.")
ENDIF

If you do this, are you doing this while being logged in as "bryan"? If not, you're trying to write into someone elses user profile. If you want to test how this works for "bryan" you can only test this logged in has him or change to your own user profile for the testing. Even with admin elevation, where you could read and write, the file generated will likely end up not in the users profile but it will be generated and FILETOSTR(lcSourceFile) == FILETOSTR(lcTargetFile) proves that.

If you don't see that file within an already open Windows Explorer you have to refresh the content with F5, if it's not shown even then it's likely generated by redirection elswhere - still FILETOSTR(lcTargetFile) is able to read it in as reading also is redirected to the same place. I already mentioned UAC and VirtualStore. You had not asked back, but you don't seem to know this, although it is also about 20 years old by now, at least 18.

Besides all that, copying the app.ini is just the first step on your journey, isn't it? You then need to modify the ini and start tmg9.exe to react to the changes, i.e. changing the INI does not change anything about an already runnung TMG9.exe process - it'll not read in the ini once more just because you change it and changing it clearly won't retroactively change what has already been read from an already running TMG9.exe

Chriss
 
Here's a small demo qabout how File redisrection and your profiles VirtualStorefolder work:

Requirement: UAC (user access control) has to be turned on. It is by default, so if you don't know what UAC is, it likely is on, you can check it in Windows Control Panel -> User Accounts -> Turn UAC on or off.
Better idea: Go into Windows Settings and via the "Find a setting" search box search "UAC".

Code:
#Define CONTENT 'test'
Local lcProgramFiles, lcNewFile, lcBackupFile, lcVirtualStore

lcProgramFiles = GetEnv("ProgramFiles")
lcNewFile = lcProgramFiles+"\vfpgenerated.txt"
lcBackupFile = ForceExt(lcNewFile,"bak")

If StrToFile(CONTENT,lcNewFile)=Len(CONTENT)
   ? 'File created'
   Copy File (lcNewFile) TO (lcBackupFile)
   ? 'File copied'
EndIf

If FileToStr(lcBackupFile)== CONTENT
   ? 'Copy verified Ok'
EndIf

? File(lcBackupFile)

lcVirtualStore = GetEnv("LOCALAPPDATA")+"\VirtualStore\"+JustFname(lcProgramFiles)

* Files will not be seen here
Run /n explorer.exe "&lcProgramFiles"
* As redirection put them into your VirtualStore folder
Run /n explorer.exe "&lcVirtualStore"

* nevertheless redirection also works when reading from the path where the redirected file doesd not exis:
? lcBackupFile
? FileToStr(lcBackupFile)
? lcVirtualStore+"\vfpgenerated.bak"
? FileToStr(lcVirtualStore+"\vfpgenerated.bak")

If you have questoins about what the oiutputs are for, please ask.

One thing to know and do is in the Windows Explorer showing the Program Files folder, you have to scroll down to see NO generated and copied file, which due to redirection is generated in the PRogram Files subfolder of the VirtualStore folder, which the seconf Windows Explorer is showing. So there you see the effect of redirection. Not only wrintg, also reading the file is redirected. Therefore the last two FILETOSTR() commands actually both read the file from the VirtualStore, even though the backup fiel does not exist at the location of lcBackupFile.

What does this mean?

It means your backup process succeeds, proven by reading in the file copy. That you don't see it, no matter if you use Windows Explorer or your Wizfile tool, because you look at the wrong place.

And why is Microsft doing this?

To keep legacy software working, or software of programmers that think their software should write into folders under system control. MS thereby lets code work without error and it works twoways, when writing and reading.

Are they doing a great service with this? If you ask me, no. Of course legacya software that can't be modified can now still work, but if you have a permission problem like that as a company with your important legcy software of which - unllike in your situation - the developer may not even live anymore - you could also solve that damn problem by giving write permission into the application folder. So it's not a big service. On top of that, change UAC from time to time, turn it off and on, and this redirection doesn't work anymore. Install a software with UAC off and then use it with UAC on, it doesn't work. There are more situations this is unhelpful than this is helpful, if you ask me.

I guess we're at a point where - at least as of today - your backup works, you still don't see it with WizFile, but that's not your problem (anymore). I think you bark up the wrong tree, as you stand in the wrong forrest. So I suggest you get to the bottom of the problem, not to solution but what actually does not work out. After 10 years, wouldn't there also be changes in TMG, maybe your INI key/value changes don't work. I hear you say TMG9.exe ist still also the old software and nothing could have changed? Are you sure it has no self updating mechanism?

All we're doing here is taking stabs in the dark, and that has to change.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top