如何使用默认文本编辑器打开文件?

4

我想打开一个*.conf文件。我希望使用标准的Windows编辑器(例如notepad.exe)打开此文件。

我目前有以下ShellExecute代码:

var
  sPath, conf: String;
begin
  try
  sPath := GetCurrentDir + '\conf\';
  conf := 'nginx.conf';
ShellExecute(Application.Handle, 'open', PChar(conf), '', Pchar(sPath+conf), SW_SHOW);
  except
    ShowMessage('Invalid config path.');
  end;
end; 

但是什么都没有发生。那我该改变什么?
3个回答

8
我该如何使用默认文本编辑器打开文件?
您需要使用 ShellExecuteEx 函数,并使用SHELLEXECUTEINFO 结构体的 lpClass 成员来指定您希望以文本文件的形式打开该文件。示例如下:
procedure OpenAsTextFile(const FileName: string);
var
  sei: TShellExecuteInfo;
begin
  ZeroMemory(@sei, SizeOf(sei));
  sei.cbSize := SizeOf(sei);
  sei.fMask := SEE_MASK_CLASSNAME;
  sei.lpFile := PChar(FileName);
  sei.lpClass := '.txt';
  sei.nShow := SW_SHOWNORMAL;
  ShellExecuteEx(@sei);
end;

将文件的完整路径作为FileName传递。


我可能会将类名设置为.txt,而不是txtfile,因为并不保证在所有系统上txtfile都是文本文件的注册progid。一些应用程序确实会更改它。 - Remy Lebeau
@RemyLebeau,谢谢你的回答。我承认对于Shell类名知之甚少,会听从你的经验和知识。 - David Heffernan
其实,在使用ShellExecuteEx()之前,我从未需要使用类名。我只是评论了文档中所说的内容(即类名可以是文件扩展名或progid),以及我对文件扩展名progid如何工作的一般了解。 - Remy Lebeau

4

主要问题在于你使用了 nginx.conf 作为文件名。你需要完整的文件名(包括驱动器和目录)。如果文件与你的EXE文件位于同一目录中,你应该这样做:

ShellExecute(Handle, nil,
  PChar(ExtractFilePath(Application.ExeName) + 'nginx.conf'),
  nil, nil, SW_SHOWNORMAL)

无需设置目录,通常应使用SW_SHOWNORMAL

此外,仅当运行应用程序的系统正确设置了.conf文件的文件关联时,此方法才有效。如果运行应用程序的系统使用MS Paint打开.conf文件,则上述代码将启动MS Paint。如果没有任何关联,则该行代码将无法工作。

您可以手动指定使用notepad.exe

ShellExecute(Handle, nil, PChar('notepad.exe'),
  PChar(ExtractFilePath(Application.ExeName) + 'nginx.conf'),
  nil, SW_SHOWNORMAL)

现在我们开始运行notepad.exe并将文件名作为第一个参数传递。
第三,你现在不应该像你这样使用try..exceptShellExecute可能因为其他原因而失败,而且无论如何,它都不会引发异常。相反,考虑
if FileExists(...) then
  ShellExecute(...)
else
  MessageBox(Handle, 'Invalid path to configuration file', 'Error', MB_ICONERROR)

现在,回到主要问题。我的第一个代码片段只有在运行您的应用程序的系统恰好具有适当的文件关联后缀.conf文件时才起作用,而第二个将始终打开记事本。更好的选择可能是使用用于打开.txt文件的应用程序。David的答案给出了一个例子。


+1 我没有发现文件名错误,认为关联是问题所在。我会保留我的回答,因为它展示了如何确保 .conf 文件被视为文本文件。 - David Heffernan
ShellExecute是一个Windows API调用,无论如何都不会引发Delphi异常。返回值小于等于32表示发生了错误。 - Gerry Coll
事实上,对于ShellExecute的错误处理相当无望。如果您想要进行真正的错误检查,您需要使用ShellExecuteEx - David Heffernan
2
在没有关联“.conf”扩展名的机器上(例如我现在使用的机器),这里的第一个代码示例将不起作用。第二个示例会强制使用记事本,而我讨厌那个。因为那不是我的默认文本编辑器,所以我从来没有使用过记事本。你肯定想要做的是用用户喜欢的文本编辑器打开文本文件。 - David Heffernan

0
使用
ShellExecute(0, 'Open', PChar(AFile), nil, '', 1{SW_SHOWNORMAL});

在 Delphi DX10 中,此函数定义在

Winapi.ShellAPI


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接