2012-09-28 15 views
17

Poniższy kod nie uruchamia dokumentów. Pojawia się błąd 193 (% 1 nie jest prawidłową aplikacją Win32). Uruchamianie plików wykonywalnych działa dobrze. Pliki są poprawnie powiązane, po dwukrotnym kliknięciu rozpoczynają odpowiednią aplikację. Przeszukałem SO i gdzie indziej na komunikat o błędzie, CreateProccess rzeczy itp (np Why is CreateProcess failing in Windows Server 2003 64-bit? wiem o cytowanie wiersza poleceń.Dlaczego CreateProcess daje błąd 193 (% 1 nie jest prawidłową aplikacją Win32)

  • To Delphi XE2 (Update 4) aplikacja Win32 w Win7 64bit VMWare VM.

  • Kod zawiedzie także na maszynie hosta (Win7 64 bit) oraz w Virtual PC VM z 32bit XP.

  • aplikacje, które powinny rozpocząć się w Win7 VM (Excel 2003 i Crimson Editor) są 32-bitowe:

  • Niepowodzenie występuje zarówno przy uruchamianiu z IDE lub gdy działa aplikacja testy samodzielnych

  • Kiedyś kod Delphi2007, skompilowaną aplikację D2007 gdzie ten kod pochodzi z działa dobrze wszędzie.

Co jest nie tak z kodem? To prawie tak, jakbym widokiem na coś bardzo oczywistego ....

góry dzięki,

Jan

procedure StartProcess(WorkDir, Filename: string; Arguments : string = ''); 
var 
    StartupInfo : TStartupInfo; 
    ProcessInfo : TProcessInformation; 
    lCmd   : string; 
    lOK   : Boolean; 
    LastErrorCode: Integer; 
begin 
    FillChar(StartupInfo, SizeOf(TStartupInfo), 0); 
    StartupInfo.cb := SizeOf(TStartupInfo); 
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW; 
    StartupInfo.wShowWindow := sw_Normal; 

    FillChar(ProcessInfo, SizeOf(TProcessInformation), 0); 

    lCmd := '"' + WorkDir + FileName + '"';  // Quotes are needed https://stackoverflow.com/questions/265650/paths-and-createprocess 
    if Arguments <> '' then lCmd := lCmd + ' ' + Arguments; 

    lOk := CreateProcess(nil, 
         PChar(lCmd), 
         nil, 
         nil, 
         FALSE, // TRUE makes no difference 
         0,  // e.g. CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS makes no difference 
         nil, 
         nil, // PChar(WorkDir) makes no difference 
         StartupInfo, 
         ProcessInfo); 

    if lOk then 
    begin 
    try 
     WaitForSingleObject(ProcessInfo.hProcess, INFINITE); 
    finally 
     CloseHandle(ProcessInfo.hThread); 
     CloseHandle(ProcessInfo.hProcess); 
    end; 
    end 
    else 
    begin 
    LastErrorCode := GetLastError; 
    ShowMessage(IntToStr(LastErrorCode) + ': ' + SysErrorMessage(LastErrorCode)); 
    end; 
end; 

procedure TFrmStartProcess.Button1Click(Sender: TObject); 
begin 
    StartProcess('c:\program files (x86)\axe3\','axe.exe'); // Works 
end; 

procedure TFrmStartProcess.Button2Click(Sender: TObject); 
begin 
    StartProcess('d:\','klad.xls');       // Fails 
end; 

procedure TFrmStartProcess.Button3Click(Sender: TObject); 
begin 
    StartProcess('d:\','smimime.txt');       // Fails 
end; 
+0

Co dzieje się powiedzieć ostatni jeśli specjalnie zadzwonić notes w pliku tekstowym? – BugFinder

+9

Nie jestem zaznajomiony z Delphi, ale WINAPI 'CreateProcess()' może być użyty tylko do uruchomienia '.exe's. Jeśli chcesz _run_ inne typy plików, musisz użyć ['ShellExecute()'] (http://msdn.microsoft.com/en-us/library/windows/desktop/bb762153 (v = vs.85) .aspx). – hmjd

+0

@hjmd Ten kod działał w poprzedniej wersji kodu, wywołując pliki .XLS. –

Odpowiedz

23

Najbardziej prawdopodobne wyjaśnienia tego błędu są:

  1. Plik, który próbujesz wczytać, nie jest plikiem wykonywalnym. CreateProcess wymaga podania pliku wykonywalnego. Jeśli chcesz otworzyć dowolny plik z powiązaną aplikacją, potrzebujesz ShellExecute zamiast CreateProcess.
  2. Występuje problem podczas ładowania jednej z zależności pliku wykonywalnego, tj. Bibliotek DLL, które są połączone z plikiem wykonywalnym. Najczęstszym tego powodem jest niedopasowanie między 32-bitową i 64-bitową biblioteką DLL lub na odwrót. Aby zbadać, użyj trybu profilu Dependency Walker's, aby dokładnie sprawdzić, co się dzieje.

Czytanie w dół do dolnej części kodu, widzę, że problem jest numer 1.

+1

O mój Boże. Przepisujemy nasz kod z D2007 na XE2, a przy okazji usuwamy niektóre biblioteki zewnętrzne. W tym procesie wyrzuciliśmy składnik "Launcher" innej firmy, który użył ShellExecute, i zastąpiliśmy go naszym własnym komponentem Launcher, który był odpowiedni tylko dla plików wykonywalnych, a zatem używał CreateProcess. Jak mylące może to uzyskać. Przepraszam chłopaki. –

+1

# 2 bit mnie wczoraj. Delphi dodaje 32-bitowe ścieżki BPL i 64-bitowe BPL do tej samej ścieżki globalnej, więc nazwy DLL MUSZĄ się różnić, dowiedziałem się wczoraj po pewnym bólu. To pytanie jest przydatne samodzielnie. Zatrzymaj to. –

+0

O ile nie określono pełnych ścieżek, istnieją tylko dwa sposoby, aby 32 i 64-bitowe biblioteki DLL używały tej samej nazwy. Są one umieszczone w systemie32, ale tylko MS mają to zrobić, lub żyją w tym samym katalogu co plik wykonywalny. –

6

Twoje Button2Click i Button3Click funkcje przejść klad.xls i smimime.txt. Te pliki najprawdopodobniej nie są rzeczywistymi plikami wykonywalnymi.

W celu otwarcia dowolnych plików przy użyciu aplikacji powiązanych z nimi wykorzystać ShellExecute

+1

Uwielbiam niedomówienia! :) –