Process.Start failes on Win 2000 after showing open file dialog

G

Guest

Hi,

I have an application that is launching a process (see the code below) to
perfom some operation on a file. On Windows 2000, if my application first
uses the OpenFileDialog to open a file on the desktop, Process.Start failes
with the following exception:

System.ComponentModel.Win32Exception: The system cannot find the file
specified
at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo
startInfo)
at System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)

The code is roughly as follows:

// here we ask the user to open a file
OpenFileDialog openFileBox = new OpenFileDialog();
openFileBox.Filter = mAddFileFilter.ToString();
openFileBox.FilterIndex = 1;
if(openFileBox.ShowDialog() == DialogResult.OK) {
inputFilePath = openFileBox.FileNames;
}

// later we launch a process to perform an operation on the file
outputFilePath = System.IO.Path.GetTempFileName();
string arguments = "\"" + inputFilePath + "\" \"" + outputFilePath + "\"";
arguments += " /a";
arguments += " /dm1";
arguments += " /DL0";
arguments += " /a1";
arguments += " /h" + progressWindow.ClassId;
string ConverterPath = @"C:\Program Files\foo\bar\converter\go.exe"; // for
example
ProcessStartInfo psInfo = new ProcessStartInfo(ConverterPath, arguments);
psInfo.WindowStyle = ProcessWindowStyle.Hidden;
mProcess = Process.Start(psInfo);

The exception is observed on Windows 2000, but never on Windows XP. It works
fine on Windows 2000 if I never call the OpenFileDialog. I tried setting the
WorkingDirectory of the ProcessStartInfo instance to the directory that
contains the process executable, but this does not help.

Thanks,
Bret
 
W

Walter Wang [MSFT]

Hi Bret,

I'm not sure if it's a typo or not:

inputFilePath = openFileBox.FileNames;

FileNames returns an array of string rather than a string.


Also, I think this might not be related to the open file dialog; you could
verify this by hard code the inputFilePath using the result from the file
dialog and test it again. This looks like a command line length limit,
please verify the command line string length before pass to
Process.Start().

I wasn't able to reproduce the issue on Windows 2000 using the information
you provided; you might have to create a smaller reproducible project and
send it to me. Thank you.

Sincerely,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications. If you are using Outlook Express, please make sure you clear the
check box "Tools/Options/Read: Get 300 headers at a time" to see your reply
promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi,

Thanks for your quick response Walter.

Setting the inputFilePath from the open dialog was a typo. I did not paste
the full code here, but meant just to give an impression of what I am doing.

My first observation was that the same exact command that fails after the
open file dialog works fine normally. So, I don't think the problem can be in
the command string.

I am, in fact, also having trouble reproducing in a minimal project. Perhaps
there is something else going on that I haven't noticed. Yet, I seem to have
a process start command whose success is depending on something outside of
the actual command itself. What things could possibly cause this?

Thanks,
Bret
 
W

Walter Wang [MSFT]

Hi Bret,

So the issue only occurs for the specific program with specific arguments,
and only occurs when the OpenFileDialog has been used? I must say that's a
very strange one. By default, Process.Start is using ShellExecuteEx (you
can use Reflector to view the source). The exception seems either
ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND, it didn't tell exactly reason
why the call failed.

#ShellExecuteEx function()
http://msdn2.microsoft.com/en-us/library/ms647733.aspx

I would really appreciate it if you could create a reproducible project and
let me see if there's anything I can do to find the root cause.

By the way, you might want to use CreateProcess instead, just set the
ProcessStartInfo.UseShellExecute to false:

#ProcessStartInfo.UseShellExecute
http://msdn2.microsoft.com/en-gb/library/system.diagnostics.processstartinfo
..useshellexecute.aspx

CreateProcess has much longer command line length limit than ShellExecute:

#The Old New Thing: What is the command line length limit?
http://blogs.msdn.com/oldnewthing/archive/2003/12/10/56028.aspx

Although according to your description, this issue might not be related to
command line length limit, you might want to try CreateProcess to see if it
works.


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Walter,

I am as confident as you that setting UseShellExecute=false will solve my
problem. I had a similar issue a while back with a different process
launching on Win 2000, and doing this fixed it. In this case, I have not
applied this solution because my process opens a window that I need to hide,
and it seems that setting WindowStyle=ProcessWindowStyle.Hidden does not work
with UseShellExecute=false. Is this normal (I'm using .NET 1.1)? I've just
disassembled and it seems that System.Diagnostics.ProcessStartWithCreate
isn't copying the WindowStyle property into the STARTUPINFO structure for
CreateProcess. Normally, can the window be supressed using CreateProcess, as
it is with UseShellExecute=true + ProcessWindowStyle.Hidden?

Otherwise, I agree that I need to reproduce the issue in a minimal project
before I can expect a real answer here...

Thanks,
Bret
 
W

Walter Wang [MSFT]

Hi Bret,

It seems Process.Start will only apply the ProcessWindowStyle when we use
ShellExecute; you might have to use P/Invoke to call CreateProcess directly
to hide the window:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public STARTF dwFlags;
public SHOWWINDOW wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}

public enum SHOWWINDOW : uint
{
SW_HIDE = 0,
SW_SHOWNORMAL = 1,
SW_NORMAL = 1,
SW_SHOWMINIMIZED = 2,
SW_SHOWMAXIMIZED = 3,
SW_MAXIMIZE = 3,
SW_SHOWNOACTIVATE = 4,
SW_SHOW = 5,
SW_MINIMIZE = 6,
SW_SHOWMINNOACTIVE = 7,
SW_SHOWNA = 8,
SW_RESTORE = 9,
SW_SHOWDEFAULT = 10,
SW_FORCEMINIMIZE = 11,
SW_MAX = 11,
}

[Flags]
public enum STARTF : uint
{
STARTF_USESHOWWINDOW = 0x00000001,
STARTF_USESIZE = 0x00000002,
STARTF_USEPOSITION = 0x00000004,
STARTF_USECOUNTCHARS = 0x00000008,
STARTF_USEFILLATTRIBUTE = 0x00000010,
STARTF_RUNFULLSCREEN = 0x00000020, // ignored for non-x86
platforms
STARTF_FORCEONFEEDBACK = 0x00000040,
STARTF_FORCEOFFFEEDBACK = 0x00000080,
STARTF_USESTDHANDLES = 0x00000100,
}

[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}

[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}

[DllImport("kernel32.dll")]
static extern bool CreateProcess(string lpApplicationName,
string lpCommandLine, ref SECURITY_ATTRIBUTES
lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles,
uint dwCreationFlags, IntPtr lpEnvironment, string
lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);

public static void Test()
{
const uint NORMAL_PRIORITY_CLASS = 0x0020;

bool retValue;
string Application =
Environment.GetEnvironmentVariable("windir") + @"\Notepad.exe";
string CommandLine = string.Empty;
PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
STARTUPINFO sInfo = new STARTUPINFO();
sInfo.dwFlags = STARTF.STARTF_USESHOWWINDOW;
sInfo.wShowWindow = SHOWWINDOW.SW_HIDE;
SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
SECURITY_ATTRIBUTES tSec = new SECURITY_ATTRIBUTES();
pSec.nLength = Marshal.SizeOf(pSec);
tSec.nLength = Marshal.SizeOf(tSec);

//Open Notepad
retValue = CreateProcess(Application, CommandLine, ref pSec,
ref tSec, false, NORMAL_PRIORITY_CLASS, IntPtr.Zero, null, ref sInfo, out
pInfo);

Process p = Process.GetProcessById(pInfo.dwProcessId);
p.WaitForExit();
}


You can find most of the P/Invoke declaration on http://www.pinvoke.net.


Regarding the OpenFileDialog issue, I was wondering is it possible that
it's related to current working directory? As far as I know, a common file
dialog might change the working directory. Will it have impact on your
application?

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Walter,

Thank you for the example code. Indeed, calling CreateProcess directly fixes
my problem and allows me to hide the process window.

I will leave the interference of OpenFileDialog and ShellExecute as a
mystery...

Thanks,
Bret
 
W

Walter Wang [MSFT]

Hi Bret,

Thanks for the update.

Please feel free to open a new post if you're able to reproduce the issue
of OpenFileDialog and ShellExecute on Win2000. Thanks.


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hello,

I have had the same problem. Trying to reproduce this problem learned me:

Only occurs on W2K with Internet Explorer 6.

In my application directory I have a SHDOCVW.DLL, looks like its generated
by .Net/Visual Studion, (when my app was still 1.0 maybe), but is not needed
anymore.

If I delete SHDOCVW.DLL from the application directory all works fine.

Hope this helps,

Gert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top