I'm trying to run a process as a different user that has Administrator privilege in 2 different computers running Vista and their UAC enabled but in one of them I get a Win32Exception that says "The directory name is invalid"
Can anyone tell me what is wrong with my code?
var myFile = "D:\\SomeFolder\\MyExecutable.exe";
var workingFolder = "D:\\SomeFolder";
var pInfo = new System.Diagnostics.ProcessStartInfo();
pInfo.FileName = myFile;
pInfo.WorkingDirectory = workingFolder;
pInfo.Arguments = myArgs;
pInfo.LoadUserProfile = true;
pInfo.UseShellExecute = false;
pInfo.UserName = {UserAccount};
pInfo.Password = {SecureStringPassword};
pInfo.Domain = ".";
System.Diagnostics.Process.Start(pInfo);
UPDATE
The application that executes the above code has requireAdministrator execution level.
I even set the working folder to "Path.GetDirectoryName(myFile)" and "New System.IO.FileInfo(myFile).DirectoryName"
You need to specify the WorkingDirectory property of ProcessStartInfo`. From Win32Exception error code 267 "The directory name is invalid":
I'm currently working on an "Automated Run As" tool. Its goal is
helping admins which, like me, have to give users a means to execute
one or two programs as Administrator and would like to do so without
having to surrender an admin's password.
So, I'm developing on Vista and I just whipped up a small proof of
concept prototype, that'd run calc.exe as a different user, using
ProcessStartInfo and Process. This worked fine when I executed it as
myself (a rather pointless exercise, I must admit), but when I created
a new user and tried to run it as him, I stumbled upon a
Win32Exception complaining that the directory name is invalid, native
error code 267. I was instsantly baffled, as I knew of no supplied
directory name that could be invalid. I then tested the code on an XP
machine and it worked!
I started googling on it to no avail, many reports of that error but
no conclusive solution, or on different contexts. Finally, after a
while it dawned on me, I wasn't specifying the WorkingDirectory
property of the ProcessStartInfo class, as soon as I added the lines
FileInfo fileInfo = new FileInfo(path); startInfo.WorkingDirectory =
fileInfo.DirectoryName;
To my code, it was allowed to run code as different than logged in
user. ...
It is because the path length of the file exceeds 255 characters.
Try to replace
pInfo.WorkingDirectory = New System.IO.FileInfo(myFile).DirectoryName;
with
pInfo.WorkingDirectory = Path.GetDirectoryName(myFile);
The FileInfo makes an access to the filesystem, and I would assume only the admin user has access to that directory. If it doesn't solve your problem, at least it will make your code a tiny bit faster...
Is the directory the logged-on user's mapped home folder or below that? Than this knowledge base article might help:
"The directory name is invalid" error message when you start Cmd.exe or Notepad.exe by using the Run as feature in Windows
Update: Please note that being member of the Local Administrators group and having administrative privileges are not the same on Vista.
I suppose that everything works fine when you run your C# application as administrator. Right-click the executable, then choose Run as Administrator, or start the application from an elevated command prompt (the fastest way to get one is by pressing Start, enter 'cmd' followed by Ctrl+Shift+Return).
Or, as an alternative, disable UAC for the account running that process.
It is due to space in the folder name. Once I removed the space it started working file when I hit this issue.
I had a similar experience and it turned out to be an issue with our development environment. We map our source code directory to a virtual drive using the subst command. So the FileName and WorkingDirectory properties were being set to "W:\SomeFolder\FileName.exe"
When I hard-coded the FileName & WorkingDirectory to access the files via my actual disk (C:), I stopped receiving the "Invalid Directory" exception.
Related
I have a really strange situation.
In our company we develop big web application which consist of several modules. Each module is divided in separate folders on server. There is one module which launches application mapped on users L:\app.exe disk.
My goal is update the invoking method which first will start the switcher.exe file INSIDE the module and after will start L:\app.exe as it was before.
The problem is that when i build this module on my local it works perfectly fine but when i downloading the content from my bin\Debugg on server-including swither.exe (say on Dev environment) the application fails to find "switcher.exe" in folder on server. It throws an exception which says {"The system cannot find the file specified"}.
The code behind is pretty simple:
private void LaunchSwitherExe()
{
string executionPath = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
MessageBox.Show(executionPath);
Process themeSwitchProc = new Process();
themeSwitchProc.StartInfo.FileName = "Switcher.exe";
themeSwitchProc.StartInfo.WorkingDirectory = executionPath;
themeSwitchProc.Start();
}
The messagebox shows(for test purposes) the path to swither.exe. And this path is absolutely correct. It has swither.exe inside.
Do you have any ideas?
---UPDATE---
The problem way in the string to the path. This:
string executionPath = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
Chould be changed to:
string exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Directory.SetCurrentDirectory(exeDir);
Thanks to all folks who answered and especially to "Rick S."
Have you considered it might be permissions issue? What process Id is the code running under and does it have access to that folder?
I also found this:
When the UseShellExecute property is false, gets or sets the working directory for the
process to be started. When UseShellExecute is true, gets or sets the directory that
contains the process to be started.
And maybe try this:
Defining a working directory for executing a program (C#)
Simple code:
ProcessStartInfo psi = new ProcessStartInfo(path);
psi.UseShellExecute = false;
Process.Start(psi);
if path = C:\Users\Marat\AppData\Local\MyCompany\Program.exe, it's OK!
but if path = C:\Users\Marat\Local Settings\Application Data\MyCompany\Program.exe
getting Exception:
System.ComponentModel.Win32Exception(0x80004005): An invalid name request was made. The name requested cannot be
retrieved at this time
Actually, everything worked fine, but at some moment it began to give this error.
As far as i can remember the Local Settings folder in Windows 7 it's a link to the AppData folder, mainly used for compatibility with old pre-Windows Vista applications, actually you can't access it directly unless you change the owner of that link (It's System), so that's probably why you're getting this error.
Another cause, could be the white spaces in the name, as you don't show how you construct path or its contents when you start the process.
We have a .exe which we need to execute at the time an order is placed on a website. When
we test this locally it works fine using IIS Express. When we move it to IIS, it fails. We assume this is a permissions error as if we set the App Pool to run as the administrator then the script works again. The question we have is how do we execute the .exe as the administrator whilst the App Pool is ApplicationIdentity? We are using the following code:
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = executablePath,
Arguments = argumentList,
Domain = domain,
UserName = userName,
Password = securePassword,
UseShellExecute = false,
LoadUserProfile = true
}
};
process.Start();
process.WaitForExit();
process.Close();
The .exe is trying to write to the Users AppData folder which is why it fails. It is a 3rd party app so we cannot change the source code.
EDIT: Just to clarify also, when we specify the username and password in procmon it still appears to run from ISUR.
We fixed this by enabling User profile on IIS AppPool and setting permission for the IIS user on the folder it was trying to write to.
We sue ProcMon to find where the program was failing and the folder it was trying towrite to was C:\Windows\System32\config\systemprofile
i dont remember actually, but one of them is working 100% ( i had this issue before)
just let me know ehich one of them is the correct one.
I have an application that requeres to register a dll into a gac on a client computer everytime a new dll is deployed the problem is that the client computers only have restricted users with UAC turned on.
The application knows the credentials of a user that has admin rights.
The problem is if I have processStartInfo.UseShellExecute = false; then I can't get trough the UAC getting the error "The requested opperation requires elevation"
and if I have processStartInfo.UseShellExecute = true; then it does not allow to run the whole thing as a different user: "The process object must have UseShellExecute property set to false in order to start the process as a user"
internal static void Register(String assemblyName)
{
ProcessStartInfo processStartInfo = new ProcessStartInfo(lcDir + "gacutil.exe", string.Format("/i {0}.dll", assemblyName));
processStartInfo.UseShellExecute = false;
processStartInfo.WorkingDirectory = lcDir;
processStartInfo.UserName = lcUser;
processStartInfo.Password = Password;
processStartInfo.Domain = lcDomain;
processStartInfo.Verb = "runas";
Process process = Process.Start(processStartInfo);
process.WaitForExit();
}
I would like to know what the "Best practice" for that kind of thing is? I know the whoe concept looks to windows like a virus.
What I would like to achive the following:
User dosen't need to know an account with admin rights
The credencal's of the admin user are saved in the program's database
As much as possable Automated registration.
You should run this part of your code as Administrator.
What you need is impersonation.
See this article
Aricle Impersonation on Code project
You are not meant to embed such user strings within an application for security reasons.
The design idea is that you deploy using System Management Services or similar to manage the deployment (which sucks).
I got round it my using private assemblies, very similar to the way unix works.
If you are looking to add class support in SQL Native Client, then you will find it is an uphill struggle to get deployed each time.
If you know a local administrator name and password, you could use a central deployment solution and not try to get your app to impersonate an administrator.
In my application, after the user logs in I set a few picturebox/button/etc images and do some scaling on them and whatnot. I use relative paths for example:
#".\Images\SomeImage.png"
It works fine when the application is launched directly, but if you try to run it via another application:
Process process = new Process();
process.StartInfo.FileName = networkPath;
process.Start();
It dies and comes up with a file not found error, because it cannot locate the images. It also does this if I try to launch it via the command prompt. The executable is stored on a network drive. Why won't the relative path work in this situation? I can just go ahead and hard code the full path but that makes me feel dirty... Any thoughts?
This is because the working directory is different - by default when starting a new process the working directory for the new process is set to the working directory of the existing process (which will in turn probably be the directory that existing application is contained within).
Normally your application will be run with the working directory as the directory that the executable is contained in - this is the default when creating a new shortcut for example (you can see this in the shortcut properties under the "Start in" field.
When your application is run from the command prompt or from another application however the working directory is changed and the relative paths are resolved to a completely different directory.
You can either change the calling application to se the WorkingDirectory property of the new process to the value it expects, however the proper way of fixing this it to modify your application so that it uses absolute paths based on the path to the executable. Assembly.GetExecutingAssembly().Location can be used to get the path to the executable being run and so the following code should do the trick:
static string GetAbsolutePathFromRelative(string RelativePath)
{
string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string absolutePath = Path.Combine(directory, RelativePath);
// This final call is to stop paths like "C:\Dir\..\OtherDir\file.txt" being returned
return Path.GetFullPath(absolutePath);
}
You need to set the Process.WorkingDirectory property to the correct path.
The path you posted:
#".\Images\SomeImage.png"
Is not a network path (it is not UNC or using a mapped drive).