views:

487

answers:

7

(See end for solution)

I didn't think this was going to be hard. I have a commmand file, d:\a.cmd which contains:

copy /b d:\7zS.sfx + d:\config.txt + d:\files.7z d:\setup.exe

But these lines of C# won't execute it:

Process.Start("d:\\a.cmd");
Process.Start("cmd", "/c d:\\a.cmd");

Throws Win32Exception: "%1 is not a valid Win32 application."

Process.Start opens .pdf files...why not execute command files?

This works if I type it in a cmd window:

cmd /c d:\a.cmd

Windows XP, MS Visual Studio 2008.

Thanks in advance, Jim

SOLUTION I'm only SLIGHTLY embarrassed :( There was a file named cmd.exe, size zero in my app's dir. I have no idea how it got there but it is now toast and both of the above C# statements now work. I'm off to find a Harry Potter book so I can get some self-punishment ideas from Dobby...

A: 

Have you tried executing cmd.exe, and passing the .cmd file to it as an argument?

Thanatos
Yes, (see my comment to Johannes Rossel). Do you know of a way that will work?
Jim C
+1  A: 

Or you can do a .bat file, then call this file through System.Diagnostics.Process.Start(). It won't redirect output to Console Application, but it would certainly execute the commands inside.

MainMa
I get the same error when I use the .bat extension, too.
Jim C
+2  A: 

I've got four things for you that you can try out:

(1) Try providing the full path for cmd.exe (e.g. on my machine: C:\WINDOWS\SYSTEM32\CMD.EXE).


(2) Try adding call to the command to be executed:

Process.Start(@"C:\WINDOWS\SYSTEM32\CMD.EXE", @"/c call D:\a.cmd");

(3) Besides that, I can only guess where the %1 in the Win32Exception is coming from. Maybe your file associations are set-up incorrectly.

If you type the following on the command-line:

> assoc .cmd

You will likely get a mention of cmdfile. If you then look up this token with:

> ftype cmdfile

You might get an answer along the lines of:

cmdfile="%1" %*

Those settings are stored in the registry, and this is how the command-line interpreter knows how to execute files with custom extensions. (You can find out how a PDF document is started by executing the above two statements for the .pdf extension.)


(4) If you start to suspect that your machine might be mis-configured, start regedit (the registry editor) and locate the key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor.

On my Windows XP machine (and your Process.Start example works on my machine, with different filenames though), I've got the following values stored in there:

//  Name                Type        Value
//  -----------------------------------------------
//  (standard)          REG_SZ      (not set)
//  AutoRun             REG_SZ
//  CompletionChar      REG_DWORD   0x00000040 (64)
//  DefaultColor        REG_DWORD   0x00000000 (0)
//  EnableExtensions    REG_DWORD   0x00000001 (1)
//  PathCompletionChar  REG_DWORD   0x00000040 (64)

Of those, the AutoRun value might be of some interest. I think it corresponds to the /d command-line switch of cmd.exe, which controls whether cmd.exe attempts to start files with custom extensions. Usually, this is enabled. Maybe, on your machine, it isn't?

stakx
Changed my accepted answer to yours 'cause I noticed you posted 2 minutes before SchlaWiener.
Jim C
Note: stakz's first suggestion was the resolution. For more info, see comments I added at the end of my question.
Jim C
+2  A: 

You need to specify the process full name (cmd.exe).
You should try

Environment.GetFolderPath(Environment.SpecialFolder.System) + "cmd.exe"

So you can be sure to execute the right file even if a cmd.exe is in your applications directory.

SchlaWiener
A: 

hmm try:

System.Diagnostics.Process myproc = new System.Diagnostics.Process();
myproc.EnableRaisingEvents=false;
myproc.StartInfo.FileName="d:\\a.cmd";
myproc.Start();
MessageBox.Show("did the command");
Mark Schultheiss
+1  A: 

It looks like something wrong with your computer. Try running this on another machine. This should work. Process.Start(string) uses ShellExecuteEx to launch the file, so it's pretty much the same thing as double-clicking the file in Explorer, as you supposed.

A simple test worked for me.

B:\foo.cmd:

@echo Hello from foo.cmd!
@pause

Program.cs:

class Program{
    static void Main(){
        System.Diagnostics.Process.Start("B:\\foo.cmd");
    }
}

This works as expected.

Your error message is suspicious, "%1 is not a valid Win32 application." The value in my registry at HKCR\cmdfile\shell\open\command is

"%1" %*

The %1 gets replaced by the file name, and the %* can be ignored here (it indicates that any further command-line arguments should be passed along, but we're not concerned with that right now).

The fact that the file itself is launched to handle this type of file indicates that Windows itself knows how to launch this type of file. On a normal installation of Windows, the following extensions should be set up similarly:

  • .exe Windows and DOS executable files
  • .com DOS "command" files
  • .bat Windows and DOS batch files
  • .cmd Windows NT batch files
  • .pif Windows shortcuts to DOS executable files

If you go to HKCR\.xxx (where xxx is any of the above), the "(Default)" value should be xxxfile. If you then go to HKCR\xxxfile\shell\open\command, the "(Default)" value should be "%1" %*. Also the "(Default)" value of HKCR\xxxfile\shell should be either not set or open.

If you have anything else in any of these values, then some program has attempted to insert itself into the execution process. Viruses sometimes do this (Sircam, for example).

P Daddy
Note that you don't need to look at the registry to check file associations. You can look them up from the command line using the commands `assoc` and `ftype`.
stakx
You're still looking in the registry, just using a different tool to do it.
P Daddy
And note that ftype doesn't honor the value set at `HKCR\filehandler\shell`. It assumes `open`. This can bite you, since Explorer/ShellExecuteEx **does** honor this.
P Daddy
For instance, on my system, `assoc .bmp` returns `.bmp=Paint.Picture`. Then `ftype Paint.Picture` returns `Paint.Picture=rundll32.exe C:\WINNT\System32\shimgvw.dll,ImageView_Fullscreen %1`. But in my `HKCR\Paint.Picture\shell`, I have `View`, and at `HKCR\Paint.Picture\shell\View\command` is a different executable, which is what is actually launched when you double-click a .bmp file on my computer.
P Daddy
A: 

Have you tested your batch file in the directory, context it's going to run? The error message with %1 looks like the problem may be in there?

kenny