| /* TimeWin.cpp --- A simple Windows tool inspired by Unix' "time". | |
| * | |
| * ==================================================================== | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| * ==================================================================== | |
| */ | |
| #include "targetver.h" | |
| #include <Windows.h> | |
| #include <stdio.h> | |
| #include <tchar.h> | |
| void usage() | |
| { | |
| _tprintf(_T("Execute a command, redirect its stdout to NUL and print\n")); | |
| _tprintf(_T("execution times ELAPSED\\tUSER\\tKERNEL in seconds.\n")); | |
| _tprintf(_T("\n")); | |
| _tprintf(_T("Usage: TimeWin.EXE COMMAND [PARAMETERS]\n")); | |
| } | |
| LPCTSTR skip_first_arg(LPCTSTR targv) | |
| { | |
| LPCTSTR s = _tcschr(targv, ' '); | |
| while (s && *s == ' ') | |
| ++s; | |
| return s; | |
| } | |
| double as_seconds(FILETIME time) | |
| { | |
| return (double)*reinterpret_cast<LONGLONG *>(&time) / 10000000.0; | |
| } | |
| int _tmain(int argc, LPTSTR argv[]) | |
| { | |
| // Minimal CL help support | |
| if (argc < 2 || _tcscmp(argv[1], _T("/?")) == 0) | |
| { | |
| usage(); | |
| return 0; | |
| } | |
| // Get a file handle for NUL. | |
| SECURITY_ATTRIBUTES sa; | |
| sa.nLength = sizeof(sa); | |
| sa.lpSecurityDescriptor = NULL; | |
| sa.bInheritHandle = TRUE; | |
| HANDLE nul = CreateFile(_T("nul"), FILE_APPEND_DATA, FILE_SHARE_WRITE, | |
| &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | |
| // Construct a process startup info that uses the same handles as this | |
| // one but redirects stdout to NUL. | |
| STARTUPINFO startup_info; | |
| GetStartupInfo(&startup_info); | |
| startup_info.dwFlags |= STARTF_USESTDHANDLES; | |
| startup_info.hStdOutput = nul; | |
| // Execute the command line. | |
| PROCESS_INFORMATION process_info; | |
| CreateProcess(NULL, _tscdup(skip_first_arg(GetCommandLine())), NULL, NULL, | |
| TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &startup_info, | |
| &process_info); | |
| // Get a handle with the needed access rights to the child process. | |
| HANDLE child = INVALID_HANDLE_VALUE; | |
| DuplicateHandle(GetCurrentProcess(), process_info.hProcess, | |
| GetCurrentProcess(), &child, | |
| PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, 0); | |
| // Wait for the child to finish. | |
| // If there was problem earlier (application not found etc.), this will fail. | |
| bool success = false; | |
| if (WaitForSingleObject(child, INFINITE) == WAIT_OBJECT_0) | |
| { | |
| // Finally, query the timers and show the result | |
| FILETIME start_time, end_time, user_time, kernel_time; | |
| if (GetProcessTimes(child, &start_time, &end_time, &kernel_time, | |
| &user_time)) | |
| { | |
| _tprintf(_T("%1.3f\t%1.3f\t%1.3f\n"), | |
| as_seconds(end_time) - as_seconds(start_time), | |
| as_seconds(user_time), as_seconds(kernel_time)); | |
| success = true; | |
| } | |
| } | |
| // In case of failure, give some indication that something went wrong. | |
| if (!success) | |
| _tprintf(_T("?.???\t?.???f\t?.???\n"), | |
| // Be good citizens and clean up our mess | |
| CloseHandle(child); | |
| CloseHandle(process_info.hThread); | |
| CloseHandle(process_info.hProcess); | |
| CloseHandle(nul); | |
| return 0; | |
| } |