簡體   English   中英

屏幕捕獲命令行工具可從命令行使用,但從UI內部啟動時

[英]Screen capture command line tool works from command line but when started from inside of UI

快速版本:在我的項目中,我有一個命令行工具,可以獲取計算機上所有窗口的屏幕快照(用於測試產品的錯誤收集工具)。 這是命令行CollectSystemLogs.exe一部分,該命令行收集許多東西,屏幕截圖只是其中一項。

我有一個小的UI( CollectUSLogs.exe ),讓測試人員/用戶選擇他們想要選擇的項目。 它只是一個UI前端,使用CollectSystemLogs.exe命令行完成所有實際工作(帶有參數來指示要收集什么)。

我可以從命令行運行命令行CollectSystemLogs.exe ,並且所有屏幕截圖都可以正常收集。

但是,當我運行UI工具CollectUSLogs.exe並選擇屏幕截圖時,它只會抓住一些,然后似乎掛起了什么。 它停止了,我不知道為什么。 不幸的是,由於它是由UI啟動的進程,因此我無法對其進行調試,並且如果僅運行命令行,它將可以正常工作。


相關代碼:

這是用於收集屏幕截圖的代碼(請忽略所有詳細的日志記錄.....進行老式的printf調試)。

/// <summary>Gets images of each window on the screen.</summary>
public static void CaptureWindows(string savePath)
{
    LogManager.LogDebugMessage($"Starting CaptureWindows({savePath})");
    AutomationElementCollection desktopChildren = AutomationElement.RootElement.FindAll(TreeScope.Children, Condition.TrueCondition);
    int windowCount = 1;

    LogManager.LogDebugMessage($"{desktopChildren.Count} desktopChildren (windows) found.");

    foreach (AutomationElement window in desktopChildren)
    {
        LogManager.LogDebugMessageConsole($"Capturing window [{window.Current.Name}]");


        Rect rect = window.Current.BoundingRectangle;
        if (Double.IsInfinity(rect.Width) || Double.IsInfinity(rect.Height))
        {
            LogManager.LogErrorMessageConsole($"[{window.Current.Name}] has at leat one infinite dimension.");
            LogManager.LogErrorMessageConsole($"w: {rect.Width}, h: {rect.Height}");
        }

        try
        {
            // TODO: Get rid of unneeded debug log prints
            LogManager.LogDebugMessage("In try{}");
            using (var bitmap = new Bitmap((int)rect.Width, (int)rect.Height))
            {
                LogManager.LogDebugMessage($"Bitmap Created {(int)rect.Width}x{(int)rect.Height}");
                using (Graphics graphic = Graphics.FromImage(bitmap))
                {
                    LogManager.LogDebugMessage($"Graphics created {graphic.ToString()}");
                    IntPtr handleDeviceContext = graphic.GetHdc();
                    var hwnd = (IntPtr)window.Current.NativeWindowHandle;
                    LogManager.LogDebugMessage($"hwnd created {hwnd.ToString()}");
                    if (hwnd == IntPtr.Zero) break;
                    NativeMethods.PrintWindow(hwnd, handleDeviceContext, 0);
                    LogManager.LogDebugMessage("PrintWindow() complete.");
                    graphic.ReleaseHdc(handleDeviceContext);
                }

                // Create File Name for image to be saved
                string fileName = Path.Combine(savePath, windowCount++.ToString("Window00") + ".png");
                LogManager.LogDebugMessage($"Saving {fileName}");
                bitmap.Save(fileName, ImageFormat.Png);
                LogManager.LogDebugMessage($"{fileName} saved");
            }
            LogManager.LogDebugMessage("End of try{}");
        }
        catch (Exception e)
        {
            LogManager.LogExceptionMessageConsole(e);
        }
        LogManager.LogDebugMessage("End of foreach");
    }
    LogManager.LogDebugMessage("Exiting CaptureWindows()");
}

我用以下命令調用命令行:

if (!ProcessHelpers.RunCommandProcessCollectOutput(command, args, out output))
{
    MessageBox.Show($"Error running command line tool to collect system logs. Please save {Path.Combine(LogManagerConstants.LogFilePath,LogManagerConstants.LogFileBasename)} for analysis.", 
                @"CollectSystemLogs.exe Execution Error", MessageBoxButtons.OK,
                MessageBoxIcon.Exclamation);
}

該代碼在這里:

public static bool RunCommandProcessCollectOutput(string command, string args, out string output)
{
    // cmd arg /c => run shell and then exit
    // cmd arg /d => disables running of autorun commands from reg 
        //               (may inject extra text into output that could affect parsing)
    string localArgs = $"/d /c {command} {args}";
    string localCommand = @"cmd";

    if (command.StartsWith(@"\\"))
    {
        NetworkHelpers.CreateMapPath(Path.GetDirectoryName(command));
    }

    ProcessStartInfo procStartInfo = new ProcessStartInfo(localCommand, localArgs);

    procStartInfo.UseShellExecute = false; // use shell (command window)
    procStartInfo.CreateNoWindow = false; // Yes, create a window
    procStartInfo.ErrorDialog = false; // Will not show error dialog if process can't start
    procStartInfo.WindowStyle = ProcessWindowStyle.Normal; // Normal type window
    procStartInfo.RedirectStandardOutput = true; // redirect stdout so we can capture
    procStartInfo.RedirectStandardError = true; // redirect stderr so we can capture

    return _RunProcessCollectOutput(procStartInfo, out output);
} 

最后一塊:

private static bool _RunProcessCollectOutput(ProcessStartInfo procStartInfo, out string output)
{
    bool successful = true;
    output = ""; // init before starting
    LogManager.LogDebugMessage("_RunProcessCollectOutput");
    try
    {
        // Create proc, assign ProcessStartInfo to the proc and start it
        Process proc = new Process();
        proc.StartInfo = procStartInfo;

        // if collecting output, we must wait for process to end in order
        // to collect output.
        LogManager.LogDebugMessage($"Starting {procStartInfo.FileName} {procStartInfo.Arguments}");
        LogManager.LogDebugMessage("[wait forever]");

        successful = proc.Start();

        string temp1 = proc.StandardOutput.ReadToEnd(); // return output if any
        string temp2 = proc.StandardError.ReadToEnd(); // return error output if any

        proc.WaitForExit(); // Wait forever (or until process ends)

        if (temp1.Length > 0)
        {
            output += "[STDOUT]\n" + temp1 + "[/STDOUT]\n";
        }
        if (temp2.Length > 0)
        {
            successful = false;
            output += "[STDERR]\n" + temp2 + "[/STDERR]\n";
        }
    }
    catch (Exception e)
    {
        if (procStartInfo != null)
        {
            LogManager.LogErrorMessage($"Error starting the process {procStartInfo.FileName} {procStartInfo.Arguments}");
        }
        LogManager.LogExceptionMessage(e);
        successful = false;
    }

    return successful;
}

因此,正如我所說的那樣,當我從命令行運行時,它工作正常,但是當以這種方式從UI內調用該命令時,它似乎只會獲得前幾個窗口,然后掛起。

查看日志中的輸出。 它得到前幾個(似乎是我擁有的三台顯示器上的任務欄,然后掛起。它似乎停在第四台之后,即使它告訴我:

找到40個桌面兒童(Windows)。

我猜第四個中的cmd窗口是運行該工具的窗口,但我不認為這應該有多重要。

[20190116164608|DBG|CollectUSLogs.exe]_RunProcessCollectOutput
[20190116164608|DBG|CollectUSLogs.exe]Starting cmd /d /c C:\XTT\UsbRoot\bin\CollectSystemLogs.exe  -ss -dp D:\
[20190116164608|DBG|CollectUSLogs.exe][wait forever]
[20190116164608|DBG|CollectSystemLogs.exe]Argument: -ss 
[20190116164608|DBG|CollectSystemLogs.exe]Argument: -dp 
[20190116164608|DBG|CollectSystemLogs.exe]D:\
[20190116164608|ERR|CollectSystemLogs.exe]Could not find a part of the path 'e:\host\config\iu\systemoptions.xml'.
[20190116164608|ERR|CollectSystemLogs.exe]   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
[20190116164608|ERR|CollectSystemLogs.exe]   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRigh
[20190116164608|ERR|CollectSystemLogs.exe]ts, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Bo
[20190116164608|ERR|CollectSystemLogs.exe]olean bFromProxy, Boolean useLongPath, Boolean checkHost)
[20190116164608|ERR|CollectSystemLogs.exe]   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 buffe
[20190116164608|ERR|CollectSystemLogs.exe]rSize)
[20190116164608|ERR|CollectSystemLogs.exe]   at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCac
[20190116164608|ERR|CollectSystemLogs.exe]hePolicy cachePolicy)
[20190116164608|ERR|CollectSystemLogs.exe]   at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
[20190116164608|ERR|CollectSystemLogs.exe]   at System.Xml.XmlTextReaderImpl.FinishInitUriString()
[20190116164608|ERR|CollectSystemLogs.exe]   at System.Xml.XmlTextReaderImpl..ctor(String uriStr, XmlReaderSettings settings, XmlParserContext context
[20190116164608|ERR|CollectSystemLogs.exe], XmlResolver uriResolver)
[20190116164608|ERR|CollectSystemLogs.exe]   at System.Xml.XmlReaderSettings.CreateReader(String inputUri, XmlParserContext inputContext)
[20190116164608|ERR|CollectSystemLogs.exe]   at System.Xml.XmlReader.Create(String inputUri, XmlReaderSettings settings, XmlParserContext inputContext
[20190116164608|ERR|CollectSystemLogs.exe])
[20190116164608|ERR|CollectSystemLogs.exe]   at System.Xml.Linq.XDocument.Load(String uri, LoadOptions options)
[20190116164608|ERR|CollectSystemLogs.exe]   at System.Xml.Linq.XDocument.Load(String uri)
[20190116164608|ERR|CollectSystemLogs.exe]   at XTT.USCartHelpers.get_SerialNumber() in C:\XTT\XTT_Tools\XTT\Helpers\USCartHelpers.cs:line 64
[20190116164608|ERR|CollectSystemLogs.exe]Cannot find Registry32 HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Philips\PHC\Ultrasound
[20190116164608|WRN|CollectSystemLogs.exe]GetOptionalRegValue: Unable to find ProductModel.
[20190116164608|ERR|CollectSystemLogs.exe]Cannot find Registry32 HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Philips\PHC\Ultrasound
[20190116164608|WRN|CollectSystemLogs.exe]GetOptionalRegValue: Unable to find ProductProgram.
[20190116164608|DBG|CollectSystemLogs.exe]Zipfilename: D:\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND).zip
[20190116164608|DBG|CollectSystemLogs.exe]ZipFolder = C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND)
[20190116164608|WRN|CollectSystemLogs.exe]Can't empty C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND). It doesn't exist.
[20190116164608|INF|CollectSystemLogs.exe]C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND) created
[20190116164608|ERR|CollectSystemLogs.exe]Can't copy SystemOption*.xml in e:\host\config\iu. It doesn't exist.
[20190116164608|ERR|CollectSystemLogs.exe]ERROR collecting SystemOptions.
[20190116164608|ERR|CollectSystemLogs.exe]SystemOptions may not be included in zip file.
[20190116164609|DBG|CollectSystemLogs.exe]Starting CaptureWindows(C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND))
[20190116164624|DBG|CollectSystemLogs.exe]40 desktopChildren (windows) found.
[20190116164624|DBG|CollectSystemLogs.exe]Capturing window []
[20190116164624|DBG|CollectSystemLogs.exe]In try{}
[20190116164624|DBG|CollectSystemLogs.exe]Bitmap Created 1920x40
[20190116164624|DBG|CollectSystemLogs.exe]Graphics created System.Drawing.Graphics
[20190116164624|DBG|CollectSystemLogs.exe]hwnd created 2626768
[20190116164624|DBG|CollectSystemLogs.exe]PrintWindow() complete.
[20190116164624|DBG|CollectSystemLogs.exe]Saving C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND)\Window01.png
[20190116164624|DBG|CollectSystemLogs.exe]C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND)\Window01.png saved
[20190116164624|DBG|CollectSystemLogs.exe]End of try{}
[20190116164624|DBG|CollectSystemLogs.exe]End of foreach
[20190116164624|DBG|CollectSystemLogs.exe]Capturing window []
[20190116164624|DBG|CollectSystemLogs.exe]In try{}
[20190116164624|DBG|CollectSystemLogs.exe]Bitmap Created 1080x40
[20190116164624|DBG|CollectSystemLogs.exe]Graphics created System.Drawing.Graphics
[20190116164624|DBG|CollectSystemLogs.exe]hwnd created 66184
[20190116164624|DBG|CollectSystemLogs.exe]PrintWindow() complete.
[20190116164624|DBG|CollectSystemLogs.exe]Saving C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND)\Window02.png
[20190116164624|DBG|CollectSystemLogs.exe]C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND)\Window02.png saved
[20190116164624|DBG|CollectSystemLogs.exe]End of try{}
[20190116164624|DBG|CollectSystemLogs.exe]End of foreach
[20190116164624|DBG|CollectSystemLogs.exe]Capturing window []
[20190116164624|DBG|CollectSystemLogs.exe]In try{}
[20190116164624|DBG|CollectSystemLogs.exe]Bitmap Created 1920x40
[20190116164624|DBG|CollectSystemLogs.exe]Graphics created System.Drawing.Graphics
[20190116164624|DBG|CollectSystemLogs.exe]hwnd created 333194
[20190116164624|DBG|CollectSystemLogs.exe]PrintWindow() complete.
[20190116164624|DBG|CollectSystemLogs.exe]Saving C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND)\Window03.png
[20190116164624|DBG|CollectSystemLogs.exe]C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND)\Window03.png saved
[20190116164624|DBG|CollectSystemLogs.exe]End of try{}
[20190116164624|DBG|CollectSystemLogs.exe]End of foreach
[20190116164624|DBG|CollectSystemLogs.exe]Capturing window [C:\WINDOWS\SYSTEM32\cmd.exe]
[20190116164624|DBG|CollectSystemLogs.exe]In try{}
[20190116164624|DBG|CollectSystemLogs.exe]Bitmap Created 993x519
[20190116164624|DBG|CollectSystemLogs.exe]Graphics created System.Drawing.Graphics
[20190116164624|DBG|CollectSystemLogs.exe]hwnd created 269574
[20190116164624|DBG|CollectSystemLogs.exe]PrintWindow() complete.
[20190116164624|DBG|CollectSystemLogs.exe]Saving C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND)\Window04.png
[20190116164624|DBG|CollectSystemLogs.exe]C:\temp\20190116164608_TestCart00_(NOTFOUND)_(NOTFOUND)\Window04.png saved
[20190116164624|DBG|CollectSystemLogs.exe]End of try{}
[20190116164624|DBG|CollectSystemLogs.exe]End of foreach

任何想法或建議將不勝感激。

我創建了一個虛擬命令行,該虛擬命令行調用相同的命令行(CollectSystemLogs.exe),並且使用相同的方法調用RunCommandProcessCollectOutput()來工作。

好吧...事實證明,@ Adam Plocher在第一次猜測中是正確的。 它是UseShellExecute標志。

我將包裝程序用於具有UseShellExecute = false的啟動過程,因為這是重定向我想要的STDOUT和STDERR以便將它們放入我的日志中所必需的。

我以為以前嘗試過UseShellExecute = true,但我想當我嘗試時遇到錯誤,因為它仍在嘗試重定向那些流,而且我必須在此停止。

我使用了另一個具有UseShellExecute = true的包裝器,但沒有給我STDOUT和STDERR,並且它可以工作。 我想我可以忍受,就像在我的代碼中詳細記錄日志一樣。

我仍然不知道為什么在使用UseShellExecute = false運行進程時它會以這種方式運行;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM