2012-12-21 255 views
4

我一直在設置一個launchd.plist XML,每次安裝特定的USB設備時都會運行該XML。我按照xpc_events(3) man page上的說明進行操作,並且每次安裝設備時都會運行該應用程序。launchd.plist每10秒運行一次而不是一次

我遇到的問題是,只要設備仍然安裝,應用程序就會每隔10秒再次運行一次。我該如何設置它,以便在設備插入USB端口時僅運行一次?

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
<dict> 
    <key>Label</key> 
    <string>com.myapp.agent</string> 
    <key>Program</key> 
    <string>/Applications/MyApp.app/Contents/MacOS/MyAgent</string> 
    <key>LaunchEvents</key> 
    <dict> 
     <key>com.apple.iokit.matching</key> 
     <dict> 
      <key>com.apple.device-attach</key> 
      <dict> 
       <key>idVendor</key> 
       <integer>2316</integer> 
       <key>idProduct</key> 
       <integer>4096</integer> 
       <key>IOProviderClass</key> 
       <string>IOUSBDevice</string> 
       <key>IOMatchLaunchStream</key> 
       <true/> 
      </dict> 
     </dict> 
     <key>com.apple.notifyd.matching</key> 
     <dict> 
      <key>com.apple.interesting-notification</key> 
      <dict> 
       <key>Notification</key> 
       <string>com.apple.interesting-notification</string> 
      </dict> 
     </dict> 
    </dict> 
</dict> 
</plist> 

回答

2

AIUI您的應用程序必須調用xpc_set_event_stream_handler從隊列中移除事件。您可能還需要將<key>KeepAlive</key><false/>添加到.plist中,但我不確定。

+0

順便說一句,如果您不IOMatchLaunchStream設置爲true,那麼xpc_set_event_stream_handler不作任何區別,你的應用程序儘快重新推出了個遍你放棄了它。只是一個有用的提示。每個'launchd.plist'手冊頁 – dgatwood

+0

,'KeepAlive'的默認值是'false' – Ford

1

我想用這樣的:

#include <xpc/xpc.h> 
#include <unistd.h> 
#include <asl.h> 

int main(int argc, char *argv[]) { 
    if (argc < 2) { 
     return 1; 
    } 

    asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "event_stream_handler: starting"); 

    xpc_set_event_stream_handler("com.apple.iokit.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(xpc_object_t event) { 
     const char *name = xpc_dictionary_get_string(event, XPC_EVENT_KEY_NAME); 
     uint64_t id = xpc_dictionary_get_uint64(event, "IOMatchLaunchServiceID"); 
     asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "event_stream_handler: received event: %s: %llu", name, id); 

     execv(argv[1], argv + 1); 
    }); 

    dispatch_main(); 

    return 0; 
} 

所以消耗的情況下,並運行作爲參數傳遞腳本的腳本。

+0

我認爲在'xpc_set_event_stream_handler'處理程序中調用'execv'可以防止消耗事件。在處理程序外部調用'execv'運行得非常好。我發佈了我的代碼[下方](https://stackoverflow.com/a/48895921/74530)。 – Ford

0

這個工作對我來說:

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
     dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 
     xpc_set_event_stream_handler("com.apple.iokit.matching", NULL, ^(xpc_object_t _Nonnull object) { 
      const char *event = xpc_dictionary_get_string(object, XPC_EVENT_KEY_NAME); 
      dispatch_semaphore_signal(semaphore); 
     }); 
     dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 
     if(argc >= 2) { 
      execv(argv[1], (char **)argv+1); 
     } 
    } 
} 

full source code here