📄 hx_moreprocesses.c
字号:
info.processAppSpec = nil;
if (noErr != (e = GetProcessInformation (&psn, &info))) break;
if (AppSignature != info.processSignature) continue;
theResult++;
} /* while */
return (theResult);
}
//
// ActivateApplication
//
void ActivateApplication(OSType AppSignature) {
OSErr e = noErr;
ProcessSerialNumber psn = {kNoProcess, kNoProcess};
while (noErr == (e = GetNextProcess (&psn))) {
ProcessInfoRec info;
info.processInfoLength = sizeof (info);
info.processName = nil;
info.processAppSpec = nil;
if (noErr != (e = GetProcessInformation (&psn, &info))) break;
if (AppSignature != info.processSignature) continue;
ActivateApplicationPSN(&psn);
break;
} /* while */
}
//
// ActivateApplicationPSN
//
void ActivateApplicationPSN(ProcessSerialNumber *psn) {
if (psn == 0L) return;
SetFrontProcess(psn);
}
//
// FSpLaunchApplication launches a Mac application given a file spec
//
OSErr FSpLaunchApplication (FSSpec *appSpec) {
return FSpLaunchApplicationWithParams(appSpec, NULL, NULL);
}
//
// FSpLaunchApplication launches a Mac application given a file spec
// and an option Apple Event to include as a launch parameter
//
// If psn is non-nil, the launched processes' PSN is returned
//
OSErr FSpLaunchApplicationWithParams(FSSpec *appSpec, const AppleEvent *theEvent, ProcessSerialNumber *psn)
{
return FSpLaunchApplicationWithParamsAndFlags(appSpec, theEvent, psn, (launchContinue | launchNoFileFlags));
}
OSErr FSpLaunchApplicationWithParamsAndFlags(FSSpec *appSpec, const AppleEvent *theEvent, ProcessSerialNumber *psn, short launchFlags)
{
OSErr err = noErr;
LaunchParamBlockRec launchPB;
AEDesc paramsDesc;
paramsDesc.dataHandle = NULL;
launchPB.launchBlockID = extendedBlock;
launchPB.launchEPBLength = extendedBlockLen;
launchPB.launchFileFlags = 0;
launchPB.launchControlFlags = launchFlags;
launchPB.launchAppSpec = appSpec;
launchPB.launchAppParameters = NULL;
// if we were passed an event, convert and attach that to the launch param block
if (theEvent)
{
err = AECoerceDesc(theEvent, typeAppParameters, ¶msDesc);
if (err == noErr)
{
#if !defined(_CARBON) && !defined(_MAC_UNIX)
HLock(paramsDesc.dataHandle);
#endif
launchPB.launchAppParameters = (AppParametersPtr) *paramsDesc.dataHandle;
}
}
// do the launch
if (err == noErr)
{
err = LaunchApplication(&launchPB);
if (err == noErr && psn != NULL)
{
*psn = launchPB.launchProcessSN;
}
}
// if we had an event to convert and attach, dispose our converted version
if (paramsDesc.dataHandle) (void) AEDisposeDesc(¶msDesc);
return err;
}
OSErr FSpLaunchApplicationPSN (FSSpec *appSpec,ProcessSerialNumber* psn) {
return FSpLaunchApplicationWithParams(appSpec, NULL, psn);
}
//
// OpenDocumentWithApplication sends an event to the target application
// to open the document, launching the application if necessary.
//
// Unlike sending an Apple event to the finder, this gives us an
// error if the open doesn't happen
//
OSErr OpenDocumentWithApplication(OSType signature, FSSpec *file)
{
OSErr err;
ProcessSerialNumber appPSN;
FSSpec appSpec;
AEDesc targetAddrDesc;
AppleEvent theAppleEvent, theReplyEvent;
AliasHandle fileAlias;
theAppleEvent.dataHandle = NULL; // to facilitate cleanup
targetAddrDesc.dataHandle = NULL;
appPSN.lowLongOfPSN = 0;
fileAlias = NULL;
err = GetPSNFromSignature(signature, &appPSN);
if (err != noErr)
{
// app isn't running, we'll try to launch it
//
// address the event target by the process's signature
err = AECreateDesc(typeApplSignature, &signature, sizeof(DescType), &targetAddrDesc);
}
else
{
// address target by PSN
err = AECreateDesc(typeProcessSerialNumber, &appPSN, sizeof(ProcessSerialNumber), &targetAddrDesc);
}
if (err == noErr)
{
// make the Apple event, stuff in an alias to the file as the direct object
err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &targetAddrDesc,
kAutoGenerateReturnID, kAnyTransactionID, &theAppleEvent);
if (err == noErr)
{
err = NewAliasMinimal(file, &fileAlias);
if (err == noErr)
{
HLock((Handle) fileAlias);
err = AEPutParamPtr(&theAppleEvent, keyDirectObject, typeAlias,
*fileAlias, GetHandleSize((Handle) fileAlias));
}
}
}
if (err == noErr)
{
if (appPSN.lowLongOfPSN)
{
// app is running and we know its PSN, so
// send the event directly to it
err = AESend(&theAppleEvent, &theReplyEvent, kAENoReply,
kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
(void) SetFrontProcess(&appPSN);
}
else
{
// the app isn't running, so launch it with the
// event attached
err = FindApplicationBySignature(signature, &appSpec);
if (err == noErr)
{
err = FSpLaunchApplicationWithParams(&appSpec, &theAppleEvent, NULL);
}
}
}
if (fileAlias) DisposeHandle((Handle) fileAlias);
if (theAppleEvent.dataHandle) (void) AEDisposeDesc(&theAppleEvent);
if (targetAddrDesc.dataHandle) (void) AEDisposeDesc(&targetAddrDesc);
return err;
}
//
// LaunchApplicationBySignature finds an application on a local
// volume and launches it. theEvent can be null if no Apple
// event should be attached.
//
OSErr LaunchApplicationBySignature(OSType signature, AppleEvent *theEvent)
{
OSErr err;
FSSpec appSpec;
err = FindApplicationBySignature(signature, &appSpec);
if (err == noErr)
{
err = FSpLaunchApplicationWithParams(&appSpec, theEvent, NULL);
}
return err;
}
//
// FindApplicationBySignature finds an application on a local (not server)
// volume by checking the Desktop Databases of the mounted drives
//
// appSpec can be NULL if the caller is just interested in if the app
// exists or not
//
OSErr FindApplicationBySignature(OSType signature, FSSpec *appSpec)
{
#ifndef _MAC_UNIX
Str63 name;
short volIndex;
short vRefNum;
HParamBlockRec hpb;
DTPBRec dtpb;
GetVolParmsInfoBuffer gvpb;
Boolean foundAppFlag;
Boolean giveUpFlag;
#endif
OSErr err;
#if defined(_CARBON) || defined(_MAC_UNIX)
if (IsRunningNativeOnMacOSX())
{
// Mac OS X; we can't rely on the desktop database, so use launch services
FSRef appRef;
err = GetApplicationFSRefFromSignature(signature, &appRef);
if (err == noErr)
{
err = FSRefMakeFSSpec(&appRef, appSpec);
}
return err;
}
#endif
#if defined(_MAC_UNIX)
return -1; // should never get here
#else
foundAppFlag = false;
giveUpFlag = false;
// step through each volume available
volIndex = 1;
do {
name[0] = 0;
hpb.volumeParam.ioNamePtr = name;
hpb.volumeParam.ioVolIndex = volIndex;
hpb.volumeParam.ioVRefNum = 0;
hpb.volumeParam.ioCompletion = NULL; // shouldn't matter since we're calling sync
err = PBHGetVInfoSync(&hpb);
if (err == noErr)
{
vRefNum = hpb.volumeParam.ioVRefNum;
// check only local volumes for the application
//
// PBHGetVolParms returns vMServerAdr of zero for local volumes
//
// name and vRefNum are already set in param block hpb from the PBHGetVInfo call
hpb.ioParam.ioBuffer = (char *) &gvpb;
hpb.ioParam.ioReqCount = sizeof(GetVolParmsInfoBuffer);
err = PBHGetVolParmsSync(&hpb);
if (err == noErr && gvpb.vMServerAdr == 0)
{
// now we know this is a valid, local volume;
// see if it has a desktop database
dtpb.ioNamePtr = NULL;
dtpb.ioVRefNum = vRefNum;
err = PBDTGetPath(&dtpb);
if (err == noErr)
{
// this volume has a desktop database; search it
name[0] = 0;
dtpb.ioNamePtr = name;
dtpb.ioIndex = 0; // get newest application
dtpb.ioFileCreator = signature;
dtpb.ioCompletion = NULL; // shouldn't matter since we're calling sync
// dtpb.ioDTRefNum set by GetPath call
err = PBDTGetAPPLSync(&dtpb);
if (err == noErr)
{
FSSpec foundSpec;
err = FSMakeFSSpec(vRefNum, dtpb.ioAPPLParID, name, &foundSpec);
if (err == noErr)
{
if (appSpec) *appSpec = foundSpec;
// we got the app; bail
foundAppFlag = true;
}
}
}
}
}
else
{
// PBHGetVInfoSync returned an error
giveUpFlag = true;
}
volIndex++;
} while (!giveUpFlag &&!foundAppFlag);
// at this point, we should have noErr indicating that we found
// an app and the FSSpec is valid
return err;
#endif // !defined _MAC_UNIX
}
OSErr SendQuitEventToApplication(ProcessSerialNumber *psn)
{
OSErr err;
AEAddressDesc targetAddrDesc;
AppleEvent theAppleEvent;
AppleEvent replyAppleEvent;
// address target by PSN
err = AECreateDesc(typeProcessSerialNumber, psn, sizeof(ProcessSerialNumber), &targetAddrDesc);
if (err == noErr)
{
// make the quit event
err = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &targetAddrDesc,
kAutoGenerateReturnID, kAnyTransactionID, &theAppleEvent);
(void) AEDisposeDesc(&targetAddrDesc);
}
if (err == noErr)
{
// send it
err = AESend(&theAppleEvent, &replyAppleEvent, kAENoReply,
kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
(void) AEDisposeDesc(&theAppleEvent);
}
return err;
}
#if defined(_CARBON) || defined(_MAC_UNIX)
OSStatus GetApplicationFSRefFromSignature(OSType signature, FSRef *outAppFSRef)
{
OSStatus err;
const OSType kAnyFileType = kLSUnknownType;
const CFStringRef kAnyExtension = NULL;
CFURLRef* kDontWantURL = NULL;
if (IsRunningNativeOnMacOSX())
{
err = LSGetApplicationForInfo(kAnyFileType, signature, kAnyExtension, kLSRolesAll, outAppFSRef, kDontWantURL);
}
else
{
FSSpec appSpec;
err = FindApplicationBySignature(signature, &appSpec);
if (err == noErr)
{
err = FSpMakeFSRef(&appSpec, outAppFSRef);
}
}
return err;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -