Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros temas > Trucos
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Los mejores trucos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 03-08-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 12.504
Poder: 26
dec Va camino a la famadec Va camino a la fama
Cómo abrir una URL con Microsoft Edge en Windows 10

Hola a todos,

En Microsoft Windows 10 viene incorporado, además de Internet Explorer 11, otro navegador, Microsoft Edge. Buscando información sobre cómo abrir una determinada URL con este navegador, encontraremos que podemos usar la función "ShellExecute" (de toda la vida) proporcionando como argumento "FileName" una cadena similar a esta:

Código:
microsoft-edge:http://www.clubdelphi.com
Ya está. Ese es el truco. ¡¿Ese es el truco?!

Bueno, en realidad esto da para un poco más. Ponte en el caso de tener que detectar si Microsoft Edge está instalado o no en el sistema. Como ves arriba, no invocamos ningún ejecutable, y, de hecho, en mi sistema aparecen tres "MicrosoftEdge.exe" en lugares diferentes. Así que, ¿cómo saber que Microsoft Edge está disponible?

La forma de hacerlo (o al menos lo que yo he hecho) ha sido averiguando la versión de Windows en que corre mi programa. Ahora mismo, al menos, Microsoft Edge está disponible sólo en Windows 10, de modo que lo que tenemos que averiguar es si nuestro programa corre o no en Windows 10.

Y ahora sí, ese es el truco. ¡¿Ese es el truco?!

Bueno (bueno estaba y se murió, ¡pues no estaría tan bueno!), en realidad esto da para un poco más todavía. Resulta que hay cierto lío montado con el asunto de averiguar la versión de Windows desde nuestros programas. Microsoft ha llevado a cabo ciertos cambios (que tampoco conozco a fondo) en la forma en que se manejan las versiones de Windows.

De este modo, un programa escrito en Delphi XE2 (al menos) en Windows 10 nos dará datos erróneos si tratamos de usar el registro "SysUtils.TOSVersion", por ejemplo, o bien otras funciones del API de Windows para obtener la versión del sistema. Con nuestros propios ojos podremos ver que ejecutándose nuestro programa en Windows 10 este nos informa de que corre en Windows 8.

Buscando por internet encontré una unidad que implementa ciertas funciones de un nuevo API de Windows disponibles a partir de Windows 10, y que, sin atribuirme autoría alguna (creo que es una copia de cierto código C que también he podido ver, pero, desconozco la autoría) aquí están porque igual pueden serle a alguien tan útiles como a mí mismo:

Código Delphi [-]
unit AppBuilder.Shared.WindowsVersion;

interface

uses
  // Delphi
  Winapi.Windows,
  System.SysUtils;

const
  VER_SERVICEPACKMAJOR = $0000010;
  VER_MAJORVERSION = $0000002;
  VER_MINORVERSION = $0000001;
  VER_NT_WORKSTATION = 1;
  VER_PRODUCT_TYPE = $80;

  VER_EQUAL = 1;
  VER_GREATER = 2;
  VER_GREATER_EQUAL = 3;
  VER_LESS = 4;
  VER_LESS_EQUAL = 5;
  VER_AND = 6;
  VER_OR = 7;
  WIN32_WINNT_NT4 = $0400;
  WIN32_WINNT_WIN2K = $0500;
  WIN32_WINNT_WINXP = $0501;
  WIN32_WINNT_WS03 = $0502;
  WIN32_WINNT_VISTA = $0600;
  WIN32_WINNT_WS08 = $0600;
  WIN32_WINNT_LONGHORN = $0600;
  WIN32_WINNT_WIN7 = $0601;
  WIN32_WINNT_WIN8 = $0602;
  WIN32_WINNT_WINBLUE = $0603;
  WIN32_WINNT_WIN10 = $0A00;

  kernel32 = 'kernel32.dll';

type
  OSVERSIONINFOEX = record
    dwOSVersionInfoSize: DWord;
    dwMajorVersion: DWord;
    dwMinorVersion: DWord;
    dwBuildNumber: DWord;
    dwPlatformID: DWord;
    szCSDVersion: array [1 .. 128] of char;
    wServicePackMajor: Word;
    wServicePackMinor: Word;
    wSuiteMask: Word;
    wProductType: Byte;
    wReserved: Byte;
  end;

function IsWindowsXPOrGreater: Bool; stdcall;
function IsWindowsXPSP1OrGreater: Bool; stdcall;
function IsWindowsXPSP2OrGreater: Bool; stdcall;
function IsWindowsXPSP3OrGreater: Bool; stdcall;
function IsWindowsVistaOrGreater: Bool; stdcall;
function IsWindowsVistaSP1OrGreater: Bool; stdcall;
function IsWindowsVistaSP2OrGreater: Bool; stdcall;
function IsWindows7OrGreater: Bool; stdcall;
function IsWindows7SP1OrGreater: Bool; stdcall;
function IsWindows8OrGreater: Bool; stdcall;
function IsWindows8Point1OrGreater: Bool; stdcall;
function IsWindows10OrGreater: Bool; stdcall;
function IsWindowsServer: Bool; stdcall;

function IsWindowsVersionOrGreater(wMajorVersion, wMinorVersion,
  wServicePackMajor: Word): Bool; stdcall;

implementation

function VerifyVersionInfo(var LPOSVERSIONINFOEX: OSVERSIONINFOEX;
  dwTypeMask: DWord; dwlConditionMask: int64): Bool; stdcall;
  external kernel32 name 'VerifyVersionInfoA';

function VerSetConditionMask(dwlConditionMask: int64; dwTypeBitMask: DWord;
  dwConditionMask: Byte): int64; stdcall; external kernel32;

function IsWindowsVersionOrGreater;
var
  osvi: OSVERSIONINFOEX;
  condmask: int64;
begin
  FillChar(osvi, sizeof(osvi), 0);
  osvi.dwOSVersionInfoSize := sizeof(osvi);
  FillChar(condmask, 8, 0);
  condmask := VerSetConditionMask(condmask, VER_MAJORVERSION,
    VER_GREATER_EQUAL);
  condmask := VerSetConditionMask(condmask, VER_MINORVERSION,
    VER_GREATER_EQUAL);
  condmask := VerSetConditionMask(condmask, VER_SERVICEPACKMAJOR,
    VER_GREATER_EQUAL);
  osvi.dwMajorVersion := wMajorVersion;
  osvi.dwMinorVersion := wMinorVersion;
  osvi.wServicePackMajor := wServicePackMajor;
  Result := VerifyVersionInfo(osvi, VER_MAJORVERSION or VER_MINORVERSION or
    VER_SERVICEPACKMAJOR, condmask) <> false;
end;

function IsWindowsXPOrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_WINXP),
    LOBYTE(WIN32_WINNT_WINXP), 0);
end;

function IsWindowsXPSP1OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_WINXP),
    LOBYTE(WIN32_WINNT_WINXP), 1);
end;

function IsWindowsXPSP2OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_WINXP),
    LOBYTE(WIN32_WINNT_WINXP), 2);
end;

function IsWindowsXPSP3OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_WINXP),
    LOBYTE(WIN32_WINNT_WINXP), 3);
end;

function IsWindowsVistaOrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_VISTA),
    LOBYTE(WIN32_WINNT_VISTA), 0);
end;

function IsWindowsVistaSP1OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_VISTA),
    LOBYTE(WIN32_WINNT_VISTA), 1);
end;

function IsWindowsVistaSP2OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_VISTA),
    LOBYTE(WIN32_WINNT_VISTA), 2);
end;

function IsWindows7OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_WIN7),
    LOBYTE(WIN32_WINNT_WIN7), 0);
end;

function IsWindows7SP1OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_WIN7),
    LOBYTE(WIN32_WINNT_WIN7), 0);
end;

function IsWindows8OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_WIN8),
    LOBYTE(WIN32_WINNT_WIN8), 0);
end;

function IsWindows8Point1OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_WINBLUE),
    LOBYTE(WIN32_WINNT_WINBLUE), 0);
end;

function IsWindows10OrGreater;
begin
  Result := IsWindowsVersionOrGreater(HiByte(WIN32_WINNT_WIN10),
    LOBYTE(WIN32_WINNT_WIN10), 0);
end;

function IsWindowsServer;
var
  osvi: OSVERSIONINFOEX;
  condmask: int64;
begin
  FillChar(osvi, sizeof(osvi), 0);
  osvi.dwOSVersionInfoSize := sizeof(osvi);
  FillChar(condmask, 8, 0);
  condmask := VerSetConditionMask(condmask, VER_PRODUCT_TYPE, VER_EQUAL);
  osvi.wProductType := VER_NT_WORKSTATION;
  Result := not VerifyVersionInfo(osvi, VER_PRODUCT_TYPE, condmask) <> false;
end;

end.

Así que en principio con estas funciones podemos averiguar si nuestro programa correo finalmente en Windows 10, de modo que podamos abrir una URL con el navegador Microsoft Edge, por ejemplo. Sin embargo, ni siquiera estas funciones ofrecerán los resultados esperados... ¡este truco no va a terminar nunca!

En efecto, tenemos que utilizar un manifiesto para nuestro programa diferente del que incluye Delphi XE2, al menos, porque, de lo contrario, las funciones anteriores (u otras) ofrecerán resultados equivocados, por lo menos, confundirán Windows 10 con Windows 8. Básicamente, podemos partir del manifiesto que usa Delphi por defecto:

Código:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
 <dependency>
   <dependentAssembly>
     <assemblyIdentity
       type="win32"
       name="Microsoft.Windows.Common-Controls"
       version="6.0.0.0"
       publicKeyToken="6595b64144ccf1df"
       language="*"
       processorArchitecture="*"/>
   </dependentAssembly>
 </dependency>
 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
   <security>
     <requestedPrivileges>
       <requestedExecutionLevel
         level="asInvoker"
         uiAccess="false"/>
       </requestedPrivileges>
   </security>
 </trustInfo>
</assembly>
A este manifiesto hemos de añadir una opción de compatibilidad al menos: para indicar que nuestro programa requiere de las nuevas características de Windows 10:

Código:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
 <dependency>
   <dependentAssembly>
     <assemblyIdentity
       type="win32"
       name="Microsoft.Windows.Common-Controls"
       version="6.0.0.0"
       publicKeyToken="6595b64144ccf1df"
       language="*"
       processorArchitecture="*"/>
   </dependentAssembly>
 </dependency>
 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
   <security>
     <requestedPrivileges>
       <requestedExecutionLevel
         level="asInvoker"
         uiAccess="false"/>
       </requestedPrivileges>
   </security>
 </trustInfo>
 <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
  <application>
   <!--This Id value indicates the application supports Windows 7 functionality-->
   <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
   <!--This Id value indicates the application supports Windows 8 functionality-->
   <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
   <!--This Id value indicates the application supports Windows 8.1 functionality-->
   <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
   <!-- This Id value indicates the application supports Windows 10 functionality -->
   <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
  </application>
 </compatibility>
</assembly>
El manifiesto anterior es el que yo he empezado a usar en mis programas y, una vez lo añadamos a los mismos:



... ahora sí, podremos usar las funciones anteriores para averiguar si nuestro programa corre en Windows 10.

¡Fin del truco!

En conclusión:

Por lo que parece, a partir de Windows 10 (que yo sepa) los programas que no incluyan en su manifiesto la compatibilidad con dicha versión de Windows, tampoco podrán delegar en la versión del sistema operativo, o sea, el programa no tendrá modo de saber si corre en Windows 10, al menos usando los recursos y funciones habituales.
__________________
David Esperalta
www.davidesperalta.com
Responder Con Cita
  #2  
Antiguo 03-08-2015
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Poder: 14
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
David,

Cita:
Empezado por dec
...lo que tenemos que averiguar es si nuestro programa corre o no en Windows 10...


Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ActiveX, ComObj;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// Obtiene la versión de Windows vía WMI
function GetWindowsVersion : String;
const
  wbemFlagForwardOnly = $00000020;

var
  FSWbemLocator : OLEVariant;
  FWMIService : OLEVariant;
  FWbemObjectSet : OLEVariant;
  FWbemObject : OLEVariant;
  oEnum : IEnumvariant;
  iValue : LongWord;
  SQLWMI : String;

begin

  // Obtiene Acceso a WMI
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');

  // Obtiene Acceso al NameSpace root\CIMV2 localmente que contiene la Clase Win32_Process
  FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');

  // Contruye la Consulta SQL WMI (WQL) a la Clase Win32_Process
  SQLWMI := 'SELECT * FROM Win32_OperatingSystem';

  // Ejecuta la Consulta
  FWbemObjectSet := FWMIService.ExecQuery(SQLWMI,'WQL',wbemFlagForwardOnly);

  // Interface a los objetos COM de la consulta por medio de enumeración
  oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;

  // Accesa las propiedades de los objetos de la enumeración
  if oEnum.Next(1, FWbemObject, iValue) = 0 then
  begin
     Result := Format('%s %s',[FWbemObject.Caption, FWbemObject.Version]);
     FWbemObject:=Unassigned;
  end

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   MessageDlg(GetWindowsVersion,mtInformation,[mbOK],0);
end;

end.
El código anterior en Delphi 7 sobre Windows 7 Professional x32, Permite por medio de Windows Management Instrumentation (WMI) obtener la versión de Windows, como se muestra en la siguiente imagen:



Espero sea útil

Nelson.
Responder Con Cita
  #3  
Antiguo 03-08-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 12.504
Poder: 26
dec Va camino a la famadec Va camino a la fama
Hola,

Gracias por el aporte. Había leído que a través de WMI era también posible hacerlo, pero, no sé porqué he preferido la otra opción, ¿quizá porque me parece más rápida de algunas pruebas que hice hace tiempo con WMI? Ojo que esto no quita que sea otra posible solución y que además lo mío es más bien una impresión que puede estar equivocada.

P.D. No había probado con WMI, pero, acabo de hacerlo y parece que funciona sin necesidad de cambiar el manifiesto que por defecto incorpora Delphi XE2.
__________________
David Esperalta
www.davidesperalta.com
Responder Con Cita
  #4  
Antiguo 20-08-2015
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Poder: 14
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
Club Delphi,

Cita:
Empezado por dec
...lo que tenemos que averiguar es si nuestro programa corre o no en Windows 10...



Tomado de: Getting the System Version

Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.StrUtils;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// Obtiene la versión de Windows vía APIs
function GetWindowsKernelVersion : String;
const
   FileName : String = 'C:\Windows\System32\Kernel32.dll';

type
   PLanguageCodepage = ^TLanguageCodepage;
   TLanguageCodepage = record
      Language : Word;
      CodePage : Word;
   end;

var
   None, Size: LongWord;
   Buffer, Ptr : Pointer;
   Lang, AuxStr, Version : String;
   WinList : TStringList;
   P : Integer;

   function IsWindowsServer : Boolean;
   var
      OSVersion : OSVersionInfoEX;
      ConditionMask : Int64;
   begin
      FillChar(OSVersion, SizeOf(OSVersion), 0);
      OSVersion.dwOSVersionInfoSize := SizeOf(OSVersion);
      OSVersion.wProductType := VER_NT_WORKSTATION;
      ConditionMask := VerSetConditionMask(ConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
      Result := not VerifyVersionInfo(OSVersion, VER_PRODUCT_TYPE, ConditionMask);
   end;

begin

   Size := GetFileVersionInfoSize(PChar(FileName), None);

   if Size = 0 then
      Exit;

   WinList := TStringList.Create;

   WinList.Add('10.0=Windows 10');
   WinList.Add('Svr 10.0=Windows Server');
   WinList.Add('6.3=Windows 8.1');
   WinList.Add('Svr 6.3=Windows Server 2012 R2');
   WinList.Add('6.2=Windows 8');
   WinList.Add('Svr 6.2=Windows Server 2012');
   WinList.Add('6.1=Windows 7');
   WinList.Add('Svr 6.1=Windows Server 2008 R2');
   WinList.Add('6.0=Windows Vista');
   WinList.Add('Svr 6.0=Windows Server 2008');
   WinList.Add('5.2=Windows XP x64');
   WinList.Add('Svr 5.2=Windows Server 2003');
   WinList.Add('5.1=Windows XP');
   WinList.Add('5.0=Windows 2000');
   WinList.Add('4.0=Windows NT');

   Result := '0.0.0.0';

   GetMem(Buffer, Size);

   try
      GetFileVersionInfo(PChar(FileName), 0, Size, Buffer);

      VerQueryValue(Buffer, '\VarFileInfo\Translation\', Ptr, Size);

      Lang := Format('%.4x%.4x', [PLanguageCodepage(Ptr)^.Language, PLanguageCodepage(Ptr)^.CodePage]);

      if VerQueryValue(Buffer, PChar('\StringFileInfo\' + Lang + '\FileVersion'), Ptr, Size) then
      begin
         AuxStr := PChar(Ptr);
         P := PosEx('.',AuxStr,Pos('.',AuxStr)+1);
         Version := Copy(AuxStr,1,P-1);
         if IsWindowsServer then
            Result := WinList.Values['Svr ' + Version] + ' ' + Version
         else
            Result := WinList.Values[Version] + ' ' + Version;
      end;
   finally
      FreeMem(Buffer);
      WinList.Free;
   end;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   TaskMessageDlg('Windows Version', GetWindowsKernelVersion, mtInformation, [mbOK], 0);
end;

end.
El código anterior en Delphi XE7 sobre Windows 7 Professional x32, Permite por medio de funciones de Windows (APIs) obtener la versión del SO, como se muestra en la siguiente imagen:



Notas:

1- Esta función es un bit más compleja y rápida que la planteada en el Msg #2.

2- La función basada en WMI del Msg #2, es más simple y expresiva en información.

3- Ambas funciones detectan correctamente la versión de Windows.

Información relacionada:
Espero sea útil

Nelson.

Última edición por nlsgarcia fecha: 22-08-2015 a las 22:49:42.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Windows XP and Windows 8: The worst possible combination for Microsoft nlsgarcia La Taberna 0 04-02-2014 07:34:17
Como abrir aplicaciones de Android en un PC con Windows rrf Noticias 4 25-04-2011 20:09:35
Microsoft autoriza a los fabricantes a instalar Windows XP en vez de Windows Vista Ñuño Martínez Noticias 4 26-09-2007 06:11:19
Menú de apagado en Windows Vista y como trabaja Microsoft DarKraZY La Taberna 8 29-11-2006 20:00:55
Abrir un documento existente con Microsoft Word dec Trucos 1 15-11-2006 20:12:30


La franja horaria es GMT +2. Ahora son las 13:48:06.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi