Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
sources/LaunchApplication.c
// |
// Apple Macintosh Developer Technical Support |
// |
// Copyright (work in progress) Apple Computer, Inc All rights reserved. |
// |
// You may incorporate this sample code into your applications without |
// restriction, though the sample code has been provided "AS IS" and the |
// responsibility for its operation is 100% yours. However, what you are |
// not permitted to do is to redistribute the source as "DSC Sample Code" |
// after having made changes. If you're going to re-distribute the source, |
// we require that you make it clear in the source that the code was |
// descended from Apple Sample Code, but that you've made changes. |
// |
#include <Processes.h> |
#include "LaunchApplication.h" |
static OSErr FindApplicationProcess (OSType creatorToFind, ProcessSerialNumberPtr processSN); |
static OSErr FindApplicationOnDisk (OSType creatorToSearchFor, short startVRefNum, FSSpec* foundApp); |
//------------------------------------------------------------------------------------ |
OSErr LaunchApplication (OSType creator) |
//------------------------------------------------------------------------------------ |
{ |
ProcessSerialNumber theAppPSN; |
FSSpec theAppToLaunch; |
OSErr err = noErr; |
// Check for already running app |
err = FindApplicationProcess(creator , &theAppPSN ); |
if(err == noErr) |
{ |
err = SetFrontProcess( &theAppPSN ); |
} |
else |
{ |
err = FindApplicationOnDisk (creator, 0, &theAppToLaunch); |
if(err == noErr) |
{ |
LaunchParamBlockRec launchPB; |
launchPB.launchBlockID = extendedBlock; |
launchPB.launchEPBLength = extendedBlockLen; |
launchPB.launchFileFlags = 0; |
launchPB.launchControlFlags = launchContinue | launchNoFileFlags; |
launchPB.launchAppSpec = &theAppToLaunch; |
launchPB.launchAppParameters = nil; |
LaunchApplication( &launchPB ); |
} |
} |
return err; |
} |
// |
// This runs through the process list looking for the requested application. It searches for |
// applications of type 'APPL', 'APPC' (control panel apps), 'APPE' (extension apps), and |
// 'APPD' (desk accessory apps). Once the requested application has been found processSN |
// will contain the process serial number of the running application that was just found. |
// |
static OSErr FindApplicationProcess (OSType creatorToFind, ProcessSerialNumberPtr processSN) |
{ |
ProcessInfoRec procInfo; |
FSSpec procSpec; |
Str31 processName; |
OSErr err = noErr; |
// Clear out the PSN so we're starting at the beginning of the list. |
processSN->lowLongOfPSN = kNoProcess; |
processSN->highLongOfPSN = kNoProcess; |
// Initialize the process information record. |
procInfo.processInfoLength = sizeof (ProcessInfoRec); |
procInfo.processName = &processName[0]; |
procInfo.processAppSpec = &procSpec; |
// Loop through all the processes until we find the process we want or |
// error out because of some reason (usually, no more processes). |
do { |
err = GetNextProcess (processSN); |
if (err == noErr) { |
err = GetProcessInformation (processSN, &procInfo); |
} |
} while ((procInfo.processSignature != creatorToFind || !(procInfo.processType == 'APPL' || |
procInfo.processType == 'APPC' || procInfo.processType == 'appe' || |
procInfo.processType == 'APPD')) && err == noErr); |
return (err); |
} |
// |
// Finds the requested application on disk searching the desktop database and returns an FSSpec to that app. |
// It first searches local disks, then searches remote disks. Once a possible application has been found |
// in the desktop database the application is verified to actually exist because the desktop database is |
// often not totally accurate. |
// |
// If startVRefNum is negative then it will be treated as a VRefNum and the search will start on specified |
// volume. If the value of startVRefNum is 0 or positive then the search starts on the first local disk, |
// runs through all local disks, and then searches the first remote volume and runs through all remote |
// volumes looking for the requested application. |
// |
static OSErr FindApplicationOnDisk (OSType creatorToSearchFor, short startVRefNum, FSSpec* foundApp) { |
HVolumeParam volPB; |
HIOParam paramPB; |
DTPBRec desktopPB; |
GetVolParmsInfoBuffer volinfo; |
FInfo fndrInfo; |
OSErr err = fnfErr; // default return value |
volPB.ioNamePtr = nil; |
paramPB.ioNamePtr = nil; |
paramPB.ioBuffer = (Ptr)&volinfo; |
paramPB.ioReqCount = sizeof (volinfo); |
// Try to find the application on the specified disk, if one was specified, first. |
if (startVRefNum < 0) { |
volPB.ioVolIndex = startVRefNum; |
if (PBHGetVInfoSync ((HParmBlkPtr)&volPB) == noErr) { |
// Call PBDTGetPath to find the desktop file on the volume. |
desktopPB.ioCompletion = nil; |
desktopPB.ioNamePtr = nil; |
desktopPB.ioVRefNum = volPB.ioVRefNum; |
desktopPB.ioIndex = 0; // Find the most recent application. |
if (PBDTGetPath (&desktopPB) == noErr) { |
desktopPB.ioFileCreator = creatorToSearchFor; |
desktopPB.ioNamePtr = (*foundApp).name; |
if (PBDTGetAPPLSync (&desktopPB) == noErr) { |
// At this point we think we have found the correct application. |
(*foundApp).vRefNum = volPB.ioVRefNum; |
(*foundApp).parID = desktopPB.ioAPPLParID; |
// Verify that this application actually exists. |
if (FSpGetFInfo (foundApp, &fndrInfo) == noErr && fndrInfo.fdCreator == creatorToSearchFor) { |
// This application actually exists, we can use it. |
err = noErr; |
} |
} |
} |
} |
} |
if (err != noErr) { |
// The application wasn't on the starting disk, so loop over every local volume looking for the application. |
for (volPB.ioVolIndex = 1; PBHGetVInfoSync ((HParmBlkPtr)&volPB) == noErr; volPB.ioVolIndex++) { |
// Call PBHGetVolParms call to ensure the volume is a local volume. |
paramPB.ioVRefNum = volPB.ioVRefNum; |
if (PBHGetVolParmsSync ((HParmBlkPtr)¶mPB) == noErr && volinfo.vMServerAdr == 0) { |
// Call PBDTGetPath to find the desktop file on the volume. |
desktopPB.ioCompletion = nil; |
desktopPB.ioNamePtr = nil; |
desktopPB.ioVRefNum = volPB.ioVRefNum; |
desktopPB.ioIndex = 0; // Find the most recent application. |
if (PBDTGetPath (&desktopPB) == noErr) { |
desktopPB.ioFileCreator = creatorToSearchFor; |
desktopPB.ioNamePtr = (*foundApp).name; |
if (PBDTGetAPPLSync (&desktopPB) == noErr) { |
// At this point we think we have found the correct application. |
(*foundApp).vRefNum = volPB.ioVRefNum; |
(*foundApp).parID = desktopPB.ioAPPLParID; |
// Verify that this application actually exists. |
if (FSpGetFInfo (foundApp, &fndrInfo) == noErr && fndrInfo.fdCreator == creatorToSearchFor) { |
// This application actually exists, we can use it. |
err = noErr; |
break; |
} |
} |
} |
} |
} |
} |
if (err != noErr) { |
// If we didn't find the application locally, check remote volumes. |
// Loop over every local volume looking for the application. |
for (volPB.ioVolIndex = 1; PBHGetVInfoSync ((HParmBlkPtr)&volPB) == noErr; volPB.ioVolIndex++) { |
// Call PBHGetVolParms call to ensure the volume is a remote volume. |
paramPB.ioVRefNum = volPB.ioVRefNum; |
if (PBHGetVolParmsSync ((HParmBlkPtr)¶mPB) == noErr && volinfo.vMServerAdr != 0) { |
// Call PBDTGetPath to find the desktop file on the volume. |
desktopPB.ioCompletion = nil; |
desktopPB.ioNamePtr = nil; |
desktopPB.ioVRefNum = volPB.ioVRefNum; |
desktopPB.ioIndex = 0; // Find the most recent application. |
if (PBDTGetPath (&desktopPB) == noErr) { |
desktopPB.ioFileCreator = creatorToSearchFor; |
desktopPB.ioNamePtr = (*foundApp).name; |
if (PBDTGetAPPLSync (&desktopPB) == noErr) { |
// At this point we have found the correct application. |
(*foundApp).vRefNum = volPB.ioVRefNum; |
(*foundApp).parID = desktopPB.ioAPPLParID; |
// Verify that this application actually exists. |
if (FSpGetFInfo (foundApp, &fndrInfo) == noErr && fndrInfo.fdCreator == creatorToSearchFor) { |
// This application actually exists, we can use it. |
err = noErr; |
break; |
} |
} |
} |
} |
} |
} |
return err; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22