什么会阻止enum窗口处理

时间:2018-06-11 18:31:39

标签: c# windows winforms service

当我调用EnumDesktopWindows_GetProcIDWindowList时,我遇到了一个非常奇怪的问题......它只是在枚举桌面窗口的过程中停止了!

我希望从这些关于程序员的丰富知识中获得的,是调试枚举停止原因的一些方面。

解决问题...这只是在计算机重新启动并首次登录后才发生。如果用户注销然后重新登录,则在初始登录后,此代码运行正常。 (那个问题真是太奇怪了)

换句话说:

1次重启

2登录

3个枚举停止

4注销(枚举停止的应用程序也停止)

5登录(应用程序重启)

6枚举现在有效

我还应该声明:Windows服务创建在用户登录时执行枚举的应用程序。该应用程序是一个具有隐藏窗口的winform

    private ProcessStartInfo StartProcessAsCurrentUser_UnderServiceContext(string appPath, SessionInformation si)
    {
        LogIt(BaseLogger.LL_2, string.Format("StartProcessAsCurrentUser_UnderServiceContext"));

        string cmdLine = null;
        string workDir = null;

        ProcessStartInfo retval = new ProcessStartInfo();
        retval.Disposition = eAgentUIDisposition.Error;

        var hUserToken = IntPtr.Zero;
        var startInfo = new STARTUPINFO();
        var procInfo = new PROCESS_INFORMATION();
        var pEnv = IntPtr.Zero;

        startInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));

        int nError = 0;
        try
        {
            bool bCallGetSessionUserToken = true;
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // GetSessionUserToken eventually calls WTSQueryUserToken..
                // which is good when this process is running under a service context,
                // but when it's running under the debugger (user context) 
                // WTSQueryUserToken fails with error 1314: A required privilege is not held by the client.
                bCallGetSessionUserToken = false;
            }

            if(bCallGetSessionUserToken)
            {
                if (!GetSessionUserToken(si.SessionID, ref hUserToken))
                {
                    string error = string.Format("ERROR : GetSessionUserToken failed ( error has already been logged ).");
                    LogIt(BaseLogger.LL_Error, error);
                    retval.Disposition = eAgentUIDisposition.Error_UserToken;
                    return retval;
                }
            }

            uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE;
            startInfo.wShowWindow = (short)(SW.SW_SHOW);
            startInfo.lpDesktop = "winsta0\\default";

            if (!localNative.CreateEnvironmentBlock(ref pEnv, hUserToken, false))
            {
                nError = Marshal.GetLastWin32Error();
                string error = string.Format("ERROR : code '{0}' CreateEnvironmentBlock failed.", nError);
                LogIt(BaseLogger.LL_Error, error);
                retval.Disposition = eAgentUIDisposition.Error_EnvironmentBlock;
                return retval;
            }

            if (!localNative.CreateProcessAsUser(
                                                    hUserToken,      // client's access token
                                                    appPath,         // file to execute
                                                    cmdLine,         // Command Line
                                                    IntPtr.Zero,     // pointer to process SECURITY_ATTRIBUTES
                                                    IntPtr.Zero,     // pointer to thread SECURITY_ATTRIBUTES
                                                    false,           // handles are not inheritable
                                                    dwCreationFlags, // creation flags
                                                    pEnv,            // pointer to new environment block 
                                                    workDir,         // name of current working directory 
                                                    ref startInfo,   // pointer to STARTUPINFO structure
                                                    out procInfo)    // receives information about new process
                )
            {
                nError = Marshal.GetLastWin32Error();
                string error = string.Format("ERROR : code '{0}' CreateProcessAsUser failed. Could NOT create process", nError);
                LogIt(BaseLogger.LL_Error, error);
                retval.Disposition = eAgentUIDisposition.Error_ProcessAsUser;
                return retval;
            }
        }
        finally
        {
            localNative.CloseHandle(hUserToken);
            if (pEnv != IntPtr.Zero)
            {
                localNative.DestroyEnvironmentBlock(pEnv);
            }
            localNative.CloseHandle(procInfo.hThread);
            localNative.CloseHandle(procInfo.hProcess);
        }

        retval.Disposition = eAgentUIDisposition.Started;
        retval.ProcID = procInfo.dwProcessId;
        retval.SessionID = si.SessionID;
        retval.User = si.User;

        LogIt(BaseLogger.LL_2, string.Format("StartProcessAsCurrentUser_UnderServiceContext returning '{0}'", si));

        return retval;
    }

隐藏的应用程序运行此代码:

    public static Dictionary<uint, iDesktopWindow> EnumDesktopWindows_GetProcIDWindowList(List<string> systemIgnoredWindows, iTitleModifier iTM)
    {
        Dictionary<uint, iDesktopWindow> retval = new Dictionary<uint, iDesktopWindow>();

        int nZorder = -1;

        InternalInterOp.EnumDelegate filter = delegate (IntPtr hWnd, int lParam)
        {
            bool include = false;
            include = InternalInterOp.IsWindowVisible(hWnd);
            if (!include)
            {
                return true; // get next window
            }

            nZorder++;

            if (include)
            {
                string temp = GetCaptionOfWindow(hWnd, iTM);
                if (string.IsNullOrEmpty(temp))
                {
                    return true;
                }

                foreach(string ignore in systemIgnoredWindows)
                {
                    if( temp.ToLower() == ignore.ToLower() )
                    {
                        return true;
                    }
                }
            }

            if (include)
            {
                uint tempProcID = GetProcessID(hWnd);

                if (!retval.ContainsKey(tempProcID))
                {
                    DesktopWindow dw = new DesktopWindow();
                    dw.ZOrder = (uint)nZorder;
                    dw.ProcID = tempProcID;
                    dw.hWnd = hWnd;

                    retval.Add(dw.ProcID, dw);
                }
            }

            return true;
        };

        bool enumRetval = false;
        try
        {
            enumRetval = InternalInterOp.EnumDesktopWindows(IntPtr.Zero, filter, IntPtr.Zero);

        }
        catch(Exception ex)
        {
            // exception does not get thrown... or I am not catching it ??
        }

        return retval;
    }

以下是一些支持定义:

public delegate bool EnumDelegate(IntPtr hWnd, int lParam);


[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction, IntPtr lParam);


[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWindowVisible(IntPtr hWnd);

[DllImport("user32.dll", EntryPoint = "GetWindowText", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);


[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);


    public static uint GetProcessID(IntPtr hWnd)
    {
        uint retval = 0;
        InternalInterOp.GetWindowThreadProcessId(hWnd, out retval);

        return retval;
    }


    public static string GetCaptionOfWindow(IntPtr hwnd, iTitleModifier iTM)
    {
        string caption = "";
        StringBuilder windowText = null;
        try
        {
            int max_length = 16384;
            windowText = new StringBuilder("", max_length);
            InternalInterOp.GetWindowText(hwnd, windowText, max_length);

            string temp = windowText.ToString();
            if (!String.IsNullOrEmpty(temp) && !String.IsNullOrWhiteSpace(temp))
            {
                caption = temp;

                // Fix for CET-217
                // prevents window text of "File1" and "File1 *" from being detected as two different files
                caption = iTM.Process(caption);
            }
        }
        catch
        {
            caption = "";
        }
        finally
        {
            windowText = null;
        }
        return caption;
    }


public enum eLocation
{
    None = 0,
    Prefix, 
    Suffix 
}

public interface iTitleModifier
{
    eLocation Location { get; }
    string Indicator { get; }

    void UpdateValues(iTitleModifier val);

    bool Enabled { get; }

    string Process(string input);
}

[Serializable]
public class TitleModifier : iTitleModifier
{
    public TitleModifier()
    {
        Location = eLocation.None;
        Indicator = "";

        SetEnabled();
    }

    public void UpdateValues(iTitleModifier tm)
    {
        Location = tm.Location;
        Indicator = tm.Indicator;
    }

    private eLocation _Location { get; set; }
    public eLocation Location
    {
        get
        {
            return _Location;
        }
        set
        {
            _Location = value;
            SetEnabled();
        }
    }

    private string _Indicator { get; set; }
    public string Indicator
    {
        get
        {
            return _Indicator;
        }
        set
        {
            _Indicator = value;
            SetEnabled();
        }
    }

    private void SetEnabled()
    {
        bool bLocationSet = Location != eLocation.None;

        bool bHasValue = !string.IsNullOrEmpty(Indicator);

        Enabled = bLocationSet && bHasValue;
    }

    [XmlIgnore]
    public bool Enabled { get; private set; }

    public string Process(string input)
    {
        string retval = input;
        if (Enabled)
        {
            // I made the _process function so testing of this can be as "simple"
            // as commenting this line out recompiling, 
            // then running the activity monitor tester
            retval = _process(input);
        }

        return retval;
    }

    private string _process(string input)
    {
        string retval = input;

        int nLen = Indicator.Length;
        if (Location == eLocation.Prefix)
        {
            if (input.StartsWith(Indicator))
            {
                retval = input.Substring(nLen, input.Length - nLen);
            }
        }
        else if (Location == eLocation.Suffix)
        {
            if (input.EndsWith(Indicator))
            {
                retval = input.Substring(0, input.Length - nLen);
            }
        }
        else
        {
            // leave it be...
        }

        return retval;
    }

    public override string ToString()
    {
        string retval = "";

        if (Enabled)
        {
            retval = string.Format(" TM {0} {1}", Location, Indicator);
        }

        return retval;
    }
}



public interface iDesktopWindow
{
    IntPtr hWndParent { get; }
    IntPtr hWnd { get; }
    uint ProcID { get; }
    uint ZOrder { get; set; }
}


public class DesktopWindow : iDesktopWindow
{
    public DesktopWindow()
    {
        hWndParent = IntPtr.Zero;
        hWnd = IntPtr.Zero;
        ProcID = 0;
        ZOrder = 0;
    }

    public IntPtr hWndParent { get; set; }
    public IntPtr hWnd { get; set; }
    public uint ProcID { get; set; }
    public uint ZOrder { get; set; }

    public override string ToString()
    {
        string retval = ""; ;

        retval = string.Format("procID:({0}) zorder:{1} hwnd:'{2}' parent '{3}'", ProcID, ZOrder, hWnd, hWndParent);

        return retval;
    }
}

0 个答案:

没有答案