Problem launching a System.Diagnostics.Process under Windows 7
Asked Answered
S

6

5

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:

  1. process is a System.Diagnostics.Process created with a simple "new Process();”
  2. path is a full path to the .exe “c:/path/to/my.exe”.
  3. enableRaisingEvents is false
  4. 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:

alt text

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:

alt text

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:

alt text

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.

Statampere answered 29/10, 2010 at 11:33 Comment(7)
I know, that's not the question, but you can simplify the if to if ( !String.IsNullOrEmpty(arguments) ). SCNRInfallible
What is DBSWIN.EXE? According to many sites it could be a problem with a 3rd Party extension to IE...could the PC be infected?Infallible
@Infallible DBSWIN.EXE is part of the software these guys use: duerrdental.de/en/home-dd (it’s actually this: duerrdental.de/en/products/imaging/dbswin-imaging-software)Statampere
@Infallible yeah, I just noticed that, thanks for pointing that out. This code comes from .NET 1.0 or 1.1 and has been untouched for “ages” so God knows what other “unoptimized” things are out there.Statampere
Does a Malware/Virus scan bring something up?Infallible
Since today is a National Holiday over here (monday 1st of Nov), I’ll contact the customer tomorrow to try the suggested answers and will get back to you guys. Thanks. @Infallible I haven’t done any Virus/Malaware but as far as I know it’s a “brand new” Win7 box, but I won’t discard that.Statampere
I’ve made a new version of our .DLL (the one that starts the process anyway) to incorporate some of the suggestions here. In any case, I’m also in contact with the people at durrdental.de and there seems to be a 1GB update to the app (yes… 1Gb), but I doubt it has anything to do. The boxes are brand new so I don’t think this is malaware related, especially because it happens in two different locations (not interconnected), that have the same machine model (brand new). So I believe there’s something else going on. Will update. Ty.Statampere
U
5

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.

Ulphiah answered 29/10, 2010 at 13:51 Comment(4)
@Kate could you point me towards a more “expanded” explanation about that? Thanks.Statampere
UseShellExecute is true by default.Auspice
@P.Brian Yes, I found that too.Statampere
Marking this as the correct answer, because the manifest/link was the starting point that lead me to the correct solution. ThanksStatampere
B
8

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.

Badoglio answered 29/10, 2010 at 14:7 Comment(2)
sadly this didn’t change anything (but I will leave it in the code anyway). We’re downloading the latest version of the software to see if it happens there too.Statampere
Hmya, focus on the last paragraph in my answer. You've seen the google hits.Badoglio
U
5

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.

Ulphiah answered 29/10, 2010 at 13:51 Comment(4)
@Kate could you point me towards a more “expanded” explanation about that? Thanks.Statampere
UseShellExecute is true by default.Auspice
@P.Brian Yes, I found that too.Statampere
Marking this as the correct answer, because the manifest/link was the starting point that lead me to the correct solution. ThanksStatampere
M
3

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";
}
Martyr answered 5/12, 2010 at 9:39 Comment(1)
thanks for the info, will surely keep it handy. Please note that according to MSDN, UseShellExecute is true by default.Statampere
A
1

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(); ...}
Autoeroticism answered 1/12, 2010 at 16:24 Comment(1)
I am not sure how this helps you troubleshoot, but you need to append a space after "/c". Also need to assign the psi object to process object for it to have any effect.Auspice
C
1

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.

Caressive answered 4/12, 2010 at 0:3 Comment(0)
A
0

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

Auspice answered 6/12, 2010 at 22:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.