黒鬚です。
ショートカットの情報を取得したいのですが
思うように動きません。
ここの過去ログをみて
http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=6#0099.txt
を参考にしてがんばって作ってみましたが
モジュールエラーが発生します。
モジュールエラーの発生は CoUninitialize で起こっています。
function TForm1.GetLinkFileName(FName: String): String;
var
HR: HRESULT;
psl: IShellLink;
ppf: IPersistFile;
wsz: array [0..MAX_PATH] of WideChar;
szGotPath: array [0..MAX_PATH] of Char;
wfd: WIN32_FIND_DATA;
begin
CoInitialize(Nil);
HR := CoCreateInstance(CLSID_ShellLink, Nil, CLSCTX_INPROC_SERVER, IShellLink, psl);
if SUCCEEDED(HR) then begin
HR := psl.QueryInterface(IPersistFile, ppf);
if SUCCEEDED(HR) then begin
MultiByteToWideChar(CP_ACP, 0, PChar(FName), -1, wsz, MAX_PATH);
HR := ppf.Load( wsz, STGM_READ );
if SUCCEEDED(HR) then begin
HR := psl.Resolve(Application.Handle, SLR_ANY_MATCH);
if SUCCEEDED(HR) then begin
HR := psl.GetPath(szGotPath, MAX_PATH, wfd, SLGP_SHORTPATH );
if SUCCEEDED(HR) then Result := szGotPath;
end;
end;
ppf._Release;
end;
psl._Release;
end;
CoUninitialize;
end;
すみません。
ppf._Release;
psl._Release;
この2つを削除すると問題が出なくなりました。
問題あるのかも
黒鬚さんのエラー対策でないのですが,参考になれば幸いです.
以下は,私が使用しているコードです.動作確認はWindowXP + Delphi5
ですが,実行ファイルはWin98,WinMe,Win2k,WinXPで動作しています.
Formに以下を配置します.
TButton
TMemo
TOpenDialog
uses ShlObj,ActiveX,ComObj;
{$R *.DFM}
{ TForm1 }
//=============================================================================
// ファイル選択ダイアログを表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
OpenDialog1.Filter:='ショートカット(*.lnk)|*.LNK';
if OpenDialog1.Execute then begin
GetLinkPath(OpenDialog1.FileName);
end;
end;
//=============================================================================
// IShellLinkを使用するにusesにShlObjが必要
// IPersistFileを使用するにはusesにActiveXが必要
// CreateComObjectを使用するにはusesにComObjが必要
//=============================================================================
procedure TForm1.GetLinkPath(FileName: String);
var
ShellLink : IShellLink;
PersistFile : IPersistFile;
FilePath : array[0..MAX_PATH] of char;
WorkDir : array[0..MAX_PATH] of char ;
Arg : array[0..MAX_PATH] of char;
FileLink : String;
wsz : array[0..MAX_PATH] of WideChar;
pfd : TWin32FindData;
begin
FileLink := FileName;
ShellLink := CreateComObject(CLSID_ShellLink) as IShellLink;
OleCheck(ShellLink.QueryInterface(IPersistFile,PersistFile));
Assert(Assigned(PersistFile));
MultiByteToWideChar(CP_ACP,0,PChar(FileLink),-1,wsz,MAX_PATH);
OleCheck(PersistFile.Load(wsz,0));
OleCheck(ShellLink.GetPath(FilePath,MAX_PATH,pfd,SLGP_RAWPATH));
OleCheck(ShellLink.GetWorkingDirectory(WorkDir,MAX_PATH));
OleCheck(ShellLink.GetArguments(Arg, MAX_PATH));
//上から順にプログラムパス名,作業フォルダ,起動オプション
//実際のPCではリンク先としてパス名に起動オプションが付加されている
Memo1.Clear;
Memo1.Lines.Add(ExtractFileName(FileName));
Memo1.Lines.Add(StrPas(FilePath));
Memo1.Lines.Add(StrPas(WorkDir));
Memo1.Lines.Add(StrPas(Arg));
end;
おっ,一足遅かったですね.
Mr.XRAY さん
早速ですが、別件の質問があって
書き込み前にちょっと試してみました。
えっと、私のやり方だと、パス名がショート(〜が付く)になってまして
質問しようと思ったのですが、Mr.XRAY さんのは
そのままロングパス名で取得できました。
こういうのを、ことわざで・・・・・・・
っていうんでしょうね?(−−;
ありがとうございました。
ちなみに、パスもファイル名もショートになっているのを
すべて一括でロングにする方法って知ってますか?
昔、ファイルやディレクトリ名の単体には FindFirst で
変換してたけど、このやり方だとパスを一つ一つ分割してからの処理で
面倒なんですよね。
もし、しってらっしゃったら教えてください。
>変換してたけど、このやり方だとパスを一つ一つ分割してからの処理で
>面倒なんですよね。
でもこれしかないようです.私が取得した情報では.
//=============================================================================
// 短いファイル名を長いファイル名に変換する関数
// 途中のディレクトリ名が短い場合を考慮して再帰処理
//=============================================================================
function TForm1.ShortToLong(ShortName: String): String;
var
S : TSearchRec;
FileDir : String;
FileName : String;
begin
FileDir := ExtractFileDir(ShortName);
FileName := ExtractFileName(ShortName);
if Length(FileName)=0 then begin
Result := FileDir;
exit;
end;
FileDir :=ShortToLong(FileDir);
FileDir :=IncludeTrailingBackslash(FileDir);
try
if FindFirst(FileDir+FileName,faAnyFile,S)<>0 then begin
Result := ShortName
end else begin
Result :=FileDir+S.Name;
end;
finally
FindClose(S);
end;
end;
すみません.現用のアプリで使用しているものをそのままアップして
いまいました.動作確認していません.多分現用のものなのでOKかと...
(ショートカットを見つけるか作らないと...簡単か?)
原理は,デリミタを除いたディレクトリ名を順番に長いファイル名に
していくという,黒鬚さんのやり方を関数にしたものです.
HDDを見ていたら,こんなのがありました.
使えるのではないかと思います.
interface部でもimplementation部も構いません.この関数を使用する前に
以下のコードを追加して下さい.
function GetLongPathNameA(ShortPathName: PChar; LongPathName: PChar;
cchBuffer: Integer): Integer; stdcall; external 'kernel32.dll';
//====================================================================
// kernel32.dll内の関数GetLongPathNameを利用
// GetLongPathNameGetFullPathNameと違いWin98でも大文字と小文字を区
// 別して取得可能
//====================================================================
function TForm1.ShortToLongPath(ShortName: String): String;
var
Buffer : array[0..MAX_PATH] of Char;
begin
if (GetLongPathNameA(PChar(ShortName),Buffer,SizeOf(Buffer)))<>0 then
begin
Result:=Buffer;
end else
begin
Result:=ShortName;
end;
end;
ツイート | ![]() |