I have an odd issue that I'm hoping someone may be able to explain.
I have written a very short piece of code to demonstrate the issue at the bottom.
I have an app that iterates through folders and there is a good chance that the file paths and names are longer than windows typically allows. I found the workaround of using \\?\ at the start of the path fixed the issue.
However, this fix only works in debug mode or when running the exe directory. If I run it from the start menu it fails with an "illegal characters in path" error.
It appears that both ways of running have the same permissions but there is something that is different. Any ideas?
To replicate:
Create a new C# form with a single textbox that fills the window
Add the following code to the Load event:
StringBuilder list = new StringBuilder();
try
{
foreach (string folder in System.IO.Directory.EnumerateDirectories(#"\\?\C:\"))
{
list.Append(folder + "\r\n");
}
textBox1.Text = list.ToString();
} catch (Exception ex)
{
textBox1.Text = ex.ToString();
}
Run in debug; you'll get a list of directories from C.
Publish it. It will fail with the illegal chars error.
Locate and run the exe directly. It will work.
Any assistance is appreciated!!
OK, I have a dirty solution. I'm not happy or proud of it, and I'm sure I'll be crucified but here it is.
It seems that anytime it is run as a ClickOnce application (using the appname.application instead of the appname.exe) it fails.
So the very first I check in the LOAD function is if it running as a ClickOnce application. If it is, I load the exe and kill the ClickOnce.
if (ApplicationDeployment.IsNetworkDeployed)
{
Process.Start(Application.ExecutablePath);
Application.Exit();
}
It's not pretty but if it helps someone else then great. :)
Use WMI reference.
Using WMI, The WMI query like “SELECT * FROM Win32_Directory Where Drive= ‘C:’”
It just returns the folders until it reaches a folder with long path. The rest of the remaining folders are skipped even though they have
small paths. You will never knowthat you have encountered an error in WMI process.
Enable NTFS long paths using group policy
Enabling the long paths will allow you to get the long path’s files or folders info using System.IO or WMI. If you’re using a Windows 10
machine, then please follow the below-mentioned steps to enable long paths
a. Hit the Windows key, type gpeedit.msc and press Enter.
b. Navigate to Local Computer Policy > Computer Configuration > Administrative Templates > System > Filesystem > NTFS.
c. Double click the Enable NTFS long paths option and enable it.
Related
I saw the other topic and I'm having another problem. The process is starting (saw at task manager) but the folder is not opening on my screen. What's wrong?
System.Diagnostics.Process.Start("explorer.exe", #"c:\teste");
Have you made sure that the folder "c:\teste" exists? If it doesn't, explorer will open showing some default folder (in my case "C:\Users\[user name]\Documents").
Update
I have tried the following variations:
// opens the folder in explorer
Process.Start(#"c:\temp");
// opens the folder in explorer
Process.Start("explorer.exe", #"c:\temp");
// throws exception
Process.Start(#"c:\does_not_exist");
// opens explorer, showing some other folder)
Process.Start("explorer.exe", #"c:\does_not_exist");
If none of these (well, except the one that throws an exception) work on your computer, I don't think that the problem lies in the code, but in the environment. If that is the case, I would try one (or both) of the following:
Open the Run dialog, enter "explorer.exe" and hit enter
Open a command prompt, type "explorer.exe" and hit enter
Just for completeness, if all you want to do is to open a folder, use this:
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo() {
FileName = "C:\\teste\\",
UseShellExecute = true,
Verb = "open"
});
Ensure FileName ends with Path.DirectorySeparatorChar to make it unambiguously point to a folder. (Thanks to #binki.)
This solution won't work for opening a folder and selecting an item, since there doesn't seem a verb for that.
If you want to select the file or folder you can use the following:
Process.Start("explorer.exe", "/select, c:\\teste");
You're using the # symbol, which removes the need for escaping your backslashes.
Remove the # or replace \\ with \
You don't need the double backslash when using unescaped strings:
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
You should use one of the System.Diagnostics.Process.Start() overloads. It's quite simple!
If you don't place the filename of the process you want to run (explorer.exe), the system will recognize it as a valid folder path and try to attach it to the already running Explorer process. In this case, if the folder is already open, Explorer will do nothing.
If you place the filename of the process (as you did), the system will try to run a new instance of the process, passing the second string as a parameter. If the string is a valid folder, it is opened on the newly created process, if not, the new process will do nothing.
I don't know how invalid folder paths are treated by the process in any case. Using System.IO.Directory.Exists() should be enough to ensure that.
Use an overloaded version of the method that takes a ProcessStartInfo instance and set the ProcessWindowStyle property to a value that works for you.
You're escaping the backslash when the at sign does that for you.
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
This code works fine from the VS2010 environment and opens the local folder properly, but if you host the same application in IIS and try to open then it will fail for sure.
Ive just had this issue, and i found out why. my reason isnt listed here so anyone else who gets this issue and none of these fix it.
If you run Visual Studio as another user and attempt to use Process.Start it will run in that users context and you will not see it on your screen.
Does it open correctly when you run "explorer.exe c:\teste" from your start menu? How long have you been trying this? I see a similar behavior when my machine has a lot of processes and when I open a new process(sets say IE)..it starts in the task manager but does not show up in the front end. Have you tried a restart?
The following code should open a new explorer instance
class sample{
static void Main()
{
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
}
}
Do you have a lot of applications running when you are trying this?
I encounter weird behavior at work sometimes because my system runs out of GDI Handles as I have so many windows open (our apps use alot).
When this happens, windows and context menus no long appear until I close something to free up some GDI handles.
The default limit in XP and Vista is 10000.
It is not uncommon for my DevStudio to have 1500 GDI handles, so if you have a couple of copies of Dev studio open, it can eat them up pretty quickly. You can add a column in TaskManager to see how many handles are being used by each process.
There is a registry tweak you can do to increase the limit.
For more information see http://msdn.microsoft.com/en-us/library/ms724291(VS.85).aspx
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
Just change the path or declare it in a string
I am new to C# and I have made a simple Windows Forms Application that basically updates the persons files for a game.
They have to manually move and delete certain folders just to change version every time. I have successfully accomplished this.
However before I start giving it out I really should improve it. I know I need to change the name of the processes and remove my descriptions ETC.
I have stumbled onto an error and instead of me taking a guess I think it is best to get an opinion from a more experienced person about how to do this.
I am going to use Inno Setup to make the installer for my application, this way I can be sure it will go into their program files 32 and 64 bit. So I know this will be in program files.
So now I am wondering if I have done this the correct way or not? I was using this format to find their program files:
string programFilesFolder = Environment.GetEnvironmentVariable("PROGRAMFILES(X86)") ?? Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
However, would this work on all windows systems(XP, Vista, Win7, Win8) and is it completely accurate? I was going to use the above, and then use this:
string PATCHSELECTOR = Path.Combine(programFiles, #"PATCH SELECTOR");
if (Directory.Exists(PATCHSELECTOR))
{
string GamereliteFolder = Path.Combine(programFiles, #"GAMERELITE~1");
if (Directory.Exists(GamereliteFolder))
And then I move the files using the string method. If the file exists it is deleted before I copy the file over from PATCH SELECTOR to GAMERELITE.
Also will windows XP support using the .exe with an assembly resource embedded which is making the program need to be ran as administrator? I previously was making the assembly work through UAC however that wouldnt always work if they have UAC off or if it is XP so I thought I would try the admin assembly instead.
Can anyone possibly give me some insight, ideas or links?
For executables (not sure for websites & web application) this returns the directory where the executable lives (it's actually the base path where the framework will probe for Assemblies to load, 99% of the the that's the same thing).
System.AppDomain.CurrentDomain.BaseDirectory
This method works for any executable located in a folder which is defined in the windows PATH variable:
private string LocateEXE(String fileName)
{
string path = Environment.GetEnvironmentVariable("path");
string[] folders = path.Split(';');
foreach (var folder in folders)
{
if (File.Exists(Path.Combine(folder, fileName)))
{
return Path.Combine(folder, fileName);
}
}
return String.Empty;
}
Usage:
string pathToEXE = LocateEXE("Example.exe");
Reference:
how to find the execution path of a installed software
How can I get another application's installation path programmatically?
Couple things:
Among the already stated answers, Assembly.GetExecutingAssembly().Location will also give you the full file path of the currently "executing" Assembly. (Alternatively, GetCurrentAssembly)
If I'm reading your question correctly, you're trying to find both your own location as well as another application's. I would highly recommend seeing if the other application has a registry key that specifies the exact location - it'll make your copy step WAY more stable.
I have some code that I wrote to basically clear out the directory every time the program runs through this point. I didn't want to bother enumerating files. If this is a bad way to do this, please tell me.
My main question, however, is about how to deal with the following: one of the files in the folder appears to be in use when it is most certainly not. The program runs on a ButtonClick event, and it exploded the first four or five times, but it worked after I confirmed that nobody was using the file on the server. There is only one person besides myself that would have been using it, and he confirmed that there was nothing running on his side that would be touching the file. Any ideas for what would cause this error/how to avoid it/how to handle it?
I am also having trouble reproducing the error...
string directory = #"\\server\directory\folder\";
DirectoryInfo di = new DirectoryInfo(directory);
if (di.Exists)
di.Delete(true);
Directory.CreateDirectory(directory);
If you are using Windows XP, this may help : http://msdn.microsoft.com/en-us/library/dd997370.aspx#remove_open_handles
Just an extract from the top of this page :
"If you are running Windows XP or earlier, a delete operation on a file or directory that follows an enumeration could fail if there is an open handle that remains on one of the enumerated directories or files."
You may also use a software like Unlocker to identify the process locking your file.
If the file is in use, then someone is most certainly using it. :)
If you can access the server the files reside on, you can use a tool such as Process Explorer to find out which process has opened the file.
I’m trying to launch an application (Operating System, My Application and the application I want to launch are all 32 bits), from .NET 3.51.
The code that launches the Process is used for other applications, but there’s one that is giving us a headache. If we “double click” on the application’s icon, it works as expected, meaning that it works fine as an application in the computer. Double clicking the .exe directly, also works.
The operating system is Windows 7 32Bits (Home and/or Professional).
Our .NET application is compiled with x86 to avoid problems.
The code that launches “Processes” is located inside a DLL (also 32 bits) made by us, basically it’s a simple DLL that holds some “Common Code” across the board, common methods, functions and stuff we use throughout our code. One of those methods look like this:
public static bool FireUpProcess( Process process, string path, bool enableRaisingEvents,
ProcessWindowStyle windowStyle, string arguments )
{
if ( process != null )
{
try
{
process.StartInfo.FileName = #path;
if ( arguments != null )
{
if ( arguments != String.Empty )
{
process.StartInfo.Arguments = arguments;
}
}
process.StartInfo.WindowStyle = windowStyle;
process.EnableRaisingEvents = enableRaisingEvents;
process.Start();
}
catch
{
try
{
process.Kill();
}
catch ( InvalidOperationException )
{
} // The process is not even created
return false;
}
}
else
{
return false;
}
return true;
}
I don’t know who wrote this method, but it has been working for roughly six years with different applications, therefore I assume it’s “ok”. However, we have a customer with a piece of software that won’t launch when passed through that argument.
The arguments are:
process is a System.Diagnostics.Process created with a simple "new Process();”
path is a full path to the .exe “c:/path/to/my.exe”.
enableRaisingEvents is false
windowStyle is Maximized (but have tried others).
It gives a crappy MessageBox… which I have happily immortalized. It’s in spanish but the translation ought to be easy:
It says:
Application Error
An unexpected exception has occurred for the program (0x0eedfade) at …
Googling that 0x0eedfade gives strange results that look scary, but the truth is, if I go to the .exe that I’m trying to launch and double click it, it works perfectly.
For The Record: If I try to launch other things (I.e.: Notepad.exe, Adobe Acrobat Reader) it works, but Firefox doesn’t open and doesn’t show an error.
This “some work, some doesn’t” behavior leads me to believe that there might be a problem with a Windows 7 security mechanism or similar that I don’t know.
What am I missing or doing wrong?
UPDATE: Ok; I’ve gotten a copy of the software. It’s a messy software but it works. Now that I can debug, I see that the program gives an error when launched with my FireUpProcess method.
As suggested I added the WorkingDirectory code, but here’s the code:
public static bool FireUpProcess(Process process, string path, bool enableRaisingEvents, ProcessWindowStyle windowStyle)
{
if (process != null)
{
try
{
if ( !String.IsNullOrEmpty(#path) )
{
process.StartInfo.FileName = #path;
process.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(#path);
process.StartInfo.WindowStyle = windowStyle;
// Suscribe to the exit notification
process.EnableRaisingEvents = enableRaisingEvents;
// Disable to prevent multiple launchs
Framework.Check.LogWarning("LAUNCHING EXTERNAL DEVICE WITH PATH: " + path);
process.Start(); // HERE The program reports the following:
That means, “The program could not be started because ddip.dll is missing… try reinstalling bla bla”.
The thing is, if I execute the same #path from the command line, the program opens perfectly:
That opens the program. And the same happens if I click on the “shortcut” that it’s located in the “programs” menu. There aren’t any parameters in that shortcut, it’s a simple call to the executable file.
So the question is now: What is the difference between my code and the other methods?
There has got to be something different that causes my process not to start.
Any ideas?
UPDATE AND SOLUTION
I made it work by using one of the below provided answers. Turns out that none directly pointed me to the solution, but they all gave me good ideas here and there.
I added an app manifest to our application (should have had it since the age of vista, don’t know why it wasn’t there in the 1st place). The app manifest I added by using VStudio 2008 add file -> app manifest.
In it, I made sure we have this:
<requestedExecutionLevel level=“asInvoker” uiAccess=“false” />
We don’t need admin or anything like that, but apparently Vista/7 need to know it.
After that was added, the process is correctly launched.
note: UseShellExecute is true by default (as suggested by some), you have to explicitly turn it to false if that’s what you want.
You are not setting the process.StartInfo.WorkingDirectory property. There's plenty of poorly written software out there that assumes the working directory will be the directory in which the EXE is stored. At least add this line:
process.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(#path);
The exception is however rather strange. I'd definitely recommend you tell the customer to update their anti-malware tools.
If the exe has a manifest, you should set UseShellExecute to true on the process object before you call Start. It's not a bad idea in any case.
As Kate Gregory pointed out, if you want to "emulate" the user double clicking on the icon, you have to set UseShellExecute to true. Setting this flags make the code use a totally different path, using the underlying windows ShellExecute function.
Now, I will add to this, that if you're running on a UAC-equipped Windows (Vista, 7, 2008, ...) you maybe should also try to use the runas verb as explained here and here.
With .NET, that would be:
if (System.Environment.OSVersion.Version.Major >= 6) // UAC's around...
{
processStartInfo.Verb = "runas";
}
I've had similar problems in the past. I resolved it by executing the cmd app as follows:
public static bool FireUpProcess(Process process, string path, bool enableRaisingEvents, ProcessWindowStyle windowStyle)
{
//if path contains " ", surround it with quotes.
//add /c and the path as parameters to the cmd process.
//Any other parameters can be added after the path.
ProcessStartInfo psi = new ProcessStartInfo("cmd", "/c" + path ));
psi.WorkingDirectory = System.IO.Path.GetDirectoryName(#path);
psi.WindowStyle = windowStyle;
// Suscribe to the exit notification
process.EnableRaisingEvents = enableRaisingEvents;
// Disable to prevent multiple launchs
Framework.Check.LogWarning("LAUNCHING EXTERNAL DEVICE WITH PATH: " + path);
process.Start(); ...}
If it is possible I would try to use Process Monitor from Sysinternals. When you start it up you can deselect Registry and Network Activity on the toolbar (the 5 icons on the right side). Then you only see Process and Disk activity. Since it looks like a file not found problem you should use the Filter dialog (6. icon from the left) select Process Name from the Drop down list (Architecture is the default) and enter your failing executable name. This will greatly limit the captured output so you can see what is going on. Then start the exectuable and check in the Result Column for NAME NOT FOUND result. This are the locations where a file was searched but not found. If you know the offending dll name you can search for it with Ctrl+F as usual to dig it out. Then you can compare the different search paths from your working application and when it was started from your application.
Could it be that the environment variable PATH has a different value inside your process? It could be that adding . (the current directory) helps to fix the dll search path. Or is the application started from a different user account? It could also be the new feature that when an application is installing things into Programm Files but has no rights (only administrator can do this) Windows will redirect the writes into the user profile. This is a secure and transparent way to get more secure. But this could cause e.g. during first application startup some e.g. config file to be deployed into the Administrators Profile when he is running the application not with consent from the UAC dialog. Then other users might also start the application but fail because the additional config file is located in the Administrators profile and not in Program Files as expected for everyone.
I believe Hans Passant is on the right track. In addition to what he said, check to ensure that ddip.dll and the exe are in the same directory. This is not always the case as there are other ways to bind assemblies outside the bin. Namely, the GAC and AssemblyResolve event. Considering your situation I see no reason the GAC is involved. Check the exe's code that is launched for any hooks into the AssemblyResolve event. If it's hooked into you may need to update the implementation to allow another process to launch it.
Because you are getting an exception regarding a missing DLL, I have little confidence in the answers regarding path delimiter issues. Nonetheless, you have the application code, so verify that it references ddip.dll. This will give you a good deal of confidence that you are in fact referencing the correct .exe and therefore it's not just a path delimiter problem with the command prompt (E.G. misinterpreted spaces).
I saw the other topic and I'm having another problem. The process is starting (saw at task manager) but the folder is not opening on my screen. What's wrong?
System.Diagnostics.Process.Start("explorer.exe", #"c:\teste");
Have you made sure that the folder "c:\teste" exists? If it doesn't, explorer will open showing some default folder (in my case "C:\Users\[user name]\Documents").
Update
I have tried the following variations:
// opens the folder in explorer
Process.Start(#"c:\temp");
// opens the folder in explorer
Process.Start("explorer.exe", #"c:\temp");
// throws exception
Process.Start(#"c:\does_not_exist");
// opens explorer, showing some other folder)
Process.Start("explorer.exe", #"c:\does_not_exist");
If none of these (well, except the one that throws an exception) work on your computer, I don't think that the problem lies in the code, but in the environment. If that is the case, I would try one (or both) of the following:
Open the Run dialog, enter "explorer.exe" and hit enter
Open a command prompt, type "explorer.exe" and hit enter
Just for completeness, if all you want to do is to open a folder, use this:
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo() {
FileName = "C:\\teste\\",
UseShellExecute = true,
Verb = "open"
});
Ensure FileName ends with Path.DirectorySeparatorChar to make it unambiguously point to a folder. (Thanks to #binki.)
This solution won't work for opening a folder and selecting an item, since there doesn't seem a verb for that.
If you want to select the file or folder you can use the following:
Process.Start("explorer.exe", "/select, c:\\teste");
You're using the # symbol, which removes the need for escaping your backslashes.
Remove the # or replace \\ with \
You don't need the double backslash when using unescaped strings:
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
You should use one of the System.Diagnostics.Process.Start() overloads. It's quite simple!
If you don't place the filename of the process you want to run (explorer.exe), the system will recognize it as a valid folder path and try to attach it to the already running Explorer process. In this case, if the folder is already open, Explorer will do nothing.
If you place the filename of the process (as you did), the system will try to run a new instance of the process, passing the second string as a parameter. If the string is a valid folder, it is opened on the newly created process, if not, the new process will do nothing.
I don't know how invalid folder paths are treated by the process in any case. Using System.IO.Directory.Exists() should be enough to ensure that.
Use an overloaded version of the method that takes a ProcessStartInfo instance and set the ProcessWindowStyle property to a value that works for you.
You're escaping the backslash when the at sign does that for you.
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
This code works fine from the VS2010 environment and opens the local folder properly, but if you host the same application in IIS and try to open then it will fail for sure.
Ive just had this issue, and i found out why. my reason isnt listed here so anyone else who gets this issue and none of these fix it.
If you run Visual Studio as another user and attempt to use Process.Start it will run in that users context and you will not see it on your screen.
Does it open correctly when you run "explorer.exe c:\teste" from your start menu? How long have you been trying this? I see a similar behavior when my machine has a lot of processes and when I open a new process(sets say IE)..it starts in the task manager but does not show up in the front end. Have you tried a restart?
The following code should open a new explorer instance
class sample{
static void Main()
{
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
}
}
Do you have a lot of applications running when you are trying this?
I encounter weird behavior at work sometimes because my system runs out of GDI Handles as I have so many windows open (our apps use alot).
When this happens, windows and context menus no long appear until I close something to free up some GDI handles.
The default limit in XP and Vista is 10000.
It is not uncommon for my DevStudio to have 1500 GDI handles, so if you have a couple of copies of Dev studio open, it can eat them up pretty quickly. You can add a column in TaskManager to see how many handles are being used by each process.
There is a registry tweak you can do to increase the limit.
For more information see http://msdn.microsoft.com/en-us/library/ms724291(VS.85).aspx
System.Diagnostics.Process.Start("explorer.exe",#"c:\teste");
Just change the path or declare it in a string