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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

RDP with no HDD

cfsjohn

Programmer
Sep 1, 2016
64
US
I have a VFP9 app written with framework Visual FoxExpress. My app uses a native VFP database. Over 200 tables and over 2000 views. Basically an accounting app with Point-Of-Sale features.

I have many companies using my app. Each company has it's own instance of my app that resides on one of my cloud servers.

The cloud server file structure looks like this. Each company is a separate instance of my app, each instance with it's own home directory and data subdirectory, etc:
\Company1
\Company1\data\myvfpdbc.dbf
\Company2
\Company2\data\myvfpdbc.dbf
\Company3
\Company3\data\myvfpdbc.dbf
etc.

On the user's local workstation's HDD:
c:\Company1\ws_settings.txt
c:\Company1\Reports

When user click the RemoteApp shortcut on their desktop:
User connects to the cloud using a cloud userid and cloud password (I maintain an active directory for all cloud users)
After connected to the cloud server, my app has built in security so the user sees my app's login screen and user logs into my app. (I maintain user accounts for that "company" in each instance of my app)
When user exits my app, they are automatically disconnected from the cloud about 20 seconds later.
Users never have access to the HDD on the cloud server. They are either running my app or not.

My app uses XFRX to generate reports and if the users wants the report in a pdf, xls, etc, my app sends the pdf, xls, etc to the user's local reports folder (c:\Company1\Reports)

My app has workstation specific settings. For example, in my app, I can maintain the names of a printer for reports (plain paper) and for checks (a dedicated checks printer that holds blank check stock). Users never select a printer from my app. My app knows if they are printing a report and sends the print job to that workstation's "reports" printer. My app knows if they are printing a check and send the print job to that workstation's "checks" printer.

Via settings in the RemoteApp shortcut to run my app on the cloud server, my app can see the users local HDD.
When my app starts up, immediately after the user logs into my app, my app looks for a file on the users local HDD named \\tsclient\c\"+ALLTRIM(JUSTFNAME(SYS(2003)))+"\ws_settings.txt"
This text file contains a guid which uniquely identifies this workstation to my app.
My app can then know the settings for this particular workstation that is running my app, so with regard to my example, my app knows this workstation's printers.

New twist:
I have a new company that will be using my app.
The workstations have no HDD. I understand they are using Citrix and that all workstations are "virtual". I am sure I am not saying this correctly. I have been told that all workstations are using terminal emulation and I believe that means they are all like "dumb terminals".

So, the workstations that will be accessing my app have no local HDD.
Finally my question: What do I do differently so that my app continues to be able to find the local ws_settings.txt file for the workstation that is running my app?

Thanks, John
 
At one of my clients, users working on terminals have dedicated space assigned to their logins on local company server. On each terminal, it is mapped under symbol "H". Users keep their documents there: Excel, Word, etc. I and other software providers keep individual settings of our programs there separately for each user. Changing symbol "C" to "H" in the access paths was no problem for us in code program.

I don't know what kind of terminal system is it and I don't want to know. Some... #@!&^% sick system.
 
I think Piotr is on to something there. I remember diskless "dumb" terminals from way back in the day (they at least were a real computer, but just no hard drive). The login to the Novell network - remember them? - would map a drive to a folder on the server. Sounds similar to what Piotr is talking about. Ultimately, I'd say that you need to find a way to map them to a server folder in one way or another.

Now, as for your setup. It sounds impressive. How many servers are you using? These are Remote Desktop Services servers, I assume (a product that supposedly will go away in 2028). I'm needing to set up something similar, so a little more detail - though not needed to answer your question - would certainly be interesting and helpful to me. And it would be appreciated, if you have the time and inclination.

Thanks.
 
From your description I'm not sure what the setup actually is, but when a thin client has no hdd it will need to boot using a Preboot Execution Environment (PXE) which means booting from network.

You say workstations will be virtual. Well, that means their thin clients are actually unimportant for you, The system as you provide it has to see their virtual machines as the client PC, not their actual thin client. And a virtual PC can then have a hdd, including a C drive, where everything would work as usual.

Not sure I got it completely right, but my impression is they'd use a virtual PC to finally make an rdp connection to your servers and run remote twice, that way.

What I am sure about is that an RDP file is just a text file and will allow you to configure what of the client is shared, in that case not of the actual physical thin client the users sit at, but the virtual PC that makes the RDP connection to you. And if that virtual PC still has no C drive, then I think what Piotr said is relevant, i.e. there will be any other drive letter mappped to some network drive or other. Otherwise I'd wonder about using RDP. Don't you need a Windows client to even use RDP? So their Virtual PC will be a Windows client, no matter what their thin client is. Otherwise you'd (they'd) need something specialised on only running an RDP connection, but then they wouldn't need their own virtual PC, they'd only be a terminal to your remote server. I think they want to run other things, too, so from your persepctive their client is not the thin client hardware without hdd, that's irrelevant to you, the clientt connecting to you is the virutal PC they actually run in the cloud. And that can have a hdd, again.
 
I agree that Piotr has made me think about something. I know that I can and always add this line to the rdp file that runs my app: drivestoredirect:s:C:\; and I am sure I can add additional drive letters like drivestoredirect:s:C:\;D:\; etc Now I need to go back to the IT personnel at my new customer and see what drive letter would be appropriate for this customer site and hope that it is always the same for all workstations. Assuming it is, it should not be any different whether my app looks in c:\ vs D:\ etc. I will do that research and let you know.

WRT, my app in general, per GTGeek88's request, it has taken years to understand all this and I still do not fully understand. Here is what I can tell you briefly:


Like most VFP apps we used to run on a local server (local meaning at the customer site). Workstations had the exe and used a mapped drive to see the data folder on the server. As \you likely know, index corruption was a constant pain and it was slow because the data moved across the network from the server to the workstation. The concept with RDP is all the users are getting a slice of windows on the server, they are running the app on the server and the only thing being moved between the server and the workstation is pictures (the screen). No more data corruption and very fast. Of couse printing is always a challenge. Because the app can see the local printers, the print jobs are simply printed on the local printer or displayed in the app (previewer) using the local printer's driver. The app will get confused when anything changes the default printer so you always uncheck the "let windows manage my default printer" setrting on the workstations. Still it will sometimes (pretty infrequent) get confused. The solution is exit the app, let it disconnect from the server and reconnect and log back in. Not a great solution but I have not had time to find a complete solution. Sometimes we install the printer drivers on the server. I do not like doing that but when you do so, windows can find the print driver more easily and it does help. So this is conceptually pretty simple when you realize the server is like a bunch of workstations in one machine and the users are just remotely connected to their workstation on the server (say that fast 10 times).

So that I can run the app from the server, I have a shortcut to run the app on the server itself. I RDP to the server and click the shortcut on the server's desktop to run the app. So that the app knows whether it is being run locally on the server vs from a user's workstation, I have a different config file named on the shortcut. I will have to put together an example for you on that subject. For users connecting remotely temp files are sent to the windows temp directory in the users folder on the server. When I am running the app from the server I use a TEMP folder under the apps home so using my example structure c:\Company1\temp.

I am doing a lot of disconnected rambling here so I will close for now but I do want to help if I can. I still work 80 hours a week so as it has always been my time is limited. I will put something together and post it as soon as I can.

John
 
From your description I'm not sure what the setup actually is, but when a thin client has no hdd it will need to boot using a Preboot Execution Environment (PXE) which means booting from network.

You say workstations will be virtual. Well, that means their thin clients are actually unimportant for you, The system as you provide it has to see their virtual machines as the client PC, not their actual thin client. And a virtual PC can then have a hdd, including a C drive, where everything would work as usual.

Not sure I got it completely right, but my impression is they'd use a virtual PC to finally make an rdp connection to your servers and run remote twice, that way.

What I am sure about is that an RDP file is just a text file and will allow you to configure what of the client is shared, in that case not of the actual physical thin client the users sit at, but the virtual PC that makes the RDP connection to you. And if that virtual PC still has no C drive, then I think what Piotr said is relevant, i.e. there will be any other drive letter mappped to some network drive or other. Otherwise I'd wonder about using RDP. Don't you need a Windows client to even use RDP? So their Virtual PC will be a Windows client, no matter what their thin client is. Otherwise you'd (they'd) need something specialised on only running an RDP connection, but then they wouldn't need their own virtual PC, they'd only be a terminal to your remote server. I think they want to run other things, too, so from your persepctive their client is not the thin client hardware without hdd, that's irrelevant to you, the clientt connecting to you is the virutal PC they actually run in the cloud. And that can have a hdd, again.
Chris, I believe I understand enough to be able to ask the question.

My VFP app needs to be able to read from, and write to, some location on the client.
My customer is telling me that location should be %appdata%
My app allows user to generate reports that are saved as pdf's on the client.
Assuming the name of the pdf is XYZ.pdf, What does the code in my VFP app look like, that would put XYZ.pdf on the client?

At the risk of being wrong about something I feel I should tell you:
My users are accessing my app via RDP (more specifically RemoteApp) and I can see the client by addressing \\tsclient from my app that is running on a cloud server. Normally I would see the client's C drive by using \\tsclient\c\Reports\XYZ.pdf but that will not work because the client's C drive is some sort of "gold image" meaning it is not persistent across logins, so the file would not be retained on the client when the user logs out of my app.

Thanks,
John
 
John,

that all seems right, little doubt. Thanks for pointing out the "gold image" nature of the virtual HDD. Well, so in short the requirement is impossible to be met, as %appdata% is on C:\, and it's not like other profile related system folders like users documents, that can be optionally configured to be on a network share instead of local. So to persist something it must be on a network share for them, which they would need to map in the RDP file.

It'll be a line on the RDP file that'll allow sharing client drives, local or network shares and then you'd use something along the lines of \\tsclient\x\Reports\xyz.pdf
 
Chris, I believe we are getting dangerously close to a solution, but not there yet. Thank you for your help.

When setting up a workstation to access my app, step 1 is to create a folder on the users local C drive named C:\Reports (it's actually something like C:\MyAppsHomeDirectory\Reports but I do not believe that matters for this conversation).
The RemoteApp shortcut can be modified with Notepad. The line drivestoredirect:s:* can be modified to something like drivestoredirect:s:E:\;
Just a note here: My experience is that using the default * does not always work. It works just fine as long as the C drive is available but when you need something besides the C drive, it is better to explicitly say what drive letter.

Until now, my app has always assumed the client's C drive was where the reports folder existed so all my shortcuts contained drivestoredirect:s:* and my app wrote the xyz.pdf to \\tsclient\c\Reports\xyz.pdf The \\tsclient\c\Reports was hardcoded in my app.

Because of this project, in hopes of making my app more likely to be able to handle this new customer's environment, I modified my app. I added a field to "softcode" this path. I set the value in that field to \\tsclient\E\

I modified the RemoteApp shortcut to say drivestoredirect:s:E:\;

I placed the Reports folder on my E drive

I modified my code to use the "softpath" so now my code says <softcodedpath>\Reports\xyz.pdf which equates to \\tsclient\e\reports\xyz.pdf

I tested that. It works for me. So, here is where I believe I am on this issue:

The last question my customer asked me was:
Is it possible to write these pdf's to a user-unique path that will persist between logins, such as %appdata%
Based on your earlier post (Chris Miller), I believe I should tell the customer, Yes, I do need to write the pdf's to a user-unique path that will persist between logins, but that %appdata% would not be such a location. Instead, I need to know what drive letter points to the location of the user's persistent data in your environment?

Does that sound correct?

Thanks,
John
 
s it possible to write these pdf's to a user-unique path that will persist between logins, such as %appdata%
It mkes me think, whether I'm wrong. There are multiple appdata system directories, local app data and roaming appdata. 'And the latter would be persisted as it's not local only. It's also on C but persisted with logging off and persisting the roaming user profile data in a domain server, fro where it's copied to whatever other client the same user may use next time (roaming). GetEnv("APPDATA") is the roaming profile folder, specific to a user: C:\Users\<Account>\Appdata\Roaming.

The recommended usage of that root path is to add your application specific path, so GetEnv("APPDATA")+"\yourapplication\Reports", not directly GetEnv("APPDATA")+"\reports".

There is one disadvantage of that, though, as the persisting of that roaming profile files depends on the user logging out the session. So if you want files like your report PDFs to immediately be stored persisted in a network share you'd negotiate a drive mapping like drive X: being a network share mapped to drive letter X and have user specific folders in there, like you have for companies.

Then it would just be a matter of data privacy policies and realising them with folder access permissions to arrange these user specific network share folders in a way only the owning user can access his documents or the documents could be available seen for everyone, just like in a central database on a share, still separated by username to avoid name collisions and overwritng existing pdfs.

Note to myself: I made the same wrong assumption about %APPDATA% being local appdata back in another thread, and should better remember this is the roaming appdata. It has the disadvantage of needing disciplined users logging out of their session.

If your customer still wants to handle it with roaming appdata, make them aware of the issue this could lead to missing files. They might arrange an automatic session ending in a way this always works, no matter if their users are disciplined or not. Then there is a less straight forward but more specific way to address roaming appdata by a known folder id FOLDERID_RoamingAppData (See https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid and https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath).

Whether you use %APPDATA% or the API function SHGetKnownFolderPath you do this on the RDP host and need to find out the value for the client. That's another reason I'd rather negotiate a network share to use instead of the roaming profile. %APPDATA% on the RDP host usually will be the same as it is on the client, so you can just replace C:\ with \\tsclient\c and know the same path on the client as on the RDP host session. But I think the username on your RDP host session could also differ in other setups, where an application user is defined for the RDP host. Which would mean what you'd store on %APPDATA% directly, not translated with \\tsclient UNC path, would also be stored in a user profile, but not within the same user, in that case.

On the other hand the latter also means, that if the RDP host session is a user session of the same user, there would be no need to translate C:\ of %APPDATA% with \\tsclient\c, the roaming profile data meachnism then also acts on the RDP host itself.

To ensure it works, just try it out in multiple ways and see what works easiest. Using the RDP host %APPDATA% would mean it's then up to you to end the RDP session disciplined with a logout that persists the RDP host roaming folder to the server storing user profile data.

A simple test run could store two files like this
Code:
STRTOFILE('appdata',GETENV("APPDATA")+"\yourapp\appdata.txt")
STRTOFILE('appdata translated with tsclient',STRTRAN(GETENV("APPDATA"),"C:\","\\tsclient\c\")+"\yourapp\appdatatsclient.txt")
Then let the user log off and restart to see which files you see in the next session.

Then repeat with other filenames and/or other content stored and test truning off the thinclient without logging off the session, letting it time out and see what you get in that scenario.
 
Last edited:
Chris, I'm not going to tell you I understand all of what you said but I was able to understand enough to use getenv("appdata"). I have that working BUT, now I have run into something I failed to consider. Any user should be able to connect to our cloud server and run our app from any workstation. That is not working and here is why:

If I am on workstation ABC123 and I connect using a userid of PersonThatNormallyUsesWorkstationABC123, getenv("appdata") returns c:\users\PersonThatNormallyUsesWorkstationABC123\appdata\roaming. That works just fine because that folder would exist on workstation ABC123.

Here is what does NOT work: PersonThatNormallyUsesWorkstationXYZ456 needs to run my app from workstationABC123. PersonThatNormallyUsesWorkstationXYZ456 connects. getenv("appdata") returns c:\users\PersonThatNormallyUsesWorkstationXYZ456\appdata\roaming. That folder does NOT exist on workstation ABC123.

I believe the question becomes something like: appdata is more or less user specific. Is there a "workstation specific" environment variable?

I know I can user getenv("clientname") to get the workstation name. I guess I am looking for an app specific folder on a workstation. No matter which user is connected, my app should write any pdf's that get generated by my app, to this app specific folder on the workstation. Of course all of this has to be a location that is pewrsistent meaning when the user logs out, the pdf's are not lost.

My app has always written pdf's to a app specific folder on the client because when I setup a workstation to access my app the first step in that setup is to create a C:\<MyApp> folder on the client's HDD. That doesn't work for this new customer because C:\ is the "gold image" and not persistent. OK, that is where appdata came in. The concept is OK but it is user specific and that is NOT OK. Warning: The answer could be really simple and I just do not see it.

Any help greatly appreciated,
John
 
User unsepcific appdata is not called appdata, it's called Programdata, known as both GETENV("ALLUSERSPROFILE") and GETENV("PROGRAMDATA")
It's not roaming, though.

There is one other user unsepcific folder, the AllUsers profile folder. It has no AppData subfolder, though and thus, again, no Roaming folder.

If you mean that on the application host computer, any local drive folder is that - user unspecific and the same for all users, i.e. C:\Yourapp\. It's not on their network, you'd host these files just like you host the application for them. It's inded not illogical, it's one of the advantages of an application you provide in a terminal server, it can have a database shared with all users that's not in the network but local. BEcause all users run sessions on the same terminal server you provide. It only breaks, when you need to server more users in parallel than a single termina server can serve.

Not sure with what you'll get happy, if you do want to store something user specific, it can't be something user unsepcific, can it be? Well, I'm pointing back to your own user specific subfolder structure within a commonly used network share. So \\tsclient\x\username\... It wouldn't need to be windows user name but your own application username.
 

Part and Inventory Search

Sponsor

Back
Top