Delphi:从Edge ver 38+获取URL(安装所有Windows 10更新)

时间:2016-12-20 17:28:44

标签: delphi windows-10 microsoft-edge

此代码(取自其他文章)适用于较旧的MS Edge版本,但在安装最新的windows10更新后,edge进入版本38,我得到 edgeElement = nil 。我们该如何解决这个问题?

procedure TForm1.Button1Click(Sender: TObject);
const
  propertyName                : integer = 30005; // UIA_NamePropertyId
  propertyAutomationId        : integer = 30011; // UIA_AutomationIdPropertyId
  propertyClassName           : integer = 30012; // UIA_ClassNamePropertyId
  propertyNativeWindowHandle  : integer = 30020; // UIA_NativeWindowHandlePropertyId
  edgeAutomationId            : WideString  = 'TitleBar';
  urlElementClassName         : WideString  = 'Internet Explorer_Server';
  tabsListAutomationId        : WideString  = 'TabsList';
  selectionPatternId          : integer = 10001; // UIA_SelectionPatternId
var
  uiAutomation                    : IUIAutomation;
  rootElement,edgeElement,urlElement,tabsListElement,titleElement   : IUIAutomationElement;
  hresult                         : longint;
  condition,conditionUrl,conditionTabsList     : IUIAutomationCondition;
  cacheRequestNativeWindowHandle,cacheRequest  : IUIAutomationCacheRequest;
  edgeWindowHandle                : Pointer;
  url                             : WideString;
  selectionPattern                : IUnknown; 
  elementArray                    : IUIAutomationElementArray;
  title                           : WideString;

  a,b: cardinal;
begin
//rootElement:=nil;

  a := gettickcount;

  try
  uiAutomation:= CoCUIAutomation.Create;
  except
    showmessage('not supported');
    exit;
  end;
  hresult:= uiAutomation.GetRootElement(rootElement);
  if hresult<>S_OK then begin showmessage('Error GetRootElement');exit;end;

  // Get the main Edge element, which is a direct child of the UIA root element.
  // For this test, assume that the Edge element is the only element with an
  // AutomationId of "TitleBar".
  hresult:= uiAutomation.CreatePropertyCondition(propertyAutomationId, edgeAutomationId, condition);

  if hresult<>S_OK then begin showmessage('Error CreatePropertyCondition');exit;end;

  // Have the window handle cached when we find the main Edge element.
  hresult:= uiAutomation.CreateCacheRequest(cacheRequestNativeWindowHandle);

  if hresult<>S_OK then begin showmessage('Error CreateCacheRequest');exit;end;

  hresult:=cacheRequestNativeWindowHandle.AddProperty(propertyNativeWindowHandle);

  if hresult<>S_OK then begin showmessage('Error cacheRequestNativeWindowHandle.AddProperty');exit;end;

  hresult:= rootElement.FindFirstBuildCache(TreeScope_Children, condition, cacheRequestNativeWindowHandle, edgeElement);

  if hresult<>S_OK then begin showmessage('Error rootElement.FindFirstBuildCache');exit;end;

   b := gettickcount;

  if edgeElement<>nil then
    begin
      hresult:= edgeElement.Get_CachedNativeWindowHandle(edgeWindowHandle);
      if hresult<>S_OK then begin showmessage('Error edgeElement.CachedNativeWindowHandle');exit;end;

      // Next find the element whose name is the url of the loaded page. And have
      // the name of the element related to the url cached when we find the element.
      hresult:= uiAutomation.CreateCacheRequest(cacheRequest);
      if hresult<>S_OK then begin showmessage('Error uiAutomation.CreateCacheRequest');exit;end;

      hresult:=cacheRequest.AddProperty(propertyName);
      if hresult<>S_OK then begin showmessage('Error cacheRequest.AddProperty');exit;end;

      // For this test, assume that the element with the url is the first descendant element
      // with a ClassName of "Internet Explorer_Server".
      hresult:= uiAutomation.CreatePropertyCondition(propertyClassName, urlElementClassName, conditionUrl);
      if hresult<>S_OK then begin showmessage('Error CreatePropertyCondition');exit;end;

      hresult:= edgeElement.FindFirstBuildCache(TreeScope_Descendants, conditionUrl, cacheRequest, urlElement);
      if hresult<>S_OK then begin showmessage('Error edgeElement.FindFirstBuildCache');exit;end;

      hresult:= urlElement.Get_CachedName(url);
      if hresult<>S_OK then begin showmessage('Error urlElement.Get_CachedName');exit;end;

      // Next find the title of the loaded page. First find the list of
      // tabs shown at the top of Edge.
      hresult:= uiAutomation.CreatePropertyCondition(propertyAutomationId, tabsListAutomationId, conditionTabsList);
      if hresult<>S_OK then begin showmessage('Error uiAutomation.CreatePropertyCondition');exit;end;

      hresult:= edgeElement.FindFirst(TreeScope_Descendants, conditionTabsList, tabsListElement);
      if hresult<>S_OK then begin showmessage('Error edgeElement.FindFirst');exit;end;

      // Find which of those tabs is selected. (It should be possible to
      // cache the Selection pattern with the above call, and that would
      // avoid one cross-process call here.)

      hresult:= tabsListElement.GetCurrentPattern(selectionPatternId, selectionPattern);
      if hresult<>S_OK then begin showmessage('Error tabsListElement.GetCurrentPattern');exit;end;

      // For this test, assume there's always one selected item in the list.
      hresult:= (selectionPattern as IUIAutomationSelectionPattern).GetCurrentSelection(elementArray);
      if hresult<>S_OK then begin showmessage('Error selectionPattern.GetCurrentSelection');exit;end;

      hresult:= elementArray.GetElement(0, titleElement);
      if hresult<>S_OK then begin showmessage('Error elementArray.GetElement');exit;end;

      hresult:= titleElement.Get_CurrentName(title);
      if hresult<>S_OK then begin showmessage('Error titleElement.Get_CurrentName');exit;end;

      b := gettickcount;

      showmessage('Page title: ' + title+#13#10+
                  'URL: '+url+#13#10+
                  'hwnd: '+IntToStr( Integer(edgeWindowHandle) ) +#13#10+
                  'time: ' + inttostr(b-a));
    end
    else showmessage('edgeElement = nil' + ', time: ' + inttostr(b-a));

    b := gettickcount;
    caption := inttostr(b-a)
end;

1 个答案:

答案 0 :(得分:1)

看起来他们改变了窗口层次结构。您可以通过运行

来检查当前层次结构
C:\Program Files (x86)\Windows Kits\10\bin\x64\inspect.exe 

以下代码适用于最新的Windows 10周年纪念版,包含所有更新。

已更新至Edge v40

function GetElement(AuiAutomation: IUIAutomation; AParentElement: IUIAutomationElement;
  out AElement: IUIAutomationElement; const AClassName: string;
  const AAutomationID: string = ''; const AName: string = ''): Boolean;
const
  UIA_NamePropertyId          : integer = 30005;
  UIA_AutomationIdPropertyId  : integer = 30011;
  UIA_ClassNamePropertyId     : integer = 30012;
  UIA_NativeWindowHandlePropertyId  : integer = 30020;
var
  hresult       : longint;
  condition     : IUIAutomationCondition;
  cacheRequest  : IUIAutomationCacheRequest;
begin
  Result := False;
  if AName <> '' then
  begin
    hresult := AuiAutomation.CreatePropertyCondition(UIA_NamePropertyId, AName, condition);
  end
  else if AAutomationID = '' then
  begin
    hresult := AuiAutomation.CreatePropertyCondition(UIA_ClassNamePropertyId, AClassName, condition);
  end
  else
  begin
    hresult := AuiAutomation.CreatePropertyCondition(UIA_AutomationIdPropertyId, AAutomationID, condition);
  end;

  if hresult<>S_OK then begin showmessage('Error CreatePropertyCondition');exit;end;

  hresult:= AuiAutomation.CreateCacheRequest(cacheRequest);
  if hresult<>S_OK then begin showmessage('Error CreateCacheRequest');exit;end;

  cacheRequest.Set_TreeScope(TreeScope_Element or TreeScope_Children);

  hresult:=cacheRequest.AddProperty(UIA_NativeWindowHandlePropertyId);
  if hresult<>S_OK then begin showmessage('Error AddProperty');exit;end;

  hresult := cacheRequest.AddProperty(UIA_NamePropertyId);
  if hresult<>S_OK then begin showmessage('Error AddProperty');exit;end;

  hresult := AParentElement.FindFirstBuildCache(TreeScope_Children, condition, cacheRequest, AElement);
  result := (hresult = S_OK) and Assigned(AElement);
  if hresult<>S_OK then begin showmessage('Error FindFirstBuildCache');exit;end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  uiAutomation                    : IUIAutomation;
  rootElement   : IUIAutomationElement;
  hresult                         : longint;
  edgeWindowHandle                : Pointer;
  url                             : WideString;
  a,b: cardinal;
var
  ApplicationFrameWindowElement: IUIAutomationElement;
  WindowsUICOreElement: IUIAutomationElement;
  LandmarkTargetElement: IUIAutomationElement;
  ScrollViewerElement: IUIAutomationElement;
  IEServerElement: IUIAutomationElement;
  TabContentElement: IUIAutomationElement;
begin
  a := gettickcount;

  try
  uiAutomation:= CoCUIAutomation.Create;
  except
    showmessage('not supported');
    exit;
  end;
  hresult:= uiAutomation.GetRootElement(rootElement);
  if hresult<>S_OK then begin showmessage('Error GetRootElement');exit;end;

  if GetElement(uiAutomation, rootElement, ApplicationFrameWindowElement, 'ApplicationFrameWindow') then
  begin
    if GetElement(uiAutomation, ApplicationFrameWindowElement, WindowsUICoreElement, 'Windows.UI.Core.CoreWindow') then
    begin
      if GetElement(uiAutomation, WindowsUICoreElement, LandmarkTargetElement, 'LandmarkTarget') then
      begin
        if GetElement(uiAutomation, LandmarkTargetElement, ScrollViewerElement, 'ScrollViewer') then
        begin
          if GetElement(uiAutomation, ScrollViewerElement, TabContentElement, '', 'm_tabContentDCompVisualElement') then
          begin
            if GetElement(uiAutomation, TabContentElement, IEServerElement, 'Internet Explorer_Server') then
            begin
              begin
                IEServerElement.Get_CurrentName(url);
                hresult:= ApplicationFrameWindowElement.Get_CachedNativeWindowHandle(edgeWindowHandle);
                if hresult<>S_OK then begin showmessage('Error ApplicationFrameWindowElemen.CachedNativeWindowHandle');exit;end;
                b := gettickcount;

                showmessage('URL: '+url+#13#10+
                            'hwnd: '+IntToStr( Integer(edgeWindowHandle) ) +#13#10+
                            'time: ' + inttostr(b-a));
              end;
            end;
          end;
        end;
      end;
    end;
  end;
end;