Hola amigos
A ver, se abrir una instancia de la CMD de 3 maneras y se recibir el código de salida
puts %x[Tasklist /v | Find "%tmp:~0,30%" >NUL]
response = $?.exitstatus
Eso me funciona.
Pero ahora necesito abrir la consola en modo oculto (Y solo se hacerlo con el modulo Win32ole), y entonces el exitstatus me manda error , no se porque:(:
require 'win32ole'
shell = WIN32OLE.new('Shell.Application')
shell.ShellExecute('CMD', '/K Tasklist /v | Find "%tmp:~0,30%" >NUL', '', '', 0)
response = $?.exitstatus
if response == 0
puts "hola"
end
undefined method `exitstatus' for nil:NilClass (NoMethodError)
EDITO: Esto tampoco me funciona:
require 'win32ole'
$shell = WIN32OLE.new('Shell.Application')
$shell.ShellExecute('CMD', '/c echo aaaa & pause', '', '', 1)
$!.is_a?(win32ole)
puts $!.exited?
`is_a?': class or module required (TypeError)
EDITO2: esto támpoco xD
require 'win32ole'
$shell = WIN32OLE.new('Shell.Application')
output = $shell.ShellExecute('CMD', '/c echo aaaa & echo %errorlevel%', '', '', 1)
p output
(El caso es que con "system" si funciona :-( )
A ver...
Después de tirarme horas leyendo documentación sobre Ruby, he llegado a una conclusion, Aunque no se si es posible...
"Unless" funciona como: "A menos que..."
Y yo busco un operador que funcione así:
"Hasta que..."
Vale perdón, no sabia la traducción al ingles xD
Me estoy haciendo un lio tremendo, alguien me ayuda a arreglar esto?:
until...
EDITO:
Ya lo he arreglado, Pero me he dado cuenta de que no me sirve para el propósito...
until file.readable? comprueba exactamente el archivo, Pero va demasiado rápido y, osea, cuando lo comprueba, no hay datos escritos todavía en el archivo, está vacío
y por eso: puts File.zero? siempre es "true" , A menos que ponga un "sleep 1.0" entre until y puts... y así le doy tiempo a que el comando de la CMD escriba los datos en el archivo...
Nada, no me sirve, depende mucho de la velocidad de un PC.
Necesito alguna manera más práctica para recibir el código de salida, bueno, el "exitsatatus" de la instancia de la CMD lanzada con win32ole
De todas formas aqui dejo esto...
def Access(source_file, dest_file)
ENV['tmp'] = $archivo.split('\\').last.split('.').first
'cheat environment_variables --add'
$shell.ShellExecute('CMD', '/C Tasklist /v | Find "%tmp:~10%">c:/Windows/temp/moveitexitcode.txt', '', '', 0)
until File.exist?('c:\Windows\temp\moveitexitcode.txt').eql? true
end
puts File.zero?('c:\Windows\temp\moveitexitcode.txt')
if File.zero?('c:\Windows\temp\moveitexitcode.txt').eql? false
reintentar($archivo.encode('utf-8').gsub("\û", "-"), ARGV[0])
end
if File.zero?('c:\Windows\temp\moveitexitcode.txt').eql? true
FileUtils.mv $archivo.encode('utf-8').gsub("\û", "-"), ARGV[0]
end
begin
File.delete('c:\Windows\temp\moveitexitcode.txt')
rescue Errno::EACCES
retry
end
end
Definitivamente el método de "comprobar el exitstatus" no me sirve para nada, engaña mucho, Por ejemplo he echo comprobaciones y el Winamp tarda 10 segundos en actualizarse en el "tasklist" (o al revés, el tasklist será el q tarda 10 segundos, no se)...
Resumiendo, Necesito una forma más nátiva y eficaz en Ruby para comprobar si un archivo está siendo usado por algún proceso:
Ejemplo:
If $archivo ABIERTO POR $cualquier_programa_de_windows
Sleep 01
elsif
mover $archivo a...
end
Aqui dejo esto, lo siento por tanto borrador xD
def Access(source_file, dest_file)
begin
ENV['tmp'] = $archivo.split('\\').last.split('.').first
'cheat environment_variables --add'
# CÓDIGO ORIGINAL:
# system('start /b /MIN cmd /C Tasklist /v | Find "%tmp:~10%" >NUL')
# ESTA PARTE HAY QUE MEJORARLA PARA QUE NO SE VEA LA CONSOLA
system('Title MOVEMEBYELEKTRO & NirCMD win hide ititle "MOVEMEBYELEKTRO" & Tasklist /v | Find "%tmp:~10%" >NUL')
until $?.exitstatus.eql? 1 or $?.exitstatus.eql? 0
sleep 0.1
end
if $?.exitstatus.eql? 0
reintentar($archivo.encode('utf-8').gsub("\û", "-"), ARGV[0])
end
if $?.exitstatus.eql? 1
FileUtils.mv $archivo.encode('utf-8').gsub("\û", "-"), ARGV[0]
end
rescue
reintentar($archivo.encode('utf-8').gsub("\û", "-"), ARGV[0])
end
end
Por fin he encontrado algo útil!!!
Lo malo es que el ejemplo es para Delphi...
CitarUsing the Native API function NtQuerySystemInformation you can list all open handles from all processes
http://stackoverflow.com/questions/1575286/delphi-get-what-files-are-opened-by-an-application
API: Win32API
Función:
NtQuerySystemInformationhttp://msdn.microsoft.com/en-us/library/ms724509%28VS.85%29.aspx
¿Alguien podria ayudarme a entender como utilizarla para averiguar lo que necesito, en ruby?EDITO:
He encontrado un ejemplo en chino, pero no hace lo que necesito ,lo único que he encontrado:
#!/usr/local/bin/ruby
# WindowsNTŒn,ÅCPU•‰‰×,ƃƒ,ƒŠ•‰‰×,ð‹L˜^,·,é
require "Win32API"
# '²¸ŠÔŠu[•b]
interval = 1
# CPU •‰‰×,ÌŽæ"¾—p
NtQuerySystemInformation = Win32API.new('NTDLL', 'NtQuerySystemInformation', 'LPLP', 'I')
perfInfo = "\0\0\0\0" * 78
timeInfo = "\0\0\0\0" * 8
sysInfoLen = "\0\0\0\0"
# ƒƒ,ƒŠÁ"ï,ÌŽæ"¾—p
GlobalMemoryStatus = Win32API.new('kernel32','GlobalMemoryStatus','P','V')
memStruct = "\0\0\0\0" * 8
$regular = false
$formerIdle = 0
$formerTime = 0
while true
# ƒAƒCƒhƒ‹ŽžŠÔ,ÌŽæ"¾
NtQuerySystemInformation.call(2, perfInfo, perfInfo.size, sysInfoLen)
idle = perfInfo.unpack("L")[0]
# ƒVƒXƒeƒ€ŽžŠÔ,ÌŽæ"¾
NtQuerySystemInformation.call(3, timeInfo, timeInfo.size, sysInfoLen)
time = timeInfo.unpack("L3")[2]
# ·•ª,Å CPU •‰‰×,ðŒvŽZ[%]
cpuLoad = 100.0 - ((100.0 * (idle - $formerIdle)) / (time - $formerTime))
if cpuLoad < 0 or cpuLoad > 100
$regular = false
end
$formerIdle = idle
$formerTime = time
# ƒƒ,ƒŠÁ"ï,ÌŽæ"¾[%]
GlobalMemoryStatus.call(memStruct)
memLoad =memStruct.unpack("L2")[1]
if $regular
printf "time=%s cpu=%4.1f mem=%4.1f\n", \
Time.now.strftime("%H:%M:%S"), cpuLoad, memLoad
else
$regular = true
end
sleep interval
end
Acabo de intentarlo usando win32ole, pero no hay nada que muestre el archivo que tiene abierto el proceso:
Lo más parecido es el:
puts process.CommandLine
Pero no es lo mismo...
:-( :-( :-(
require 'win32ole'
wmi = WIN32OLE.connect("winmgmts://")
processes = wmi.ExecQuery("select * from win32_process")
for process in processes do
puts process.Caption
puts process.CommandLine
puts process.CreationClassName
puts process.CreationDate
puts process.CSCreationClassName
puts process.CSName
puts process.Description
puts process.ExecutablePath
puts process.ExecutionState
puts process.Handle
puts process.HandleCount
puts process.InstallDate
puts process.KernelModeTime
puts process.MaximumWorkingSetSize
puts process.MinimumWorkingSetSize
puts process.Name
puts process.OSCreationClassName
puts process.OSName
puts process.OtherOperationCount
puts process.OtherTransferCount
puts process.PageFaults
puts process.PageFileUsage
puts process.ParentProcessId
puts process.PeakPageFileUsage
puts process.PeakVirtualSize
puts process.PeakWorkingSetSize
puts process.Priority
puts process.PrivatePageCount
puts process.ProcessId
puts process.QuotaNonPagedPoolUsage
puts process.QuotaPagedPoolUsage
puts process.QuotaPeakNonPagedPoolUsage
puts process.QuotaPeakPagedPoolUsage
puts process.ReadOperationCount
puts process.ReadTransferCount
puts process.SessionId
puts process.Status
puts process.TerminationDate
puts process.ThreadCount
puts process.UserModeTime
puts process.VirtualSize
puts process.WindowsVersion
puts process.WorkingSetSize
puts process.WriteOperationCount
puts process.WriteTransferCount
end
EDITO:
Vale, Si, Si que me sirve:
wmi = WIN32OLE.connect("winmgmts://")
processes = wmi.ExecQuery("select * from win32_process")
for process in processes do
puts process.CommandLine
end
Pero no es del todo eficiente en algunos casos, Así que necesito además de esa comprobación, una segunda comprobación para comprobar el nombre de la ventana del programa, he encontrado un code que lo hace pero es para VBS creo...
Una ayuda para "Convertirlo" a Ruby? Lo he intentado pero no lo consigo:
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_ProcessStartup",,48)
For Each objItem in colItems
Wscript.Echo "ShowWindow: " & objItem.ShowWindow
Wscript.Echo "Title: " & objItem.Title
Next
require 'win32ole'
wmi = WIN32OLE.connect("winmgmts://")
processes = wmi.ExecQuery("Select * from Win32_ProcessStartup")
for process in processes do
puts process.ShowWindow
puts process.Title
end
No me muestra nada, Pero támpoco da error :(
¿Que me falta?
He encontrado otro script (Chino...) pero es demasiadooo avanzado para mi, no se como utilizarlo
Creo que sirve para buscar el titulo de la ventana de un proceso
Una ayuda???
require 'Win32API'
class Wnd
#for GetWindow
=begin
GW_CHILD=
GW_OWNER=
GW_HWNDFIRST=
GW_HWNDNEXT=
#for GetNextWindow
GW_HWNDNEXT=
GW_HWNDPREV=
=end
def initialize
@hw = nil
@GetWindow = Win32API.new("user32","GetWindow",['L']*2,'L')
#top child
@GetTopWindow = Win32API.new("user32","GetTopWindow",['L'],'L')
# @GetNextWindow = Win32API.new("user32","GetNextWindowA",['L']*2,'L')
@GetActiveWindow = Win32API.new("user32","GetActiveWindow",[],'L')
@GetDesktopWindow = Win32API.new("user32","GetDesktopWindow",[],'L')
@FindWindow=Win32API.new("user32","FindWindowA",['L','P'],'L')
@SetForegroundWindow=Win32API.new("user32","SetForegroundWindow",['L'],'V')
@GetWindowText = Win32API.new("user32","GetWindowText",['L','P','i'],'i')
end
def find(cap)
@hw = @FindWindow.Call(0,cap)
end
def fg
@SetForegroundWindow.Call(@hw)
end
def caption
lpString="\0"*251
len = @GetWindowText.Call(@hw,lpString,250)
p len
lpString[0,len]
end
def test
end
end
wnd1=Wnd.new
wnd1.find("Win32 SDK Reference Help")
wnd1.fg
puts wnd1.caption
__END__
EDITO:
He conseguido sacar el título de la consola de windows , la CMD:
require 'Win32API'
b = Win32API.new('kernel32' , 'GetConsoleWindow' , [] , 'L').call
title = ' '*100
win = Win32API.new('user32', 'GetWindowText', ['L', 'P', 'I'], 'I').Call(b, title, 256)
puts title
Pero ni idea de como hacerlo para todos los processos abiertos....
Quisiera algo así:
require 'Win32API'
b = Win32API.new('kernel32' , 'Get ALL WINDOWS' , [] , 'L').call
title = ' '*100
if title.include? "archivo abierto"
abort
end
Al final la insistencia y el esfuerzo dan sus frutos
require 'win32/api'
include Win32
# Callback example - Enumerate windows
EnumWindows = API.new('EnumWindows', 'KP', 'L', 'user32')
GetWindowText = API.new('GetWindowText', 'LPI', 'I', 'user32')
EnumWindowsProc = API::Callback.new('LP', 'I'){ |handle, param|
buf = "\0" * 200
GetWindowText.call(handle, buf, 200);
if (!buf.index(param).nil?)
puts "window was found: handle #{handle}"
0 # stop looking after we find it
else
1
end
}
EnumWindows.call(EnumWindowsProc, ' AQUI VA EL TITULO ')
Saludosss
PD: ¿Alguien lee mis problemas con Ruby? xD :-(