0

When i try to create a helper for an application that retrieve system software and hardware details using system_profiler command i got the following error.

Response from XPC service: HELLO XPC
Response from XPC service: /usr/sbin/system_profiler: /usr/sbin/system_profiler: cannot execute binary file"

The code is given below.

class CommandHelper: NSObject,CommandHelperProtocol {
  func upperCaseString(_ string: String, withReply reply: @escaping (String) -> Void) {
    let response = string.uppercased()
    reply(response)
  }
  func loadServerURL(_ string: String, withReply reply: @escaping (String) -> Void) {
    let pipe = Pipe()
    let process = Process()
    process.launchPath = "/bin/sh"
    process.arguments = ["system_profiler","SPHardwareDataType"]
    process.standardOutput = pipe
    process.standardError = pipe
    let fileHandle = pipe.fileHandleForReading
    process.launch()
    let response = String(data: fileHandle.readDataToEndOfFile(), encoding: .utf8)

    print(response!)
    reply(response!)
  }
}

When i set launchPath to /usr/sbin/system_profiler i got blank output.

biju
  • 15
  • 7
  • First question, why are you launching `/bin/sh`? Why not execute `system_profiler` directly? – James Bucanek Nov 23 '18 at 19:11
  • Secondly, even if you want to use `/bin/sh` this won't work. From the `bash` man page: "If arguments remain after option processing, and neither the -c nor the -s option has been supplied, the first argument is assumed to be the name of *a file containing shell commands*", emphasis mine. – James Bucanek Nov 23 '18 at 19:12
  • Finally, if parsing the output of `system_profiler` programmatically I would suggest the `-xml` option. – James Bucanek Nov 23 '18 at 19:16
  • Is the app sandboxed? If yes you have no permission to run shell scripts via `Process` – vadian Nov 23 '18 at 20:52
  • Yes. The app is sandboxed.Is there is any issue for validation (for sandboxing) if i use "/usr/sbin/system_profiler" to grab the hardware information ? – biju Nov 26 '18 at 04:13

1 Answers1

0

Shells execute scripts, not binaries. The solution is to run the tool directly; there's hardly any reason to launch a shell just to execute a program:

process.launchPath = "/usr/sbin/system_profiler"
process.arguments = ["SPHardwareDataType"]

Also, there's no point in setting the stderr pipe if you're not going to use it:

/* process.standardError = pipe */
James Bucanek
  • 3,299
  • 3
  • 14
  • 30
  • How use grep in arguments? like this . `system_profiler -xml SPHardwareDataType | grep "serial_number"` – biju Nov 26 '18 at 04:25
  • Using system_profiler like this some of the DataTypes (eg: SPManagedClientDataType,SPConfigurationProfileDataType) gives blank output. But it gives output if run in terminal. – biju Nov 26 '18 at 04:48
  • You don't need grep; you get back data, which you decode and turn into a string–see `String(data:,encoding:)`–which you can then search using `String` methods or (if you need it) `NSRegularExpression`. – James Bucanek Nov 26 '18 at 07:29
  • There should be no difference between the output you get in the shell and the output you read from the tool: same program, same output. But you might want to check to see if there's anything being sent to the `stderr` pipe. (I know this contradicts my previous comment, but if you're launching `system_profiler` with the right arguments, I can't imagine why there should be any error output.) – James Bucanek Nov 26 '18 at 07:31
  • `func loadProvisioningProfileDetails(_ string: String, withReply reply: @escaping (String) -> Void) { let pipe = Pipe() let process = Process() process.launchPath = "/usr/sbin/system_profiler" process.arguments = ["SPConfigurationProfileDataType"] process.standardOutput = pipe let fileHandle = pipe.fileHandleForReading process.launch() let response = String(data: fileHandle.readDataToEndOfFile(), encoding: .utf8) reply(response!) }`. The code used now. – biju Nov 26 '18 at 09:21
  • The ouput is `Response from XPC service: HELLO XPC Response from XPC service: ` – biju Nov 26 '18 at 09:22
  • It sounds like you're getting an XPC service error in certain cases. Check the status value returned by the process (`process.waitUntilExit(); if process.terminationStatus != 0 ...`) and debug from there. It's possible your execution environment is different than Terminal's (but if this is a plain-vanilla non-sandboxed Cocoa app, that seems unlikely—unless you're running it as another user). – James Bucanek Nov 26 '18 at 16:34
  • Oh and I forgot to mention that if you're using the `-xml` option, you'll need to create an XML decoder from the data (instead of a string) and use that to parse the output. Start with `NSXMLDocument(data:,options:)`... – James Bucanek Nov 26 '18 at 16:37