Pregunta

Cuando un ActiveXObject está alojado en un escritorio de Windows / Sidebar Gadget, que se ActiveXObject especie de caché y el archivo DLL para que quede bloqueado (lo que significa que no se puede mover, borrar o renombrar). El problema es el siguiente; cuando el aparato se cierra posteriormente, la DLL está siendo bloqueado por la barra lateral de Windows y no se puede quitar. Esto causa un problema significativo por el que una nueva versión del gadget no se puede instalar sobre la parte superior de una versión anterior del aparato, se produce un error durante el proceso de eliminarlo sin mensajes de error.

Esto no es muy fácil de usar, así que estoy buscando una manera de "romper" vínculos con el control ActiveX de alguna manera durante el evento de descarga del gadget. Estoy esperando que alguien me puede decir si es o no es posible y si es darme algunas ideas sobre cómo ponerlo en práctica.

Para su información, Windows Sidebar Gadgets son en realidad sólo las ventanas de servidores de Internet Explorer, por lo que es probablemente seguro asumir IE presenta el mismo comportamiento.

EDIT: Unlocker parece hacer casi todo lo que necesito hacer, así que ¿cómo puedo lograr lo mismo mediante programación en .NET?

¿Fue útil?

Solución

Está bien este es un problema bastante complejo. He visto este comportamiento antes, no estoy familiarizado con el escritorio de Windows / Sidebar Gadget como yo no lo uso. Sin embargo, me las he arreglado para llegar a tres posibles métodos de ataque

1. manija de TechNet

Esto no era mi idea, hay otro hilo StackOverflow que recomienda este método. Sin embargo soy escéptico en cuanto a si es o no va a funcionar. Hay una diferencia entre un archivo de bloqueo (lo que se encarga de esta utilidad) y una cerradura "biblioteca de carga", que es lo que supongo que es el problema que tiene con ActiveX.

He modificado el código de ese hilo ligeramente, hay que utilizan Process.Kill () para liberar el bloqueo, yo creo que es mejor utilizar Handle.exe para liberar el bloqueo.

public struct LockInfo
{
    public int PID;
    public string Handle;

    public LockInfo(int pid, string handle)
    {
        this.PID = pid;
        this.Handle = handle;
    }
}      

static List<LockInfo> getLockingInfo(string fileName)
{            
    List<LockInfo> lockingProcesses = new List<LockInfo>();

    Process tool = new Process();
    tool.StartInfo.FileName = "handle.exe";
    tool.StartInfo.Arguments = fileName;
    tool.StartInfo.UseShellExecute = false;
    tool.StartInfo.RedirectStandardOutput = true;
    tool.Start();
    tool.WaitForExit();
    string outputTool = tool.StandardOutput.ReadToEnd();

    // I;m not so hot with regex, so a bit of regex and a bit of manual splitting
    string matchPattern = @"(?<=\s+pid:\s+)\b(\d+)\b(\s+)\b(\S+:)";
    foreach (Match match in Regex.Matches(outputTool, matchPattern))
    {
        string[] temp = match.Value.Replace(":", "").Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        if (temp.Length == 2)
        {
            lockingProcesses.Add(new LockInfo(int.Parse(temp[0].Trim()), temp[1].Trim()));
        }
    }
    return lockingProcesses.Count > 0 ? lockingProcesses : null;
}

static bool closeFileHandle(List<LockInfo> lockingInfo)
{
    if ((lockingInfo == null) || (lockingInfo.Count == 0))
    {
        throw new ArgumentException("lockingProcesses cannot be null or empty");
    }

    bool fileClosed = true;

    foreach (LockInfo lockInfo in lockingInfo)
    {
        Process tool = new Process();
        tool.StartInfo.FileName = "handle.exe";
        tool.StartInfo.Arguments = string.Format("-c {0} -y -p {1}", lockInfo.Handle, lockInfo.PID.ToString());
        tool.StartInfo.UseShellExecute = false;
        tool.StartInfo.RedirectStandardOutput = true;
        tool.Start();
        tool.WaitForExit();
        string outputTool = tool.StandardOutput.ReadToEnd();
        if (outputTool.IndexOf("Handle closed") == -1)
        {
            fileClosed = false;
        }
    }
    return fileClosed;
}

public static void Main()
{            
    //Path to locked file, make sure the full path is in quotes
    string fileName = "\"" + @"C:\Your_Path\To_The\ActiveX.ocx" + "\"";
    List<LockInfo> lockInfo = getLockingInfo(fileName);
    if ((lockInfo != null) && (lockInfo.Count > 0))
    {
        closeFileHandle(lockInfo);
    }                                 
}

...


2. Win32 Estilo

No hay una gran cantidad de información en los Internet acerca de esto, y parecería que hay algunas llamadas a la API sin papeles que se necesitan para sacar esto adelante sin problemas.

c ++ estos ejemplos pueden ayudar.

Por desgracia no pude conseguir que esto funcione a la perfección. He probado este método utilizando un ActiveX cargado en MS Word. Luego trató de desbloquear el ActiveX, que no es muy estable y palabra a menudo causada se bloquee. Supongo que no tengo las heridas de guerra c ++ necesarios para descifrar los programas anteriores correctamente.

Junto con este ejemplo de CreateRemoteThread en C # he puesto este código juntos.

public struct ProcessInfo
{
    public Process Process;
    public ProcessModule Module;

    public ProcessInfo(Process process, ProcessModule module)
    {
        this.Process = process;
        this.Module = module;
    }
}

private static List<ProcessInfo> getProcessInfo(string fileName, bool partialMatch)
{
    List<ProcessInfo> myProcesses = new List<ProcessInfo>();

    Process[] runningProcesses = Process.GetProcesses();
    int i = 0;
    for (i = 0; i < runningProcesses.Length; i++)
    {
        Process currentProcess = runningProcesses[i];
        try
        {
            if (!currentProcess.HasExited)
            {
                try
                {
                    ProcessModuleCollection modules = currentProcess.Modules;
                    int j = 0;
                    for (j = 0; j < modules.Count; j++)
                    {
                        if (partialMatch)
                        {
                            if ((modules[j].FileName.ToLower().IndexOf(fileName.ToLower()) != -1))
                            {
                                myProcesses.Add(new ProcessInfo(currentProcess, modules[j]));
                                break;
                            }
                        }
                        else
                        {
                            if ((modules[j].FileName.ToLower().CompareTo(fileName.ToLower()) == 0))
                            {
                                myProcesses.Add(new ProcessInfo(currentProcess, modules[j]));
                                break;
                            }
                        }
                    }
                }
                catch (NotSupportedException)
                {
                    // You are attempting to access the Modules property for a process that is running on a remote computer. 
                    // This property is available only for processes that are running on the local computer. 
                }
                catch (InvalidOperationException)
                {
                    // The process Id is not available.
                }
                catch (Win32Exception)
                {
                    // You are attempting to access the Modules property for either the system process or the idle process. 
                    // These processes do not have modules.
                }
            }
        }
        catch (InvalidOperationException)
        {
            // There is no process associated with the object. 
        }
        catch (Win32Exception)
        {
            // The exit code for the process could not be retrieved. 
        }
        catch (NotSupportedException)
        {
            // You are trying to access the HasExited property for a process that is running on a remote computer.
            // This property is available only for processes that are running on the local computer.

        }
    }
    return myProcesses.Count > 0 ? myProcesses : null;
}

private static void forceRemoteCloseHandle(ProcessInfo processInfo)
{
    // Open remote process for write
    IntPtr hProcess = NativeMethods.OpenProcess(NativeMethods.PROCESS_CREATE_THREAD | NativeMethods.PROCESS_VM_OPERATION |
            NativeMethods.PROCESS_VM_WRITE | NativeMethods.PROCESS_VM_READ, false, processInfo.Process.Id);

    // Get the handle to CloseHandle in kernel32.dll
    IntPtr hKernel32 = NativeMethods.LoadLibrary("kernel32.dll");
    IntPtr hCloseHandle = NativeMethods.GetProcAddress(hKernel32, "CloseHandle");
    uint temp = 0;

    // Create the remote thread and point it to CloseHandle
    IntPtr hCreateRemoteThread = NativeMethods.CreateRemoteThread((IntPtr)hProcess, (IntPtr)0, 0, hCloseHandle, (IntPtr)processInfo.Module.BaseAddress, 0, out temp);

    // Wait for thread to end
    NativeMethods.WaitForSingleObject(hCreateRemoteThread, 2000);

    //Closes the remote thread handle
    NativeMethods.CloseHandle(hCreateRemoteThread);

    //Free up the kernel32.dll
    if (hKernel32 != null)
        NativeMethods.FreeLibrary(hKernel32);

    //Close the process handle
    NativeMethods.CloseHandle(hProcess);
}

private static void forceRemoteFreeLibrary(ProcessInfo processInfo)
{
    // Open remote process for write
    IntPtr hProcess = NativeMethods.OpenProcess(NativeMethods.PROCESS_CREATE_THREAD | NativeMethods.PROCESS_VM_OPERATION |
            NativeMethods.PROCESS_VM_WRITE | NativeMethods.PROCESS_VM_READ, false, processInfo.Process.Id);

    // Get the handle to FreeLibrary in kernel32.dll
    IntPtr hKernel32 = NativeMethods.LoadLibrary("kernel32.dll");
    IntPtr hFreeHandle = NativeMethods.GetProcAddress(hKernel32, "FreeLibrary");

    // Create the remote thread and point it to FreeLibrary
    uint temp = 0;
    IntPtr hCreateRemoteThread = NativeMethods.CreateRemoteThread((IntPtr)hProcess, (IntPtr)0, 0, hFreeHandle, (IntPtr)processInfo.Module.BaseAddress, 0, out temp);

    // Wait for thread to end
    NativeMethods.WaitForSingleObject(hCreateRemoteThread, 2000);

    //Closes the remote thread handle
    NativeMethods.CloseHandle(hCreateRemoteThread);

    //Free up the kernel32.dll
    if (hKernel32 != null)
        NativeMethods.FreeLibrary(hKernel32);

    // Close the process handle
    NativeMethods.CloseHandle(hProcess);        
}

public static void Main()
{
    string strFile = @"C:\Program Files\Microsoft Office\OFFICE11\MSCAL.OCX";
    List<ProcessInfo> lockingProcesses = getProcessInfo(strFile, false);

    foreach (ProcessInfo processInfo in lockingProcesses)
    {
        forceRemoteCloseHandle(processInfo);
        // OR
        forceRemoteFreeLibrary(processInfo);
    }

    // OR
    foreach (ProcessInfo procInfo in lockingProcesses)
    {
        procInfo.Process.Kill();
    }

}

internal static class NativeMethods
{
    internal const int PROCESS_TERMINATE = 0x0001;
    internal const int PROCESS_CREATE_THREAD = 0x0002;
    internal const int PROCESS_VM_OPERATION = 0x0008;
    internal const int PROCESS_VM_READ = 0x0010;
    internal const int PROCESS_VM_WRITE = 0x0020;

    internal const int PROCESS_QUERY_INFORMATION = 0x0400;

    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    internal static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
    internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    internal static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);

    [DllImport("kernel32", SetLastError = true)]
    internal static extern IntPtr LoadLibrary(string lpFileName);


    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern bool FreeLibrary(IntPtr hModule);

    [DllImport("kernel32")]
    public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId);

    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    internal static extern int CloseHandle(IntPtr hPass);
}

...


3. Sólo tiene que usar Unlocker

Este es mi mejor recomendación. Manejar de TechNet no puede manejar cargados cerraduras DLL / OCX (bajo mis pruebas). Win32 es desordenado y no documentada.

Unlocker permite el acceso de línea de comandos para que pueda llamarlo exactamente de la misma manera que Handle.exe. Sólo Wack a /? después unlocker.exe en un símbolo del sistema para ver los interruptores.

También hay un versión portátil de Unlocker disponibles para que pueda empaquetar en su implementación sin forzar a los usuarios finales a instalar la aplicación.

Si todo lo demás falla que podría ponerse en contacto con el autor de Unlocker, echa un vistazo a esto desde el readme.

  

Licensing

     

Si está interesado en   redistribuir Unlocker, ya sea en   forma original o modificada, o deseo de   utilizar código fuente Unlocker en un producto,   envíe un correo electrónico a   ccollomb@yahoo.com con los detalles.

...


4. Process Hacker uso compartido Bibliotecas

acabo de descubrir esta brillante herramienta: Process Hacker que está escrito en el 100% de código C # (aunque hace uso de una gran cantidad de funciones WinAPI a través de P / Invoke bajo el capó).

Lo mejor de esto: es de código abierto (LGPL) y proporciona dos bibliotecas que los desarrolladores pueden hacer referencia en sus soluciones: Proceso ProcessHacker.CommonHacker.Native.

He descargado la fuente y sólo una palabra de advertencia es una solución bastante grande, así que puede tomar un poco de tiempo para averiguar exactamente qué / cómo usarlo.

Utiliza las funciones API de indocumentados (ntdll.dl) me hablaron de la opción 2 y se puede hacer todo Unlocker puede y mucho más.

Otros consejos

No estoy seguro si esto funciona para objetos ActiveX pero definitivamente hace para ensamblados .NET. Yo lo uso para prueba unitaria, donde las DLL tienen que ser sobrescritos sin problemas. El mecanismo utilizado es copia sombra .

Cierre maneja desde fuera una aplicación no parece realmente una opción muy segura.

No es la solución tal vez una idea o dirección ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top