Excel, create an automatic save/change log, how to? - vba

I teach at a university and one assignment i have developed tests some quite specific modelling skill sets in Excel. Because of this, and because all assignments need to be fairly weighted, they end up having largely the same content (in terms of the final code) with different variables so that they are not exact copies - so it is fairly easy for students to take another persons completed file and input their own variables, change a few cosmetic items (drag data locations, colours, borders etc) and hand the work in as their own. i am confident that this is occurring and most of the time i can identify the suspects easily but proving the collusion (not so much detecting it), this is difficult.
I am trying to work out how i can include somewhere on the worksheet (which i will provide as a template) a function that logs the user ID and time each incidence that the save button is pressed (or at a set interval)? This way i can have this info logged in the background (hopefully where nobody can find or goes looking for it) and it will be quite easy for me to see if at any point along the way the student working on the sheet changed - indicating collusion. Of course there are other ways around this, and i am not looking for a fail safe system, just an easy way to catch lazy cheats.
I can find functions that save the last user to a cell, but none that can provide an ongoing log. Ideally, i would like it to be as covert as possible, i.e., avoiding obvious macros would be handy but i can understand this might be a problem. Does anyone have any tricks up their sleeve to help me in my quest to wipe out student copying?

Type sign in Excel's help. Look at digital signatures. There may be some way of using them?
From Help
After you have installed your digital certificate, you can sign files and macro projects.
When you digitally sign a file, you certify that the information in the file is valid and that it has not been modified since the file was signed. As long as a file is unchanged, reviewers can attach signatures to it. You might use a digital signature with important files. When you digitally sign a macro project, your digital signature says that you guarantee that the project is safe. Just as signed files remain signed until the file is modified, signed macro projects remain signed until the macro code is altered.
Or perhaps turn on track changes and make an initial change yourself.

Related

VBA to automatically print page ranges of a PDF

At work, attached files size to email is limited to 10 Mo and because of many reasons :
Outlook is the only way to share files
I can only use the programs already installed
I am trying to create a VBA macro to :
automatically split PDF bigger than 10 Mo by printing them into smaller files
merge them on the other side
I know it is far from ideal (and many tools exists to do it), but I have no other options.
So far, it seems that I can only use PDFCreator and Adobe Reader for this task, as no other helpfull tools are deployed on my PC (mostly Office)... and I can not figure a way to use command line for printing range of pages.
I successfully created a working (very) inelegant macro, based on Shell commands and SendKeys VBA, basically emulating human interaction to print range A, then waiting for the job to be done, them printing range B, and so on... Among the many problems I should now solve :
add protection to take into account machines with different processing power (replace my timings with file creation verification and detect if jobs are still running in the background)
create a robust merging system when receiving the mail
Plus I am very dependant of the software versions installed, and I foresee a lot of issues with software updates/version if this macro is to be used by many people.
So this method doesn't have a bright futur for now, and unless I find an other way to solve this problem, I will probably give up and keep doing this manually (after all, if my employer doesn't provide better tool, I should not be expected to be as efficient as I could).
Have you any insight about how to cleverly solve this issue ?
(Yes, I already told my boss that working like this is a nightmare, but easy file exchange is not the priority).
I managed to solve my problem using 7-zip and its "-v" option using command line : I split my big file into binary smaller files and automatically create new mail with them as attachments.

Getting the value at the end of a long chain of registry entries

This is my first attempt to use the registry in any depth, so bear with me...
I write small VB.net programs that interact with Excel and other programs to produce complex reports. As part of this we sometimes have to interact with a 3rd party DLL. Since this DLL is generally very rare, we took an "always install" policy, and run their installer on first-start.
Well now we have a customer who already has the 3rd party app, so the install fails (as it should). But this leaves me trying to find where the DLL/app has been installed so I can call it properly. Poking about in regedit (causing it to repeatedly crash) I have found it seems to be like this...
Installing the DLL produces an entry called APLW.WSEngine in HKEY_CLASSES_ROOT, as well as an apparently identical copy in HKEY_LOCAL_MACHINE\SOFTWARE\Classes\. Those entries both contain a CLSID which can be found in HKEY_CLASSES_ROOT\Interface\[the key]\TypeLib as well as entries for a variety of sub-parts of the install. I also find it at HKEY_CLASSES_ROOT\TypeLib\[the key], and here it has a key called \3.0\HELPDIR\ that contains the directory I'm looking for.
So...
What is the minimum number of calls I need to make to find the value in that HELPDIR key, or get Nothing or "" if any of the keys doesn't exist. In the end I either need that path, or nothing if the software has not been installed. Currently I'm making repeated calls into the reg to look up each entry and key in turn, but I suspect there is a way to chain them?
To make things slightly more complex, that \3.0\ in the path may change, the actual value is in the Version key in the original CLSID entry. If there is an easy way to add this I'll use it, but since we only work with 3.0 (AFAIK) it can be ignored.
Maybe 1. Maybe more. Don't know, this was not a very typically laid out question (which is probably why you got down voted), but I'm going to assume that you are more of a numbers / reporting person than a software engineer. So proceeding with that assumption, I will try and be helpful instead of pointing out any breaches of etiquette and provide you a couple resources that may help.
For starters, how to read a registry value:
https://msdn.microsoft.com/en-us/library/xz88758e.aspx
Secondly, the full tech spec on the Registry class in vb.net:
https://msdn.microsoft.com/en-us/library/microsoft.win32.registry(v=vs.110).aspx
Both give plenty of samples that should aid you along your way. But keep in mind that in certain situations and certain computer setups, these sorts of registry calls might require you to elevate your UAC permissions, if you run into such a case, you can try this resource, which covers in some detail how to make your applications UAC aware:
http://www.codeproject.com/Articles/17968/Making-Your-Application-UAC-Aware
I hope this helps, and good luck!

Secure data in VB.NET?

My VB.NET application has a very important boolean variable. I need to be able to save it "somewhere" and read it back in the future (even if the application is closed).
Currently, I store the variable as a .bin file somewhere. But I fear that the user can simply grab the file and do some magic to edit the value.
I need to make this value completely unavailable from the user's eyes. Or at least, make it impossible to edit. What is the best way to hide such value?
I managed to store the variable in my online MySQL database. But honestly, that doesn't work very well for my purposes. I need to store it locally...
Any ideas?
Theoretically, you can never hide this variable at all. However, you can make it harder to find or read. To know how to hide the variable, you must first know some common ways of retrieving it.
Typical problems and solutions
How others could theoretically retrieve your variable value
Decompiling your program with a single click using .NET Reflector or any other .NET Decompilation program.
Analyze the memory of the PC while the program is running, and retrieve the value from there.
If your value was saved in a file, the user could easily find it by analyzing harddrive IO activity through a hook or a dump comparison.
If your value was saved in the registry, a simple registry hook or registry dump comparison tool could figure out where the value is stored.
If your value is encrypted, method #1 (decompiling the program) could be used to figuring out how a decryption could be done.
Solving the possible issues above
A general obfuscation program can be used to make it harder to decompile applications. For this, I suggest SmartAssembly. Other than that, there's a tool called Spoon Studio (previously called PostBuild) which will recompile your application into assembly code (and also make it run without the .NET Framework installed).
The SecureString class could be used to make it harder to find and decrypt the value while it's in the memory. This class also cleans itself up after usage, but is generally slightly slower to use than a normal string.
Storing things in a file is not nescessarily a bad idea (even if people can sniff file activity), since you can always store the variable in a non-pretty way. For instance, you could have a file called IsFullScreen.bin, that contained the value of your boolean variable (1 or 0, or true or false), even though it has nothing to do with full-screen rendering. This would make it a bit confusing, but also not very pretty programming-wise.
For the registry, everything in solution #3 still applies.
Encryption is not a bad idea either, and it is hard to decrypt some encryption types (for instance public/private key encryption if you have a server), or hashing (such as MD5 or SHA1).
In your scenario, could you store the value on a server instead?
So to summarize ...
You can't protect your application entirely. But you can use some of the solutions above (or combine them) for a better protection making it harder.
Of course, premature security is bad. If that boolean isn't VERY important, then some simple encryption would be fine too in my opinion.
There's more ...
Edit 1
I just noticed that you've commented on your own answer saying that the file should not be "valid" after copying it to another computer and reading it from there.
If that's the case, you could use some key-based encryption such as XOR encryption, and then use the MAC-address of the PC or the motherboard serial number as key for that encryption.
Being on the computer that the file was created on would then be needed to read the file as well. If you're interested in this, add a comment and I'll give you a code example.
I would store it in the registry in a non-obvious way. For example, make the name of the registry entry appear to be important and store a random numeric value then ensure it ends in 0 or 1 or contains a 0 or 1 embedded at a fixed position in the number.
You can then read the value from the registry and extract the 0 or 1 from the appropriate location.
Encrypt the value before storing it. Use .NET Cryptography Model. For more on how to implement something using that model see

How to implement an NSTextView that performs on-the-fly markup to RTF conversions

I'm trying to build an NSTextView that can take "marked up" input that is automatically translated into beautiful RTF-style text while the user types.
The idea is to let the user enter text in "plain text" format, but to "beautify" it on the spot, e.g.
H1 A quick list:
* first item
* second item
would be translated into a first line with a header font, followed by a bulleted list.
I have found plenty of potential ways of doing this, but the Text System is incredibly complicated (with reason) and I don't want to start "cooking my own" if there is already something suitable built-in. BTW I would be happy with a Snow Leopard only API.
The first thing I thought of was "data detectors", but I can't find a public API for doing this.
Having reached the end of the road with that, I turned to the new "Text Input Sources API". This does all kinds of things, but the "data-driven input methods" section of the WWDC 2006 presentation "Take Charge of the Text Input" seems interesting in my context. Beyond that single presentation slide however nothing seems to exist anywhere, so it's a bit of a dead end again.
Finally, I had a look at the NSSpellChecker class which is also supposed to offer completion features and automatic corrections.. but I'm not sure how this could be re-purposed for my requirements either.
At the moment, I'm tempted to just re-parse the entire NSTextStorage manually and make the changes myself when the user stops typing.. but I'm sure there are cleverer heads around this forum..
Any advice or pointers in the right direction would be greatly appreciated.
Neither data detectors nor the spell checker are appropriate for this task. Assuming you're just looking for a way to pass the input to a parser/formatter you already have, interfacing with the text system isn't too difficult. You're on the right track with handling the editing to NSTextStorage.
Along those lines, there's no need to re-parse the entire thing when the user stops. The text system sends you the modified range and gives you the opportunity to act on those changes (and even reject them out of hand). Since all changes funnel through this (typing, pasting, dropping...), this is the point where you want to intercede.
Because you're dealing with headings and bulleted lists, I'd get the enclosing paragraph of the modified range. This gives you a nice, round unit of work that is easily discovered and perfectly fits what you're trying to accomplish.
Good luck!

Encrypt resources in Cocoa app?

I have a shell script stored in the resources folder of my Cocoa app. If used improperly it could be dangerous (even though I have taken precautions to reduce exploits, such as using the absolute path to commands) so is there any way to encrypt the script in binary format, then decrypt it when it needs to be used?
Thanks
It seems as if your concern is about people getting write access to the script and modifying it to run arbitrary code. You could keep a checksum for the script in the binary and compare that with the checksum of the script before you run it. Now, how do you stop people from editing the binary too? Code signing. In fact, if you keep the shell script in the app bundle then editing the script will break the signature of the bundle anyway.
This does not make a lot of sense. If an attacker has access to edit this script file, then they likely have access to edit any number of files, your application is less likely to be a security risk than any number of other things would be attacker could do.
No. If the user will decrypt it to use it, then she can see (and intercept) the clear text at some point. If you think you have "shell-like" things to do, do them in C/ObjC... This can be your friend.
What you're asking for is essentially DRM. A different purpose (“security” instead of thwarting copyright infringement), but the same approach, with the same problems.
In order for the user to be able to normally use the (music|video|script), they must be able to decrypt it. You would do this for them under only the right conditions in your (player|app), but that doesn't matter: no matter how well you hide it, you still have to provide the user with all the technology and keys necessary to decrypt the (music|video|script), so that your (player|app) can do that.
And then, since the user has all the technology and keys necessary to decrypt it, an attacker can and eventually will uncover them all and decrypt the (music|video|script) on their own.
I second Massa's suggestion of switching away from a shell script. This doesn't completely eliminate risk: If an attacker can gain access to write to your shell script, they can gain access to write to a Mach-O executable just as easily. But editing a Mach-O executable is not nearly as easy, so you are at least raising the bar that way.