Programmatically check in OS X if there is an active ethernet connection? - macos

How can I know my mac is connect to network by ethernet. Is there any method in cocoa which checks it?
I flung a wifi connection check, but no ethernet connection check.

Try like this:-
First import this below framework and then write the below code
#include <SystemConfiguration/SystemConfiguration.h>
NSString *pingHost = #"abc.apple.com"
SCNetworkConnectionFlags flags = 0;
if (pingHost && [pingHost length] > 0) {
flags = 0;
BOOL found = NO;
SCNetworkReachabilityRef reachabilityRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [pingHost UTF8String]);
if (reachabilityRef) {
found = SCNetworkReachabilityGetFlags(reachabilityRef, &flags)
&& (flags & kSCNetworkFlagsReachable)
&& !(flags & kSCNetworkFlagsConnectionRequired);
CFRelease(reachabilityRef);
reachabilityRef = NULL;
}
if (found) {
NSLog(#"Connection established");
}
if (!found) {
NSLog(#"Connection not established");
}
}

Take a look at this answer, you need to add the SystemConfiguration framework to your project

Related

Monitor changes on Thunderbolt port connection

I am working on a requirement where i need to monitor changes in Thunderbolt port connection. (When Thunderbolt cable is connected or disconnected).
I tried to use IOServiceMatching(kIOUSBInterfaceClassName) from IOKit framework but i cannot monitor changes on Thunderbolt port.
Is there any way i can achieve it? Any help is appreciated.
Thunderbolt devices (except displays that use the DisplayPort portion of the Thunderbolt port) are PCI devices, not USB, so they will show up in the IOService registry as IOPCIDevices. They will however also show up as IOThunderboltPort objects in the Thunderbolt subtree, where the "PCI Path" property will indicate the IOService path to the relevant IOPCIDevice. By monitoring the appearance and disappearance of IOThunderboltPort services, and checking their PCI Path property, you can avoid matching other kinds of PCI devices.
To illustrate what I'm talking about, open up IORegistryExplorer or IOJones and hotplug a Thunderbolt device; you should see both the IOThunderboltPort (and a bunch of other types of related object, such as AppleThunderboltPCIUpAdapter etc.) and the IOPCIDevice (as well as the PCI2PCI bridges via which the Thunderbolt bus works) appear. (Alternatively you can use ioreg to take snapshots before and after the hotplug.)
So in summary, I would match IOThunderboltPort services, ignore any without a PCI path property, and look up the corresponding IOPCIDevice in the IO Registry for the ones that have it to get to the actual device.
Finally i figured out a way indeed to monitor Thunderbolt Connection. Thanks to the apple tech guy who pointed me out in a right direction.
Monitoring the I/O Registry for IOEthernetInterface entries.  It’s relatively easy to filter out Thunderbolt networking (I’m not sure what the best option is, but an easy option is to look for “ThunderboltIP” in the “IOModel” property of the parent IOEthernetController). This was the response from one of the Tech guys from apple on Apple forum. Using the above info i wrote a piece of code which will return you the status of Thunderbolt port.
#include <IOKit/network/IOEthernetController.h>
- (void) monitorThunderboltConnection
{
CFMutableDictionaryRef matchingDict;
io_iterator_t iter;
io_object_t controllerService;
kern_return_t kr;
UInt8 MACAddress[kIOEthernetAddressSize];
QNInterfaceModel *interfaceModel = [[QNInterfaceModel alloc] initWithInterfaceModel];
/* set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOEthernetInterfaceClass);
if (matchingDict == NULL)
{
NSLog(#"Failed");
return;
}
/* Now we have a dictionary, get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr == kIOReturnSuccess)
{
// Actually iterate through the found devices.
io_registry_entry_t serviceObject;
while ((serviceObject = IOIteratorNext(iter)))
{
// Put this services object into a dictionary object.
kr = IORegistryEntryGetParentEntry(serviceObject,
kIOServicePlane,
&controllerService);
if (KERN_SUCCESS != kr)
{
printf("IORegistryEntryGetParentEntry returned 0x%08x\n", kr);
}
else
{
CFMutableDictionaryRef serviceDictionary;
CFTypeRef networkType;
CFTypeRef MACAddressAsCFData;
NSNumber *linkStatus;
if (IORegistryEntryCreateCFProperties(serviceObject,
&serviceDictionary,
kCFAllocatorDefault,
kNilOptions) == kIOReturnSuccess)
{
networkType = IORegistryEntryCreateCFProperty(controllerService,
CFSTR(kIOModel),
kCFAllocatorDefault,
0);
if(networkType)
{
if (CFGetTypeID(networkType) == CFStringGetTypeID())
{
CFStringRef networkName = networkType;
interfaceModel.interfaceName = (__bridge NSString *)networkName;
}
CFRelease(networkType);
}
if([interfaceModel.interfaceName isEqualToString:#"ThunderboltIP"])
{
MACAddressAsCFData = IORegistryEntryCreateCFProperty(controllerService,
CFSTR(kIOMACAddress),
kCFAllocatorDefault,
0);
if (MACAddressAsCFData)
{
CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr
// Get the raw bytes of the MAC address from the CFData
CFDataGetBytes(MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress);
if (KERN_SUCCESS != kr)
{
printf("GetMACAddress returned 0x%08x\n", kr);
}
else
{
interfaceModel.macAddress = [[NSString stringWithFormat:#"%02x:%02x:%02x:%02x:%02x:%02x",MACAddress[0], MACAddress[1], MACAddress[2], MACAddress[3], MACAddress[4], MACAddress[5]] uppercaseString];
}
CFRelease(MACAddressAsCFData);
}
linkStatus = (__bridge NSNumber *)(IORegistryEntryCreateCFProperty(controllerService,
CFSTR(kIOLinkStatus),
kCFAllocatorDefault,
0));
if (linkStatus)
{
NSLog(#"%#", [linkStatus stringValue]);
if([linkStatus integerValue] == 3) // Thunderbolt IP is Connnected
{
interfaceModel.connectedStatus = YES;
}
else
{
interfaceModel.connectedStatus = NO;
}
}
CFStringRef bsdName = ( CFStringRef ) IORegistryEntrySearchCFProperty (controllerService,
kIOServicePlane,
CFSTR ( kIOBSDNameKey ),
kCFAllocatorDefault,
kIORegistryIterateRecursively);
interfaceModel.interfaceName = (__bridge NSString *) bsdName;
if(interfaceModel.connectedStatus == YES)
{
NSLog(#"Connected");
}
else
{
NSLog(#"DisConnected");
}
}
// Failed to create a service dictionary, release and go on.
IOObjectRelease(serviceObject);
// Done with the parent Ethernet controller object so we release it.
(void) IOObjectRelease(controllerService);
continue;
}
}
}
}
/* Done, release the iterator */
IOObjectRelease(iter);
}
NOTE: I am using Interface model to collect all the thunderbolt info like Hardware Address, BSD Name, Link Status etc. You also need add I/O Kit framework to your project.

How to show simple text messages (toasts/alerts) in a Cocoa MacOS Webview?

I've already searched "everything" about this in Google/Stackoverflow, but I'm still stuck. I have just started developing OSX Apps, so I'm a (almost) complete newbie in Objective-C and Xcode 5 (5.0.2).
All I need is a simple webview to load a webgame from a given URL. This webview must behave just like a very simple Safari browser. My app is already working relatively well. It loads the game OK, and after a lot of struggling I succeeded making it show javascript alerts and confirms.
THE POINT: I need to display a simple text message to the user, in case of no internet connection is detected, then I need to close the app. It seems a very trivial thing, but I can't find a way to do that!!
That's my appDelegate.M:
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize myWebView;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
// Check if there's internet connection:
#include <SystemConfiguration/SystemConfiguration.h>
static BOOL internetOk()
{
BOOL returnValue = NO;
struct sockaddr zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sa_len = sizeof(zeroAddress);
zeroAddress.sa_family = AF_INET;
SCNetworkReachabilityRef reachabilityRef = SCNetworkReachabilityCreateWithAddress(NULL, (const struct sockaddr*)&zeroAddress);
if (reachabilityRef != NULL)
{
SCNetworkReachabilityFlags flags = 0;
if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
{
BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
BOOL connectionRequired = ((flags & kSCNetworkFlagsConnectionRequired) != 0);
returnValue = (isReachable && !connectionRequired) ? YES : NO;
}
CFRelease(reachabilityRef);
}
return returnValue;
}
// -
if(internetOk())
{
[self.window setContentView:self.myWebView];
[self.window toggleFullScreen:#""];
[self.myWebView setMainFrameURL:#"http://www.mywebgameurl.com"];
}
else
{
// SHOWS ERROR MESSAGE AND CLOSES APP! HOW CAN I DO IT????
}
}
#end
Any help is welcome, thanks!!
You're looking for the NSAlert class, check here for Apple's docs.
Sample usage:
NSAlert* alert = [NSAlert alertWithMessageText:#"Internet Error"
defaultButton:nil
alternateButton:nil
otherButton:nil
informativeTextWithFormat:#"No internet."];
[alert runModal];

How to force kill another application in cocoa Mac OS X 10.5

I've this task, from my application i need to kill another my application, the problem is that the other application has a Termination Confirm Dialog (there is no critical data to save, only confirmation of user intent to quit).
On 10.6+ you will use:
bool TerminatedAtLeastOne = false;
// For OS X >= 10.6 NSWorkspace has the nifty runningApplications-method.
if ([NSRunningApplication respondsToSelector:#selector(runningApplicationsWithBundleIdentifier:)]) {
for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:#"com.company.applicationName"]) {
[app forceTerminate];
TerminatedAtLeastOne = true;
}
return TerminatedAtLeastOne;
}
but on <10.6 this commonly used Apple Event:
// If that didn‘t work either... then try using the apple event method, also works for OS X < 10.6.
AppleEvent event = {typeNull, nil};
const char *bundleIDString = "com.company.applicationName";
OSStatus result = AEBuildAppleEvent(kCoreEventClass, kAEQuitApplication, typeApplicationBundleID, bundleIDString, strlen(bundleIDString), kAutoGenerateReturnID, kAnyTransactionID, &event, NULL, "");
if (result == noErr) {
result = AESendMessage(&event, NULL, kAENoReply|kAEAlwaysInteract, kAEDefaultTimeout);
AEDisposeDesc(&event);
}
return result == noErr;
can't Force Quit!!!
So what can you use?
You can use this simple code that I've digged out on cocoabuilder:
// If that didn‘t work then try shoot it in the head, also works for OS X < 10.6.
NSArray *runningApplications = [[NSWorkspace sharedWorkspace] launchedApplications];
NSString *theName;
NSNumber *pid;
for ( NSDictionary *applInfo in runningApplications ) {
if ( (theName = [applInfo objectForKey:#"NSApplicationName"]) ) {
if ( (pid = [applInfo objectForKey:#"NSApplicationProcessIdentifier"]) ) {
//NSLog( #"Process %# has pid:%#", theName, pid ); //test
if( [theName isEqualToString:#"applicationName"] ) {
kill( [pid intValue], SIGKILL );
TerminatedAtLeastOne = true;
}
}
}
}
return TerminatedAtLeastOne;

MacOSX Lion: how to move a named window using CoreGraphics, without AppleScript?

Using CoreGraphics in a cocoa objective-c program running under Lion, I'd like to move a named window that is owned by a different process. I know I can do this via an auxiliary AppleScript method via ASOC, but I want to perform this task entirely within cocoa using CoreGraphics (or at least entirely within C or objective-c), and without any AppleScript, at all.
I know how to locate a named window of a named process using the code below, but once I get the info for that window, I haven't been able to figure out how to move it (see the comment "What do I do here ... ?" within this code). Could someone point me to some docs or make a suggestion as to how I can proceed?
Thanks in advance.
+(boolean_t)moveWindow:(NSString*)windowName ofProcess:(NSString*)processName to:(CGPoint*)location {
boolean_t result = false;
if (windowName == nil || processName == nil || location == nil) {
return (result);
}
CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
CFIndex nWindows = CFArrayGetCount(windows);
for (CFIndex i = 0; i < nWindows; i++) {
CFDictionaryRef windict = CFArrayGetValueAtIndex(windows, i);
CFNumberRef winOwnerPidRef = CFDictionaryGetValue(windict, kCGWindowOwnerPID);
if (winOwnerPidRef == nil) {
continue;
}
pid_t winOwnerPid = 0;
CFNumberGetValue(winOwnerPidRef, kCFNumberSInt32Type, (int*)&winOwnerPid);
if (winOwnerPid < 1) {
continue;
}
ProcessSerialNumber winOwnerPSN;
GetProcessForPID(winOwnerPid, &winOwnerPSN);
NSString* winOwner = nil;
ProcessSerialNumber psn;
psn.lowLongOfPSN = kNoProcess;
psn.highLongOfPSN = 0;
while (winOwner == nil && GetNextProcess(&psn) == noErr) {
if (psn.lowLongOfPSN != winOwnerPSN.lowLongOfPSN ||
psn.highLongOfPSN != winOwnerPSN.highLongOfPSN) {
continue;
}
CFStringRef procName = NULL;
if (CopyProcessName(&psn, &procName) == noErr) {
winOwner = (NSString*) procName;
}
CFRelease(procName);
}
if (winOwner == nil || [winOwner compare:processName] != NSOrderedSame) {
continue;
}
CFStringRef winNameRef = CFDictionaryGetValue(windict, kCGWindowName);
NSString* winName = (NSString*) winNameRef;
if (winName != nil && [winName compare:windowName] == NSOrderedSame) {
// ********************************************** //
// What do I do here in order to move the window? //
// ********************************************** //
result = true;
break;
}
}
return (result);
}
You can move the windows of other applications using Accessibility. Take a look at AXUIElementCreateApplication() and AXUIElementSetAttributeValue() with the attribute kAXPositionAttribute.
Note that Accessibility will need to be enabled (check "Enable access for assistive devices" in Universal Access Preferences) or your process will need to be trusted (see AXMakeProcessTrusted())

check internet connection in cocoa application

How do I check internet connection in an OS X cocoa application?
Can Apple's iOS Reachability example code be reused for this purpose?
Thanks,
Nava
The current version of Reachability code (2.2) listed on Apple's site and referenced above does NOT compile as-is for a Mac OS X Cocoa application. The constant kSCNetworkReachabilityFlagsIsWWAN is only available when compiling for TARGET_OS_IPHONE and Reachability.m references that constant. You will need to #ifdef the two locations in Reachability.m that reference it like below:
#if TARGET_OS_IPHONE
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
#else
0,
#endif
and
#if TARGET_OS_IPHONE
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
// ... but WWAN connections are OK if the calling application
// is using the CFNetwork (CFSocketStream?) APIs.
retVal = ReachableViaWWAN;
}
#endif
This code will help you to find if internet is reachable or not:
-(BOOL)isInternetAvail
{
BOOL bRet = FALSE;
const char *hostName = [#"google.com" cStringUsingEncoding:NSASCIIStringEncoding];
SCNetworkConnectionFlags flags = 0;
if (SCNetworkCheckReachabilityByName(hostName, &flags) && flags > 0)
{
if (flags == kSCNetworkFlagsReachable)
{
bRet = TRUE;
}
else
{
}
}
else
{
}
return bRet;
}
For more information you can look at the iphone-reachability
Unicorn's solution is deprecated, but you can get equivalent results using the following code:
SCNetworkReachabilityRef target;
SCNetworkConnectionFlags flags = 0;
Boolean ok;
target = SCNetworkReachabilityCreateWithName(NULL, hostName);
ok = SCNetworkReachabilityGetFlags(target, &flags);
CFRelease(target);
Apple has a nice code which does it for you. You can check if your connection is WiFi for instnace or just cell/WiFi.
link text
I know this is an old thread but for anyone running into this in 2018, there's an simpler and quicker solution using a Process and the ping command.
Swift 4 example:
func ping(_ host: String) -> Int32 {
let process = Process.launchedProcess(launchPath: "/sbin/ping", arguments: ["-c1", host])
process.waitUntilExit()
return process.terminationStatus
}
let internetAvailable = ping("google.com") == 0
print("internetAvailable \(internetAvailable)")

Resources