How do I specify the username and password in order for my program to open
a file for reading?
The program that needs to access the file is running from an account that
does not have read access to the folder the file is in.
Program is written in C# and .NET 2, running under XP and file is on a Windows Server 2003 machine.
You want to impersonate a user who does have the rights to access the file.
I recommend using a class like this - http://www.codeproject.com/KB/cs/zetaimpersonator.aspx. It hides all the nasty implementation of doing impersonation.
using (new Impersonator("myUsername", "myDomainname", "myPassword"))
{
string fileText = File.ReadAllText("c:\test.txt");
Console.WriteLine(fileText);
}
I have used the Nuget package NuGet Gallery | Simple Impersonation Library 1.1.0 but there are others; search on Impersonation for the others.
Example usage using the interactive login to work with file structures:
using (Impersonation.LogonUser("{domain}",
"{UserName}",
"{Password}",
LogonType.Interactive))
{
var directory = #"\\MyCorpServer.net\alpha\cars";
Assert.IsTrue(Directory.Exists(directory));
}
James' answer below was before Nuget and before he would later have the most downloaded package on Nuget. Ironic eh?
You can impersonate a user who has the necessary rights. There is an article on MSDN that describes how to do this.
Related
I'm making the GUI program that users can decompile/recompile an APK file but compiling won't work correctly becuase the framework file is missing. I'm making the simple framework installer that must be installed on user folder (for apktool.jar). Instead using the path that only works on my computer. i want to make it work for all users.
here is the code i made
File.Copy(#"do-not-touch\1.apk", #"C:\Users\quoc\apktool\framework\1.apk");
You can use the Environment.SpecialFolder Enumeration to get the path like so:
var userDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
Note: Please use ApplicationData and not the root profile, it's rude to fill the user's toplevel profile with stuff.
I have a default application setup created using Visual Studio 2005. When my application is installed, it's only work running as administrator, because some files are written in the Application Folder.
I have found that on Visual Studio 2010 there is a property for change this permission on some folders inside application folder.
How can I allow to my application create and edit specific files inside the application folder without run it as admin?
Here are your options, assuming that you cannot change where the application itself attempts to read/write files:
Change the default installation directory of the installer of the application, to not go inside C:\ProgramFiles, but instead to a folder just off the C:\ drive that has more lax access permissions. This was standard practice in Windows 3.1 and even Windows 95, but these days you can't get a program "certified" by Microsoft as compatible with any supported Windows version unless it installs into the proper Program Files directory. These modern OSes also have the root of the C:\ drive locked down pretty tight so you'd need administrative permissions to install the app (but not to run it).
Create a custom action for the installer which increases the access rights of the program subfolder during installation. Again, Microsoft is unlikely to certify the app if you do this, and this also requires admin permissions to install the app, meaning the average user on your network can't just pull it down and run it.
Install the files that must be altered in the "proper" places (Application Data for user-specific files, Program Data for files pertaining to the software as a whole), and then create shortcuts within the main application folder that point to the files in their accessible locations. The legacy app shouldn't know the difference.
EDIT: Here's a method straight out of the custom actions of the installer for an app I wrote that has a similar "legacy" app, which has to read/write data from config files in a subfolder of the app's "home" directory. The IDictionary passed in is the one you get from the various custom action methods (OnBeforeInstall, OnAfterInstall, OnCommit, etc), so you simply drop this into an Installer class, call it from the handler for the install event of your choice (which must be after the installer has made the file system changes), and call it:
private void SetEditablePermissionOnConfigFilesFolder(IDictionary savedState)
{
if (!Context.Parameters.ContainsKey("installpath")) return;
//Get the "home" directory of the application
var path = Path.GetFullPath(Context.Parameters["installpath"]);
//in my case the necessary files are under a ConfigFiles folder;
//you can do something similar with individual files
path = Path.Combine(path, "ConfigFiles");
var dirInfo = new DirectoryInfo(path);
var accessControl = dirInfo.GetAccessControl();
//Give every user of the local machine rights to modify all files
//and subfolders in the directory
var userGroup = new NTAccount("BUILTIN\\Users");
var userIdentityReference = userGroup.Translate(typeof(SecurityIdentifier));
accessControl.SetAccessRule(
new FileSystemAccessRule(userIdentityReference,
FileSystemRights.Modify,
InheritanceFlags.ObjectInherit
| InheritanceFlags.ContainerInherit,
PropagationFlags.None,
AccessControlType.Allow));
//Commit the changes.
dirInfo.SetAccessControl(accessControl);
}
You could manually change the NTFS folder permissions using Windows Explorer to the Application Folder. However, it would be best practice to read/write to a different folder.
Don't write anything to the application folder (under program files). Instead use the user's home folder, or, if you want to write something that's relevant to all users on the machine - ProgramData.
EDIT:
If you can't change your application code, you should still avoid placing program data files under ProgramFiles if you can. There's one other thing you can do. You can create a folder under c:\ProgramData, and just create a symbolic link to it from C:\Program Files... . That way, your legacy application still finds the data where it expects to find it.
Maybe this isn't possible due to Security implications...
I have a Deployment Package created in Visual Studio for a Win Form. The application references an app.config file locally and allows the user to change the settings in it, through the application.
When I deploy the application and attempt to save the changes I have made, Windows is saying "Permission denied". Is there a command I can run as part of the installation that will give the "Everyone" security permission to my app.config file....and thus allow my Application to edit it?
Thank you.
If you want to be able to write to the app.config file you need to move it to the Shared Application Data directory and modify your application to read the configuration information from there. On Win7 for example:
C:\ProgramData\YourCompany\YourApp\app.config
In C#, to get the common app data directory:
// using System.IO;
string appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
You might be able to use a custom action in your installer to run icacls in order give full access to Everyone:
icacls {Path to App.config} /grant Everyone:(F)
I have an exe (test.exe) which is a 32 bit written in c++ (unicode charset). This exe will perform the restore operation. The steps include:
check outlook installation and load msmapi32.dll
create a subfolder in inbox of the specified user.
importing eml file into the subfolder.
These operations are done using temporary user who has given full access permission.
This exe is executing fine. The issue is when I try to spawn this exe using C# Process.start(), it fails with [MAPI_E_FAILONEPROVIDER] while calling "createstoreentryid".
Any suggestions please.
using (UNCAccessWithCredentials unc = new UNCAccessWithCredentials())
{
if (unc.NetUseWithCredentials(path,
userName,
domain,
passWord,textFile))
{
System.Diagnostics.Process.Start(path);
}
}
The documentation for GetWindowsDirectory says:
TS-Aware applications get the actual Windows directory.
Non-TS-Aware applications get the current user's "private" Windows directory.
So, I am working on a C# class library that needs to be TS-Aware, because I cannot require all apps using this library to be non-TS-Aware. The C# default is to be TS-Aware.
I need to drop INI files into the Windows directory to communicate with a legacy App that is NOT TS-Aware. This works without difficulty in a regular user, but not in a Terminal Services session.
Under Terminal Services:
The Legacy App uses the INI file in the user's "private" Windows directory.
The C# library uses the INI file in the system Windows directory.
I need to:
Detect when running under Terminal Services. I can do this by checking the SystemInformation.TerminalServerSession flag.
From a TS-Aware process, locate the user's "private" Windows directory. I can find no documentation that tells me how to do this.
I think it is always under the user folder in the windows sub directory, so:
System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "windows");