1

I am trying to run command lines to take screenshots in my Xcode project and using Pipe() to log output data. When I build and run this project in Xcode, I can get the output information as a string, like this screenshot's basic information. But when I archive this project as a MacOS applicaiton and run it, I get an error. I can't get any information for outputData.

The result of "outpipe.fileHandleForReading.readDataToEndOfFile()" is empty.

Here are my codes:

let task = Process()
task.launchPath = "/usr/sbin/screencapture"
var arguments = [String]();
arguments.append("-s") 
let ScreenshotPath = "screenshotpath.jpg"
arguments.append(ScreenshotPath)
task.arguments = arguments

let outpipe = Pipe()
task.standardOutput = outpipe
task.standardError = outpipe

do {
    try task.run()
} catch {
    print("error in process")
}
let outputData = outpipe.fileHandleForReading.readDataToEndOfFile()
let resultInformation = String(data: outputData, encoding: .utf8)
task.waitUntilExit()
print(resultInformation)

Can somebody help me with this out? Thank you so much!

Han
  • 29
  • 4
  • Is this a GUI application or a command-line tool? — Also this is obviously not your real code. Please don't do that. Copy your real code and paste it right into the question. Don't type pieces of it by hand. – matt Feb 23 '22 at 22:00
  • GUI application. more specifically, it's a menu bar application. I call command lines to take screenshots in this application. Sorry, I didn't get your point. But this is the real code. Is something missing? @matt – Han Feb 23 '22 at 22:13
  • It wasn't your real code when it said `taks.run()`, and you know it. That's why you changed it. – matt Feb 25 '22 at 03:03
  • Let me ask you this; are you sandboxed? (Meaning, your app.) – matt Feb 25 '22 at 03:04
  • I deleted several meaningless comments between lines and made a typo in the tasks.run(). Sorry about this mistake. I didn't open the sandbox. Because I need permission to access local folders and files. The problem is that Pipe() can read data from "/usr/sbin/screencapture"'s output when I run it as a project in Xcode. However, when I archive this project as an application, Pipe() read nothing. @matt – Han Feb 28 '22 at 05:37

2 Answers2

1

The main issue is that you are trying to read from your file before any output is captured and written to disk.

The '-s' option specifies mouse selection mode, which is interactive. Trying running it from the command line as:

screenshot -s screenshot.jpg

You should end up seeing some large crosshairs with x and y coordinates.

The output file isn't written in this case until you finish your selection.

The other problem is that you are trying to read the contents of the file without knowing if it is actually complete. You could use the terminationHandler of the completion block as in:

task.terminationHandler = {
    let outputData = outpipe.fileHandleForReading.readDataToEndOfFile()
    let resultInformation = String(data: outputData, encoding: .utf8)        
}

This will ensure you read the file after it's actually written. Hope that helps.

jbadger3
  • 26
  • 3
0

I believe the issue is assigning your Pipe object to both task.standardOutput and task.standardError. I recommend creating two distinct Pipe objects, then passing them to the outputs respectively.

We used the function from this answer in production on the Mac App Store.

Alex
  • 527
  • 4
  • 10