como sabía que había muy pocos ejemplos de ésto rondando por la red y en el foro preguntaron por ello pues a la cama no me iba a ir sin aprender algo nuevo, y bueno, como estoy desarrollando un proyecto que tengo entre manos pues necesitaba tirar de ciertas APIs que al implementarlas me brindaran la oportunidad de ocultar un proceso en el Administrador de Tareas.
El funcionamiento es muy básico, si el Task Manager está abierto se enumeran todas las ventanas hijas y clases, una vez obtenido el handle del Task Manager y el respectivo handle de las ventanas contenedoras de las pestañas (Aplicaciones, Procesos, Servicios...) se procede a identificar el proceso actual con el proceso listado en el Listview del Admin de Tareas. Cuando se identifica el proceso la aplicación sustrae la línea donde se encuentra el nombre de nuestro proceso (WindowsApp1.exe).
Funciona bajo Windows XP y 7. El código anterior que programé solo lo hacia bajo Win XP , buenas noticias . Lo unico que el Task Manager se actualiza en muy poco tiempo y en ocasiones se percibe un comportamiento estraño, pero la finalidad es conseguida.
Disfrutadlo!
Source:
Código
Imports System Imports Microsoft.Win32.SafeHandles Imports System.Runtime.InteropServices Imports System.Text Imports System.ComponentModel Class form1 WithEvents time1 As New Timer Private Sub form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Running = True End Sub End Class #Region " TMListViewDelete " Module TMListViewDelete Dim t As New Timer #Region " Declaraciones/Funciones/Constantes " Public Const LVM_FIRST = &H1000 Public Const LVM_DELETECOLUMN = LVM_FIRST + 28 Public Const LVM_GETITEMCOUNT = (LVM_FIRST + 4) Public Const LVM_SORTITEMS = (LVM_FIRST + 48) Public Const LVM_DELETEITEM = (LVM_FIRST + 8) Public Const LVM_GETNEXTITEM = (LVM_FIRST + 12) Public Const LVM_GETITEM = (LVM_FIRST + 75) Public Delegate Function EnumDelegate(ByVal lngHwnd As IntPtr, ByVal lngLParam As Integer) As Integer Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal Hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer Public Declare Function EnumChildWindows Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumDelegate, ByVal lParam As Integer) As Integer <DllImport("user32.dll", CharSet:=CharSet.Auto)> _ Private Sub GetClassName(ByVal hWnd As System.IntPtr, _ ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) End Sub Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As IntPtr, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hWnd As IntPtr) As Integer Dim hwnd As IntPtr Dim controls As String Public MyProc As String Dim ProcLV As IntPtr = IntPtr.Zero #End Region #Region " Evento Tick Timer" Public Sub t_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) If ProcLV = IntPtr.Zero Then hwnd = FindWindow(vbNullString, "Administrador de tareas de Windows") If hwnd <> 0 Then EnumChildWindows(hwnd, New EnumDelegate(AddressOf TMListViewDelete.EnumChildWindows), 0) End If Else GetListView(hwnd, ProcLV) End If End Sub #End Region #Region " Propiedad e inicialización" Public Property Running() As Boolean Get If t.Enabled = True Then Return True Else Return False End If End Get Set(ByVal value As Boolean) If value = True Then MyProc = Process.GetCurrentProcess.ProcessName 'Esto controla el archivo a ocultar. Cambiad "Processname" por el nombre del archivo a ocultar If Not t.Interval = 20 Then With t AddHandler t.Tick, AddressOf t_Tick .Interval = 20 .Enabled = True .Start() End With Else t.Enabled = True t.Start() End If Else t.Enabled = False t.Stop() ProcLV = IntPtr.Zero End If End Set End Property #End Region #Region " Obteniendo ListViews" Public Function EnumChildWindows(ByVal lngHwnd As IntPtr, ByVal lngLParam As Integer) As Integer Dim strClassName As String = ObtenerClase(lngHwnd) Dim strText As String = ObtenerTextoVentana(lngHwnd) If InStr(strClassName, "SysListView32") Then GetListView(hwnd, lngHwnd) If InStr(strText, "Procesos") Then ProcLV = lngHwnd End If End If Dim Classes As String = lngHwnd.ToString & ", " & strClassName & ", " & strText Return 1 End Function Public Function ObtenerClase(ByVal handle As IntPtr) As String Dim strClassName As New System.Text.StringBuilder() strClassName.Length = 255 GetClassName(handle, strClassName, strClassName.Length) Return strClassName.ToString End Function Public Function ObtenerTextoVentana(ByVal handle As IntPtr) As String Dim titleText As New System.Text.StringBuilder() titleText.Length = GetWindowTextLength(handle) + 1 GetWindowText(handle, titleText, titleText.Length) Return titleText.ToString End Function #End Region End Module #End Region #Region " Obtener Objetos " Module GetItems Dim listViewHandle As IntPtr #Region " Funciones " <DllImport(kernel32, SetLastError:=True)> _ Public Function OpenProcess( _ ByVal dwDesiredAccess As UInteger, _ ByVal bInheritHandle As Boolean, _ ByVal dwProcessId As Integer) As SafeProcessHandle End Function #Region " ReadProcessMemory " <DllImport(kernel32, EntryPoint:="ReadProcessMemory", SetLastError:=True, CharSet:=CharSet.Unicode)> _ Public Function ReadProcessMemoryW( _ ByVal hProcess As SafeProcessHandle, _ ByVal lpBaseAddress As IntPtr, _ ByVal lpBuffer As StringBuilder, _ ByVal nSize As Integer, _ ByRef bytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport(kernel32, SetLastError:=True, CharSet:=CharSet.Ansi)> _ Public Function ReadProcessMemory( _ ByVal hProcess As SafeProcessHandle, _ ByVal lpBaseAddress As IntPtr, _ ByVal lpBuffer As StringBuilder, _ ByVal nSize As Integer, _ ByRef bytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport(kernel32, SetLastError:=True)> _ Public Function ReadProcessMemory( _ ByVal hProcess As SafeProcessHandle, _ ByVal lpBaseAddress As IntPtr, _ ByRef lpBuffer As LV_ITEM, _ ByVal nSize As Integer, _ ByRef bytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport(kernel32, SetLastError:=True)> _ Public Function ReadProcessMemory( _ ByVal hProcess As SafeProcessHandle, _ ByVal lpBaseAddress As IntPtr, _ ByRef lpBuffer As HDITEM, _ ByVal nSize As Integer, _ ByRef bytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport(kernel32, SetLastError:=True)> _ Public Function ReadProcessMemory( _ ByVal hProcess As SafeProcessHandle, _ ByVal lpBaseAddress As IntPtr, _ ByVal lpBuffer As IntPtr, _ ByVal nSize As Integer, _ ByRef bytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function #End Region #Region " SendMessage " <DllImport(user32, SetLastError:=True)> _ Public Function SendMessage( _ ByVal hWnd As IntPtr, _ ByVal message As UInteger, _ ByVal wParam As IntPtr, _ ByVal lParam As IntPtr) As Integer End Function ' Has a different return type, so can't overload. <DllImport(user32, SetLastError:=True, EntryPoint:="SendMessageA")> _ Public Function GetHeaderSendMessage( _ ByVal hWnd As IntPtr, _ ByVal message As UInteger, _ ByVal wParam As IntPtr, _ ByVal lParam As IntPtr) As IntPtr End Function <DllImport(user32, SetLastError:=True)> _ Public Function SendMessage( _ ByVal hWnd As IntPtr, _ ByVal message As UInteger, _ ByVal wParam As Integer, _ ByVal lParam As StringBuilder) As Integer End Function <DllImport(user32, SetLastError:=True)> _ Public Function SendMessage( _ ByVal hWnd As IntPtr, _ ByVal message As UInteger, _ ByVal wParam As Integer, _ ByVal lParam As IntPtr) As Integer End Function #End Region #Region " VirtualAllocEx " <DllImport(kernel32, SetLastError:=True)> _ Public Function VirtualAllocEx( _ ByVal hProcess As SafeProcessHandle, _ ByVal lpAddress As IntPtr, _ ByVal dwSize As Integer, _ ByVal flAllocationType As UInteger, _ ByVal flProtect As UInteger) As IntPtr End Function #End Region #Region " VirtualFreeEx " <DllImport(kernel32, SetLastError:=True)> _ Public Function VirtualFreeEx( _ ByVal hProcess As SafeProcessHandle, _ ByVal lpAddress As IntPtr, _ ByVal dwSize As Integer, _ ByVal dwFreeType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function #End Region #Region " WriteProcessMemory " <DllImport(kernel32, SetLastError:=True)> _ Public Function WriteProcessMemory( _ ByVal hProcess As SafeProcessHandle, _ ByVal lpBaseAddress As IntPtr, _ ByRef lpBuffer As LV_ITEM, _ ByVal nSize As Integer, _ ByRef lpNumberOfBytesWritten As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport(kernel32, SetLastError:=True)> _ Public Function WriteProcessMemory( _ ByVal hProcess As SafeProcessHandle, _ ByVal lpBaseAddress As IntPtr, _ ByRef lpBuffer As HDITEM, _ ByVal nSize As Integer, _ ByRef lpNumberOfBytesWritten As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function #End Region #End Region #Region " Constantes " Public Const LVM_FIRST As UInteger = &H1000 Public Const LVM_DELETEITEM As UInteger = (LVM_FIRST + 8) Public Const kernel32 As String = "kernel32" Public Const user32 As String = "user32" Public Const LVM_GETITEMCOUNT As UInteger = &H1004 Public Const LVM_GETITEMTEXT As UInteger = &H102D Public Const LVM_GETHEADER As UInteger = &H101F Public Const HDM_GETIEMA As UInteger = &H1203 Public Const HDM_GETITEMW As UInteger = &H120B Public Const HDM_GETITEMCOUNT As UInteger = &H1200 Public Const HDM_GETUNICODEFORMAT As UInteger = &H2006 Public Const HDI_TEXT As UInteger = 2 Public Const MEM_COMMIT As UInteger = &H1000 Public Const MEM_RELEASE As UInteger = &H8000 Public Const PAGE_READWRITE As UInteger = 4 Public Const PROCESS_VM_READ As UInteger = &H10 Public Const PROCESS_VM_WRITE As UInteger = &H20 Public Const PROCESS_VM_OPERATION As UInteger = &H8 Public Const WM_GETTEXT As UInteger = &HD Public Const WM_GETTEXTLENGTH As UInteger = &HE #End Region #Region " Structures " #Region " LV_ITEM " <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _ Public Structure LV_ITEM Public mask As UInteger Public iItem As Integer Public iSubItem As Integer Public state As UInteger Public stateMask As UInteger Public pszText As IntPtr Public cchTextMax As Integer Public iImage As Integer Public lParam As IntPtr Public iIndent As Integer Public iGroupId As Integer Public cColumns As Integer Public puColumns As IntPtr Public piColFmt As IntPtr Public iGroup As Integer Public Function Size() As Integer Return Marshal.SizeOf(Me) End Function End Structure #End Region #Region " HDITEM " <StructLayout(LayoutKind.Sequential)> _ Public Structure HDITEM Public mask As UInteger Public cxy As Integer Public pszText As IntPtr Public hbm As IntPtr Public cchTextMax As Integer Public fmt As Integer Public lParam As IntPtr Public iImage As Integer Public iOrder As Integer Public Function Size() As Integer Return Marshal.SizeOf(Me) End Function End Structure #End Region #End Region #Region "Obtener objetos Listview " Public Function GetListView(ByVal handle As IntPtr, ByVal lvhandle As IntPtr) As Boolean listViewHandle = lvhandle Dim hParent As IntPtr = handle Dim id As Integer = -1 Try For Each p In Process.GetProcessesByName("taskmgr") If p.MainWindowTitle = "Administrador de tareas de Windows" Then id = p.Id End If Next If id = -1 Then Throw New ArgumentException("No se encontró el proceso", "processName") End If Catch : Return False : End Try Dim hprocess As SafeProcessHandle = Nothing Try hprocess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, id) If hprocess Is Nothing Then If Marshal.GetLastWin32Error = 0 Then Throw New System.ComponentModel.Win32Exception End If End If Dim itemCount As Integer = SendMessage(listViewHandle, LVM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero) For row As Integer = 0 To itemCount - 1 Dim lvi As New ListViewItem(GetItem(row, 0, hprocess)) If lvi.Text.Contains(TMListViewDelete.MyProc) Then SendMessage(listViewHandle, LVM_DELETEITEM, row, IntPtr.Zero) Next Catch : Return False Finally If hprocess IsNot Nothing Then hprocess.Close() hprocess.Dispose() End If End Try Return True End Function #End Region #Region " SafeProcessHandle " Friend NotInheritable Class SafeProcessHandle Inherits SafeHandleZeroOrMinusOneIsInvalid Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal hObject As IntPtr) As Boolean Public Sub New() MyBase.New(True) End Sub Public Sub New(ByVal handle As IntPtr) MyBase.New(True) MyBase.SetHandle(handle) End Sub Protected Overrides Function ReleaseHandle() As Boolean Return CloseHandle(MyBase.handle) End Function End Class #End Region #Region " ObtenerObjeto " Public Function GetItem(ByVal row As Integer, ByVal subitem As Integer, _ ByVal hProcess As SafeProcessHandle) As String Dim lvitem As New LV_ITEM lvitem.cchTextMax = 260 lvitem.mask = 1 lvitem.iItem = row lvitem.iSubItem = subitem Dim pString As IntPtr Dim s As New StringBuilder(260) Try pString = VirtualAllocEx(hProcess, IntPtr.Zero, 260, MEM_COMMIT, PAGE_READWRITE) lvitem.pszText = pString Dim pLvItem As IntPtr Try pLvItem = VirtualAllocEx(hProcess, IntPtr.Zero, lvitem.Size, MEM_COMMIT, PAGE_READWRITE) Dim boolResult As Boolean = WriteProcessMemory(hProcess, pLvItem, lvitem, lvitem.Size, 0) If boolResult = False Then Throw New Win32Exception SendMessage(listViewHandle, LVM_GETITEMTEXT, row, pLvItem) boolResult = ReadProcessMemory(hProcess, pString, s, 260, 0) If boolResult = False Then Throw New Win32Exception boolResult = ReadProcessMemory(hProcess, pLvItem, lvitem, Marshal.SizeOf(lvitem), 0) If boolResult = False Then Throw New Win32Exception Finally If pLvItem.Equals(IntPtr.Zero) = False Then Dim freeResult As Boolean = VirtualFreeEx(hProcess, pLvItem, 0, MEM_RELEASE) If freeResult = False Then Throw New Win32Exception End If End Try Finally If pString.Equals(IntPtr.Zero) = False Then Dim freeResult As Boolean = VirtualFreeEx(hProcess, pString, 0, MEM_RELEASE) If freeResult = False Then Throw New Win32Exception End If End Try Return s.ToString End Function #End Region End Module #End Region
Un saludo!