1
/* TimeWin.cpp --- A simple Windows tool inspired by Unix' "time".
3
* ====================================================================
4
* Licensed to the Apache Software Foundation (ASF) under one
5
* or more contributor license agreements. See the NOTICE file
6
* distributed with this work for additional information
7
* regarding copyright ownership. The ASF licenses this file
8
* to you under the Apache License, Version 2.0 (the
9
* "License"); you may not use this file except in compliance
10
* with the License. You may obtain a copy of the License at
12
* http://www.apache.org/licenses/LICENSE-2.0
14
* Unless required by applicable law or agreed to in writing,
15
* software distributed under the License is distributed on an
16
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
* KIND, either express or implied. See the License for the
18
* specific language governing permissions and limitations
20
* ====================================================================
23
#include "targetver.h"
32
_tprintf(_T("Execute a command, redirect its stdout to NUL and print\n"));
33
_tprintf(_T("execution times ELAPSED\\tUSER\\tKERNEL in seconds.\n"));
35
_tprintf(_T("Usage: TimeWin.EXE COMMAND [PARAMETERS]\n"));
38
LPCTSTR skip_first_arg(LPCTSTR targv)
40
LPCTSTR s = _tcschr(targv, ' ');
41
while (s && *s == ' ')
47
double as_seconds(FILETIME time)
49
return (double)*reinterpret_cast<LONGLONG *>(&time) / 10000000.0;
52
int _tmain(int argc, LPTSTR argv[])
54
// Minimal CL help support
55
if (argc < 2 || _tcscmp(argv[1], _T("/?")) == 0)
61
// Get a file handle for NUL.
62
SECURITY_ATTRIBUTES sa;
63
sa.nLength = sizeof(sa);
64
sa.lpSecurityDescriptor = NULL;
65
sa.bInheritHandle = TRUE;
67
HANDLE nul = CreateFile(_T("nul"), FILE_APPEND_DATA, FILE_SHARE_WRITE,
68
&sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
70
// Construct a process startup info that uses the same handles as this
71
// one but redirects stdout to NUL.
72
STARTUPINFO startup_info;
73
GetStartupInfo(&startup_info);
74
startup_info.dwFlags |= STARTF_USESTDHANDLES;
75
startup_info.hStdOutput = nul;
77
// Execute the command line.
78
PROCESS_INFORMATION process_info;
79
CreateProcess(NULL, _tscdup(skip_first_arg(GetCommandLine())), NULL, NULL,
80
TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &startup_info,
83
// Get a handle with the needed access rights to the child process.
84
HANDLE child = INVALID_HANDLE_VALUE;
85
DuplicateHandle(GetCurrentProcess(), process_info.hProcess,
86
GetCurrentProcess(), &child,
87
PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, 0);
89
// Wait for the child to finish.
90
// If there was problem earlier (application not found etc.), this will fail.
92
if (WaitForSingleObject(child, INFINITE) == WAIT_OBJECT_0)
94
// Finally, query the timers and show the result
95
FILETIME start_time, end_time, user_time, kernel_time;
96
if (GetProcessTimes(child, &start_time, &end_time, &kernel_time,
99
_tprintf(_T("%1.3f\t%1.3f\t%1.3f\n"),
100
as_seconds(end_time) - as_seconds(start_time),
101
as_seconds(user_time), as_seconds(kernel_time));
106
// In case of failure, give some indication that something went wrong.
108
_tprintf(_T("?.???\t?.???f\t?.???\n"),
110
// Be good citizens and clean up our mess
112
CloseHandle(process_info.hThread);
113
CloseHandle(process_info.hProcess);