I have a Windows service, running using the login localhost\administrator. This service is meant to invoke another executable (MyProcess.exe), which is supposed to write some stuff to a log file. The service uses Process.Start() to create the process, like so:
var p = new Process();
p.StartInfo.FileName = processFileName;
p.StartInfo.Arguments = arg;
p.Start();
Problem is, it appears that MyProcess.exe is being denied rights to write to the log file, even though localhost\administrator unquestionably has rights to the log folder. If I run MyProcess.exe from a command line, it works perfectly.
So, is it possible that the process is being executed using a different user login?
Can you think of any other reason why MyProcess.exe is being denied rights to write the log file?
UPDATE: the log file is being written to the local machine, but using a network address, i.e. \\MyPC\LogFolder. When I change the code to refer to C:\MyFolder, everything works fine. It's obviously having a problem with the network address (even though it's local).
What sharing settings do I need to put on the folder so that the local system account can access the file?
If you are using impersonating, than it impersonates a user that can be the currrent or a specified user. if not it will run under the Local System, with the privileges of the local system.
p.StartInfo.Domain = "UserName";
p.StartInfo.Password = "Passw0rd!";
You can get the username from:
Thread.CurrentPrincipal.Identity.Name
I've worked it out.
The problem, as noted in my update, is that the process was addressing the log folder using a network share address, \\MyPC\LogFolder, and when we switched the configuration so that it wrote instead to c:\Logfolder, it worked fine.
So it seems that when you address a local folder, the localhost\Administrator account is deemed to have sufficient rights. But when you go via the network share, you need to present valid network credentials, and localhost\Administrator just doesn't cut it. If you change to use MYDOMAIN\MyUser, it works even using the network share address.
Related
I work with emergency services and they have an application that uses map files to let them know where they need to go and it uses GPS to let them know where they are. We have to update the map files as things change and before I started here they were being done through VB scripts which started to fail. I decided to code my own app in C# to do this which works fine.
I created a package in SCCM 2012 that caches all of the files locally and then it compares the files in the cache to what is on the machine and then replaces any older files. This all works fine but the application they use called MobileCAD locks the files so I have to kill this process and then do the file copy and start the application again. We never know when an emergency happens so this update may start when they are on the road so it is important that it starts the application again as soon as possible. If it does not start the application then the emergency services people may try to do so manually but if core files are being updated then it may not start or cause issues.
I coded my application which uses an app manifest to force it to run as an administrator for the file copy. This application is run through SCCM which uses the local 'System' account to do all of the work and killing MobileCAD and copying files which works great. What I originally found was that it does start MobileCAD but it does so under the System account and the process would be there but it was not visible. I think this is the same problem they were originally having so the emergency services people would need to reboot the computer and wait for it to log back in and then start the wireless service so they could get back into MobileCAD.
To address this issue I did research and found that I could use the ProcessStartInfo in .NET and force it to use another account. As we use an automatic logon for these machines the users name, password, and domain are all in the registry so it was easy to pull it out and inject it into the code. Awesome, looks like it is easy enough so I code it up and sure enough it works perfectly when run under my admin account. In my basic testing everything worked perfectly until I try the same in SCCM, now it fails with the following error message.
System.ComponentModel.Win32Exception (0x80004005): Access is denied
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at UpdateFDM.Program.StartProcess(String processName)
I am sorry for all of the words but I believe it helps if you have a good understanding of the issue and what I am trying to do. I have also hard coded the user information into the code instead of pulling it from the registry but I get the same error. Again, this works fine under my admin account but fails when it is pushed through SCCM and it is only launching MobileCAD that fails.
This is the code I am using for launching MobleCAD, do you see where my issue may lie? I know SCCM confuses it but SCCM basically runs things just as you would from the command line but it uses the local System account.
Thanks for any help.
// Declares the new start instance
ProcessStartInfo process = new ProcessStartInfo();
// Gets the process to start
process.FileName = processName;
// Maximizes the process windows at start-up
process.WindowStyle = ProcessWindowStyle.Maximized;
// Gets the user name from the autologon information
process.UserName = GetDefaultUserInfo("DefaultUserName");
// Gets the domain for the user
process.Domain = GetDefaultUserInfo("DefaultDomainName");
// Holds the password for the default user
SecureString password = new SecureString();
// Gets the raw password from the registry
string rawPassword = GetDefaultUserInfo("DefaultPassword");
// Copies the password in a secure string
foreach (char ch in rawPassword)
{
password.AppendChar(ch);
}
// Sets the password
process.Password = password;
// Needed to launch the app as the logged on user
process.LoadUserProfile = true;
process.UseShellExecute = false;
// Starts the process
Process.Start(process);
// Process started, return true
return true;
I have an application, it first maps a network drive using credentials entered by a user. The drives successfully map, however when it tries to run a program from Process.Start(). I get Directory Name is invalid.
From my research I've read to put the working directory for when using a username/password in the StartInfo. However this doesn't work. The working directory is a mapped drive. Before this starts I do a if (File.exists(w:\folder\filename)..Process.start....
I tried to hardcode the working directory to C:\ but it still failed as it stated it could not find the file.
So when running the Process.Start as another user you cannot use a network path, even though that path was mapped by the same account? Am I forced to download the app locally so the Process.Start can work properly?
Any help would be greatly appreciated.
You are correct, network shares are a per user token. Running a process as another user (or as the same user in a elevated state) causes a new user token to be created and therefor all active shares are "unmapped" from the perspective of the new process.
You have a few options. The first thing I would try using is use the full UNC path instead of a mapped network drive letter. It may just work if you try that (the new user you are running as will need permissions to connect to the share)
If you are forced to use a drive letter instead of a UNC path then write a small loader program that you launch as the new user, have that map the network drive in the context of the new user token, then start up your program that relies on the drive.
P.S.) Using C:\ did not work as the working directly likely because C:\ is a protected folder that only administrators can write files to. If you created a sub folder C:\MyTestFolder\ and set the proper permissions on it I bet it would have worked.
I am trying to create a file on the remote machine but I am getting The "Network name cannot be found". I checked the network path and I was able to access the path from my machine. Could you please let me know what could be wrong?
Here is my code.
using (StreamWriter sw = new StreamWriter("\\\\servername\\TEST1\\TEST\\NEWFILE.csv", true))
{
sw.WriteLine(sw);
}
Go to \servername\TEST1 and give write permission to the user or aspnet (if you have a web application) on test folder and then re-run your program. It will work.
To give write permissions, just refer to this article:
How to share a folder/File
In case it still does not work, replace servername with server IP address and do the same as stated above.
Give the access rights to the user under which this application runs either it is a IIS pool or windows service etc
it is surely a security isssue. you need to give Write access to the remote machine
I'm using EWS to grab file attachments from emails in an inbox, and need to put those files (if they meet certain criteria) onto a network directory path that requires an active directory user/pass that is not the same as what the machine running the service is using.
There's probably multiple ways to attack this. Without having to set that directory path to allow the user/pass that is running the windows service to have rights to read/write is there a way in code that I can set the user/pass before I try and place the files in that path?
In the installer setup of the windows service I've tried the following:
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User;
this.serviceProcessInstaller1.Password = "password";
this.serviceProcessInstaller1.Username = #"\\serverName\user";
when I try and install I get an error about mapping the user pass, so I tried this:
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.NetworkService;
this.serviceProcessInstaller1.Password = "password";
this.serviceProcessInstaller1.Username = #"\\serverName\user";
the installer works, the service shows up and I can start it, but when I debug/attach to the process it throws an exception when trying to write to the directory about access rights.
So maybe I'm not even attacking the right issue/section, as this is probably an active directory issue and something not done in code.
Any suggestions?
What you tried there is irrelevant to your problem.
If you're on windows 7, you may workaround by going to [Control Panel]->[User Accounts]->[Credential Manager] to store login information of target machines.
While I am trying to upload a registry in my registries using the C# code , the application is throwing the error "a required privilege is not held by the client". If I am using the same code on some other machine it is working fine but not particularly on my machine
I am using below mentioned code to upload the registry files
Process my_p = new Process();
my_p.StartInfo.FileName = "reg";
my_p.StartInfo.Arguments = "load HKLM\TEST C:\Documents and Settings\Administrator\NTUSER.DAT";
my_p.Start();
my_p.WaitForExit();
System.IO.StreamReader srOutPut = my_p.StandardOutput;
System.IO.StreamReader srError = my_p.StandardError;
my_p.Close();
results = srOutPut.ReadToEnd().Trim();
Errors = srError.ReadToEnd().Trim();
Moreover One thing I have noticed that the above code I am using in http based web site, but when I am using it in a File Syatem based web site it is working fine. Please help I am not getting the error.
Regards,
Vikram
You can load RegLoadKey function directly to load the hive as a subkey. Another API is RegLoadAppKey but it works only starting from Windows Vista. Different versions of Reg.exe use the API. How you can read in the description the RegLoadKey you need have SE_RESTORE_NAME and SE_BACKUP_NAME privileges and enable these (see http://msdn.microsoft.com/en-us/library/ms717797.aspx). If you are in the Group of Administrators or Backup Operators you have these privileges. One more problem can be if Reg.exe use RegLoadKey function and you have a local administrative rights, but you start on Vista or Windows 7 a command without admin rights because of UAC (User Account Control).