File not found when executable launched from another application - c#

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).

Related

Environment.GetFolderPath(Environment.SpecialFolder) is returning wrong value

I have a UWP project, and wrote this code:
foreach (var foldertype in (Environment.SpecialFolder[])Enum.GetValues(typeof(Environment.SpecialFolder)))
{
//string d = Environment.CurrentDirectory;
var path = Environment.GetFolderPath(foldertype);
var folder = await StorageFolder.GetFolderFromPathAsync(path);
StorageApplicationPermissions.FutureAccessList.Add(folder, folder.Path);
Debug.WriteLine($"Opened the folder: {folder.DisplayName}");
this.MenuFolderItems.Add(new MenuFolderItem(folder));
}
It is supposed to enumerate all the special folders, and get their folder. However, while debugging, this is what happens:
foldertype = Desktop
path = "C:\\Users\\cuent\\AppData\\Local\\Packages\\402b6149-1adf-4994-abc9-504111b3b972_a5s740xv383r0\\LocalState\\Desktop"
folder = [ERROR] System.IO.FileNotFoundException: 'The system cannot find the file specified. (Exception from HRESULT: 0x80070002)'
I do not know what is happening here, it seems to be appending the path to the installed location of the app. How do I fix this?
Expected output of GetFolderPath() is wherever the Desktop is, not the weird path.
UWP apps are different from desktop applications when accessing the file system. UWP apps are running in the sandbox so there are limitations for UWP apps when trying to access the file system. You could check this document: File access permissions. The document lists all the locations that UWP apps have permission to access.
Back to your scenario, what you need first is a broadFileSystemAccess restricted capability. This capability enables your app could use the StorageFolder.GetFolderFromPathAsync() API with a Path parameter. This is mentioned in the last part of the document I posted above.
Then the second issue is the Environment.GetFolderPath API. It looks like the API will return a Path that points to a local folder inside the app's local folder. But there is no such desktop folder inside the app's local folder so you will get the FileNotFoundException. You might need to set the correct path by yourself like C:\Users\your user name\Desktop. After that, your code should be able to work correctly.

C# Windows Service Enviroment.GetFolderPath() returning empty string

The question is pretty straight forward, I am making a Windows Service Program and the enviroment.getfolderpath isnt working.
Here is the code I have
string savePath = AppDomain.CurrentDomain.BaseDirectory; // this works
string savePath2 = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); // this returns an empty string...but why?
The documentation says
The path to the specified system special folder, if that folder
physically exists on your computer; otherwise, an empty string ("").A
folder will not physically exist if the operating system did not
create it, the existing folder was deleted, or the folder is a virtual
directory, such as My Computer, which does not correspond to a
physical path.
When running the Service as a Local System it doesn't run with any specific user permissions. Hence the GetFolderPath is returning empty because it is not able to recognize the path Desktop for LocalSystem.
You can either use Environment.SpecialFolder.CommonDesktopDirectory which will give C:\Users\Public\Desktop or
run the service with a specific user (in my case it's sampleuser) which will give the output as C:\Users\sampleuser\Desktop

ProcessStartInfo.WorkingDirectory can't find the location on server

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#)

Error when start application through \Local Settings\Application Data\ in Windows 7

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.

Win32Exception: The directory name is invalid

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.

Categories