2012-12-21 4 views
4

특정 USB 장치가 마운트 될 때마다 실행되는 launchd.plist 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를 호출하여 대기열에서 이벤트를 제거해야합니다. .plist에 <key>KeepAlive</key><false/>을 추가해야 할 수도 있지만, 확실하지 않습니다.

+0

을하고 응용 프로그램은 가능한 한 빨리 반복해서 다시 실행 : – 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; 
} 

그래서 인수로 전달 스크립트를 이벤트를 소비하며 실행되는 스크립트. 당신이 다음 xpc_set_event_stream_handler 어떤 차이가되지 않습니다 true로 IOMatchLaunchStream을 설정하지 않을 경우, 덧붙여

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

+0

'xpc_set_event_stream_handler' 핸들러 안에서'execv'를 호출하면 이벤트가 소비되는 것을 막을 수 있습니다. 핸들러 외부에서'execv'를 호출하면 큰 효과가있었습니다. 내 코드 [아래] (https://stackoverflow.com/a/48895921/74530)를 게시했습니다. – Ford

0

은 나를 위해 작동 그만 뒀어. 유용한 팁. `launchd.plist` 맨 페이지마다