あまつぶ

12.2 【元ファイルを探せ】

 誕生日を迎えた。起動中に「Happy Birthday!」などと表示されるとちょっとうれしいが、フリーズして再起動した時にも表示されるのはなんだかむなしい(笑)。

 ふとちょうど1年前はなにをしていたのかなと思って見てみると、IconPartyのバグフィックスにおわれていた。1年たってもやっていることは同じなのか(汗)。ま、バージョンは次を0.20b1にするとかそんなところだったらしいからそこから比べたらだいぶ進化(?)したかな。

 Phut。終了時にフリーズするという問題はいまだに解決していないようだ。11.27に解決したと書いたが、勘違いであった。
 1.15b5で追加したログ作成機能で多少は進展した気がするが、問題がある可能性のある場所が減っただけで場所を特定するところまではいたっていない状況。本当にちゃんと解決できるのかどうか……。

 これもバグ(仕様?)のようなものなのだけど、AppleShare上のボリューム(っていう表現が正しいのかどうかよく知らないけど、別のマシン上の……ってこと)を登録した時に再起動するとアイコンが「?」になってしまうという問題もある(当然、マウントされていない時の話)。また、マウントされていない状態でエイリアスを登録しようとすると止まってしまうらしい(ドラッグ&ドロップ中だからログインダイアログが出ないのかな?)。
 うちではネットワークを構築していないので調べることができないのだが、Zipのディスクのエイリアスなんかで同じようなことをしてみるとResolveAlias()を呼んだ時点でディスクの挿入を要求してくるから、ネットワークの場合も同様にログインダイアログが表示されるのだろうと思われる。ディスク挿入のダイアログではドロップ時に呼ばれても問題ないのだが、ログインの方はだめなんだろうか。
 ResolveAlias()を呼んだ時点でダイアログが表示されるなら、別の方法で元のファイル/フォルダを探してやるしかない。IMを読むとMatchAlias()というResolveAlias()の下請けルーチンのようなものがあってそれで地道にやればできるらしい(元ファイルを探すルールを指定できる)。ヘッダファイル(Aliases.h)を見ると、IMには載っていない、ResolveAliasFileWithMountFlags()とか使えそうなものがいくつかある。これってどんな環境で使えるものなんだろう。
 IMには載っていないからAppleのHPで検索してみる。すると、Technote FL 30「Resolving Alias Files Quietly」というのを発見。それによればMacOS 8.5以降で使用可能とのこと(これらのルーチンはこれまでドキュメントに載っていなかったFollowFinderAlias()を内部的に呼び出しているらしい)。そうすると、それ以前の環境では、FollowFinderAlias()は使えるかも知れないが他はだめということか。使えるかも知れないFollowFinderAlias()についても、内部的に使用されるものだからアプリケーションからの使用は奨励されないということで、結局だめみたいだ。

 そうすると、やはりMatchAlias()を使ってがんばるしかない。MatchAlias()では一度に1段階しか解決することができないから、再帰的に呼び出してやることになる。とりあえず、

/* エイリアスの元ファイルを探す。ユーザインタラクションを許可しない */
OSErr ResolveAliasFileWithNoUI(FSSpec *fromFile,
		Boolean resolveAliasChains,Boolean *wasAliased)
{
	OSErr	err;
	Boolean	isFolder;
	
	err=MyIsAliasFile(fromFile,wasAliased,&isFolder);
	if (*wasAliased)
	{
		err=ResolveAliasFileWithNoUIMain(fromFile,
			resolveAliasChains);
	}
	
	return err;
}

OSErr ResolveAliasFileWithNoUIMain(FSSpec *fromFile,
		Boolean resolveAliasChains)
{
	OSErr	err;
	short	refNum,curRefNum=CurResFile();
	AliasHandle	theAlias;
	short	count=1;
	Boolean	needsUpdate,wasChanged;
	FSSpec	theSpec;
	Boolean	isAlias,isFolder;
	
	refNum=FSpOpenResFile(fromFile,fsRdPerm);
	if (refNum <= 0) return ResError();
	
	theAlias=(AliasHandle)Get1Resource(rAliasType,0);
	if (theAlias == nil) return -1;
	
	err=MatchAlias(nil,kARMNoUI+kARMMultVols+kARMSearch,theAlias,
		&count,&theSpec,&needsUpdate,nil,nil);
	if (err==noErr)
	{
		*fromFile=theSpec;
		if (needsUpdate)
			err=UpdateAlias(nil,&theSpec,theAlias,
				&wasChanged);
	}
	CloseResFile(refNum);
	
	if (err==noErr && resolveAliasChains)
	{
		err=MyIsAliasFile(fromFile,&isAlias,&isFolder);
		if (err==noErr && isAlias)
			err=ResolveAliasFileWithNoUIMain(fromFile,
				resolveAliasChains);
	}
	
	return err;
}

/* エイリアスかどうかをチェック */
OSErr MyIsAliasFile(const FSSpec *fileFSSpec,
		Boolean *aliasFileFlag,Boolean *folderFlag)
{
	OSErr	err;
	FInfo	fInfo;
	
	*aliasFileFlag=false;
	*folderFlag=false;
	
	err=FSpGetFInfo(fileFSSpec,&fInfo);
	if (err==noErr)
	{
		*aliasFileFlag = (fInfo.fdFlags & kIsAlias) != 0;
	}
	else
	{
		DInfo	dInfo;
		
		err=FSpGetDInfo(fileFSSpec,&dInfo);
		if (err==noErr) *folderFlag=true;
	}
	
	return err;
}

こんなルーチンを書いてみた。呼び出し方法はResolveAliasFile()とほぼ同じだからすぐにわかると思う。下請けのルーチンが2つあって、片方は再帰呼び出しをするメインルーチン、もうひとつはファイルがエイリアスかどうかを調べるもの。内部でMoreFilesのFSpGetDInfo()を使っている。
 Zipのディスクのエイリアスで試してみると、めでたくダイアログが表示されなくなった。おそらく、AppleShareの場合にもできているはず……。

 というところでPhut 1.15b6をリリース。ネットワーク上のファイルなどを登録する場合には今回のバージョンからはエイリアスを登録するといい(ネットワークに接続されていない状態で)。そうすればアイコンが表示されなくなることもないし(エイリアス自体は見つけられるわけだから)、クリックすれば(おそらく)ログインのダイアログが表示される。実際にはPhut自体でアイコンも保持しておくべきなのだろうが、ま、裏技みたいな感じかな。


November 28, 1999 ↑ December index → December 3, 1999