// // DeVercruesseProcess.m // // Created by Frank Vercruesse on Wed Apr 04 2001. // Copyright (c) 2001 Frank Vercruesse. // // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. #import "DeVercruesseProcess.h" #import "DeVercruesseProcessManager.h" @implementation DeVercruesseProcess + (id)processWithPSN:(ProcessSerialNumber*)sn { return [[[self alloc] initWithPSN:sn] autorelease]; } - (id)init { return [self initWithPSN:nil]; } - (id)initWithPSN:(ProcessSerialNumber*)sn { OSErr err; CPSProcessInfoRec pInfo; int dummy; if( sn ) { err = CPSGetProcessInfo( (CPSProcessSerNum*) sn, &pInfo, nil, 0, &dummy, nil, 0); if( !err ) { self = [super init]; if( self ) { psn.highLongOfPSN = sn->highLongOfPSN; psn.lowLongOfPSN = sn->lowLongOfPSN; pid = pInfo.UnixPID; flavour = pInfo.Flavour; attributes = pInfo.Attributes; type = pInfo.ExecFileType; creator = pInfo.ExecFileCreator; bundleIdentifier = nil; identifier = nil; name = nil; loc = nil; img = nil; } } else { [self dealloc]; return nil; } } else { [self dealloc]; return nil; } return self; } - (void)dealloc { [bundleIdentifier release]; [identifier release]; [name release]; [img release]; [cachedImage release]; [loc release]; [super dealloc]; } - (NSString *)executableLoc; { CFStringRef bundleLoc = (CFStringRef) [self loc]; CFURLRef bundleURL; CFBundleRef bundleRef; if (bundleLoc == NULL) { // GetProcessBundleLocation returns NULL on 10.1.5 for certain CFM Carbon applications (BBEdit 6.5.3) - njr return nil; // XXX should really handle this better, but for the purposes of F-Script Anywhere, we donŐt care if itŐs not a Carbon app, and this works fine going forward. } bundleURL = CFURLCreateWithFileSystemPath(NULL, bundleLoc, kCFURLPOSIXPathStyle, NO); bundleRef = CFBundleCreate(NULL, bundleURL); if (bundleRef == NULL) { BOOL isDir; CFRelease(bundleURL); if ([[NSFileManager defaultManager] fileExistsAtPath: [self loc] isDirectory: &isDir] && !isDir) return [self loc]; return nil; // not a bundle or file } else { CFURLRef execURL = CFBundleCopyExecutableURL(bundleRef); CFURLRef absURL = CFURLCopyAbsoluteURL(execURL); CFStringRef execPath = CFURLCopyFileSystemPath(absURL, kCFURLPOSIXPathStyle); if (absURL != NULL) CFRelease(absURL); if (execURL != NULL) CFRelease(execURL); CFRelease(bundleRef); return [(NSString *)execPath autorelease]; } } - (NSString*)loc { char buffer[1025]; FSRef location; if( !loc ) { if( !GetProcessBundleLocation( &psn, &location) ) { FSRefMakePath( &location, buffer, 1024); loc = [NSString stringWithUTF8String:buffer]; [loc retain]; } } return loc; } - (NSString*)name; { char buffer[1025]; CFStringRef pName; if( !name ) { if( !name && (CopyProcessName( &psn, &pName) == noErr) ) // with thanks to Dylan Ashe { CFStringGetCString( pName, buffer, 256, CFStringConvertNSStringEncodingToEncoding( [NSString defaultCStringEncoding])); name = [NSString stringWithCString:buffer]; [name retain]; CFRelease( pName); } // CFBundleName code demoted to alternate method because it was causing plist processing issues in Jaguar, yet CopyProcessName doesn't work for everything, e.g. Help Viewer - njr else if( [self loc] ) { NSBundle *b = [NSBundle bundleWithPath:loc]; if( b ) { name = [b localizedStringForKey:@"CFBundleName" value:@"_AsM_nO_nAmE_" table:@"InfoPlist"]; if( [name isEqualToString:@"_AsM_nO_nAmE_"] ) name = [[b infoDictionary] objectForKey:@"CFBundleName"]; if( name ) [name retain]; } } } return name ? name : NSLocalizedString(@"<>", "Name used when application name cannot be determined"); } - (NSImage*)img { if( !img ) { if( [self loc] ) { img = [[NSWorkspace sharedWorkspace] iconForFile:loc]; if( img ) { [img setDataRetained:YES]; // [img setCachedSeparately:YES]; // added 8/26/01 by Frank [img retain]; } } } return img; } - (NSImage *)cachedImage; { return cachedImage; } - (void)setCachedImage:(NSImage *)anImage; { if (anImage != cachedImage) { [anImage retain]; [cachedImage release]; cachedImage = anImage; } } - (ProcessSerialNumber*)psn { return &psn; } - (UInt32)pid { return pid; } - (UInt32)flavour { return flavour; } - (UInt32)attributes { CPSProcessInfoRec pInfo; int dummy; if( CPSGetProcessInfo( (CPSProcessSerNum*) &psn, &pInfo, nil, 0, &dummy, nil, 0) == noErr ) attributes = pInfo.Attributes; return attributes; } - (UInt32)type { return type; } - (UInt32)creator { return creator; } - (NSString*)identifier { if( !identifier ) { identifier = [[NSString alloc] initWithFormat:@"%@%.8X%.8X", [self bundleIdentifier], [self type] ? type : 'APPL', [self creator] ? creator : '\?\?\?\?']; } return identifier; } - (NSString*)bundleIdentifier { NSBundle *b; if( !bundleIdentifier && [self loc] && (b = [NSBundle bundleWithPath:loc]) ) bundleIdentifier = [[b bundleIdentifier] retain]; return bundleIdentifier ? bundleIdentifier : @""; } - (unsigned)hash { return psn.lowLongOfPSN; // return pid; } - (BOOL)isEqual:(id)anObject { if( anObject ) return CPSEqualProcess( (CPSProcessSerNum*) &psn, (CPSProcessSerNum*) [anObject psn]); else return NO; } - (BOOL)isEqualToCurrent { return [self isEqual:[ProcessMgr currentProcess]]; } - (BOOL)isEqualToFront { return [self isEqual:[ProcessMgr frontProcess]]; } - (BOOL)isStillRunning { CPSProcessInfoRec pInfo; int dummy; if( CPSGetProcessInfo( (CPSProcessSerNum*) &psn, &pInfo, nil, 0, &dummy, nil, 0) == noErr ) return YES; else return NO; } - (BOOL)isBackgroundOnly { return (((attributes & kCPSBGOnlyAttr) | (attributes & kCPSUIElementAttr)) != 0); } - (BOOL)isHidden { return (([self attributes] & kCPSHiddenAttr) != 0); } - (BOOL)isClassic { return (flavour == kCPSBlueApp); } - (BOOL)isCarbon { return (flavour == kCPSCarbonApp); } - (BOOL)isCocoa { return (flavour == kCPSYellowApp); } - (void)show { if( [self isStillRunning] ) CPSPostShowReq( (CPSProcessSerNum*) &psn); } - (void)hide { if( [self isStillRunning] ) CPSPostHideReq( (CPSProcessSerNum*) &psn); } - (void)makeFront { if( [self isStillRunning] ) { CPSSetFrontProcess( (CPSProcessSerNum*) &psn); CPSPostShowReq( (CPSProcessSerNum*) &psn); } } - (void)kill { [self kill:NO]; } - (void)kill:(BOOL)hard { if( [self isStillRunning] ) CPSPostKillRequest( (CPSProcessSerNum*) &psn, hard ? bfCPSKillHard : 0 ); } - (NSString *)description; { return [NSString stringWithFormat: @"%@ pid %d: '%@' (%@)", [super description], [self pid], [self name], [self identifier]]; } @end