切换网络代理macos app开发

前言

因为每次在设置里手动切换代理太浪费时间了,所以这两天想做一个可以mac app, 可以打开或关闭网络代理,app不能有主窗口,只在菜单栏上有个按钮,这样比较简洁。

截屏2020-02-29下午9.11.18.png

步骤一:创建项目

new project->macos->app。

步骤二:去掉主窗口

截屏2020-02-29下午9.22.39.png

打开main.storyboard,打这两项删掉(直接按delete),再次run之后发现主窗口不显示了

步骤三:添加菜单栏

在AppDelegate.m里添加代码如下:

@interface AppDelegate ()

@property (nonatomic,strong) NSStatusItem *statusItem; //必须应用、且强引用,否则不会显示。

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
    NSStatusBar *statusBar = [NSStatusBar systemStatusBar];
        
    NSStatusItem *statusItem = [statusBar statusItemWithLength: NSSquareStatusItemLength];
    [statusItem setHighlightMode:YES];
    [statusItem.button setImage: [NSImage imageNamed:@"abc"]]; //设置图标,请注意尺寸
    [statusItem.button setToolTip:@"代理切换"];
    
    NSMenu *subMenu = [[NSMenu alloc] initWithTitle:@"Load_TEXT"];
    [subMenu addItemWithTitle:@"打开"action:@selector(clickItem1) keyEquivalent:@"E"];
    [subMenu addItemWithTitle:@"关闭"action:@selector(clickItem2) keyEquivalent:@"R"];
    statusItem.menu = subMenu;
    
    self.statusItem = statusItem;
}

- (void)clickItem1{
}

- (void)clickItem2{
}

注意:图片是本地,选个大小适中的图片。
运行后发现menu上显示app图标,说明成功了。

步骤四:执行shell命令

一. 切换网络代理命令

切换网络代理命令会用到networksetup指令,
打开自动代理配置命令:
sudo networksetup -setautoproxyurl 网络名称 pac地址//设置自动代理的url
sudo networksetup -setautoproxystate 网络名称 on//自动代理的状态改为 打开
关闭自动代理配置命令:
sudo networksetup -setautoproxystate 网络名称 off
注意:“网络名称”一般都是“Wi-Fi”,也可能是其他的,但是不是你家wifi的名字...,看下图:

截屏2020-02-29下午9.41.49.png

二. 运行shell命令的几种方法
1. c语言的system方法
 system(@"sudo networksetup -setautoproxystate Wi-Fi on".UTF8String);

此方法只能运行非root权限命令

2. NSTask

可以运行root或非root权限命令。运行root命令时会弹用户名密码提示
代码如下:

- (NSString *)runNSTaskCmd:(NSString *)cmd
{
    NSMutableArray *components = [[cmd componentsSeparatedByString:@" "] mutableCopy];
    NSString *launchPath = components[0];
    [components removeObjectAtIndex:0];
    
    // 初始化并设置shell路径
    NSTask *task = [[NSTask alloc] init];
    [task setLaunchPath: launchPath];
    // -c 用来执行string-commands(命令字符串),也就说不管后面的字符串里是什么都会被当做shellcode来执行
    NSArray *arguments = components;
    [task setArguments: arguments];
    
    // 新建输出管道作为Task的输出
    NSPipe *pipe = [NSPipe pipe];
    [task setStandardOutput: pipe];
    
    // 开始task
    NSFileHandle *file = [pipe fileHandleForReading];
    [task launch];
    
    // 获取运行结果
    NSData *data = [file readDataToEndOfFile];
    return [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
}

调用代码如下:

    [self runNSTaskCmd:@"/usr/sbin/networksetup -setautoproxystate Wi-Fi off"];
3. 第三方库STPrivilegedTask Github地址
- (void)runPrivilegedTask:(NSString*) cmdStr{
    STPrivilegedTask *privilegedTask = [[STPrivilegedTask alloc] init];
    
    NSMutableArray *components = [[cmdStr componentsSeparatedByString:@" "] mutableCopy];
    NSString *launchPath = components[0];
    [components removeObjectAtIndex:0];
    
    [privilegedTask setLaunchPath:launchPath];
    [privilegedTask setArguments:components];
    [privilegedTask setCurrentDirectoryPath:[[NSBundle mainBundle] resourcePath]];
    
    //set it off
    OSStatus err = [privilegedTask launch];
    if (err != errAuthorizationSuccess) {
        if (err == errAuthorizationCanceled) {
            NSLog(@"User cancelled");
            return;
        }  else {
            NSLog(@"Something went wrong: %d", (int)err);
            // For error codes, see http://www.opensource.apple.com/source/libsecurity_authorization/libsecurity_authorization-36329/lib/Authorization.h
        }
    }
    
    [privilegedTask waitUntilExit];
}

调用代码如下:

    [self runPrivilegedTask:@"/usr/sbin/networksetup -setautoproxystate Wi-Fi off"];

其实NSTask或者是STPrivilegedTask的传的参数是一样的,不过内部原理不同(STPrivilegedTask使用了AuthorizationRef进行提权)。
推荐使用NSTask,理由如下:
NSTask除了在第一次使用时会弹权限提示窗口,后面即便杀掉app再启动时执行shell命令也不会弹权限提示窗口,总之只弹了一次,我很奇怪,这样难道不更不安全了吗?而STPrivilegedTask无论重不重启app,只要执行一次shell命令就会弹权限窗口,非常的烦。

结语

代码放在了 github上,欢迎大家指正~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,365评论 0 5
  • 1.描述计算机的组成及其功能 (一)计算机的组成 1.CPU 2.CPU风扇 3.BIOS 4.内存 5.硬盘 6...
    whamai阅读 1,431评论 0 1
  • 进入带空格的文件或者文件夹 Linux文件权限详解 文件和目录权限概述 在linux中的每一个文件或目录都包含有访...
    annkee阅读 2,642评论 0 4
  • 第 2 章 SHELL 基础知识2.1 shell脚本我们在上面简单介绍了一下什么是shell脚本,现在我们来进一...
    LiWei_9e4b阅读 1,553评论 0 0
  • 今天和同洋、翠云、岩岩、晓晨、江娜、思宇一起拍照,拿着音响去操场上疯。很开心,大家沉浸在毕业的欢愉中……羡慕...
    IamCircle阅读 171评论 0 0