2012-02-10 22 views
9

Tôi muốn cho phép người dùng chọn liên kết (mở bằng) cho tiện ích mở rộng tệp hiện chưa được đăng ký.Làm cách nào để hiển thị hộp thoại "mở bằng" cho tiện ích mở rộng tệp chưa đăng ký?

Hiện tại tôi đang yêu cầu API mở tệp bằng cách sử dụng ShellExecute và nó trả về mã lỗi ERROR_NO_ASSOCIATION.

Có cách nào để nói cho API biết rằng nó có nên cho phép người dùng chọn một liên kết mới không?

+0

điều này có thể thực hiện: 'rundll32.exe shell32.dll, OpenAs_RunDLL" C: \ Đường dẫn \ TEXT.TXT "' –

+0

có thể trùng lặp của [Cách mở hộp thoại mặc định cho cửa sổ nếu ShellExecute không thành công do không có liên kết tệp nào trong C++?] (Http: // stackoverflow.com/questions/6364879/how-to-open-a-mặc định-hộp thoại-cho-cửa sổ-if-shellexecute-lỗi-do-no-file-ass) – Anders

Trả lời

11

tôi sử dụng

procedure ShellOpenAs(const AFileName: string; AHandle: HWND); 
begin 
    ShellExecute(AHandle, 'open', PChar('rundll32.exe'), PChar('shell32.dll,OpenAs_RunDLL ' + AFileName), nil, SW_SHOWNORMAL); 
end; 

Sửa (lấy cảm hứng từ bình luận và https://stackoverflow.com/a/13229516/1431618 David): Người ta có thể bỏ qua ShellExecuteRunDll32 bằng cách gọi OpenAs_RunDLL trực tiếp:

procedure OpenAs_RunDLL(hwnd: HWND; hinst: HINST; lpszCmdLine: LPSTR; nCmdShow: Integer); stdcall; external shell32; 

procedure ShellOpenAs(AHandle: HWND; const AFileName: string); 
begin 
    OpenAs_RunDLL(AHandle, HInstance, PChar(AFileName), SW_SHOWNORMAL); 
end; 

Cũng SHOpenWithDialog là trên Windows Vista và sau đó. (Tôi tìm thấy nó thú vị mà Microsoft đã viết một RUNDLL điểm vào tương thích nhưng cho đến Vista không bận tâm để cung cấp một hàm API thông thường.)

+0

Cảm ơn, tôi sẽ thêm điều này làm dự phòng nếu lần đầu tiên không thành công, vì tôi chỉ muốn hộp thoại nếu tôi không thể mở nó. –

+1

Cách chính xác để gọi hộp thoại là sử dụng động từ 'openas' thay thế:' ShellExecute (AHandle, 'openas', PChar (AFileName), nil, nil, SW_SHOWNORMAL); ' –

+0

@Remy: Điều này không hiệu quả đối với tôi (Windows 7 64 bit). Tôi gặp lỗi hệ thống 1155 - được dịch từ tiếng Đức: "Tệp được chỉ định không có ứng dụng liên quan". –

3

Go với mã sau đây bạn sẽ nhận được của bạn solution-

public const uint SEE_MASK_INVOKEIDLIST = 12;//add this line in your code 


CoInitializeEx(NULL, COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE); 
SHELLEXECUTEINFO sei = { sizeof(sei) }; 
sei.nShow = SW_SHOWNORMAL; 
sei.lpVerb = "openas"; 
sei.lpFile = "C:\\yourfile.ext"; 
sei.lfmask= SEE_MASK_INVOKEIDLIST;//add this line in your code 
ShellExecuteEx(&sei); 

SEE_MASK_INVOKEIDLIST this variable set "Verb" from presented system registry. 
3

Simply không sử dụng động từ rõ ràng. Sử dụng một động từ cụ thể như 'mở' là một sai lầm lớn:

  • 'mở' có thể không phải là một động từ mặc định (ví dụ, nó có thể là 'chơi', 'chỉnh sửa' hoặc 'chạy')
  • 'mở' có thể không tồn tại

Đó là cách chính xác hơn để chỉ cần chuyển số không là động từ. Hệ thống sẽ tự động chọn động từ thích hợp nhất:

  • Mặc định động từ sẽ được sử dụng, nếu nó được thiết lập
  • động từ 'mở' sẽ được sử dụng, nếu không có động từ mặc định được thiết lập
  • động từ đầu tiên sẽ được sử dụng , nếu không có mặc định và động từ 'mở' có sẵn
  • nếu không có động từ được phân công - hệ thống sẽ mang lại "Open with" hộp thoại

Nói cách khác, đơn giản

ShellExecute(0, nil, 'C:\MyFile.StrangeExt', ...); 

sẽ hiển thị hộp thoại "Mở bằng".

Chỉ sử dụng động từ cụ thể nếu bạn muốn một hành động cụ thể. Ví dụ. 'in', 'khám phá', 'runas'. Nếu không - chỉ cần vượt qua số không.

Các vấn đề liên quan