Easily configurable command arguments for a single WinForms executable? - c#

I've created a very simple Windows Form application that uses .NET 2.0 and runs from a single executable.
These single executables will be deployed to multiple users to prompt and collect information.
The catch is that I want to have the information emailed to a specific email address that can vary based on the user the executable is sent to. But, I do not want to rebuild the executable when the email changes.
I can pass command arguments to the executable via command line of course or a shortcut, but I simply want the user to enter information into the form and click submit and have it sent to a predefined email address that can vary based on the user the executable is sent to.
I can bundle the executable with a batch file that runs the executable with the command argument or a config file. But, I want to keep the deployment simple, one file if possible.
Is it possible to do this with an MSI? Am I totally missing something obvious here?
I want the person who is sending the executable out to the user to be able to easily change the email address that the WinForm will send the data to.

if your users are going to be changing the email address you might want to think about a simpler delivery mechanism than a config file, which is fragile in the sense that if a user deletes a > accidentally your app will throw System.Configuration.ConfigurationErrorsException.
One simpler solution than the app config file would be a text file with just the target email address in it, included in the same directory as the app. Your users would have an easier time editing it - or just dropping a new file in. Of course this relies on them having rights to that directory.
Another option is to treat it like a normal setting. Prompt the end user for the actual email on first run, and store it using a user specific setting, i.e. Properties.Settings.Default.SettingName. Then, give your users a UI function to change it on demand.

You could use an app.config file.
Right click the project and select Add->New Item->Application Configuration File
Have something like:
<configuration>
<appSettings>
<add key="UserEmail" value="test#test.com" />
</appSettings>
</coniguration>
And in your code retrieve the config value like:
string email = ConfigurationManager.AppSettings["UserEmail"];
Then you just need to change the value in the config file before sending it to the user, and they can also update it on their own.

One slightly different solution would be to have every instance send email to the same email address, with the 'from' being an address based on the user's Windows logged in account and domain.
Then, create a receiving email account that those emails arrive at with a filter to redirect the mail to the appropriate destination. You didn't say what email system you were using, but Exchange allows this quite simply, for example (as do other systems like GMail).
A more labor-intensive variant on this centralized design would be to create a small web service that your exe queries, with the web service telling the exe where it should send mail to. Again, you'd need a mapping table between Windows user and 'To' addresses.

I'm not sure if I understood your question, but here's my try:
You should check out the properties in visual studio:
Project -> yourProjectName Properties... -> Settings
There you can create variables, which can be either application or user scoped. By using user scoped variable, lets say userEmail, the program lets you save this information according to the logged in user. This way you can save like 20 different emails in this very same executable, depending on the logged in user.
Save the emails according to user:
Properties.Settings.Default.userEmail = "myemail#host.com";
Properties.Settings.Default.Save();
And read them the same way:
string email = Properties.Settings.Default.userEmail;

Related

How do you query the session name and ID number via ASP>

With the command prompt it is possible to query the sessions for a server, as shown here (https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/query-session).
With an aspx file you can get a unique sessin ID by using:
System.Web.HttpContext.Current.Session.SessionID
Also, with an aspx file you can get the IP address by using:
Request.UserHostAddress
Is it possible with an aspx file to obtain the session name (e.g. console, rdp-tcp#10) and the corresponding ID number (integer)? I am trying to integrate an old piece of software that records a terminal/server ID number as part of key to record a user's request in a database.
Background:
I have a file with the extension .aspx from around ~2011 that integrates an enterprise database with software delivered by a web browser (software as a service?). This file contains a call to Request["sessionId"] which I don't think returns anything as the key "sessionId" may nolonger be supportted? For the file logic, all I need to know is whether the user has the "console" session type or not. This aspx file is called by a batch file whenever a user presses one of the buttons on the enterprise database.

DPAPI ProtectData from different users

I'm using DPAPI ProtectData as follow:
var temp = new byte[32]
{
1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,3,
3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4
};
ProtectedData.Protect(temp, null, DataProtectionScope.CurrentUser);
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
Lets assume that now temp look likes:
temp = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,....31 };
I want to execute this code from .exe file and also from my WebService (IIS).
The problem is that if I'm running the code from the exe the current user is MyDomain/Administrator and if i'm running the code from WebService the current user is IIS APPPOOL/MyApp.
How can i solve this issue?
I'm trying to run from the WebService the .exe file as follow:
Process.Start(#"C:\myexe.exe");
But Its not worked from some reason (i have full access to my iis application) and anyway i dont think this is the right solution for this case.
Note: From security reason i cant change from DataProtectionScope.LocalMachine to DataProtectionScope.CurrentUser
If you don't want to use DataProtectionScope.CurrentUser, you could install it as LocalMachine to begin with. Then, have the WebService decrypt it, then re-encrypt it using CurrentUser. Make sure to delete the old value and all its transient copies. In this way, you can take it from LocalMachine and lock it down once the appropriate user is running.
This still leaves the key exposed at LocalMachine level, but for a shorter window of time.
Another solution is to use LocalMachine and use the additional entropy feature with a secret shared between the two executables. This could be an obfuscated value known to the application (no "real" security), or a user-provided password. The user-provided password solution could be more secure but is also more of a pain and more programming overhead.
If the time window between installation and WebService running is small, the first solution may be a good fit.
The problem was solved.
I running the IIS application from local user.
You can find this by selecting the app pool and clicking Advance Settings... under the Actions pane menu. Select Identity and then click the button beside the current user listed. Select Custom account and click Set. Use the format domain\username for the username and enter the password for the user.

IP address from settings is altered during start of the application

I have following problem:
In my application, I have config file, which I use to alter settings needed for standalone installations of the application.
In the settings, there is variable "OffLineServerAddress", which is set to "169.254.2.2"
The application only uses this variable, it is NOT changed anywhere in the program.
The user says (and log file confirms it), that the address, which he uses, is different. It corresponds with address of his virtual box.
Default addres in app.config file is "127.0.0.1"
Apparently, the program uses ip addres of virtual box instead of address from the config file.
I can not think about any way, that this is possible and unfortunatelly I can not post here reproducible code.
I can confirm, that config file of the user has the correct ip address and that the value of the variable is not changed programmatically by the program.
Does anyone know about some way, in which this behavior could happen?
thanks
Got the solution - problem was in saving of default settings.

WPF app writes files/data into "C:\ProgramData" but fails to write into other folders

We have developed WPF application which allows user to select folder path. WPF application writes files/data into this selected path. When we select "C:\ProgramData" as the path, it creates the file and write the data. But when the path is other than "C:\ProgramData", file is generated but data is not written into the file and it seems a permission issue. Can anybody help us in finding out , how we can assign the same kind of permission to selected folder same as "C:\ProgramData" so that it allows to write data into the file. In conclustion what is the extra permission does "ProgramData" has which is not their for other folders?
Note: it only works properly with ProgramData folder.
Whenever your application is launched with standard user rights, it can write to only those folders to which a standard user can write to. E.g. are:
C:\Users\USERNAME\
C:\ProgramData\
D:\
It will not be able to write to folders like:
C:\
C:\Users\SOME_OTHER_USERNAME\
c:\Windows
C:\Windows\System32 etc
For that you either need to disable UAC or launch the application with administrative permissions.
I would suggest that whenever user selects a folder from your application check if you can create a file/ folder in that location before accepting the path.
solution what i can give is let's user select the path after you get the folder path just check whether you can write data to it , see this code
bool HasAccessToWrite(string path)
{
try
{
using (FileStream fs = File.Create(Path.Combine(path, "Access.txt"), 1, FileOptions.DeleteOnClose))
{
}
return true;
}
catch
{
return false;
}
}
#Ganesh is right but you may go with one of the following options:
Run the installer with admin rights, ask user to select target folder during installation and set the permissions to everyone or required groups of users/roles.
If above is not applicable then configure your application to always run under admin account, in that way it will have access to all folder to write data. To configure run as admin user application manifest as explained here:
Turn off UAC, not a recommended approach though.
I had same issue so, I forced installer to be run under admin rights and asked user to create target folders during installation. Used a custom action to set full rights for everyone user group on the target folder. Since security was not issue for us so, it was ok to allow everyone but consider your environment before using this option.

Saving setting to a exe

I have a program which I want to store information in a string. I have been using the Properties.Setting.Default.STRINGname to store the information, which works fine on my PC, and I can see the saved strings (when I go to the settings in the application). But when I take the application to a new PC it losses the strings. Is there a way to be able to edit this information and save it in the app? So basically I need to be able to convert the user setting to application setting, but after the runtime.
var settings = Properties.Settings.Default;
settings.H1 = textbox1.text;
settings.H2 = textbox2.text;
settings.Save();
MSDN explicit says something about this:
Settings that are application-scoped are read-only, and can only be changed at design time or by altering the .config file in between application sessions. Settings that are user-scoped, however, can be written at run time just as you would change any property value. The new value persists for the duration of the application session. You can persist the changes to the settings between application sessions by calling the Save method.
For this, Application setting will never work for you. However, if you are using a User scoped settings it does work, but soon you change the application from one computer to another (as you say you want to) you will loose the settings as that's another machine (another user-scope)...
There are way to continue to have the same settings, you can do, at least 2 things:
use a .config file to save the settings (it's an XML file)
use a service to host the settings and you can read if user has internet access
What you can't do is
using only one executable file, save the settings from computer to computer.
User settings are compiled differently than Application settings, and thus cannot be converted after compilation. Why not compile with Application Settings?
The code you are using should save the user settings. Rememeber that user settings will be saved in the user's data folder. Not in the configuration file where the app was installed (say program files). This is the usual path:
<Profile Directory>\<Company Name>\<App Name>_<Evidence Type>_<Evidence Hash>\<Version>\user.config
See this links form more information

Categories