My question is sort of linked to this existing question
How to deploy a desktop .Net application with custom settings per user
However, I understand the idea of using Application Settings what I can't find information on is, how should I deploy the application settings for different customers?
We have a custom settings system that works just fine, however when the app is first run it needs to know a couple of things, such as Company Name and Application Server. These will obviously differ on a customer basis.
I don't want the user to have to input these settings at first run as in most cases the app will be deployed by Group Policy.
Currently my thinking is to have some sort of setting file in a separate build per customer. Is this the way to go, or have I missed some kind of native support for this idea of "customer profiles"?
EDIT:
More info that might help people grok my question.
This is an enterprise application that consists of a central database and application server, plus 100 installations of a client application. I need to be able to give the client application some application settings that will obviously be different for different customers.
A lot of applications ask you some initial settings at the first start (Microsoft Office, Visual Studio, etc.). So this behaviour is commonly known by the user.
Maybe the problem is more, that these initial settings revive an update of your application. To accomplish this you could save your data in a version independent path within the registry or somewhere below %AppData%.
Also it would be helpful to prefill these dialogs at the first startup, by getting these informations somewhere out of the machine (e.g. Company Name can be get from registry [HKLM\Software\Microsoft\WindowsNT\CurrentVersion\RegisteredOrganization] or as Application Server take the Gateway address, AD Server, whatever most commonly matches).
So in a best case the user will be presented with a already correct filled out form and just has to press enter or he makes only the changes that are necessary, but doesn't to fill out the complete dialog by himself.
Update:
So if the user doesn't know the Application Server path. Who does it? Where resides this information? Maybe you can enforce your customers to provide this information all the same way. Maybe they set some environment variable within the logon script or they put a file with the needed informations on a global accessible place (e.g. where the logon script resides).
If I understand right you want to deploy a pre-customized software for each user.
You could use WIX to create a MSI-package for each customer. You can deliver several user-settings in your customer-oriented msi. You can dynamically generate a WIX-XML-Document based on a data-source where you store your customers.
Is a bit work, but later saves a lot of work. The MSI-creation through WIX can be easily integrated into the build-process.
Given that it's an enterprise environment, have you considered using ClickOnce? We've had success mainly with startup arguments, e.g. http://servername/OurApp.application?environment=uat
It doesn't always scale, but you can pass arguments using GET variables and parsing the resulting QueryString when delivering via HTTP - http://msdn.microsoft.com/en-us/library/ms172242.aspx
You might pass in the settings in the QueryString, or create them in the database, generate a (hashed?) key and build a QueryString unique to that reference (with the added benefit that an inquisitive user wouldn't be able to manipulate the URI and fake a different set of parameters).
Related
Using multiple database connection string in web application web confing and changing the connection string base on the user in app_code file
I am working on a asp.net c# web appliaction where we have multiple connection strings defined in web config with differnet names and differnet databases, where the database name is selected based on the user at login, I have defined a public static sting 'db_name' in app code file (cs) and a public connection string in the same app code and passed the 'db_name' in the name proprty of connection string.
I am facing a issue where when mltiple users login at the same time ,all the data is stored in the database of the latest user logined.
I wanted to know wether the app code file complies evry time a new user login and that complied file is used for other user
I doubt you can achieve this in a production envorment.
App_code will likely be re-compiled if you have a conneciton string class inside of app_code.
In fact, I don't use app_code anymore, since IIS will attempt to re-compile that code EVEN WHEN using a web site application that deploys compiled code.
So, I create a folder called MyCode, and place my class(s) and code inside of that.
But, your case gets MUCH worse. Since if you modify web.config, then IIS will detect this, and not only (often) trigger a re-compile of app_code, but will also do a WHOLE app_pool re-start, and that will blow out all users current session.
This idea of having each user their own database?
Nope, not even close to practial.
What happen after 50 users a and 50 databases, and you NOW want to change a database. Maybe a simple addition of a new view, or stored procedure. What now, you going to modify 50 databases?
You REALLY can't design ANY software, let alone web based software to work this way. I suppose on a desktop, ONE user can open ONE excel file, then close, and then open another.
However, in datbase land, and "espeically" web based?
You already dealing with a so called "state-less" system, and attempts to use mutliple different datbases created for each user?
Nope, not even close to ANY kind of practial design, and it NOT done, and thus even worse, the tools, the software, the system, the design approach?
ALL of your designs will have built around the assumption of a ONE database, and attempts to shoe-horn in some design that out of the blue is going to change the connection strings for one user?
You can't really do this. Each user does not have their "own" copy of the web server. You have ONE web server, and ANY user can post back a single page, and the web server's job is to process that ONE page. That use then might close their laptop, or start browsing amazon to shop. The web server has no clue that user does not exist anymore.
All you have, and ALL your designs must then assume the web server can and will process a incomming page from any and all users.
Boatloads, but beyond boatloads of designs and assumptions will have to work on this concept, and that includes things like user sessions, session management, code management (static class values are actually SHARED among all connected usres!!! - (which is why you can use static class(s) but you can NOT use static classes with variables scoped to that class!!!
As noted, you can and its often for a web site to use and connect to several databases, but NOT on per user bases - it will not work.
You can do this on a desktop, since EACH user has their own computer, own memory, and own software running on each desktop.
on a web server?
You have one computer, one system, and it has to serve "all" users, and things like connections etc. as a general rule are NOT to be "per user", but per "system".
A correctly normalized and correct database design will MORE then take care of each user needs like creating a new project, new tours or whatever.
so I have a bundled software that a client can download and install (using an msi on win machines).
part of this software is a mongoDB database, that stores client info, configurations, etc..
When the software is first installed, it creates an empty folder for the mongoDB, and whenever the software starts, it starts a mongod process (using C#'s Process.Start()): mongod.exe --dbpath <path> --port <port> --quiet.
My goal is to secure the mongoDB database with a username / password that will be known only to my application.
this will help prevent tampering with my client's data from the outside, as well as make it harder (but not impossible, see below) for the client themselves to tamper with the application's data.
The general idea, I guess, is that on installation (or on startup), to create a user with read / write privileges which my software will use to communicate with the database.
So My questions are:
1. How do I programmatically do this? I guess this is the right direction, but I couldn't find much info on the c# driver docs
2. How do I deal with upgrades? i.e clients who installed a previous version of the software, where the database is not secure at all; i would like to create a user with a password in that case as well.
3. how do I store the application user's credentials in my application? in a config file? but that can be read by the client. any best practices here?
versions info- (unfortunately, because of my company's issues, we're not using the latest product versions); mongoDB 2.6, mongoDB driver for .net 1.5.0.
thanks!
P.S. I have read through the security section on the mongoDB website, but wasn't able to find a simple example for the use case I'm trying to implement.. maybe I'm just missing something simple here..
This is kind of an interesting, unusual use case.
First of all, I want to make sure you're aware of the licensing/copyright implications of bundling MongoDB with your software. You should check out the license section of the mongo project GitHub page and read up on the AGPL.
Second, the easiest part of your question:
how do I store the application user's credentials in my application? in a config file? but that can be read by the client. any best practices here?
This goes beyond MongoDB. If a user owns the system that the mongod process is running on, they could just copy the data files and set up a no-auth mongod on top of your application data. You cannot reasonably stop them from doing things like that, so do not count on your application's data to be secure from the client user. Plus, if you install your application code locally, any decently smart and committed person should be able to extract the username and password from the compiled application code. You can make it hard, but not impossible.
Third,
How do I programmatically do this?
Based on what I just said, I'm taking "this" to mean
on installation (or on startup), to create a user with read / write privileges which my software will use to communicate with the database.
not the part about having it be secure from the person who owns the computer it's installed on, because that's not possible. To do this, I'd either package a mini datafile to start the mongod on top of, one that included users set up already, or include a dump that you use something like mongorestore to load into the mongod after you start it up. The first option is way simpler to implement and should not require you to have to take down and respawn the mongod process, so try that - see if you can set up a mongod with auth how you want it and then transplant user info by copying data files. FWIW, I'm pretty sure the passwords are not stored in plain text in the data files (they are salted), so you won't have that directly exposed from the data files.
Finally,
How do I deal with upgrades?
You'll have to take down their mongod, restart it with auth, use the localhost exception to create the users you need, turn off the localhost exception (optional but why not), and then end that connection and start new ones using auth. It's the same process as in the security tutorials, you just have to do it with C# driver commands. Note that moving between MongoDB versions is also tricky as the seurity model has improved over time, so you should consult the upgrade guide for extra things to do to make sure user schema gets upgraded correctly if you are moving a user from a secure 2.6 to a secure 3.0, say.
C# driver connectionstring can accept login credentials for the database.
mongodb://username:pwd#server:port/dbname
for ex
mongodb://myuser:mypassword#mydbserver:30254/mydb
The best way is to store the data in a config file. If you are worried about exposing it, it can be encrypted and stored. Other less likely option is to store in a resource file and reference that as a string.
My Simple C# application contains a settings window. It actually prompts to set or reset password. Currently, I'm saving these preferences using database and displaying it accordingly during next logon.
I wonder if there could be an easy way to make the application remember those preferences when we open it for the next time.
Possible?
There are several ways to save preferences. You can use the built-in settings system through Properties.Settings.Default.yoursetting, you can use IsolatedStorage System.IO.IsolatedStorage, you could simply write a file to the application directory, you could save it in the registry by creating your own registry key. If you want something easy and simple, use the built-in settings by going to the solution explorer, open up the Properties folder and double-click on Settings.settings. Add the settings fields you want and you can access them through Properties.Settings.Default.yoursetting
if it is a normal preference or if you don't really care if someone can just read the user's credentials and use it then it's fine to store it in a config file somewhere. You can also choose to encrypt the credentials and store it some where. However, I would rather use the windows' build in credential manager to store log on information the same way TFS does for example.
"Control Panel\All Control Panel Items\Credential Manager"
storing-credentials-in-credential-manager-service
First thing to do is to have a clear understanding of your settings:
I will summarize how I usually categorize the options of an application.
I call them "DomainOptions", "MachineOptions" and "UserOptions"
DomainOptions are settings that define the behaviour of your application for every user and from whichever machine they run the app. These setting should obviously stored in the shared database and just a restrict number of users should be able to modify them (I.E. the uri of a web service, the shared folder for application data, the fixed tax value required by your local regulations and so on)
ApplicationOptions are settings that define the behaviour of your application when it is started by a specific machine. Think, for example to a machine that has VPN connection and need to authenticate before running the app. These settings could be stored in the app.config or other local storage (avoid at all cost the REGISTRY), but keep in mind that if you need to change these values at runtime you can't write them in the configuration files for the Application section because it is read only at runtime. In this case I suggest to write your own class to store some sort of XML files in your common application data directory (Environment.SpecialFolder.CommonApplicationData + yourappfolder)
UserOptions are settings that every user could personalize like colors, window positions, accessibility parameters and so on. These could easily stored through the configuration files (User section) because they are modifiable by every user. However, if you have also a class to store the ApplicationOptions it is trivial to implement a variation to store these settings in the Local application data. (Environment.SpecialFolder.ApplicationData + yourappfolder)
I'm working on a WPF application right now in C#, and I need to be able to save some images. These images need to be saved into a directory that the user that's currently logged in doesn't have access to without some administrative privileges (essentially, to control the security on what images are being saved to that directory).
How can I set up such security permissions? Is there some directory that I can add subdirectories to with these images inside?
Normally, I would try to post some code in example to what I have. I'm not entirely sure where to begin with this problem, though.
As Andrew already told in his comment you should really best start with a service. This will run under another account (normally System, but you can change this within the control panel). To start with this a service is in the first step nothing more than any other normal process. So to get a connection between the user application and the service you can use any inter-process communication as you like.
The only difference between a normal application and a service is that the service will be started and managed through the service manager and thous needs to derive from ServiceBase. Also maybe this Walkthrough might help you to start.
Default context for all non-user programs is system which it available to you via service programming and you are not familiar with it. A hack would be logging into another account (i.e administrator) and run the program in that context which is not possible on all windows versions and I believe doesn't worth the resources it cost and also is a security risk.
Another solution would be encrypt your application data and store it somewhere.
I have a web app and want to transfer data from client's machines to us every day. Assume there is a common API on every client machine to extract data from. To make this work, I have to create:
An API to receive data from clients - using WCF, seems ok at this point
An application that's installed on client machines
The client app needs to store info from the user (eg username/password to access our API - encrypted with DPAPI). The app needs to run daily (probably with a random Sleep() command so our API isn't overloaded all at once). It also needs to be easy to install.
I've created a console app which talks with the client API and our own API. I've used Visual Studio's Settings.settings with a user scope to save the persistent settings - if parameters are provided then it stores these settings, if no parameters it uses the stored settings.
How can I make this usable for the end user? I'm thinking a separate installer/configuration program that installs the exe file (and its dependencies) and asks the user to enter the settings to be stored (which can also be read by the client app). It would have to set up the scheduled task and also offer the ability to change the configuration (the stored shared variables).
Hoping someone can help architect this solution?
Thanks so much!
I think that your idea about an installer is correct since you will most likely have dependencies or prequisites to install.
However, rather than building the settings logic into the installer, I would recommend that you build a UI for this in your application so that the user can adjust it post-installation if needed.
For example, if the user changes their password, in your current design, the user will have to uninstall and reinstall the app. Also, if the scheduled time is incompatible with some other operations on their machine, then they will need to adjust the time without uninstalling and reinstalling.
You could build the UI and API interface into a single application: just change the behavior (runtime or configuration) with a command line switch (for example, only use a /runtime command line switch for the scheduled task).