check internet connection in cocoa application - macos

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)")

Related

Section of the code of our c++ DLL crashes wen ran on a Windows 7 SP1

I am developing a desktop Air application that uses an Air Native Extension (ANE). The native part of the ANE is composed only by a DLL written partially in C and partially in C++. The app was compiled with Visual Studio 2010 and requires the MSVCR100.DLL and the MSVCP100.DLL to be on the same directory as the application's exe file.
The app and DLL work great on many computers but on clean Windows 7 SP1 computers, part of its code makes the DLL crash.
I've narrowed down the conflicting code to the following:
// Addresses.
String^ defaultGateway = "Not Found";
String^ interfaceIPAddress = "Not Found";
String^ interfaceMask = "Not Found";
array<NetworkInterface^>^nics = NetworkInterface::GetAllNetworkInterfaces();
if (nics != nullptr || nics->Length > 0)
{
System::Collections::IEnumerator^ myEnum4 = nics->GetEnumerator();
while (myEnum4->MoveNext())
{
NetworkInterface^ adapter = safe_cast<NetworkInterface ^>(myEnum4->Current);
IPInterfaceProperties^ properties = adapter->GetIPProperties();
GatewayIPAddressInformationCollection^ gateways = properties->GatewayAddresses;
for each (GatewayIPAddressInformation^ gateway in gateways)
{
if (gateway->Address->AddressFamily == AddressFamily::InterNetwork)
{
defaultGateway = gateway->Address->ToString();
for each (UnicastIPAddressInformation^ unicastIPAddressInformation in properties->UnicastAddresses)
{
if (unicastIPAddressInformation->Address->AddressFamily == AddressFamily::InterNetwork)
{
interfaceIPAddress = unicastIPAddressInformation->Address->ToString();
interfaceMask = unicastIPAddressInformation->IPv4Mask->ToString();
}
}
}
}
}
}
Just to give you more context, I'll copy the entire function were that code is:
FREObject MainInterfaceInfo(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
// Addresses.
String^ defaultGateway = "Not Found";
String^ interfaceIPAddress = "Not Found";
String^ interfaceMask = "Not Found";
array<NetworkInterface^>^nics = NetworkInterface::GetAllNetworkInterfaces();
if (nics != nullptr || nics->Length > 0)
{
System::Collections::IEnumerator^ myEnum4 = nics->GetEnumerator();
while (myEnum4->MoveNext())
{
NetworkInterface^ adapter = safe_cast<NetworkInterface ^>(myEnum4->Current);
IPInterfaceProperties^ properties = adapter->GetIPProperties();
GatewayIPAddressInformationCollection^ gateways = properties->GatewayAddresses;
for each (GatewayIPAddressInformation^ gateway in gateways)
{
if (gateway->Address->AddressFamily == AddressFamily::InterNetwork)
{
defaultGateway = gateway->Address->ToString();
for each (UnicastIPAddressInformation^ unicastIPAddressInformation in properties->UnicastAddresses)
{
if (unicastIPAddressInformation->Address->AddressFamily == AddressFamily::InterNetwork)
{
interfaceIPAddress = unicastIPAddressInformation->Address->ToString();
interfaceMask = unicastIPAddressInformation->IPv4Mask->ToString();
}
}
}
}
}
}
String^ result = interfaceIPAddress + ";" + interfaceMask + ";" + defaultGateway;
// Converting the response to const uint8_t *
msclr::interop::marshal_context oMarshalContext;
const char* charResponse = oMarshalContext.marshal_as<const char*>(result);
const uint8_t * resultNativeCharArray = (const uint8_t *)charResponse;
uint32_t resultNativeCharArrayLength = 0;
while (true) {
if (NULL == resultNativeCharArray[resultNativeCharArrayLength]) {
break;
}
else {
resultNativeCharArrayLength++;
}
}
FREObject functionResult;
FRENewObjectFromUTF8(resultNativeCharArrayLength, resultNativeCharArray, &functionResult);
return functionResult;
}
I'm a noob on C and C++ because I only saw it a couple of times 10 years ago so I have no clue about what exactly is making the DLL crash. Can someone tell? Any advice will be more than appreciated.
Editted
I came to realize that the same narrowed code makes the app require the MSVCR100.DLL and the MSVCP100.DLL. If I remove that portion of code, the app can run without them.
MSVCP100.DLL contains the standard C++ Library; MSVCR100.DLL is the C runtime. It's probably something like the safe_cast call that's introducing the dependency. More details about the runtime libraries are here.
I'd suggest using the official redistributable package to deploy the Visual C++ runtimes DLLs instead of deploying them into your app's directory yourself. See Redistributing Visual C++ Files for details... the walkthrough links in there will be helpful to you. That's the sure-fire way to be sure that the target system has all the dependencies you'll need. Your older (non-clean) Win7 systems probably had some other app or Windows Update install that redistributable for you, which is why your code is working there.
Actually, the line of code that was messing everything up was:
interfaceMask = unicastIPAddressInformation->IPv4Mask->ToString();
If that line was deleted, the DLL would run without a problem.
The issue occurred because one of the inactive network interfaces of the system reported '0.0.0.0' on gateway->Address->ToString(). So when trying to unicastIPAddressInformation->IPv4Mask->ToString() the DLL would crash.
To solve the issue I just added an if (adapter->OperationalStatus == OperationalStatus::Up) at the beggining and everything worked great afterwards. The resulting code is as follows:
while (myEnum4->MoveNext())
{
NetworkInterface^ adapter = safe_cast<NetworkInterface ^>(myEnum4->Current);
IPInterfaceProperties^ properties = adapter->GetIPProperties();
if (adapter->OperationalStatus == OperationalStatus::Up)
{
GatewayIPAddressInformationCollection^ gateways = properties->GatewayAddresses;
for each (GatewayIPAddressInformation^ gateway in gateways)
{
if (gateway->Address->AddressFamily == AddressFamily::InterNetwork)
{
defaultGateway = gateway->Address->ToString();
for each (UnicastIPAddressInformation^ unicastIPAddressInformation in properties->UnicastAddresses)
{
if (unicastIPAddressInformation->Address->AddressFamily == AddressFamily::InterNetwork)
{
interfaceIPAddress = unicastIPAddressInformation->Address->ToString();
interfaceMask = unicastIPAddressInformation->IPv4Mask->ToString();
}
}
}
}
}
}

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

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

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())

Free VRam on OS X

does anyone know how to get the free(!) vram on os x?
I know that you can query for a registry entry:
typeCode = IORegistryEntrySearchCFProperty(dspPort,kIOServicePlane,CFSTR(kIOFBMemorySizeKey),
kCFAllocatorDefault,
kIORegistryIterateRecursively | kIORegistryIterateParents);
but this will return ALL vram, not the free vram. Under windows you can query for free VRAM using directshow
mDDrawResult = DirectDrawCreate(NULL, &mDDraw, NULL);
mDDrawResult = mDDraw->QueryInterface(IID_IDirectDraw2, (LPVOID *)&mDDraw2);
DDSCAPS ddscaps;
DWORD totalmem, freemem;
ddscaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
mDDrawResult = mDDraw2->GetAvailableVidMem(&ddscaps, &totalmem, &freemem);
Ugly, but it works. Anyone knows the osx way?
Best
Wendy
answering myself so others may use this:
#include <IOKit/graphics/IOGraphicsLib.h>
size_t currentFreeVRAM()
{
kern_return_t krc;
mach_port_t masterPort;
krc = IOMasterPort(bootstrap_port, &masterPort);
if (krc == KERN_SUCCESS)
{
CFMutableDictionaryRef pattern = IOServiceMatching(kIOAcceleratorClassName);
//CFShow(pattern);
io_iterator_t deviceIterator;
krc = IOServiceGetMatchingServices(masterPort, pattern, &deviceIterator);
if (krc == KERN_SUCCESS)
{
io_object_t object;
while ((object = IOIteratorNext(deviceIterator)))
{
CFMutableDictionaryRef properties = NULL;
krc = IORegistryEntryCreateCFProperties(object, &properties, kCFAllocatorDefault, (IOOptionBits)0);
if (krc == KERN_SUCCESS)
{
CFMutableDictionaryRef perf_properties = (CFMutableDictionaryRef) CFDictionaryGetValue( properties, CFSTR("PerformanceStatistics") );
//CFShow(perf_properties);
// look for a number of keys (this is mostly reverse engineering and best-guess effort)
const void* free_vram_number = CFDictionaryGetValue(perf_properties, CFSTR("vramFreeBytes"));
if (free_vram_number)
{
ssize_t vramFreeBytes;
CFNumberGetValue( (CFNumberRef) free_vram_number, kCFNumberSInt64Type, &vramFreeBytes);
return vramFreeBytes;
}
}
if (properties) CFRelease(properties);
IOObjectRelease(object);
}
IOObjectRelease(deviceIterator);
}
}
return 0; // when we come here, this is a fail
}
i am somewhat surprised that this query takes almost 3 msec ..
be aware that there may be more than one accelerator on your system ( eg. macbook )
so be sure you select the proper one for the query

Can't edit IORegistryEntry

I am creating a software on Mac and I would like to change the value of an IORegistryEntry. I can view it on the IORegistryExplorer, but I can't edit it. So it's my understanding that I have to edit it via code. Here is my code:
CFMutableDictionaryRef matchingDict = IOServiceNameMatching("AppleUSBMultitouchDriver");
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);
if(service) {
CFStringRef manufacturer = IORegistryEntryCreateCFProperty(service, CFSTR("Manufacturer"), kCFAllocatorDefault,0);
NSLog(#"%#", (NSString*)manufacturer);
kern_return_t err = IORegistryEntrySetCFProperty(service, CFSTR("Manufacturer"), CFSTR("test"));
NSLog(#"error = %d", err);
}
This will output
2010-04-10 16:09:09.015 Test[41548:a0f] Apple Inc.
2010-04-10 16:09:09.015 Test[41548:a0f] error = 0
But after I check the value in the IORegistryExplorer, it still doesn't change. Does anybody have any suggestions?
Thank you
In order for this to be possible, usually the driver for the particular hardware you're changing has to implement setProperties() (in IOKit) that makes this change for you.
It's unlikely that Apple will implement setProperty() in their AppleUSBMultitouchDriver in a way that allows you to change the manufacturer name. They want to specify what kind of fruit they are. ;)
Use IOConnectSetCFProperties instead of IORegistryEntrySetCFProperty. Pass it a dictionary with the settings you want to set.
For example to turn off three finger swipe to navigate, call it with a dictionary containing { TrackpadThreeFingerSwipe = 0; }
This is example how to change trackpad settings properly. Trackpad.prefpane do exactly this, but also save this setting somewhere in defaults (if you will not find out where exactly, ask here about it).
P.S. getEVSHandle() may be found in MachineSettings.framework.
P.P.S. Checked only on 10.5 & 10.6.
NSInteger zero = 0, one = 1;
CFNumberRef _numberWith0 = CFNumberCreate(kCFAllocatorDefault, kCFNumberNSIntegerType, &zero);
CFNumberRef _numberWith1 = CFNumberCreate(kCFAllocatorDefault, kCFNumberNSIntegerType, &one);
CFMutableDictionaryRef propertyDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, NULL, NULL);
CFDictionarySetValue(propertyDict, #"TrackpadThreeFingerSwipe", flag ? _numberWith1 : _numberWith0);
io_connect_t connect = getEVSHandle();
if (!connect)
{
// error
}
kern_return_t status = IOConnectSetCFProperties(connect, propertyDict);
if (status != KERN_SUCCESS)
{
//error
}
CFRelease(propertyDict);

Resources