Detect machine change - c#

I'm developing a small tool that is going to be distributed via executable.
The first time it is executed I want a tutorial to be displayed. As users are supposed to copy/paste the tool to theirs coworkers it would be nice if I detect that the machine has been changed and display the tutorial again for the new user.
If I could identify the machine ID somehow I could store it (as a setting for example) and compare it at startup in order to display or not the tutorial.
Is there a way to identify somehow the current machine?

Have a look at LocalStorage - which basically stores information per user. Write a small file on startup und check for it every time. If it's there, you know the user otherwise he is new.

The Process Class has a property which indicates the machine name.
Process.GetCurrentProcess().MachineName
Edit
Or get the machine name from System.Environment.MachineName
(thanks to Andreas Niedermair for mentioning it)

Related

C# Change File Location For Next Time Program Runs

I am relatively new to C#, however I do have some basic knowledge of code from courses in high school and university. However, there is one thing I have not been able to figure out over the years. I am currently making a Form Application for a database system that stores information in a List using Visual Studios 2010.
On my main form; when the save button is pressed, the information is then serialized into an XML file. When the information is loaded, the information is then deserialized and put into the List for use in the code. All this is working correctly.
This process of saving and loading is done based on a string which contains the file path. This string is the location of a folder on my desktop (I put it there for easy access), and I am able to change the string in the code to basically move where the information is stored.
However, I have a separate "Admin" form which is able to change this file path string. When the user clicks the button to change the file path, I get the input from a text box, check its formatting, move the current file to the new location and update the location for the save method so changes can be saved before the program is closed. From there, the program reacts the same way as if I had changed the string from inside the code.
The problem occurs when I close the program. I do not know how to tell the program when it runs again that the location has been changed from the default and look for the file in the new location. The program reacts just like the file was missing (like it should) when it looks in the default location.
So basically, how do I tell the program that the save location was changed from when it was last run so it knows to load the info from a new location?
I have tried looking for an answer since high school (about 2 years ago) and have not found a solution. As a result I usually just keep the save location as the default (which I set it to) and don't try to change it. But this time, its important that the save location can be customized. My experience with Visual Studios is limited, as everything I know is from messing around with the program and looking up stuff when needed.
If needed, I can post snippets of my code. Thank you in advance!
It seems like what you really want is to save some user-defined settings for recall at run-time. Here is a MSDN link describing some basic conventions for storing / retrieving these settings.
https://msdn.microsoft.com/en-us/library/bb397750(v=vs.110).aspx
A *.config file would suffice (depending on the scale of the application).
Otherwise, you may want to go down the route of storing these settings in a database (if the scale is rather large, or if user-authentication is required for the application).
Here is another previous question dealing with this same subject (regarding App.config files):
What is App.config in C#.NET? How to use it?
I recommend using a config file where the .exe is, and write the location there, then read it in on program startup.
In particular .net provides this class which can manage your config file for you (assuming you have an app.config in your solution, otherwise create one)
https://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.appsettings(v=vs.110).aspx

Where is the correct place to store my application specific data?

I'm developing a small C# Winforms game and one of the things I'm wanting to do is save application specific data. However, I'm struggling a bit to understand the correct place this should be stored.
As far as I can see there are several types of data an application might store and accordingly different places for it to be held:
1. Application properties
- Settings such as where the application stores it's data, who the last logged in user was, the default window size, position etc. Is this information suppose to go into app.settings, or perhaps into the registry?
2. Global application data
- This might include sprites and other game assets that are used by every user that runs the application on this machine. Where would this common data be stored? It's worth noting that in my particular case this data will not be provided with a default install and users will be allowed to add their own game assets which should be then available to any other user on the same computer.
3. User specific application data
- This would include a users saved game files, their specific application preferences and their profile information. Where should I be storing this?
Ideally I wish my application to be compatible with Windows XP, Vista, 7 and of course the upcoming Windows 8 - I don't know if this changes the methods but hopefully it will assist with providing advice.
This is my first foray into this kind of development and I would appreciate some 'best practice' advice.
Question 2:
I suggest using a subfolder in Environment.SpecialFolder.CommonAppData (maps to C:\ProgramData on Windows7 by default). This is a hidden folder.
Question 3:
Put those files into Environment.SpecialFolder.AppData(maps to C:\Users\[USERNAME]\AppData\Roaming by default, hidden folder), if you expect that the user does not intend to backup / modify those. Some games also put their save games into Environment.SpecialFolder.MyDocuments, probably because it is easier for users to find them there.
Example code:
var directory = Environment.GetFolderPath(Environment.SpecialFolder.AppData);
using (FileStream fs = File.Create(Path.Combine(directory, "myAppDirectory", "myFile.txt")))
{
// write data
}
For a complete list of special folders on Windows follow the link
SIDENOTES
Users are allowed to move around those directories, so make sure you use the code provided above
There is a bug in Windows 7 x64 regarding CommonAppData directory and the bug gets more severe in Windows 8 x64 CP. I've blogged about this: problems after moving CommonAppData directory on Windows 7 x64 and Windows 8 x64
Application properties - Most application data you described should be specific to each user and put in Environment.SpecialFolder.ApplicationData (the %appdata% environment variable). I would generally avoid putting data in the registry as it is hard to find, edit, and fix. If you do not want data to be associated with the user when they are roaming (maybe the files are big or connected to the computer in someway) then you can put it in Environement.SpecialFolder.LocalApplicationData (the `%localappdata% environment variable).
Global application data - I would put global application data in Environment.SpecialFolder.CommonApplicationData ( the %programdata% environment variable)
User specific application data - Same as #1, except when the data is intended to be easily found by the user (e.g. saved games) in which case it should go in Environment.SpecialFolder.MyDocuments, which has no associated environment variable.
As yas4891 points out you can reliably get these folder paths using Environment.GetFolderPath() using one of the Environment.SpecialFolder` values listed here.

How to track directory opening

I'm not sure if the question's title makes sense, and I'm sorry if it doesn't; I didn't really know what to title it.. Anyway, is there a way to make your program track the viewing of a folder?
What I'm trying to achieve: Windows 7 Home Premium doesn't allow encryption. So, I made a folder inside my user directory, and set it to hidden. Although, you can easily find it by changing windows settings.. So, is there a way to make a program pull up a window if the user tries to access that certain folder?
I don't think you can detect the "opening" of a folder.
Instead, you may want to set a FileSystemWatcher to detect any file access to the files in that particular folder.
Hope this helps.
First of all, I have to wonder why you're not just setting an ACL on the directory to prevent access.
However, it sounds like you want to find when somebody is accessing a particular directory. To do this, you enable filesystem auditing, then set the audit ACL to generate audit entries for "List folder". This will cause entries to be generated in the Security Event Log whenever the directory is viewed.
Now you just have to write a program that watches the Security event log looking for entries indicating that somebody has listed the directory in question and take action as necessary.
Well, there is an article on code project describing how you can hook into windows system calls: http://www.codeproject.com/KB/system/hooksys.aspx - it's not simple though (and also not C#) and has the potential to screw with your system but if it might be a fun project to work on.
A simpler option would be: Use a 3rd party desktop encryption tool - not much programming involved here but it might do the job better than anything else.

how to secure my c# program(.exe) for using on one drive only

I have c# program (.exe), I will give it to other people, and want that exe to work only from where it was run the first time, any copy should no not work.
How can I do it?
VERY THANKS
It is not possible. A copy being a precise copy will have no way of knowing that it is a copy and not the original. Therefore at each first run of a copy on any machine the game will start again.
The other approach you can think of is to use activation. Your program will talk to the server online and will report the first run, regardless of whether it was a copy or not. Then at each successive run the program will ask the server if it's been running on the same machine as the first time. If yes, it will run, if no, it will immediately exit.
For this to work, you will need to come up with some kind of machine signature that your program will generate and transmit to the server.
record the exe location in the registry when first launched. and check the location when it's launched next.
you can use CD and protect the CD from copying, and then you should allow your program to run from the CD drive only.
Use click once deployment, it will be difficult for simple user to find and copy from download chache, and than you can write crypted exe location somewhere in the registry and check it every time the program is run
A lot of things that you can do here.
All the suggestions above are good too. Another option is you can have a installer that generates a key that binds your application to the machine installed. Transferring to other machine won't work since it will have a different machine key signature.
sorry its an old thread. Why not read the hard drive serial number (which should be unique) sent it to a server as part of activation and make sure that all that is the same.

WPF/C#: Where should I be saving user preferences files?

What is the recommended location to save user preference files? Is there a recommended method for dealing with user preferences?
Currently I use the path returned from typeof(MyLibrary).Assembly.Location as a default location to store files generated or required by the application.
EDIT:
I found two related/interesting questions:
Best place to save user information for Windows XP and Vista applications
What's the way to implement Save / Load functionality?
EDIT #2:
This is just a note for people like me who had never used settings before.
Settings are pretty useful, but I had to do a whole bunch of digging to figure out what was going on (coming from the Python world, not something I am used too). Things got complicated as I wanted to save dictionaries and apparently they can't be serialized. Settings also seem to get stored in 3 different files depending on what you do. There is an app.config, user.config and a settings.setting file. So here are two more links that I found useful:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/ddeaca86-a093-4997-82c9-01bc0c630138
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/efe370dc-f933-4e55-adf7-3cd8063949b0/
You can use the Application Settings easily enough.
If you haven't done so before just right click on the project and choose Properties. Select the Settings tab. Make sure you chose "User" for the scope (otherwise the setting is read-only).
The code to access this is simple:
forms.Width = Application1.Properties.Settings.Default.Width;
If you need to save it:
Application1.Properties.Settings.Default.Width = forms.Width;
Application1.Properties.Settings.Default.Save();
In the sample above, Width is the custom setting name you define in the Settings tab and Application1 is the Namespace of your application.
Edit: Responding to further questions
You mentioned you wanted to store Dictionary objects in the Settings. As you discovered, you can't do this directly because Dictionary objects are not serializable. However, you can create your own serializable dictionary pretty easily. Paul Welzer had an excellent example on his blog.
You have a couple of links which sort of muddy the situation a little. Your original question is where to save "User Preference Files". I'm pretty certain Microsoft's intention with the Settings functionality is exactly that... storing user skin preferences, layout choices, etc. It not meant as a generic repository for an application's data although it could be easily abused that way.
The data is stored in separate places for a good reason. Some of the settings are Application settings and are read-only. These are settings which the app needs to function but is not specific to a user (for example, URIs to app resources or maybe a tax rate). These are stored in the app.config.
User settings are stored in an obfuscated directory deep within the User Document/Settings folder. The defaults are stored in app.config (I think, can't recall for certain off the top of my head) but any user changes are stored in their personal folder. This is meant for data that changes from user to user. (By "user" I mean Windows user, not your app's user.)
Hope this clarified this somewhat for you. The system is actually pretty simple. It might seem a little foreign at first but after a few days of using it you'll never have to think of it again... it just works.
When running as non-admin or on Vista you can't write to the "Program files" folder (or any sub folder of it).
The correct location to store user preference is (replace MyCompanyName and MyApplicationName with the correct names, obviously)
On disk:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\MyCompanyName\\MyApplicationName"
Or in the registry under the key:
HKEY_CURRENT_USER\Software\MyCompanyName\MyApplicationName
Those location are per-user and they work with non-admin user, several users using the same computer, fast user switching, terminal services and all the other ways people can interact with your software.
If you need a common location for all users then:
It will only work when the user run as an administrator
It will not work reliably on Vista
You have to take care of everything yourself (like two users running the application on the same computer at the same time via fast user switching).
and the locations are:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationCommonData) + "\\MyCompanyName\\MyApplicationName"
Or in the registry under the key:
HKEY_LOCAL_MACHINE\Software\MyCompanyName\MyApplicationName
You can use isolated storage. You can isolate by user, assembly and/or domain.
Introduction to Isolated Storage
http://msdn.microsoft.com/en-us/library/3ak841sy(VS.80).aspx
Types of Isolation
http://msdn.microsoft.com/en-us/library/eh5d60e1(VS.80).aspx
the following seems to be the best option:
Application.UserAppDataPath

Categories