I'm trying to learn how to be better at storing my variables outside of the current application in which I'm working. I mostly work in building add-ins for applications such as Excel's VBA and DraftSight's AutoLisp, and most of my work doesn't require me to store anything outside of these applications. There have been a few insistence where I've needed to store settings outside of these two applications.
To help narrow the scope of what I'm asking, I'm wanting to learn about storing application and add-in variables in the Windows OS, for personal machines.
Questions
Where should variables be place in which directories? Categories would be helpful.
What file extension(s) should be used to save the variable information?
If a variable contained sensitive information, how and where should that information be stored?
If an application lacks a dedicated place to store add-in files for itself, where should the add-in file be best placed?
Store important per-user data in %appdata% and unimportant data in %localappdata%. The Shell.NameSpace scripting method should let you access these in VBA.
You can see a list of all the special locations on MSDN. Simple settings can be stored in the registry instead.
You get to decide the file extension.
If you have proper access to the Windows API you can call CryptProtectData to store encrypted data.
Related
Is there a way how to effectively determine the number of accesses to a specific file and the process which accessed it without storing the access info by a 3rd party software? I'm looking for something built in inside the linux-based operating systems. The date of the last change is pretty obvious but I need information at least on how many times it was accessed since the creation of the file.
Can anyone shed some light on this file accessing information? Is it stored somewhere?
No, it is not stored. That would be a very odd feature.
You can monitor access to a file and count what you need yourself.
You can write your own program doing this with inotify. Here is a rather nice introduction.
Another option is using Linux audit subsystem. This way you'll set up rules telling the kernel which files are you interrested in, and later you'll be able to check logs to get whichever statistics you need. Here is a short tutorial.
My application currently writes files to its installation directory which means Program Files isn't a valid option (I know this isn't ideal). But I would also prefer my installer (Inno) not to require admin rights i.e. no UAC; I think Google Chrome does this.
Which common location would make sense to default to with both these restrictions in mind?
If you really want to make a per-user installer that does not require admin permissions, the correct settings to use are:
[Setup]
PrivilegesRequired=lowest
DefaultDirName={userpf}\YourAppName
Note that (addressing Glytzhkof's concerns) this is a local folder, not a roaming folder. If you want settings to roam then you will still need your application to keep them in (your language's equivalent of) the {userappdata}\YourAppName folder. Regardless, the user will have to separately install the software on each machine that they intend to use it on (but this is typically the best option anyway).
Some of the downsides of making a per-user application are:
You cannot use admin permissions when installing. In particular this means that you cannot install many other components (runtimes, libraries, etc) that you might have wanted to use in your application. You also can't use features like regserver and restartreplace. (This doesn't necessarily mean that you cannot still use these components, just that it's a larger hassle if the user does not already have them installed.)
If a single machine has multiple users (common for families and in some workplaces) then they will have duplicate independent copies of your application, which have to be individually upgraded by each user. This particularly annoys IT departments as they prefer doing central upgrades, and if your app is large it may waste disk space.
If the reason you don't want to make a normal {pf} based application is simply that you want to be lazy and store settings files in the program's folder, then it's probably better overall to rethink this decision. It's not hard to do it "right".
There are basically 3 types of files: 1: user data, 2: application settings, and 3: binaries. Plus a few exceptions. I assume Harry is suggesting to write to a user's application data folder with configuration and settings files, and not the whole application. Don't ever put binaries or data here, but do save settings files here.
The whole concept of "roaming files" is a bad idea in my opinion. It clogs your userprofile and increases logon time on each computer and causes all kinds of synchronization issues when people leave multiple machines logged on simultaneously for weeks at a time. The whole roaming concept works only in theory in my opinion - but it depends on user discipline and application quality in its data management. Rarely edited and mergeable files can work, if the application is good. I have seen it work well for spell checker custom dictionaries and similar. The real solution is client/server applications with back-end databases for the purpose of persisting settings. Everything else will eventually fail - if it's a light weight app that might not matter.
User data should be saved to the "My Documents" location only. and only a few configuration settings should roam. If a network is set up to allow "My Documents" to roam, the system administrator should be shot immediately :-). It must be a server share accessible regardless of the computer the user is logged on to.
I've flown off the handle here and answered too many questions you didn't ask. Just hate seeing people head for problems they might not know about. If you have a super small application that is basically "portable" as we call it in deployment. That means an application where you can run off a single folder on a USB stick, then save everything in User data, and keep the application small and lightweight with a single settings file and a binary. No UAC or admin rights should be needed.
I'm working hard on making my product work seamlessly on Windows 7. The problem is that there is a small set of global (not user-specific) application settings that all users should be able to change.
On previous versions I used HKLM\Software\__Company__\__Product__ for that purpose. This allowed Power Users and Administrators to modify the Registry Key and everything worked correctly. Now that Windows Vista and Windows 7 have this UAC feature, by default, even an Administrator cannot access the Key for writing without elevation.
A stupid solution would, of course, mean adding requireAdministrator option into the application manifest. But this is really unprofessional since the product itself is extremely far from administration-related tasks. So I need to stay with asInvoker.
Another solution could mean programmatic elevation during moments when write access to the Registry Key is required. Let alone the fact that I don't know how to implement that, it's pretty awkward also. It interferes with normal user experience so much that I would hardly consider it an option.
What I know should be relatively easy to accomplish is adding write access to the specified Registry Key during installation. I created a separate question for that. This also very similar to accessing a shared file for storing the settings.
My feeling is that there must be a way to accomplish what I need, in a way that is secure, straightforward and compatible with all OS'es. Any ideas?
Do you have to have it in the registry? If not, put it into a simple file, writable by everyone. Writing to HKLM requires additional privileges for a very good reason.
I'm new to here (otherwise i would've left a comment) and i'm not a windows guru, but...
imho the premise is wrong:
there's a reason if a non-elevated user cannot modify registry keys or directories read by all users (like Users\Public by default)
i think that allowing any users to modify a small set of global application settings may be disruptive for the experience of the other users that didn't expect their settings to be modified
on the other hand i don't know your use cases...
could you please specify why all users should be able to modify these settings?
and if indeed all users have to be able to do it... why can't you make these settings user-specific?
I've inherited a Visual Basic 6 application that accesses a database directly, and I intend to rewrite it in Java.
However, something I NEED is the database user+password, which I believe is hard-coded into the application's source.
Unfortunately, I don't have access to it's source.
How could I retrieve the DB password? Is there a way to de-compile VB6 into some half-understandable form at least? or should I just log on and sniff it from my own PC?
I'd agree with MicSim that the DBA would be the person to ask.
However if you want to hack in to the source, you might have some luck just opening up the DLL (or EXE? OCX?) in a hex/text-editor and having a look through. If the credentials are really hard-coded into the application, presumably they're stored as strings... and I've noticed that strings tend to get stored in the assemblies created by VB6 in clear text.
Goal
Let me start with my final vision of what I'd like to be able to do first: In Windows, I'd like to be able to use a global keyboard shortcut that I define (say, Ctrl+Alt+C) to copy the full path and filename of the open document in the foreground application to the clipboard.
This would be useful to, for example, be able to subsequently paste the path & filename into an "Open File" dialog in an email client to attach that document to an email, without having to manually browse to the target document in the filesystem.
Specific Question
Now, the specific part of how to do this that I'm interested in how to implement is: How can I get the path and filename of the current "open document" of any arbitrary currently-running Windows application. (If this can't be done with any Windows application, then the next best thing would be for this to work with as many applications as possible.)
Obviously, this wouldn't apply to some applications that don't necessarily have the concept of a "currently open document" that corresponds to a file on the local filesystem, such as an email client, an IM client, or (usually) a web browser.
Application-Specific Solutions
I'm aware that it's possible to write application-specific solutions to do this. For example, the following MS Word VBA subroutine will copy the filename and path of the open document in Word to the clipboard:
Dim myDataObject As DataObject
Set myDataObject = New DataObject
myDataObject.SetText ActiveDocument.FullName
myDataObject.PutInClipboard
However, what I really want is something that will work for any of the applications on my system (or, again, for as many of them as reasonably possible) without having to try and write an application-specific solution for each one.
Idea: Recent Documents Folder
One idea: Could the Recent Documents folder (and/or its underlying Windows APIs) somehow be leveraged to help with this? It seems to have information about the same concept of "open documents" that I'm interested in here, that apparently applies across various application types. (Looking at the contents of the Recent Documents folder on my machine, I see entries in there that were apparently made for documents that I opened with various applications including MS Word, MS Excel, Eclipse, Adobe Acrobat Reader, Paint.NET, TOAD, and Notepad2.)
Preferred Solution Language
I'd prefer solutions in C# or C++ code, but I'm open to any suggestions for how to go about doing this, regardless of implementation language!
Windows 7?
Update 11/2009: Now that Windows 7 is widely available, I figured it might be worth coming back to this question and asking: Does Windows 7 provide any new APIs, or any other mechanism, that would help with what I'm trying to accomplish here?
The best you could probably do is look at the recent documentation registry keys, and get the list of most recent documents. Some sample code for working with this data is in this CodeProject article. This is saved in:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs
However, this isn't going to show you whether a document is currently open or not. You could potentially check the title of all open applications, since many applications put document names in their window titles, but this is not a requirement, and many applications do not do that.
There is no mandatory mechanism for an application to specify its open document, so this is not generically possible.