3

ここからコードを少し変更しました。

Delphi-私のプログラムからファイルにアクセスしているプロセスを見つける

指定されたpIDでハンドル名のリストを返すために、すべてのエントリをTStringListに追加します。問題は、名前に「?」のようなゴミが含まれていることです。ユニコード文字を含むファイル名では、たとえば「xxx★5」は「xxx?5」として表示されます

コードの何が問題になっていますか?

4

1 に答える 1

8

非 ASCII 文字にクエスチョン マークが表示されるのは、Unicode から ANSI への変換を試みることの特徴です。

問題はこの関数にあります:

function GetFileNameHandleThr(Data: Pointer): DWORD; stdcall;
var
  dwReturn: DWORD;
  FileNameInfo: FILE_NAME_INFORMATION;
  ObjectNameInfo: TOBJECT_NAME_INFORMATION;
  IoStatusBlock: IO_STATUS_BLOCK;
  pThreadParam: TGetFileNameThreadParam;
begin
  ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION));
  pThreadParam := PGetFileNameThreadParam(Data)^;
  Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock,  @FileNameInfo, MAX_PATH * 2, FileNameInformation);
  if Result = STATUS_SUCCESS then
  begin
    Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation,  @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
    if Result = STATUS_SUCCESS then
    begin
      pThreadParam.Result := Result;
      WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], ObjectNameInfo.Name.Length, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
    end
    else
    begin
      pThreadParam.Result := STATUS_SUCCESS;
      Result := STATUS_SUCCESS;
      WideCharToMultiByte(CP_ACP, 0, @FileNameInfo.FileName[0], IoStatusBlock.Information, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
    end;
  end;
  PGetFileNameThreadParam(Data)^ := pThreadParam;
  ExitThread(Result);
end;

これにより、 への呼び出しで Unicode から ANSI に変換されますWideCharToMultiByte。コードのその部分を削除するだけです。

このレコードを変更する必要があります

TGetFileNameThreadParam = packed record
  hFile    : THandle;
  Result   : NT_STATUS;
  FileName : array [0..MAX_PATH - 1] of AnsiChar;
end;

これFileNameは の配列ですWideChar

TGetFileNameThreadParam = packed record
  hFile    : THandle;
  Result   : NT_STATUS;
  FileName : array [0..MAX_PATH - 1] of WideChar;
end;

そして、それGetFileNameHandleThrに応じて適応します。詳しくは調べていませんが、次のようなものが必要になると思います。

function GetFileNameHandleThr(Data: Pointer): DWORD; stdcall;
var
  dwReturn: DWORD;
  FileNameInfo: FILE_NAME_INFORMATION;
  ObjectNameInfo: TOBJECT_NAME_INFORMATION;
  IoStatusBlock: IO_STATUS_BLOCK;
  pThreadParam: TGetFileNameThreadParam;
begin
  ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION));
  pThreadParam := PGetFileNameThreadParam(Data)^;
  Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock,  @FileNameInfo, MAX_PATH * 2, FileNameInformation);
  if Result = STATUS_SUCCESS then
  begin
    Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation,  @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
    if Result = STATUS_SUCCESS then
    begin
      pThreadParam.Result := Result;
      Move(ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], pThreadParam.FileName[0], Min(ObjectNameInfo.Name.Length, MAX_PATH)*SizeOf(WideChar));
      //WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], ObjectNameInfo.Name.Length, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
    end
    else
    begin
      pThreadParam.Result := STATUS_SUCCESS;
      Result := STATUS_SUCCESS;
      Move(FileNameInfo.FileName[0], pThreadParam.FileName[0], Min(IoStatusBlock.Information, MAX_PATH)*SizeOf(WideChar));
      //WideCharToMultiByte(CP_ACP, 0, @FileNameInfo.FileName[0], IoStatusBlock.Information, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
    end;
  end;
  PGetFileNameThreadParam(Data)^ := pThreadParam;
  ExitThread(Result);
end;

私はこのコードを実行していないので、さらに作業する必要があるかもしれません。ただし、ANSI への変換に問題があることは明らかです。

このコードを実行したところ、うまく機能しました。

于 2013-01-14T11:12:24.377 に答える