The version of the win32-process library
Defined for interface compatibility, but not used
Process.create(key => value, …) => ProcessInfo
This is a wrapper for the CreateProcess() function. It executes a process, returning a ProcessInfo struct. It accepts a hash as an argument. There are several primary keys:
command_line (mandatory)
app_name (default: nil)
inherit (default: false)
process_inherit (default: false)
thread_inherit (default: false)
creation_flags (default: 0)
cwd (default: Dir.pwd)
startup_info (default: nil)
environment (default: nil)
close_handles (default: true)
with_logon (default: nil)
domain (default: nil)
password (default: nil)
Of these, the ‘command_line’ or ‘app_name’ must be specified or an error is raised. Both may be set individually, but ‘command_line’ should be preferred if only one of them is set because it does not (necessarily) require an explicit path or extension to work.
The ‘domain’ and ‘password’ options are only relevent in the context of ‘with_logon’.
The startup_info key takes a hash. Its keys are attributes that are part of the StartupInfo struct, and are generally only meaningful for GUI or console processes. See the documentation on CreateProcess() and the StartupInfo struct on MSDN for more information.
desktop
title
x
y
x_size
y_size
x_count_chars
y_count_chars
fill_attribute
sw_flags
startf_flags
stdin
stdout
stderr
The relevant constants for ‘creation_flags’, ‘sw_flags’ and ‘startf_flags’ are included in the Windows::Process, Windows::Console and Windows::Window modules. These come with the windows-pr library, a prerequisite of this library. Note that the ‘stdin’, ‘stdout’ and ‘stderr’ options can be either Ruby IO objects or file descriptors (i.e. a fileno). However, StringIO objects are not currently supported.
If ‘stdin’, ‘stdout’ or ‘stderr’ are specified, then the inherit value is automatically set to true and the Process::STARTF_USESTDHANDLES flag is automatically OR’d to the startf_flags value.
The ProcessInfo struct contains the following members:
process_handle - The handle to the newly created process.
thread_handle - The handle to the primary thread of the process.
process_id - Process ID.
thread_id - Thread ID.
If the ‘close_handles’ option is set to true (the default) then the process_handle and the thread_handle are automatically closed for you before the ProcessInfo struct is returned.
If the ‘with_logon’ option is set, then the process runs the specified executable file in the security context of the specified credentials.
# File lib/win32/process.rb, line 708 708: def create(args) 709: unless args.kind_of?(Hash) 710: raise TypeError, 'Expecting hash-style keyword arguments' 711: end 712: 713: valid_keys = % 714: app_name command_line inherit creation_flags cwd environment 715: startup_info thread_inherit process_inherit close_handles with_logon 716: domain password 717: / 718: 719: valid_si_keys = % 720: startf_flags desktop title x y x_size y_size x_count_chars 721: y_count_chars fill_attribute sw_flags stdin stdout stderr 722: / 723: 724: # Set default values 725: hash = { 726: 'app_name' => nil, 727: 'creation_flags' => 0, 728: 'close_handles' => true 729: } 730: 731: # Validate the keys, and convert symbols and case to lowercase strings. 732: args.each{ |key, val| 733: key = key.to_s.downcase 734: unless valid_keys.include?(key) 735: raise ArgumentError, "invalid key '#{key}'" 736: end 737: hash[key] = val 738: } 739: 740: si_hash = {} 741: 742: # If the startup_info key is present, validate its subkeys 743: if hash['startup_info'] 744: hash['startup_info'].each{ |key, val| 745: key = key.to_s.downcase 746: unless valid_si_keys.include?(key) 747: raise ArgumentError, "invalid startup_info key '#{key}'" 748: end 749: si_hash[key] = val 750: } 751: end 752: 753: # The +command_line+ key is mandatory unless the +app_name+ key 754: # is specified. 755: unless hash['command_line'] 756: if hash['app_name'] 757: hash['command_line'] = hash['app_name'] 758: hash['app_name'] = nil 759: else 760: raise ArgumentError, 'command_line or app_name must be specified' 761: end 762: end 763: 764: # The environment string should be passed as a string of ';' separated 765: # paths. 766: if hash['environment'] 767: env = hash['environment'].split(File::PATH_SEPARATOR) << 0.chr 768: if hash['with_logon'] 769: env = env.map{ |e| multi_to_wide(e) } 770: env = [env.join("\00\\00"")].pack('p*').unpack('L').first 771: else 772: env = [env.join("\00"")].pack('p*').unpack('L').first 773: end 774: else 775: env = nil 776: end 777: 778: startinfo = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 779: startinfo = startinfo.pack('LLLLLLLLLLLLSSLLLL') 780: procinfo = [0,0,0,0].pack('LLLL') 781: 782: # Process SECURITY_ATTRIBUTE structure 783: process_security = 0 784: if hash['process_inherit'] 785: process_security = [0,0,0].pack('LLL') 786: process_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE) 787: process_security[8,4] = [1].pack('L') # TRUE 788: end 789: 790: # Thread SECURITY_ATTRIBUTE structure 791: thread_security = 0 792: if hash['thread_inherit'] 793: thread_security = [0,0,0].pack('LLL') 794: thread_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE) 795: thread_security[8,4] = [1].pack('L') # TRUE 796: end 797: 798: # Automatically handle stdin, stdout and stderr as either IO objects 799: # or file descriptors. This won't work for StringIO, however. 800: ['stdin', 'stdout', 'stderr'].each{ |io| 801: if si_hash[io] 802: if si_hash[io].respond_to?(:fileno) 803: handle = get_osfhandle(si_hash[io].fileno) 804: else 805: handle = get_osfhandle(si_hash[io]) 806: end 807: 808: if handle == INVALID_HANDLE_VALUE 809: raise Error, get_last_error 810: end 811: 812: # Most implementations of Ruby on Windows create inheritable 813: # handles by default, but some do not. RF bug #26988. 814: bool = SetHandleInformation( 815: handle, 816: HANDLE_FLAG_INHERIT, 817: HANDLE_FLAG_INHERIT 818: ) 819: 820: raise Error, get_last_error unless bool 821: 822: si_hash[io] = handle 823: si_hash['startf_flags'] ||= 0 824: si_hash['startf_flags'] |= STARTF_USESTDHANDLES 825: hash['inherit'] = true 826: end 827: } 828: 829: # The bytes not covered here are reserved (null) 830: unless si_hash.empty? 831: startinfo[0,4] = [startinfo.size].pack('L') 832: startinfo[8,4] = [si_hash['desktop']].pack('p*') if si_hash['desktop'] 833: startinfo[12,4] = [si_hash['title']].pack('p*') if si_hash['title'] 834: startinfo[16,4] = [si_hash['x']].pack('L') if si_hash['x'] 835: startinfo[20,4] = [si_hash['y']].pack('L') if si_hash['y'] 836: startinfo[24,4] = [si_hash['x_size']].pack('L') if si_hash['x_size'] 837: startinfo[28,4] = [si_hash['y_size']].pack('L') if si_hash['y_size'] 838: startinfo[32,4] = [si_hash['x_count_chars']].pack('L') if si_hash['x_count_chars'] 839: startinfo[36,4] = [si_hash['y_count_chars']].pack('L') if si_hash['y_count_chars'] 840: startinfo[40,4] = [si_hash['fill_attribute']].pack('L') if si_hash['fill_attribute'] 841: startinfo[44,4] = [si_hash['startf_flags']].pack('L') if si_hash['startf_flags'] 842: startinfo[48,2] = [si_hash['sw_flags']].pack('S') if si_hash['sw_flags'] 843: startinfo[56,4] = [si_hash['stdin']].pack('L') if si_hash['stdin'] 844: startinfo[60,4] = [si_hash['stdout']].pack('L') if si_hash['stdout'] 845: startinfo[64,4] = [si_hash['stderr']].pack('L') if si_hash['stderr'] 846: end 847: 848: if hash['with_logon'] 849: logon = multi_to_wide(hash['with_logon']) 850: domain = multi_to_wide(hash['domain']) 851: app = hash['app_name'].nil? ? nil : multi_to_wide(hash['app_name']) 852: cmd = hash['command_line'].nil? ? nil : multi_to_wide(hash['command_line']) 853: cwd = multi_to_wide(hash['cwd']) 854: passwd = multi_to_wide(hash['password']) 855: 856: hash['creation_flags'] |= CREATE_UNICODE_ENVIRONMENT 857: 858: bool = CreateProcessWithLogonW( 859: logon, # User 860: domain, # Domain 861: passwd, # Password 862: LOGON_WITH_PROFILE, # Logon flags 863: app, # App name 864: cmd, # Command line 865: hash['creation_flags'], # Creation flags 866: env, # Environment 867: cwd, # Working directory 868: startinfo, # Startup Info 869: procinfo # Process Info 870: ) 871: else 872: bool = CreateProcess( 873: hash['app_name'], # App name 874: hash['command_line'], # Command line 875: process_security, # Process attributes 876: thread_security, # Thread attributes 877: hash['inherit'], # Inherit handles? 878: hash['creation_flags'], # Creation flags 879: env, # Environment 880: hash['cwd'], # Working directory 881: startinfo, # Startup Info 882: procinfo # Process Info 883: ) 884: end 885: 886: # TODO: Close stdin, stdout and stderr handles in the si_hash unless 887: # they're pointing to one of the standard handles already. [Maybe] 888: unless bool 889: raise Error, "CreateProcess() failed: " + get_last_error 890: end 891: 892: # Automatically close the process and thread handles in the 893: # PROCESS_INFORMATION struct unless explicitly told not to. 894: if hash['close_handles'] 895: CloseHandle(procinfo[0,4].unpack('L').first) 896: CloseHandle(procinfo[4,4].unpack('L').first) 897: end 898: 899: ProcessInfo.new( 900: procinfo[0,4].unpack('L').first, # hProcess 901: procinfo[4,4].unpack('L').first, # hThread 902: procinfo[8,4].unpack('L').first, # hProcessId 903: procinfo[12,4].unpack('L').first # hThreadId 904: ) 905: end
Creates the equivalent of a subshell via the CreateProcess() function. This behaves in a manner that is similar, but not identical to, the Kernel.fork method for Unix. Unlike the Unix fork, this method starts from the top of the script rather than the point of the call.
WARNING: This implementation should be considered experimental. It is not recommended for production use.
# File lib/win32/process.rb, line 1086 1086: def fork 1087: last_arg = ARGV.last 1088: 1089: # Look for the 'child#xxx' tag 1090: if last_arg =~ /child#\d+/ 1091: @i += 1 1092: num = last_arg.split('#').last.to_i 1093: if num == @i 1094: if block_given? 1095: status = 0 1096: begin 1097: yield 1098: rescue Exception 1099: status = 1 # Any non-zero result is failure 1100: ensure 1101: return status 1102: end 1103: end 1104: return nil 1105: else 1106: return false 1107: end 1108: end 1109: 1110: # Tag the command with the word 'child#xxx' to distinguish it 1111: # from the calling process. 1112: cmd = 'ruby -I "' + $LOAD_PATH.join(File::PATH_SEPARATOR) << '" "' 1113: cmd << File.expand_path($PROGRAM_NAME) << '" ' << ARGV.join(' ') 1114: cmd << ' child#' << @child_pids.length.to_s 1115: 1116: startinfo = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 1117: startinfo = startinfo.pack('LLLLLLLLLLLLSSLLLL') 1118: procinfo = [0,0,0,0].pack('LLLL') 1119: 1120: rv = CreateProcess(0, cmd, 0, 0, 1, 0, 0, 0, startinfo, procinfo) 1121: 1122: if rv == 0 1123: raise Error, get_last_error 1124: end 1125: 1126: pid = procinfo[8,4].unpack('L').first 1127: @child_pids.push(pid) 1128: 1129: pid 1130: end
Returns the process and system affinity mask for the given pid, or the current process if no pid is provided. The return value is a two element array, with the first containing the process affinity mask, and the second containing the system affinity mask. Both are decimal values.
A process affinity mask is a bit vector indicating the processors that a process is allowed to run on. A system affinity mask is a bit vector in which each bit represents the processors that are configured into a system.
Example:
# System has 4 processors, current process is allowed to run on all Process.get_affinity # => [[15], [15]] # System has 4 processors, current process only allowed on 1 and 4 only Process.get_affinity # => [[9], [15]]
If you want to convert a decimal bit vector into an array of 0’s and 1’s indicating the flag value of each processor, you can use something like this approach:
mask = Process.get_affinity.first (0..mask).to_a.map{ |n| mask[n] }
# File lib/win32/process.rb, line 106 106: def get_affinity(int = Process.pid) 107: pmask = 0.chr * 4 108: smask = 0.chr * 4 109: 110: if int == Process.pid 111: unless GetProcessAffinityMask(GetCurrentProcess(), pmask, smask) 112: raise Error, get_last_error 113: end 114: else 115: begin 116: handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0 , int) 117: 118: if handle == INVALID_HANDLE_VALUE 119: raise Error, get_last_error 120: end 121: 122: unless GetProcessAffinityMask(handle, pmask, smask) 123: raise Error, get_last_error 124: end 125: ensure 126: CloseHandle(handle) if handle != INVALID_HANDLE_VALUE 127: end 128: end 129: 130: pmask = pmask.unpack('L').first 131: smask = smask.unpack('L').first 132: 133: [pmask, smask] 134: end
Retrieves the priority class for the specified process id int. Unlike the default implementation, lower return values do not necessarily correspond to higher priority classes.
The kind parameter is ignored but required for API compatibility. You can only retrieve process information, not process group or user information, so it is effectively always Process::PRIO_PROCESS.
Possible return values are:
32 - Process::NORMAL_PRIORITY_CLASS 64 - Process::IDLE_PRIORITY_CLASS 128 - Process::HIGH_PRIORITY_CLASS 256 - Process::REALTIME_PRIORITY_CLASS 16384 - Process::BELOW_NORMAL_PRIORITY_CLASS 32768 - Process::ABOVE_NORMAL_PRIORITY_CLASS
# File lib/win32/process.rb, line 332 332: def getpriority(kind, int) 333: raise TypeError unless kind.is_a?(Integer) 334: raise TypeError unless int.is_a?(Integer) 335: 336: int = Process.pid if int == 0 # Match spec 337: 338: handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0 , int) 339: 340: if handle == INVALID_HANDLE_VALUE 341: raise Error, get_last_error 342: end 343: 344: begin 345: priority_class = GetPriorityClass(handle) 346: 347: if priority_class == 0 348: raise Error, get_last_error 349: end 350: ensure 351: CloseHandle(handle) 352: end 353: 354: priority_class 355: end
Gets the resource limit of the current process. Only a limited number of flags are supported.
Process::RLIMIT_CPU Process::RLIMIT_FSIZE Process::RLIMIT_AS Process::RLIMIT_RSS Process::RLIMIT_VMEM
The Process:RLIMIT_AS, Process::RLIMIT_RSS and Process::VMEM constants all refer to the Process memory limit. The Process::RLIMIT_CPU constant refers to the per process user time limit. The Process::RLIMIT_FSIZE constant is hard coded to the maximum file size on an NTFS filesystem, approximately 4TB (or 4GB if not NTFS).
While a two element array is returned in order to comply with the spec, there is no separate hard and soft limit. The values will always be the same.
If [0,0] is returned then it means no limit has been set.
Example:
Process.getrlimit(Process::RLIMIT_VMEM) # => [0, 0]
# File lib/win32/process.rb, line 175 175: def getrlimit(resource) 176: if resource == RLIMIT_FSIZE 177: if get_volume_type == 'NTFS' 178: return ((1024**4) * 4) - (1024 * 64) # ~4 TB 179: else 180: return (1024**3) * 4 # 4 GB 181: end 182: end 183: 184: handle = nil 185: in_job = Process.job? 186: 187: # Put the current process in a job if it's not already in one 188: if in_job && defined?(@job_name) 189: handle = OpenJobObject(JOB_OBJECT_QUERY, true, @job_name) 190: raise Error, get_last_error if handle == 0 191: else 192: @job_name = 'ruby_' + Process.pid.to_s 193: handle = CreateJobObject(nil, @job_name) 194: raise Error, get_last_error if handle == 0 195: end 196: 197: begin 198: unless in_job 199: unless AssignProcessToJobObject(handle, GetCurrentProcess()) 200: raise Error, get_last_error 201: end 202: end 203: 204: buf = 0.chr * 112 # sizeof(struct JOBJECT_EXTENDED_LIMIT_INFORMATION) 205: val = nil # value returned at end of method 206: 207: # Set the LimitFlags member of the struct 208: case resource 209: when RLIMIT_CPU 210: buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_TIME].pack('L') 211: when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS 212: buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_MEMORY].pack('L') 213: else 214: raise Error, "unsupported resource type" 215: end 216: 217: bool = QueryInformationJobObject( 218: handle, 219: JobObjectExtendedLimitInformation, 220: buf, 221: buf.size, 222: nil 223: ) 224: 225: unless bool 226: raise Error, get_last_error 227: end 228: 229: case resource 230: when Process::RLIMIT_CPU 231: val = buf[0,8].unpack('Q').first 232: when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS 233: val = buf[96,4].unpack('L').first 234: end 235: ensure 236: at_exit{ CloseHandle(handle) if handle } 237: end 238: 239: [val, val] # Return an array of two values to comply with spec 240: end
Returns whether or not the current process is part of a Job.
# File lib/win32/process.rb, line 138 138: def job? 139: pbool = 0.chr * 4 140: IsProcessInJob(GetCurrentProcess(), nil, pbool) 141: pbool.unpack('L').first == 0 ? false : true 142: end
Sends the given signal to an array of process id’s. The signal may be any value from 0 to 9, or the special strings ‘SIGINT’ (or ‘INT’), ‘SIGBRK’ (or ‘BRK’) and ‘SIGKILL’ (or ‘KILL’). An array of successfully killed pids is returned.
Signal 0 merely tests if the process is running without killing it. Signal 2 sends a CTRL_C_EVENT to the process. Signal 3 sends a CTRL_BRK_EVENT to the process. Signal 9 kills the process in a harsh manner. Signals 1 and 4-8 kill the process in a nice manner.
SIGINT/INT corresponds to signal 2 SIGBRK/BRK corresponds to signal 3 SIGKILL/KILL corresponds to signal 9
Signals 2 and 3 only affect console processes, and then only if the process was created with the CREATE_NEW_PROCESS_GROUP flag.
# File lib/win32/process.rb, line 539 539: def kill(signal, *pids) 540: case signal 541: when 'SIGINT', 'INT' 542: signal = 2 543: when 'SIGBRK', 'BRK' 544: signal = 3 545: when 'SIGKILL', 'KILL' 546: signal = 9 547: when 0..9 548: # Do nothing 549: else 550: raise Error, "Invalid signal '#{signal}'" 551: end 552: 553: killed_pids = [] 554: 555: pids.each{ |pid| 556: # Send the signal to the current process if the pid is zero 557: if pid == 0 558: pid = Process.pid 559: end 560: 561: # No need for full access if the signal is zero 562: if signal == 0 563: access = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ 564: handle = OpenProcess(access, 0 , pid) 565: else 566: handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 567: end 568: 569: begin 570: case signal 571: when 0 572: if handle != 0 573: killed_pids.push(pid) 574: else 575: # If ERROR_ACCESS_DENIED is returned, we know it's running 576: if GetLastError() == ERROR_ACCESS_DENIED 577: killed_pids.push(pid) 578: else 579: raise Error, get_last_error 580: end 581: end 582: when 2 583: if GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid) 584: killed_pids.push(pid) 585: end 586: when 3 587: if GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid) 588: killed_pids.push(pid) 589: end 590: when 9 591: if TerminateProcess(handle, pid) 592: killed_pids.push(pid) 593: @child_pids.delete(pid) 594: else 595: raise Error, get_last_error 596: end 597: else 598: if handle != 0 599: thread_id = [0].pack('L') 600: begin 601: thread = CreateRemoteThread( 602: handle, 603: 0, 604: 0, 605: GetProcAddress(GetModuleHandle('kernel32'), 'ExitProcess'), 606: 0, 607: 0, 608: thread_id 609: ) 610: 611: if thread 612: WaitForSingleObject(thread, 5) 613: killed_pids.push(pid) 614: @child_pids.delete(pid) 615: else 616: raise Error, get_last_error 617: end 618: ensure 619: CloseHandle(thread) if thread 620: end 621: else 622: raise Error, get_last_error 623: end # case 624: 625: @child_pids.delete(pid) 626: end 627: ensure 628: CloseHandle(handle) unless handle == INVALID_HANDLE_VALUE 629: end 630: } 631: 632: killed_pids 633: end
Returns the process ID of the parent of this process.
# File lib/win32/process.rb, line 1045 1045: def ppid 1046: ppid = 0 1047: 1048: return ppid if Process.pid == 0 # Paranoia 1049: 1050: handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 1051: 1052: if handle == INVALID_HANDLE_VALUE 1053: raise Error, get_last_error 1054: end 1055: 1056: proc_entry = 0.chr * 296 # 36 + 260 1057: proc_entry[0, 4] = [proc_entry.size].pack('L') # Set dwSize member 1058: 1059: begin 1060: unless Process32First(handle, proc_entry) 1061: error = get_last_error 1062: raise Error, error 1063: end 1064: 1065: while Process32Next(handle, proc_entry) 1066: if proc_entry[8, 4].unpack('L')[0] == Process.pid 1067: ppid = proc_entry[24, 4].unpack('L')[0] # th32ParentProcessID 1068: break 1069: end 1070: end 1071: ensure 1072: CloseHandle(handle) 1073: end 1074: 1075: ppid 1076: end
Sets the priority class for the specified process id int.
The kind parameter is ignored but present for API compatibility. You can only retrieve process information, not process group or user information, so it is effectively always Process::PRIO_PROCESS.
Possible int_priority values are:
Process::NORMAL_PRIORITY_CLASS
Process::IDLE_PRIORITY_CLASS
Process::HIGH_PRIORITY_CLASS
Process::REALTIME_PRIORITY_CLASS
Process::BELOW_NORMAL_PRIORITY_CLASS
Process::ABOVE_NORMAL_PRIORITY_CLASS
# File lib/win32/process.rb, line 372 372: def setpriority(kind, int, int_priority) 373: raise TypeError unless kind.is_a?(Integer) 374: raise TypeError unless int.is_a?(Integer) 375: raise TypeError unless int_priority.is_a?(Integer) 376: 377: int = Process.pid if int == 0 # Match spec 378: 379: handle = OpenProcess(PROCESS_SET_INFORMATION, 0 , int) 380: 381: if handle == INVALID_HANDLE_VALUE 382: raise Error, get_last_error 383: end 384: 385: begin 386: unless SetPriorityClass(handle, int_priority) 387: raise Error, get_last_error 388: end 389: ensure 390: CloseHandle(handle) 391: end 392: 393: return 0 # Match the spec 394: end
Sets the resource limit of the current process. Only a limited number of flags are supported.
Process::RLIMIT_CPU Process::RLIMIT_AS Process::RLIMIT_RSS Process::RLIMIT_VMEM
The Process:RLIMIT_AS, Process::RLIMIT_RSS and Process::VMEM constants all refer to the Process memory limit. The Process::RLIMIT_CPU constant refers to the per process user time limit.
The max_limit parameter is provided for interface compatibility only. It is always set to the current_limit value.
Example:
Process.setrlimit(Process::RLIMIT_VMEM, 1024 * 4) # => nil Process.getrlimit(Process::RLIMIT_VMEM) # => [4096, 4096]
# File lib/win32/process.rb, line 262 262: def setrlimit(resource, current_limit, max_limit = nil) 263: max_limit = current_limit 264: 265: handle = nil 266: in_job = Process.job? 267: 268: # Put the current process in a job if it's not already in one 269: if in_job && defined? @job_name 270: handle = OpenJobObject(JOB_OBJECT_SET_ATTRIBUTES, true, @job_name) 271: raise Error, get_last_error if handle == 0 272: else 273: @job_name = 'ruby_' + Process.pid.to_s 274: handle = CreateJobObject(nil, job_name) 275: raise Error, get_last_error if handle == 0 276: end 277: 278: begin 279: unless in_job 280: unless AssignProcessToJobObject(handle, GetCurrentProcess()) 281: raise Error, get_last_error 282: end 283: end 284: 285: # sizeof(struct JOBJECT_EXTENDED_LIMIT_INFORMATION) 286: buf = 0.chr * 112 287: 288: # Set the LimitFlags and relevant members of the struct 289: case resource 290: when RLIMIT_CPU 291: buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_TIME].pack('L') 292: buf[0,8] = [max_limit].pack('Q') # PerProcessUserTimeLimit 293: when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS 294: buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_MEMORY].pack('L') 295: buf[96,4] = [max_limit].pack('L') # ProcessMemoryLimit 296: else 297: raise Error, "unsupported resource type" 298: end 299: 300: bool = SetInformationJobObject( 301: handle, 302: JobObjectExtendedLimitInformation, 303: buf, 304: buf.size 305: ) 306: 307: unless bool 308: raise Error, get_last_error 309: end 310: ensure 311: at_exit{ CloseHandle(handle) if handle } 312: end 313: end
Returns the uid of the current process. Specifically, it returns the RID of the SID associated with the owner of the process.
If sid is set to true, then a binary sid is returned. Otherwise, a numeric id is returned (the default).
# File lib/win32/process.rb, line 404 404: def uid(sid = false) 405: token = 0.chr * 4 406: 407: raise TypeError unless sid.is_a?(TrueClass) || sid.is_a?(FalseClass) 408: 409: unless OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, token) 410: raise Error, get_last_error 411: end 412: 413: token = token.unpack('V')[0] 414: rlength = 0.chr * 4 415: tuser = 0.chr * 512 416: 417: bool = GetTokenInformation( 418: token, 419: TokenUser, 420: tuser, 421: tuser.size, 422: rlength 423: ) 424: 425: unless bool 426: raise Error, get_last_error 427: end 428: 429: lsid = tuser[8, (rlength.unpack('L').first - 8)] 430: 431: if sid 432: lsid 433: else 434: sid_addr = [lsid].pack('p*').unpack('L')[0] 435: sid_buf = 0.chr * 80 436: sid_ptr = 0.chr * 4 437: 438: unless ConvertSidToStringSid(sid_addr, sid_ptr) 439: raise Error, get_last_error 440: end 441: 442: strcpy(sid_buf, sid_ptr.unpack('L')[0]) 443: sid_buf.strip.split('-').last.to_i 444: end 445: end
Waits for any child process to exit and returns the process id of that child. If a pid is provided that is greater than or equal to 0, then it is the equivalent of calling Process.waitpid.
The flags argument is ignored at the moment. It is provided strictly for interface compatibility.
Note that the $? (Process::Status) global variable is NOT set. This may be addressed in a future release.
# File lib/win32/process.rb, line 920 920: def wait(pid = 1, flags = nil) 921: if pid && pid >= 0 922: pid, status = waitpid(pid, flags) 923: return pid 924: end 925: 926: handles = [] 927: 928: # Windows 2000 or earlier 929: unless defined? GetProcessId 930: pids = [] 931: end 932: 933: @child_pids.each_with_index{ |pid, i| 934: handles[i] = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 935: 936: if handles[i] == INVALID_HANDLE_VALUE 937: err = "unable to get HANDLE on process associated with pid #{pid}" 938: raise Error, err 939: end 940: 941: unless defined? GetProcessId 942: pids[i] = pid 943: end 944: } 945: 946: wait = WaitForMultipleObjects( 947: handles.size, 948: handles.pack('L*'), 949: 0, 950: INFINITE 951: ) 952: 953: if wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + @child_pids.size - 1 954: index = wait - WAIT_OBJECT_0 955: handle = handles[index] 956: 957: if defined? GetProcessId 958: pid = GetProcessId(handle) 959: else 960: pid = pids[index] 961: end 962: 963: @child_pids.delete(pid) 964: handles.each{ |handle| CloseHandle(handle) } 965: return pid 966: end 967: 968: nil 969: end
Waits for any child process to exit and returns an array containing the process id and the exit status of that child.
The flags argument is ignored at the moment. It is provided strictly for interface compatibility.
Note that the $? (Process::Status) global variable is NOT set. This may be addressed in a future release.
# File lib/win32/process.rb, line 983 983: def wait2(pid = 1, flags = nil) 984: if pid && pid >= 0 985: pid, status = waitpid2(pid, flags) 986: return pid 987: end 988: 989: handles = [] 990: 991: # Windows 2000 or earlier 992: unless defined? GetProcessId 993: pids = [] 994: end 995: 996: @child_pids.each_with_index{ |pid, i| 997: handles[i] = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 998: 999: if handles[i] == INVALID_HANDLE_VALUE 1000: err = "unable to get HANDLE on process associated with pid #{pid}" 1001: raise Error, err 1002: end 1003: 1004: unless defined? GetProcessId 1005: pids[i] = pid 1006: end 1007: } 1008: 1009: wait = WaitForMultipleObjects( 1010: handles.size, 1011: handles.pack('L*'), 1012: 0, 1013: INFINITE 1014: ) 1015: 1016: if wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + @child_pids.size - 1 1017: index = wait - WAIT_OBJECT_0 1018: handle = handles[index] 1019: 1020: if defined? GetProcessId 1021: pid = GetProcessId(handle) 1022: else 1023: pid = pids[index] 1024: end 1025: 1026: exit_code = [0].pack('l') 1027: 1028: unless GetExitCodeProcess(handle, exit_code) 1029: raise get_last_error 1030: end 1031: 1032: @child_pids.delete(pid) 1033: 1034: handles.each{ |handle| CloseHandle(handle) } 1035: return [pid, exit_code.unpack('l').first] 1036: end 1037: 1038: nil 1039: end
Waits for the given child process to exit and returns that pid.
The flags argument is ignored at the moment. It is provided strictly for interface compatibility.
Note that the $? (Process::Status) global variable is NOT set. This may be addressed in a future release.
# File lib/win32/process.rb, line 455 455: def waitpid(pid, flags = nil) 456: exit_code = [0].pack('L') 457: handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 458: 459: if handle == INVALID_HANDLE_VALUE 460: raise Error, get_last_error 461: end 462: 463: # TODO: update the $? global variable (if/when possible) 464: status = WaitForSingleObject(handle, INFINITE) 465: 466: begin 467: unless GetExitCodeProcess(handle, exit_code) 468: raise Error, get_last_error 469: end 470: ensure 471: CloseHandle(handle) 472: end 473: 474: @child_pids.delete(pid) 475: 476: # TODO: update the $? global variable (if/when possible) 477: exit_code = exit_code.unpack('L').first 478: 479: pid 480: end
Waits for the given child process to exit and returns an array containing the process id and the exit status.
The flags argument is ignored at the moment. It is provided strictly for interface compatibility.
Note that the $? (Process::Status) global variable is NOT set. This may be addressed in a future release if/when possible.
# File lib/win32/process.rb, line 494 494: def waitpid2(pid, flags = nil) 495: exit_code = [0].pack('L') 496: handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 497: 498: if handle == INVALID_HANDLE_VALUE 499: raise Error, get_last_error 500: end 501: 502: # TODO: update the $? global variable (if/when possible) 503: status = WaitForSingleObject(handle, INFINITE) 504: 505: begin 506: unless GetExitCodeProcess(handle, exit_code) 507: raise Error, get_last_error 508: end 509: ensure 510: CloseHandle(handle) 511: end 512: 513: @child_pids.delete(pid) 514: 515: # TODO: update the $? global variable (if/when possible) 516: exit_code = exit_code.unpack('L').first 517: 518: [pid, exit_code] 519: end
Process.create(key => value, …) => ProcessInfo
This is a wrapper for the CreateProcess() function. It executes a process, returning a ProcessInfo struct. It accepts a hash as an argument. There are several primary keys:
command_line (mandatory)
app_name (default: nil)
inherit (default: false)
process_inherit (default: false)
thread_inherit (default: false)
creation_flags (default: 0)
cwd (default: Dir.pwd)
startup_info (default: nil)
environment (default: nil)
close_handles (default: true)
with_logon (default: nil)
domain (default: nil)
password (default: nil)
Of these, the ‘command_line’ or ‘app_name’ must be specified or an error is raised. Both may be set individually, but ‘command_line’ should be preferred if only one of them is set because it does not (necessarily) require an explicit path or extension to work.
The ‘domain’ and ‘password’ options are only relevent in the context of ‘with_logon’.
The startup_info key takes a hash. Its keys are attributes that are part of the StartupInfo struct, and are generally only meaningful for GUI or console processes. See the documentation on CreateProcess() and the StartupInfo struct on MSDN for more information.
desktop
title
x
y
x_size
y_size
x_count_chars
y_count_chars
fill_attribute
sw_flags
startf_flags
stdin
stdout
stderr
The relevant constants for ‘creation_flags’, ‘sw_flags’ and ‘startf_flags’ are included in the Windows::Process, Windows::Console and Windows::Window modules. These come with the windows-pr library, a prerequisite of this library. Note that the ‘stdin’, ‘stdout’ and ‘stderr’ options can be either Ruby IO objects or file descriptors (i.e. a fileno). However, StringIO objects are not currently supported.
If ‘stdin’, ‘stdout’ or ‘stderr’ are specified, then the inherit value is automatically set to true and the Process::STARTF_USESTDHANDLES flag is automatically OR’d to the startf_flags value.
The ProcessInfo struct contains the following members:
process_handle - The handle to the newly created process.
thread_handle - The handle to the primary thread of the process.
process_id - Process ID.
thread_id - Thread ID.
If the ‘close_handles’ option is set to true (the default) then the process_handle and the thread_handle are automatically closed for you before the ProcessInfo struct is returned.
If the ‘with_logon’ option is set, then the process runs the specified executable file in the security context of the specified credentials.
# File lib/win32/process.rb, line 708 708: def create(args) 709: unless args.kind_of?(Hash) 710: raise TypeError, 'Expecting hash-style keyword arguments' 711: end 712: 713: valid_keys = % 714: app_name command_line inherit creation_flags cwd environment 715: startup_info thread_inherit process_inherit close_handles with_logon 716: domain password 717: / 718: 719: valid_si_keys = % 720: startf_flags desktop title x y x_size y_size x_count_chars 721: y_count_chars fill_attribute sw_flags stdin stdout stderr 722: / 723: 724: # Set default values 725: hash = { 726: 'app_name' => nil, 727: 'creation_flags' => 0, 728: 'close_handles' => true 729: } 730: 731: # Validate the keys, and convert symbols and case to lowercase strings. 732: args.each{ |key, val| 733: key = key.to_s.downcase 734: unless valid_keys.include?(key) 735: raise ArgumentError, "invalid key '#{key}'" 736: end 737: hash[key] = val 738: } 739: 740: si_hash = {} 741: 742: # If the startup_info key is present, validate its subkeys 743: if hash['startup_info'] 744: hash['startup_info'].each{ |key, val| 745: key = key.to_s.downcase 746: unless valid_si_keys.include?(key) 747: raise ArgumentError, "invalid startup_info key '#{key}'" 748: end 749: si_hash[key] = val 750: } 751: end 752: 753: # The +command_line+ key is mandatory unless the +app_name+ key 754: # is specified. 755: unless hash['command_line'] 756: if hash['app_name'] 757: hash['command_line'] = hash['app_name'] 758: hash['app_name'] = nil 759: else 760: raise ArgumentError, 'command_line or app_name must be specified' 761: end 762: end 763: 764: # The environment string should be passed as a string of ';' separated 765: # paths. 766: if hash['environment'] 767: env = hash['environment'].split(File::PATH_SEPARATOR) << 0.chr 768: if hash['with_logon'] 769: env = env.map{ |e| multi_to_wide(e) } 770: env = [env.join("\00\\00"")].pack('p*').unpack('L').first 771: else 772: env = [env.join("\00"")].pack('p*').unpack('L').first 773: end 774: else 775: env = nil 776: end 777: 778: startinfo = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 779: startinfo = startinfo.pack('LLLLLLLLLLLLSSLLLL') 780: procinfo = [0,0,0,0].pack('LLLL') 781: 782: # Process SECURITY_ATTRIBUTE structure 783: process_security = 0 784: if hash['process_inherit'] 785: process_security = [0,0,0].pack('LLL') 786: process_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE) 787: process_security[8,4] = [1].pack('L') # TRUE 788: end 789: 790: # Thread SECURITY_ATTRIBUTE structure 791: thread_security = 0 792: if hash['thread_inherit'] 793: thread_security = [0,0,0].pack('LLL') 794: thread_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE) 795: thread_security[8,4] = [1].pack('L') # TRUE 796: end 797: 798: # Automatically handle stdin, stdout and stderr as either IO objects 799: # or file descriptors. This won't work for StringIO, however. 800: ['stdin', 'stdout', 'stderr'].each{ |io| 801: if si_hash[io] 802: if si_hash[io].respond_to?(:fileno) 803: handle = get_osfhandle(si_hash[io].fileno) 804: else 805: handle = get_osfhandle(si_hash[io]) 806: end 807: 808: if handle == INVALID_HANDLE_VALUE 809: raise Error, get_last_error 810: end 811: 812: # Most implementations of Ruby on Windows create inheritable 813: # handles by default, but some do not. RF bug #26988. 814: bool = SetHandleInformation( 815: handle, 816: HANDLE_FLAG_INHERIT, 817: HANDLE_FLAG_INHERIT 818: ) 819: 820: raise Error, get_last_error unless bool 821: 822: si_hash[io] = handle 823: si_hash['startf_flags'] ||= 0 824: si_hash['startf_flags'] |= STARTF_USESTDHANDLES 825: hash['inherit'] = true 826: end 827: } 828: 829: # The bytes not covered here are reserved (null) 830: unless si_hash.empty? 831: startinfo[0,4] = [startinfo.size].pack('L') 832: startinfo[8,4] = [si_hash['desktop']].pack('p*') if si_hash['desktop'] 833: startinfo[12,4] = [si_hash['title']].pack('p*') if si_hash['title'] 834: startinfo[16,4] = [si_hash['x']].pack('L') if si_hash['x'] 835: startinfo[20,4] = [si_hash['y']].pack('L') if si_hash['y'] 836: startinfo[24,4] = [si_hash['x_size']].pack('L') if si_hash['x_size'] 837: startinfo[28,4] = [si_hash['y_size']].pack('L') if si_hash['y_size'] 838: startinfo[32,4] = [si_hash['x_count_chars']].pack('L') if si_hash['x_count_chars'] 839: startinfo[36,4] = [si_hash['y_count_chars']].pack('L') if si_hash['y_count_chars'] 840: startinfo[40,4] = [si_hash['fill_attribute']].pack('L') if si_hash['fill_attribute'] 841: startinfo[44,4] = [si_hash['startf_flags']].pack('L') if si_hash['startf_flags'] 842: startinfo[48,2] = [si_hash['sw_flags']].pack('S') if si_hash['sw_flags'] 843: startinfo[56,4] = [si_hash['stdin']].pack('L') if si_hash['stdin'] 844: startinfo[60,4] = [si_hash['stdout']].pack('L') if si_hash['stdout'] 845: startinfo[64,4] = [si_hash['stderr']].pack('L') if si_hash['stderr'] 846: end 847: 848: if hash['with_logon'] 849: logon = multi_to_wide(hash['with_logon']) 850: domain = multi_to_wide(hash['domain']) 851: app = hash['app_name'].nil? ? nil : multi_to_wide(hash['app_name']) 852: cmd = hash['command_line'].nil? ? nil : multi_to_wide(hash['command_line']) 853: cwd = multi_to_wide(hash['cwd']) 854: passwd = multi_to_wide(hash['password']) 855: 856: hash['creation_flags'] |= CREATE_UNICODE_ENVIRONMENT 857: 858: bool = CreateProcessWithLogonW( 859: logon, # User 860: domain, # Domain 861: passwd, # Password 862: LOGON_WITH_PROFILE, # Logon flags 863: app, # App name 864: cmd, # Command line 865: hash['creation_flags'], # Creation flags 866: env, # Environment 867: cwd, # Working directory 868: startinfo, # Startup Info 869: procinfo # Process Info 870: ) 871: else 872: bool = CreateProcess( 873: hash['app_name'], # App name 874: hash['command_line'], # Command line 875: process_security, # Process attributes 876: thread_security, # Thread attributes 877: hash['inherit'], # Inherit handles? 878: hash['creation_flags'], # Creation flags 879: env, # Environment 880: hash['cwd'], # Working directory 881: startinfo, # Startup Info 882: procinfo # Process Info 883: ) 884: end 885: 886: # TODO: Close stdin, stdout and stderr handles in the si_hash unless 887: # they're pointing to one of the standard handles already. [Maybe] 888: unless bool 889: raise Error, "CreateProcess() failed: " + get_last_error 890: end 891: 892: # Automatically close the process and thread handles in the 893: # PROCESS_INFORMATION struct unless explicitly told not to. 894: if hash['close_handles'] 895: CloseHandle(procinfo[0,4].unpack('L').first) 896: CloseHandle(procinfo[4,4].unpack('L').first) 897: end 898: 899: ProcessInfo.new( 900: procinfo[0,4].unpack('L').first, # hProcess 901: procinfo[4,4].unpack('L').first, # hThread 902: procinfo[8,4].unpack('L').first, # hProcessId 903: procinfo[12,4].unpack('L').first # hThreadId 904: ) 905: end
Creates the equivalent of a subshell via the CreateProcess() function. This behaves in a manner that is similar, but not identical to, the Kernel.fork method for Unix. Unlike the Unix fork, this method starts from the top of the script rather than the point of the call.
WARNING: This implementation should be considered experimental. It is not recommended for production use.
# File lib/win32/process.rb, line 1086 1086: def fork 1087: last_arg = ARGV.last 1088: 1089: # Look for the 'child#xxx' tag 1090: if last_arg =~ /child#\d+/ 1091: @i += 1 1092: num = last_arg.split('#').last.to_i 1093: if num == @i 1094: if block_given? 1095: status = 0 1096: begin 1097: yield 1098: rescue Exception 1099: status = 1 # Any non-zero result is failure 1100: ensure 1101: return status 1102: end 1103: end 1104: return nil 1105: else 1106: return false 1107: end 1108: end 1109: 1110: # Tag the command with the word 'child#xxx' to distinguish it 1111: # from the calling process. 1112: cmd = 'ruby -I "' + $LOAD_PATH.join(File::PATH_SEPARATOR) << '" "' 1113: cmd << File.expand_path($PROGRAM_NAME) << '" ' << ARGV.join(' ') 1114: cmd << ' child#' << @child_pids.length.to_s 1115: 1116: startinfo = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] 1117: startinfo = startinfo.pack('LLLLLLLLLLLLSSLLLL') 1118: procinfo = [0,0,0,0].pack('LLLL') 1119: 1120: rv = CreateProcess(0, cmd, 0, 0, 1, 0, 0, 0, startinfo, procinfo) 1121: 1122: if rv == 0 1123: raise Error, get_last_error 1124: end 1125: 1126: pid = procinfo[8,4].unpack('L').first 1127: @child_pids.push(pid) 1128: 1129: pid 1130: end
Returns the process and system affinity mask for the given pid, or the current process if no pid is provided. The return value is a two element array, with the first containing the process affinity mask, and the second containing the system affinity mask. Both are decimal values.
A process affinity mask is a bit vector indicating the processors that a process is allowed to run on. A system affinity mask is a bit vector in which each bit represents the processors that are configured into a system.
Example:
# System has 4 processors, current process is allowed to run on all Process.get_affinity # => [[15], [15]] # System has 4 processors, current process only allowed on 1 and 4 only Process.get_affinity # => [[9], [15]]
If you want to convert a decimal bit vector into an array of 0’s and 1’s indicating the flag value of each processor, you can use something like this approach:
mask = Process.get_affinity.first (0..mask).to_a.map{ |n| mask[n] }
# File lib/win32/process.rb, line 106 106: def get_affinity(int = Process.pid) 107: pmask = 0.chr * 4 108: smask = 0.chr * 4 109: 110: if int == Process.pid 111: unless GetProcessAffinityMask(GetCurrentProcess(), pmask, smask) 112: raise Error, get_last_error 113: end 114: else 115: begin 116: handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0 , int) 117: 118: if handle == INVALID_HANDLE_VALUE 119: raise Error, get_last_error 120: end 121: 122: unless GetProcessAffinityMask(handle, pmask, smask) 123: raise Error, get_last_error 124: end 125: ensure 126: CloseHandle(handle) if handle != INVALID_HANDLE_VALUE 127: end 128: end 129: 130: pmask = pmask.unpack('L').first 131: smask = smask.unpack('L').first 132: 133: [pmask, smask] 134: end
Retrieves the priority class for the specified process id int. Unlike the default implementation, lower return values do not necessarily correspond to higher priority classes.
The kind parameter is ignored but required for API compatibility. You can only retrieve process information, not process group or user information, so it is effectively always Process::PRIO_PROCESS.
Possible return values are:
32 - Process::NORMAL_PRIORITY_CLASS 64 - Process::IDLE_PRIORITY_CLASS 128 - Process::HIGH_PRIORITY_CLASS 256 - Process::REALTIME_PRIORITY_CLASS 16384 - Process::BELOW_NORMAL_PRIORITY_CLASS 32768 - Process::ABOVE_NORMAL_PRIORITY_CLASS
# File lib/win32/process.rb, line 332 332: def getpriority(kind, int) 333: raise TypeError unless kind.is_a?(Integer) 334: raise TypeError unless int.is_a?(Integer) 335: 336: int = Process.pid if int == 0 # Match spec 337: 338: handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0 , int) 339: 340: if handle == INVALID_HANDLE_VALUE 341: raise Error, get_last_error 342: end 343: 344: begin 345: priority_class = GetPriorityClass(handle) 346: 347: if priority_class == 0 348: raise Error, get_last_error 349: end 350: ensure 351: CloseHandle(handle) 352: end 353: 354: priority_class 355: end
Gets the resource limit of the current process. Only a limited number of flags are supported.
Process::RLIMIT_CPU Process::RLIMIT_FSIZE Process::RLIMIT_AS Process::RLIMIT_RSS Process::RLIMIT_VMEM
The Process:RLIMIT_AS, Process::RLIMIT_RSS and Process::VMEM constants all refer to the Process memory limit. The Process::RLIMIT_CPU constant refers to the per process user time limit. The Process::RLIMIT_FSIZE constant is hard coded to the maximum file size on an NTFS filesystem, approximately 4TB (or 4GB if not NTFS).
While a two element array is returned in order to comply with the spec, there is no separate hard and soft limit. The values will always be the same.
If [0,0] is returned then it means no limit has been set.
Example:
Process.getrlimit(Process::RLIMIT_VMEM) # => [0, 0]
# File lib/win32/process.rb, line 175 175: def getrlimit(resource) 176: if resource == RLIMIT_FSIZE 177: if get_volume_type == 'NTFS' 178: return ((1024**4) * 4) - (1024 * 64) # ~4 TB 179: else 180: return (1024**3) * 4 # 4 GB 181: end 182: end 183: 184: handle = nil 185: in_job = Process.job? 186: 187: # Put the current process in a job if it's not already in one 188: if in_job && defined?(@job_name) 189: handle = OpenJobObject(JOB_OBJECT_QUERY, true, @job_name) 190: raise Error, get_last_error if handle == 0 191: else 192: @job_name = 'ruby_' + Process.pid.to_s 193: handle = CreateJobObject(nil, @job_name) 194: raise Error, get_last_error if handle == 0 195: end 196: 197: begin 198: unless in_job 199: unless AssignProcessToJobObject(handle, GetCurrentProcess()) 200: raise Error, get_last_error 201: end 202: end 203: 204: buf = 0.chr * 112 # sizeof(struct JOBJECT_EXTENDED_LIMIT_INFORMATION) 205: val = nil # value returned at end of method 206: 207: # Set the LimitFlags member of the struct 208: case resource 209: when RLIMIT_CPU 210: buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_TIME].pack('L') 211: when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS 212: buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_MEMORY].pack('L') 213: else 214: raise Error, "unsupported resource type" 215: end 216: 217: bool = QueryInformationJobObject( 218: handle, 219: JobObjectExtendedLimitInformation, 220: buf, 221: buf.size, 222: nil 223: ) 224: 225: unless bool 226: raise Error, get_last_error 227: end 228: 229: case resource 230: when Process::RLIMIT_CPU 231: val = buf[0,8].unpack('Q').first 232: when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS 233: val = buf[96,4].unpack('L').first 234: end 235: ensure 236: at_exit{ CloseHandle(handle) if handle } 237: end 238: 239: [val, val] # Return an array of two values to comply with spec 240: end
Returns whether or not the current process is part of a Job.
# File lib/win32/process.rb, line 138 138: def job? 139: pbool = 0.chr * 4 140: IsProcessInJob(GetCurrentProcess(), nil, pbool) 141: pbool.unpack('L').first == 0 ? false : true 142: end
Sends the given signal to an array of process id’s. The signal may be any value from 0 to 9, or the special strings ‘SIGINT’ (or ‘INT’), ‘SIGBRK’ (or ‘BRK’) and ‘SIGKILL’ (or ‘KILL’). An array of successfully killed pids is returned.
Signal 0 merely tests if the process is running without killing it. Signal 2 sends a CTRL_C_EVENT to the process. Signal 3 sends a CTRL_BRK_EVENT to the process. Signal 9 kills the process in a harsh manner. Signals 1 and 4-8 kill the process in a nice manner.
SIGINT/INT corresponds to signal 2 SIGBRK/BRK corresponds to signal 3 SIGKILL/KILL corresponds to signal 9
Signals 2 and 3 only affect console processes, and then only if the process was created with the CREATE_NEW_PROCESS_GROUP flag.
# File lib/win32/process.rb, line 539 539: def kill(signal, *pids) 540: case signal 541: when 'SIGINT', 'INT' 542: signal = 2 543: when 'SIGBRK', 'BRK' 544: signal = 3 545: when 'SIGKILL', 'KILL' 546: signal = 9 547: when 0..9 548: # Do nothing 549: else 550: raise Error, "Invalid signal '#{signal}'" 551: end 552: 553: killed_pids = [] 554: 555: pids.each{ |pid| 556: # Send the signal to the current process if the pid is zero 557: if pid == 0 558: pid = Process.pid 559: end 560: 561: # No need for full access if the signal is zero 562: if signal == 0 563: access = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ 564: handle = OpenProcess(access, 0 , pid) 565: else 566: handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 567: end 568: 569: begin 570: case signal 571: when 0 572: if handle != 0 573: killed_pids.push(pid) 574: else 575: # If ERROR_ACCESS_DENIED is returned, we know it's running 576: if GetLastError() == ERROR_ACCESS_DENIED 577: killed_pids.push(pid) 578: else 579: raise Error, get_last_error 580: end 581: end 582: when 2 583: if GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid) 584: killed_pids.push(pid) 585: end 586: when 3 587: if GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid) 588: killed_pids.push(pid) 589: end 590: when 9 591: if TerminateProcess(handle, pid) 592: killed_pids.push(pid) 593: @child_pids.delete(pid) 594: else 595: raise Error, get_last_error 596: end 597: else 598: if handle != 0 599: thread_id = [0].pack('L') 600: begin 601: thread = CreateRemoteThread( 602: handle, 603: 0, 604: 0, 605: GetProcAddress(GetModuleHandle('kernel32'), 'ExitProcess'), 606: 0, 607: 0, 608: thread_id 609: ) 610: 611: if thread 612: WaitForSingleObject(thread, 5) 613: killed_pids.push(pid) 614: @child_pids.delete(pid) 615: else 616: raise Error, get_last_error 617: end 618: ensure 619: CloseHandle(thread) if thread 620: end 621: else 622: raise Error, get_last_error 623: end # case 624: 625: @child_pids.delete(pid) 626: end 627: ensure 628: CloseHandle(handle) unless handle == INVALID_HANDLE_VALUE 629: end 630: } 631: 632: killed_pids 633: end
Returns the process ID of the parent of this process.
# File lib/win32/process.rb, line 1045 1045: def ppid 1046: ppid = 0 1047: 1048: return ppid if Process.pid == 0 # Paranoia 1049: 1050: handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 1051: 1052: if handle == INVALID_HANDLE_VALUE 1053: raise Error, get_last_error 1054: end 1055: 1056: proc_entry = 0.chr * 296 # 36 + 260 1057: proc_entry[0, 4] = [proc_entry.size].pack('L') # Set dwSize member 1058: 1059: begin 1060: unless Process32First(handle, proc_entry) 1061: error = get_last_error 1062: raise Error, error 1063: end 1064: 1065: while Process32Next(handle, proc_entry) 1066: if proc_entry[8, 4].unpack('L')[0] == Process.pid 1067: ppid = proc_entry[24, 4].unpack('L')[0] # th32ParentProcessID 1068: break 1069: end 1070: end 1071: ensure 1072: CloseHandle(handle) 1073: end 1074: 1075: ppid 1076: end
Sets the priority class for the specified process id int.
The kind parameter is ignored but present for API compatibility. You can only retrieve process information, not process group or user information, so it is effectively always Process::PRIO_PROCESS.
Possible int_priority values are:
Process::NORMAL_PRIORITY_CLASS
Process::IDLE_PRIORITY_CLASS
Process::HIGH_PRIORITY_CLASS
Process::REALTIME_PRIORITY_CLASS
Process::BELOW_NORMAL_PRIORITY_CLASS
Process::ABOVE_NORMAL_PRIORITY_CLASS
# File lib/win32/process.rb, line 372 372: def setpriority(kind, int, int_priority) 373: raise TypeError unless kind.is_a?(Integer) 374: raise TypeError unless int.is_a?(Integer) 375: raise TypeError unless int_priority.is_a?(Integer) 376: 377: int = Process.pid if int == 0 # Match spec 378: 379: handle = OpenProcess(PROCESS_SET_INFORMATION, 0 , int) 380: 381: if handle == INVALID_HANDLE_VALUE 382: raise Error, get_last_error 383: end 384: 385: begin 386: unless SetPriorityClass(handle, int_priority) 387: raise Error, get_last_error 388: end 389: ensure 390: CloseHandle(handle) 391: end 392: 393: return 0 # Match the spec 394: end
Sets the resource limit of the current process. Only a limited number of flags are supported.
Process::RLIMIT_CPU Process::RLIMIT_AS Process::RLIMIT_RSS Process::RLIMIT_VMEM
The Process:RLIMIT_AS, Process::RLIMIT_RSS and Process::VMEM constants all refer to the Process memory limit. The Process::RLIMIT_CPU constant refers to the per process user time limit.
The max_limit parameter is provided for interface compatibility only. It is always set to the current_limit value.
Example:
Process.setrlimit(Process::RLIMIT_VMEM, 1024 * 4) # => nil Process.getrlimit(Process::RLIMIT_VMEM) # => [4096, 4096]
# File lib/win32/process.rb, line 262 262: def setrlimit(resource, current_limit, max_limit = nil) 263: max_limit = current_limit 264: 265: handle = nil 266: in_job = Process.job? 267: 268: # Put the current process in a job if it's not already in one 269: if in_job && defined? @job_name 270: handle = OpenJobObject(JOB_OBJECT_SET_ATTRIBUTES, true, @job_name) 271: raise Error, get_last_error if handle == 0 272: else 273: @job_name = 'ruby_' + Process.pid.to_s 274: handle = CreateJobObject(nil, job_name) 275: raise Error, get_last_error if handle == 0 276: end 277: 278: begin 279: unless in_job 280: unless AssignProcessToJobObject(handle, GetCurrentProcess()) 281: raise Error, get_last_error 282: end 283: end 284: 285: # sizeof(struct JOBJECT_EXTENDED_LIMIT_INFORMATION) 286: buf = 0.chr * 112 287: 288: # Set the LimitFlags and relevant members of the struct 289: case resource 290: when RLIMIT_CPU 291: buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_TIME].pack('L') 292: buf[0,8] = [max_limit].pack('Q') # PerProcessUserTimeLimit 293: when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS 294: buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_MEMORY].pack('L') 295: buf[96,4] = [max_limit].pack('L') # ProcessMemoryLimit 296: else 297: raise Error, "unsupported resource type" 298: end 299: 300: bool = SetInformationJobObject( 301: handle, 302: JobObjectExtendedLimitInformation, 303: buf, 304: buf.size 305: ) 306: 307: unless bool 308: raise Error, get_last_error 309: end 310: ensure 311: at_exit{ CloseHandle(handle) if handle } 312: end 313: end
Returns the uid of the current process. Specifically, it returns the RID of the SID associated with the owner of the process.
If sid is set to true, then a binary sid is returned. Otherwise, a numeric id is returned (the default).
# File lib/win32/process.rb, line 404 404: def uid(sid = false) 405: token = 0.chr * 4 406: 407: raise TypeError unless sid.is_a?(TrueClass) || sid.is_a?(FalseClass) 408: 409: unless OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, token) 410: raise Error, get_last_error 411: end 412: 413: token = token.unpack('V')[0] 414: rlength = 0.chr * 4 415: tuser = 0.chr * 512 416: 417: bool = GetTokenInformation( 418: token, 419: TokenUser, 420: tuser, 421: tuser.size, 422: rlength 423: ) 424: 425: unless bool 426: raise Error, get_last_error 427: end 428: 429: lsid = tuser[8, (rlength.unpack('L').first - 8)] 430: 431: if sid 432: lsid 433: else 434: sid_addr = [lsid].pack('p*').unpack('L')[0] 435: sid_buf = 0.chr * 80 436: sid_ptr = 0.chr * 4 437: 438: unless ConvertSidToStringSid(sid_addr, sid_ptr) 439: raise Error, get_last_error 440: end 441: 442: strcpy(sid_buf, sid_ptr.unpack('L')[0]) 443: sid_buf.strip.split('-').last.to_i 444: end 445: end
Waits for any child process to exit and returns the process id of that child. If a pid is provided that is greater than or equal to 0, then it is the equivalent of calling Process.waitpid.
The flags argument is ignored at the moment. It is provided strictly for interface compatibility.
Note that the $? (Process::Status) global variable is NOT set. This may be addressed in a future release.
# File lib/win32/process.rb, line 920 920: def wait(pid = 1, flags = nil) 921: if pid && pid >= 0 922: pid, status = waitpid(pid, flags) 923: return pid 924: end 925: 926: handles = [] 927: 928: # Windows 2000 or earlier 929: unless defined? GetProcessId 930: pids = [] 931: end 932: 933: @child_pids.each_with_index{ |pid, i| 934: handles[i] = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 935: 936: if handles[i] == INVALID_HANDLE_VALUE 937: err = "unable to get HANDLE on process associated with pid #{pid}" 938: raise Error, err 939: end 940: 941: unless defined? GetProcessId 942: pids[i] = pid 943: end 944: } 945: 946: wait = WaitForMultipleObjects( 947: handles.size, 948: handles.pack('L*'), 949: 0, 950: INFINITE 951: ) 952: 953: if wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + @child_pids.size - 1 954: index = wait - WAIT_OBJECT_0 955: handle = handles[index] 956: 957: if defined? GetProcessId 958: pid = GetProcessId(handle) 959: else 960: pid = pids[index] 961: end 962: 963: @child_pids.delete(pid) 964: handles.each{ |handle| CloseHandle(handle) } 965: return pid 966: end 967: 968: nil 969: end
Waits for any child process to exit and returns an array containing the process id and the exit status of that child.
The flags argument is ignored at the moment. It is provided strictly for interface compatibility.
Note that the $? (Process::Status) global variable is NOT set. This may be addressed in a future release.
# File lib/win32/process.rb, line 983 983: def wait2(pid = 1, flags = nil) 984: if pid && pid >= 0 985: pid, status = waitpid2(pid, flags) 986: return pid 987: end 988: 989: handles = [] 990: 991: # Windows 2000 or earlier 992: unless defined? GetProcessId 993: pids = [] 994: end 995: 996: @child_pids.each_with_index{ |pid, i| 997: handles[i] = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 998: 999: if handles[i] == INVALID_HANDLE_VALUE 1000: err = "unable to get HANDLE on process associated with pid #{pid}" 1001: raise Error, err 1002: end 1003: 1004: unless defined? GetProcessId 1005: pids[i] = pid 1006: end 1007: } 1008: 1009: wait = WaitForMultipleObjects( 1010: handles.size, 1011: handles.pack('L*'), 1012: 0, 1013: INFINITE 1014: ) 1015: 1016: if wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + @child_pids.size - 1 1017: index = wait - WAIT_OBJECT_0 1018: handle = handles[index] 1019: 1020: if defined? GetProcessId 1021: pid = GetProcessId(handle) 1022: else 1023: pid = pids[index] 1024: end 1025: 1026: exit_code = [0].pack('l') 1027: 1028: unless GetExitCodeProcess(handle, exit_code) 1029: raise get_last_error 1030: end 1031: 1032: @child_pids.delete(pid) 1033: 1034: handles.each{ |handle| CloseHandle(handle) } 1035: return [pid, exit_code.unpack('l').first] 1036: end 1037: 1038: nil 1039: end
Waits for the given child process to exit and returns that pid.
The flags argument is ignored at the moment. It is provided strictly for interface compatibility.
Note that the $? (Process::Status) global variable is NOT set. This may be addressed in a future release.
# File lib/win32/process.rb, line 455 455: def waitpid(pid, flags = nil) 456: exit_code = [0].pack('L') 457: handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 458: 459: if handle == INVALID_HANDLE_VALUE 460: raise Error, get_last_error 461: end 462: 463: # TODO: update the $? global variable (if/when possible) 464: status = WaitForSingleObject(handle, INFINITE) 465: 466: begin 467: unless GetExitCodeProcess(handle, exit_code) 468: raise Error, get_last_error 469: end 470: ensure 471: CloseHandle(handle) 472: end 473: 474: @child_pids.delete(pid) 475: 476: # TODO: update the $? global variable (if/when possible) 477: exit_code = exit_code.unpack('L').first 478: 479: pid 480: end
Waits for the given child process to exit and returns an array containing the process id and the exit status.
The flags argument is ignored at the moment. It is provided strictly for interface compatibility.
Note that the $? (Process::Status) global variable is NOT set. This may be addressed in a future release if/when possible.
# File lib/win32/process.rb, line 494 494: def waitpid2(pid, flags = nil) 495: exit_code = [0].pack('L') 496: handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid) 497: 498: if handle == INVALID_HANDLE_VALUE 499: raise Error, get_last_error 500: end 501: 502: # TODO: update the $? global variable (if/when possible) 503: status = WaitForSingleObject(handle, INFINITE) 504: 505: begin 506: unless GetExitCodeProcess(handle, exit_code) 507: raise Error, get_last_error 508: end 509: ensure 510: CloseHandle(handle) 511: end 512: 513: @child_pids.delete(pid) 514: 515: # TODO: update the $? global variable (if/when possible) 516: exit_code = exit_code.unpack('L').first 517: 518: [pid, exit_code] 519: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.


--- name: home.course-update url: courses/update/:id controller: CoursesCtrl as vm ---
You are not logged in.


[§431:20-106.5] Escrow depositories. Any title insurer or insurer which operates as an escrow depository as defined in chapter 449 shall be licensed in accordance with chapter 449. [L 1996, c 27, §1]


Registration Success! Please click here to login!.
Error in Adding.! Please click here to login!.
Here is a subtitle for this table
| Item Code | Name | Whole Sale Prise | Retail Prise | Actions | ||
|---|---|---|---|---|---|---|
| {{rec.code}} | {{rec.name}} | {{rec.wholesalePrice}} | {{rec.retailPrice}} | |||
| No data Available! |


I'm a Responsive Designer and Developer who thrives on visual storytelling. When I'm not working, I can be found flying my drone around capturing color pics and vids or sitting on the coach enjoying a show or movie and knitting a sweater for my baby niece.
I am a proud Utah native, but I love to travel. Utah is a beautiful place, but it's a specific kind of beauty and I love to see what other types of beauty exist around the world. Can't wait to stamp my passport again.
My passion: I LOVE music. Ever since I saw my older siblings taking piano lessons I knew that I wanted to play the piano too. I've also learned to play the saxophone, some guitar, and the cello.
A fun fact: When I was a child my older sistser taught me how to do some tumbling tricks and to this day I can do a round-off backflip. I spent many a summer evening jumping on the tramp.


Note:
This page has been enhanced for printing. Click the print button at the bottom of the report to print.Amazing Model, Inc. Date: 2/10/2014
| Qty | Product | Subtotal | ||
|---|---|---|---|---|
| 1 | Call of Duty | 455-981-221 | El snort testosterone trophy driving gloves handsome | $64.50 |
th:href="@{/admin/inventory/index}
Print


Usage: docker engine COMMAND
Manage the docker engine
Commands:
activate
Activate Enterprise Edition
check
Check for available engine updates
update
Update a local engine
Run 'docker engine COMMAND --help' for more information on a command.


|
Valkyrie Engine Core
|
Template class for ECS components. More...
#include <Component.hpp>
Public Member Functions | |
| virtual void | Delete () final override |
| Deletes this component. More... | |
| void | Attach (EntityID eId) |
| Attaches this component to an entity. More... | |
| Public Member Functions inherited from vlk::IComponent | |
| EntityID | GetEntity () const |
| Gets the id of the Entity this component is attached to. | |
Static Public Member Functions | |
| template<typename... Args> | |
| static Component< T > * | Create (EntityID eId, Args... args) |
| Creates a component. More... | |
| static VLK_NODISCARD Component< T > * | FindOne (EntityID id) |
| Find a component attached to an entity. More... | |
| static Size | FindAll (EntityID id, std::vector< Component< T > * > &vecOut) |
| Find components attached to an entity. More... | |
| static void | ForEach (std::function< void(Component< T > *)> func) |
| Performs a mutating function on every instance of this component. More... | |
| static void | CForEach (std::function< void(const Component< T > *)> func) |
| Performs a non-mutating function on every instance of this component. More... | |
| static Size | Count () |
| Returns the number of instances of this component that currently exist. More... | |
| static Size | ChunkCount () |
| Returns the number of storage blocks this component has allocated. More... | |
Additional Inherited Members | |
| Protected Attributes inherited from vlk::IComponent | |
| EntityID | entity |
| The Entity this component is attached to. | |
Template class for ECS components.
Components are storage objects that define little to no logic. Components can be attached to entities with Attach() to provide the entity with some sort of property. A Component attached to an entity can then be fetched using FindOne(EntityID) or FindMany(EntityID). Components can also be accessed or modified by passing a function object to either ForEach(std::function<void(const T*)>) or ForEach(std::function<void(T*)>)
Some behaviour related to Components can be controlled by specializing GetComponentHints() for T.
| T | The data this entity is storing. Ideally this would be a POD struct, but any type with at least one public constructor and a public destructor will work. |
|
inline |
Attaches this component to an entity.
| eId | The entity to attach this component to. |
A component can only be attached to one entity at a time, if this component is already attached to an entity when Attach is called, it is detached from that entity and attached to the new one. Components cannot exist detached from an entity.
|
inlinestatic |
Performs a non-mutating function on every instance of this component.
| func | A function object that returns void and accepts a single pointer to a const Component<T>. |
|
inlinestatic |
Returns the number of storage blocks this component has allocated.
If GetComponentHints<T>().allocAutoResize
evaluates to true, this number will not exceed 1.
|
inlinestatic |
Returns the number of instances of this component that currently exist.
If GetComponentHints<T>().allocAutoResize
evaluates to true, this number will not exceed the value specified by GetComponentHints<T>().allocBlockSize
|
inlinestatic |
Creates a component.
| eId | The entity to attach the new component to. |
| args | Arguments to be forwarded to the constructor for T. |
|
inlinefinaloverridevirtual |
Deletes this component.
If this component is attached to an entity, it is detached. Also calls the destructor for this object.
Implements vlk::IComponent.
|
inlinestatic |
Find components attached to an entity.
| id | The entity to find components for. |
| vecOut | A vector to write the found components to. Existing contents are not modified, but the vector may be resized. |
|
inlinestatic |
Find a component attached to an entity.
nullptr
if no component of this type is found. If multiple components of this type are attached to the given entity, no guarantees are made as to which component will be returned.
|
inlinestatic |
Performs a mutating function on every instance of this component.
| func | A function object that returns void and accepts a single pointer to a Component<T>. |


Branding & Contest Platform Integration
OVERVIEW
Each year Canadian Science Publishing (CSP) runs an image contest. Once of the first tasks I was assigned when I came on board was to rethink how the current contest was run and what platform it used. The current contest had no consistent visual presence, showed no growth year to year and there was no way to track the contest performance data.
My research encompassed:
ROLE
Graphic Designer
User Research, Interaction, Visual design, Front-end web design, Prototyping & Testing
June 2020 - Ongoing
To better understand the current contest process, I mapped and analyzed the current user journeys and documented the pain points I discovered. I made a list of technical requirements for the new image contest platform and researched potential candidate platforms. After trialing several of those platforms, I mapped several potential new user journeys taking into account the integration process of each platform. I presented these findings to the marketing team we came to a decision.
In addition to updating the image contest platform I also built a sub-brand specifically for the marketing team to promote the image contest. I documented how the brand would be used across all promotional aspects of the image contest and presented this to the marketing team. We successfully launched the contest through our WordPress blog in July 2021. While the contest was running I was responsible for monitoring, maintaining and updating the front-end of the contest page. The results of 2021 contest yielded triple the amount of our previous entry numbers.
eCommerce Photography & Medical Iconography
OVERVIEW
As part of my role at Canopy Growth, I was responsible for photographing products and retouching images across corporate, recreational and medical brands. These assets were used on eCommerce sites across the country. This also included designing icons for Canopy’s medical brand, Spectrum Therapeutics.
ROLE
Production Designer
Photo Retouching, Visual Design, Photography
November 2019 - May 2020
End-to-end visual design
OVERVIEW
When I joined the team at Coyle Media Group (CMG), I was joining a start-up even though they had been in the publishing industry for 17 years. Instead of outsourcing to a third party, CMG was now bringing magazine design in-house and launching digital initiatives to bring their publications up to the speed of the modern publishing world.
ROLE
Lead Graphic Designer
User research, Visual design, Front-end web design, Brand design
September 2018 - September 2019
My responsibility as the design lead was to spearhead the in-house design of the magazines and format this content for the magazine websites.
I established a design system, a project timeline and a design process. I designed the layout and typography for all of the advertorial and editorial and approximately 40% of the advertising for each issue.
The skills I learned at CMG would set me up for future implementation of processes and systems. I was able to accomplish these key achievements:


Add Button
Forename
Surname
Position
Office
Start date
Salary
Can Edit
Tokyo
London
San Francisco
New York
No. People:
=Records()
Total:
=Range(5)


The Italian Food and Beer Festival (IFBF) will take place in Cary, NC and will feature Italian foods,
drinks, beers, wines, crafts, clothing, jewelry, salons, etc. From Food Trucks to local Pizza
Parlors to Italian Restuarants, the IFBF will attempt to bring the Best in Italian foods to the
Festival.


Proxy backend for sparse matrix types.The SparseMatrixProxy class serves as a backend for the Proxy class. It is used in case the data type represented by the proxy is a sparse matrix and augments the Proxy interface by the complete interface required of sparse matrices. More...
#include <SparseMatrixProxy.h>
Inherits blaze::SparseMatrix< PT, IsColumnMajorMatrix< MT >::value >.
Public Types | |
| enum | : bool { smpAssignable = MT::smpAssignable } |
| Compilation flag for SMP assignments. | |
| using | ResultType = ResultType_< MT > |
| Result type for expression template evaluations. | |
| using | OppositeType = OppositeType_< MT > |
| Result type with opposite storage order for expression template evaluations. | |
| using | TransposeType = TransposeType_< MT > |
| Transpose type for expression template evaluations. | |
| using | ElementType = ElementType_< MT > |
| Type of the sparse matrix elements. | |
| using | ReturnType = ReturnType_< MT > |
| Return type for expression template evaluations. | |
| using | CompositeType = CompositeType_< MT > |
| Data type for composite expression templates. | |
| using | Reference = Reference_< MT > |
| Reference to a non-constant matrix value. | |
| using | ConstReference = ConstReference_< MT > |
| Reference to a constant matrix value. | |
| using | Iterator = Iterator_< MT > |
| Iterator over non-constant elements. | |
| using | ConstIterator = ConstIterator_< MT > |
| Iterator over constant elements. | |
| using | MatrixType = PT |
| Type of the matrix. | |
Public Member Functions | |
| BLAZE_ALWAYS_INLINE MatrixType & | operator~ () noexcept |
| Conversion operator for non-constant matrices. More... | |
| BLAZE_ALWAYS_INLINE const MatrixType & | operator~ () const noexcept |
| Conversion operator for constant matrices. More... | |
Data access functions | |
| Reference | operator() (size_t i, size_t j) const |
| Function call operator for the direct access to matrix elements. More... | |
| Reference | at (size_t i, size_t j) const |
| Checked access to the matrix elements. More... | |
| Iterator | begin (size_t i) const |
| Returns an iterator to the first element of row/column i of the represented matrix. More... | |
| ConstIterator | cbegin (size_t i) const |
| Returns an iterator to the first element of row/column i of the represented matrix. More... | |
| Iterator | end (size_t i) const |
| Returns an iterator just past the last element of row/column i of the represented matrix. More... | |
| ConstIterator | cend (size_t i) const |
| Returns an iterator just past the last element of row/column i of the represented matrix. More... | |
Utility functions | |
| size_t | rows () const |
| Returns the current number of rows of the represented matrix. More... | |
| size_t | columns () const |
| Returns the current number of columns of the represented matrix. More... | |
| size_t | capacity () const |
| Returns the maximum capacity of the represented matrix. More... | |
| size_t | capacity (size_t i) const |
| Returns the current capacity of the specified row/column of the represented matrix. More... | |
| size_t | nonZeros () const |
| Returns the number of non-zero elements in the represented matrix. More... | |
| size_t | nonZeros (size_t i) const |
| Returns the number of non-zero elements in the specified row/column of the represented matrix. More... | |
| void | reset () const |
| Reset to the default initial value. More... | |
| void | reset (size_t i) const |
| Reset the specified row/column to the default initial values. More... | |
| void | clear () const |
| Clearing the represented vector. More... | |
| void | finalize (size_t i) const |
| Finalizing the element insertion of a row/column. More... | |
| void | resize (size_t m, size_t n, bool preserve=true) const |
| Changing the size of the represented matrix. More... | |
| void | reserve (size_t n) const |
| Setting the minimum capacity of the represented matrix. More... | |
| void | reserve (size_t i, size_t n) const |
| Setting the minimum capacity of a specific row/column of the sparse matrix. More... | |
| void | trim () const |
| Removing all excessive capacity from all rows/columns. More... | |
| void | trim (size_t i) const |
| Removing all excessive capacity of a specific row/column of the sparse matrix. More... | |
Insertion functions | |
| Iterator | set (size_t i, size_t j, const ElementType &value) const |
| Setting an element of the represented sparse matrix. More... | |
| Iterator | insert (size_t i, size_t j, const ElementType &value) const |
| Inserting an element into the represented sparse matrix. More... | |
| void | append (size_t i, size_t j, const ElementType &value, bool check=false) const |
| Appending an element to the specified row/column of the sparse matrix. More... | |
Erase functions | |
| void | erase (size_t i, size_t j) const |
| Erasing an element from the sparse matrix. More... | |
| Iterator | erase (size_t i, Iterator pos) const |
| Erasing an element from the sparse matrix. More... | |
| Iterator | erase (size_t i, Iterator first, Iterator last) const |
| Erasing a range of elements from the sparse matrix. More... | |
| template<typename Pred > | |
| void | erase (Pred predicate) |
| Erasing specific elements from the sparse matrix. More... | |
| template<typename Pred > | |
| void | erase (size_t i, Iterator first, Iterator last, Pred predicate) |
| Erasing specific elements from a range of the sparse matrix. More... | |
Lookup functions | |
| Iterator | find (size_t i, size_t j) const |
| Searches for a specific matrix element. More... | |
| Iterator | lowerBound (size_t i, size_t j) const |
| Returns an iterator to the first index not less then the given index. More... | |
| Iterator | upperBound (size_t i, size_t j) const |
| Returns an iterator to the first index greater then the given index. More... | |
Numeric functions | |
| void | transpose () const |
| In-place transpose of the represented matrix. More... | |
| void | ctranspose () const |
| In-place conjugate transpose of the represented matrix. More... | |
| template<typename Other > | |
| void | scale (const Other &scalar) const |
| Scaling of the sparse matrix by the scalar value scalar ( ). More... | |
Proxy backend for sparse matrix types.
The SparseMatrixProxy class serves as a backend for the Proxy class. It is used in case the data type represented by the proxy is a sparse matrix and augments the Proxy interface by the complete interface required of sparse matrices.
|
inline |
Appending an element to the specified row/column of the sparse matrix.
| i | The row index of the new element. The index has to be in the range . |
| j | The column index of the new element. The index has to be in the range . |
| value | The value of the element to be appended. |
| check | true if the new value should be checked for default values, false if not. |
| std::invalid_argument | Invalid access to restricted element. |
This function provides a very efficient way to fill a sparse matrix with elements. It appends a new element to the end of the specified row/column without any additional memory allocation. Therefore it is strictly necessary to keep the following preconditions in mind:
Ignoring these preconditions might result in undefined behavior! The optional check parameter specifies whether the new value should be tested for a default value. If the new value is a default value (for instance 0 in case of an integral element type) the value is not appended. Per default the values are not tested.
|
inline |
Checked access to the matrix elements.
| i | Access index for the row. The index has to be in the range . |
| j | Access index for the column. The index has to be in the range . |
| std::invalid_argument | Invalid access to restricted element. |
| std::out_of_range | Invalid matrix access index. |
This function returns a reference to the accessed value at position (i,j). In case the sparse matrix does not yet store an element at position (i,j) , a new element is inserted into the sparse matrix. In contrast to the subscript operator this function always performs a check of the given access indices.
|
inline |
Returns an iterator to the first element of row/column i of the represented matrix.
| i | The row/column index. |
This function returns a row/column iterator to the first non-zero element of row/column i. In case the storage order is set to rowMajor the function returns an iterator to the first non-zero element of row i, in case the storage flag is set to columnMajor the function returns an iterator to the first non-zero element of column i.
|
inline |
Returns the maximum capacity of the represented matrix.
|
inline |
Returns the current capacity of the specified row/column of the represented matrix.
| i | The index of the row/column. |
This function returns the current capacity of the specified row/column. In case the storage order is set to rowMajor the function returns the capacity of row i, in case the storage flag is set to columnMajor the function returns the capacity of column i.
|
inline |
Returns an iterator to the first element of row/column i of the represented matrix.
| i | The row/column index. |
This function returns a row/column iterator to the first non-zero element of row/column i. In case the storage order is set to rowMajor the function returns an iterator to the first non-zero element of row i, in case the storage flag is set to columnMajor the function returns an iterator to the first non-zero element of column i.
|
inline |
Returns an iterator just past the last element of row/column i of the represented matrix.
| i | The row/column index. |
This function returns an row/column iterator just past the last non-zero element of row/column i. In case the storage order is set to rowMajor the function returns an iterator just past the last non-zero element of row i, in case the storage flag is set to columnMajor the function returns an iterator just past the last non-zero element of column i.
|
inline |
Clearing the represented vector.
This function clears the matrix to its default initial state.
|
inline |
Returns the current number of columns of the represented matrix.
|
inline |
In-place conjugate transpose of the represented matrix.
| std::invalid_argument | Invalid access to restricted element. |
|
inline |
Returns an iterator just past the last element of row/column i of the represented matrix.
| i | The row/column index. |
This function returns an row/column iterator just past the last non-zero element of row/column i. In case the storage order is set to rowMajor the function returns an iterator just past the last non-zero element of row i, in case the storage flag is set to columnMajor the function returns an iterator just past the last non-zero element of column i.
|
inline |
Erasing an element from the sparse matrix.
| i | The row index of the element to be erased. The index has to be in the range . |
| j | The column index of the element to be erased. The index has to be in the range . |
| std::invalid_argument | Invalid access to restricted element. |
This function erases an element from the sparse matrix.
|
inline |
Erasing an element from the sparse matrix.
| i | The row/column index of the element to be erased. The index has to be in the range . |
| pos | Iterator to the element to be erased. |
| std::invalid_argument | Invalid access to restricted element. |
This function erases an element from the sparse matrix. In case the storage order is set to rowMajor the function erases an element from row i, in case the storage flag is set to columnMajor the function erases an element from column i.
|
inline |
Erasing a range of elements from the sparse matrix.
| i | The row/column index of the element to be erased. The index has to be in the range . |
| first | Iterator to first element to be erased. |
| last | Iterator just past the last element to be erased. |
| std::invalid_argument | Invalid access to restricted element. |
This function erases a range of elements from the sparse matrix. In case the storage order is set to rowMajor the function erases a range of elements from row i, in case the storage flag is set to columnMajor the function erases a range of elements from column i.
|
inline |
Erasing specific elements from the sparse matrix.
| predicate | The unary predicate for the element selection. |
This function erases specific elements from the sparse matrix. The elements are selected by the given unary predicate predicate, which is expected to accept a single argument of the type of the elements and to be pure.
|
inline |
Erasing specific elements from a range of the sparse matrix.
| i | The row/column index of the elements to be erased. The index has to be in the range . |
| first | Iterator to first element of the range. |
| last | Iterator just past the last element of the range. |
| predicate | The unary predicate for the element selection. |
This function erases specific elements from a range of elements of the sparse matrix. The elements are selected by the given unary predicate predicate, which is expected to accept a single argument of the type of the elements and to be pure. In case the storage order is set to rowMajor the function erases a range of elements from row i, in case the storage flag is set to columnMajor the function erases a range of elements from column i.
|
inline |
Finalizing the element insertion of a row/column.
| i | The index of the row/column to be finalized . |
| std::invalid_argument | Invalid access to restricted element. |
This function is part of the low-level interface to efficiently fill a matrix with elements. After completion of row/column i via the append() function, this function can be called to finalize row/column i and prepare the next row/column for insertion process via append().
|
inline |
Searches for a specific matrix element.
| i | The row index of the search element. The index has to be in the range . |
| j | The column index of the search element. The index has to be in the range . |
This function can be used to check whether a specific element is contained in the sparse matrix. It specifically searches for the element with row index i and column index j. In case the element is found, the function returns an row/column iterator to the element. Otherwise an iterator just past the last non-zero element of row i or column j (the end() iterator) is returned. Note that the returned sparse matrix iterator is subject to invalidation due to inserting operations via the function call operator or the insert() function!
|
inline |
Inserting an element into the represented sparse matrix.
| i | The row index of the new element. The index has to be in the range . |
| j | The column index of the new element. The index has to be in the range . |
| value | The value of the element to be inserted. |
| std::invalid_argument | Invalid access to restricted element. |
| std::invalid_argument | Invalid sparse matrix access index. |
This function inserts a new element into the sparse matrix. However, duplicate elements are not allowed. In case the sparse matrix already contains an element with row index i and column index j, a std::invalid_argument exception is thrown.
|
inline |
Returns an iterator to the first index not less then the given index.
| i | The row index of the search element. The index has to be in the range . |
| j | The column index of the search element. The index has to be in the range . |
In case of a row-major matrix, this function returns a row iterator to the first element with an index not less then the given column index. In case of a column-major matrix, the function returns a column iterator to the first element with an index not less then the given row index. In combination with the upperBound() function this function can be used to create a pair of iterators specifying a range of indices. Note that the returned sparse matrix iterator is subject to invalidation due to inserting operations via the function call operator or the insert() function!
|
inline |
Returns the number of non-zero elements in the represented matrix.
|
inline |
Returns the number of non-zero elements in the specified row/column of the represented matrix.
| i | The index of the row/column. |
This function returns the current number of non-zero elements in the specified row/column. In case the storage order is set to rowMajor the function returns the number of non-zero elements in row i, in case the storage flag is set to columnMajor the function returns the number of non-zero elements in column i.
|
inline |
Function call operator for the direct access to matrix elements.
| i | Access index for the row. The index has to be in the range . |
| j | Access index for the column. The index has to be in the range . |
| std::invalid_argument | Invalid access to restricted element. |
This function returns a reference to the accessed value at position (i,j). In case the sparse matrix does not yet store an element at position (i,j) , a new element is inserted into the sparse matrix. Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, the at() function is guaranteed to perform a check of the given access indices.
|
inlinenoexceptinherited |
Conversion operator for non-constant matrices.
|
inlinenoexceptinherited |
Conversion operator for constant matrices.
|
inline |
Setting the minimum capacity of the represented matrix.
| n | The new minimum capacity of the matrix. |
| std::invalid_argument | Invalid access to restricted element. |
This function increases the capacity of the sparse matrix to at least nonzeros elements. The current values of the matrix elements and the individual capacities of the matrix rows are preserved.
|
inline |
Setting the minimum capacity of a specific row/column of the sparse matrix.
| i | The row/column index of the new element or . |
| n | The new minimum capacity of the specified row/column. |
| std::invalid_argument | Invalid access to restricted element. |
This function increases the capacity of row/column i of the sparse matrix to at least nonzeros elements. The current values of the sparse matrix and all other individual row/column capacities are preserved. In case the storage order is set to rowMajor, the function reserves capacity for row i and the index has to be in the range . In case the storage order is set to columnMajor, the function reserves capacity for column i and the index has to be in the range .
|
inline |
Reset to the default initial value.
This function resets all elements of the matrix to the default initial values.
|
inline |
Reset the specified row/column to the default initial values.
| i | The index of the row/column. |
This function resets the values in the specified row/column to their default value. In case the storage order is set to rowMajor the function resets the values in row i, in case the storage order is set to columnMajor the function resets the values in column i. Note that the capacity of the row/column remains unchanged.
|
inline |
Changing the size of the represented matrix.
| m | The new number of rows of the matrix. |
| n | The new number of columns of the matrix. |
| preserve | true if the old values of the matrix should be preserved, false if not. |
| std::invalid_argument | Invalid access to restricted element. |
This function resizes the matrix using the given size to . Depending on the type of the matrix, during this operation new dynamic memory may be allocated in case the capacity of the matrix is too small. Note that this function may invalidate all existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation potentially changes all matrix elements. In order to preserve the old matrix values, the preserve flag can be set to true.
|
inline |
Returns the current number of rows of the represented matrix.
|
inline |
Scaling of the sparse matrix by the scalar value scalar ( ).
| scalar | The scalar value for the matrix scaling. |
| std::invalid_argument | Invalid access to restricted element. |
This function scales the matrix by applying the given scalar value scalar to each element of the matrix. For built-in and complex
data types it has the same effect as using the multiplication assignment operator.
|
inline |
Setting an element of the represented sparse matrix.
| i | The row index of the new element. The index has to be in the range . |
| j | The column index of the new element. The index has to be in the range . |
| value | The value of the element to be set. |
| std::invalid_argument | Invalid access to restricted element. |
| std::invalid_argument | Invalid sparse matrix access index. |
This function sets the value of an element of the sparse matrix. In case the sparse matrix already contains an element with row index i and column index j its value is modified, else a new element with the given value is inserted.
|
inline |
In-place transpose of the represented matrix.
| std::invalid_argument | Invalid access to restricted element. |
|
inline |
Removing all excessive capacity from all rows/columns.
| std::invalid_argument | Invalid access to restricted element. |
The trim() function can be used to reverse the effect of all row/column-specific reserve() calls. The function removes all excessive capacity from all rows (in case of a rowMajor matrix) or columns (in case of a columnMajor matrix). Note that this function does not remove the overall capacity but only reduces the capacity per row/column.
|
inline |
Removing all excessive capacity of a specific row/column of the sparse matrix.
| i | The index of the row/column to be trimmed ( or ). |
| std::invalid_argument | Invalid access to restricted element. |
This function can be used to reverse the effect of a row/column-specific reserve() call. It removes all excessive capacity from the specified row (in case of a rowMajor matrix) or column (in case of a columnMajor matrix). The excessive capacity is assigned to the subsequent row/column.
|
inline |
Returns an iterator to the first index greater then the given index.
| i | The row index of the search element. The index has to be in the range . |
| j | The column index of the search element. The index has to be in the range . |
In case of a row-major matrix, this function returns a row iterator to the first element with an index greater then the given column index. In case of a column-major matrix, the function returns a column iterator to the first element with an index greater then the given row index. In combination with the upperBound() function this function can be used to create a pair of iterators specifying a range of indices. Note that the returned sparse matrix iterator is subject to invalidation due to inserting operations via the function call operator or the insert() function!


An implementation of tools for design of attribute variable sampling interval cumulative sum chart. It currently provides information for monitoring of mean increase such as average number of sample to signal, average time to signal, a matrix of transient probabilities, suitable control limits when the data are (zero inflated) Poisson/binomial distribution. Functions in the tools can be easily applied to other count processes. Also, tools might be extended to more complicated cumulative sum control chart. We leave these issues as our perpetual work.
| Version: | 0.1.0 |
| Depends: | R (≥ 3.3.2) |
| Imports: | Rcpp (≥ 0.12.8), stats (≥ 3.3.2), utils (≥ 3.3.2) |
| LinkingTo: | Rcpp (≥ 0.12.8), RcppArmadillo (≥ 0.7.500.0.0) |
| Suggests: | testthat (≥ 1.0.2), knitr (≥ 1.15.1), rmarkdown (≥ 1.2) |
| Published: | 2016-12-28 |
| Author: | Hanwool Kim [aut, cre], Sangyeol Lee [aut] |
| Maintainer: | Hanwool Kim <stat.hanwool at gmail.com> |
| License: | GPL-2 | GPL-3 [expanded from: GPL (≥ 2)] |
| NeedsCompilation: | yes |
| Materials: | README |
| CRAN checks: | attrCUSUM results |
| Reference manual: | attrCUSUM.pdf |
| Vignettes: |
Tools for Attribute VSI CUSUM Charts |
| Package source: | attrCUSUM_0.1.0.tar.gz |
| Windows binaries: | r-devel: attrCUSUM_0.1.0.zip, r-release: attrCUSUM_0.1.0.zip, r-oldrel: attrCUSUM_0.1.0.zip |
| OS X binaries: | r-release: attrCUSUM_0.1.0.tgz, r-oldrel: attrCUSUM_0.1.0.tgz |
Please use the canonical form https://CRAN.R-project.org/package=attrCUSUM to link to this page.


Hello World
Here I would like to share my
abilities of bootstrap
And so on until will be 12 col's in a row
Priority
But there are priority between
col and col-[with breakpoint]-md | xl | sm
Col-lg-6 Col-md-6
col-sm-6
Mobile
Bootstrap well done at first for mobile!
Small devices = 12 col, but other equals set breakpoint in a class
Here are sm-8
Small devices = 12 col, but other equals set breakpoint in a class
Here are md-6
Offset's
The main question of many novice web developers are offsets of the columns
<< This block exactly in center of the page >>
Total block amount (T) = 12
Needed block amount (N) = 6
(T-N)/2 = Needed offset (only integer value) = 3


For full functionality of this site it is necessary to enable JavaScript. Here are the instructions how to enable JavaScript in your web browser. PLEASE NOTE: You will be taken to an external website, which is not controlled by SQuark. We do not take any responsibility of the contents displayed by this website.


--- layout: post title: dired move line wrap up categories: [productivity] tags: [emacs] ---
When the cursor is at the buffer end of ibuffer
, it will wrap back
to the beginning of the buffer list if I continue pressing n
to next
buffer. But in dired
, this does not happen. The cursor will stay at
the end of the file list, if I continue pressing n
to navigate to
next buffer.
Here is the trick to wind the cursor up to the first item of the file
list. I redefine the function dired-next-line
and dired-previous-line
:
(defun dired-next-line (arg) "Move down lines then position at filename. Optional prefix ARG says how many lines to move; default is one line." (interactive "p") (forward-line arg) (if (eobp) (progn (goto-char (point-min)) (forward-line 2))) ;; skip two lines: file path and summary (dired-move-to-filename)) (defun dired-previous-line (arg) "Move up lines then position at filename. Optional prefix ARG says how many lines to move; default is one line." (interactive "p") (if (= 3 (line-number-at-pos)) ;; line num of first item (progn (goto-char (point-max)) (forward-line -1)) ;; skip the last empty line (forward-line (- arg))) (dired-move-to-filename))


RmlUi
RmlUi is a third-party GUI library that uses an HTML-like syntax to describe UI elements, and CSS to style them. RmlUi is lightweight, yet flexible.
Support for RmlUi is provided through a dedicated engine plugin. To enable it in your project, activate the plugin in the project settings.
Rml Documentation
The documentation for RmlUi can be found here.
Please refer to that documenation for any questions around how to use RmlUi.
Sample
The RTS Sample shows how to use RmlUi. Have a look at it the project in the editor, it contains Rml assets. The editor shows a live preview for Rml canvases, and you can edit the respective .rml
files to see the effect:
The sample uses multiple RmlUi Canvas 2D components in its scene to place the UI elements. At runtime the RTS sample's game code accesses the RmlUi functionality through the ezRmlUiCanvas2DComponent
. Search the sample's code for those places to see how to interact with the GUI.
Using ezRmlUiCanvas2DComponent::GetRmlContext()
you get access to the ezRmlUiContext
. This class implements Rml::Core::Context
. This gives you access to all the RmlUi features. See the RmlUi documentation for details.
Work in Progress
The integration of RmlUi into ezEngine is functional, but still a work-in-progress. At the moment you can only build 2D GUIs that appear on top of the screen. In the future we plan to also support placing GUI elements inside the 3D environment.
Also, currently you need to work directly with the RmlUi C++ code to interact with the UI. We may add convenience functionality to make simple use cases of GUIs easier.
There is no TypeScript binding for RmlUi. Most likely this will never change, however, if we get around to adding some convenience features, that may make it possible to use a limited feature set from script code.


| Folders | |||
| <parent> |
| File | File | File | File | File | File | File | File | File | File |
|---|---|---|---|---|---|---|---|---|---|
| AreaUnder...m.java | Celebrity.java | Intervals.java | MinStack.java | MouseAndC...e.java | PhoneNumb...a.java | ShortestK...k.java | SimplifyD...h.java | StackUtil...s.java | Structure...e.java |
| CanConnect.java | ClosingPrices.java | Maze.java |
Folders: 1
Files: 13
Size of all files: 0.019 MG


Use the buttons on this map to draw the charge extent.
Start again
Do you have an extent saved on file?
You have added out of 500 possible extents.


{% include<EMAIL_ADDRESS>%} {% include<EMAIL_ADDRESS>%}


This is a list of the members of the Zoology Faculty
Courses in Zoology cover the entire animal kingdom.The goal of these classes are to better students understanding on the animal kindom and the daily lives of individual animals
| Name | Judith Pointer Jia | Isabella La Rocca | Sheldon Tapley |
|---|---|---|---|
| Picture |