PDA

Ver la Versión Completa : Compilación condicional


santiago14
26-06-2014, 03:23:16
Buenas, tengo un dilema.
Resulta que tengo que incluir una unit si el ejecutable está corriendo en Win7 o Win8, caso contrario no se incluye.
Tengo entendido que se hace con los condicionales.
¿Alguien me puede dar una mano? Gracias.


{$IfDef DefName} //Esto debería indicarme si estoy en Win7 o Win8 o en ninguno.
thinfinity,
{$Else}
system, controls, ...
{$EndIf}

Al González
26-06-2014, 04:58:42
Hola Santiago.

Las directivas de compilación sirven para indicar cómo debe ser generado (compilado) el programa ejecutable. Una vez obtenido éste, será el mismo programa lo instales en donde lo instales. Si deseas un comportamiento diferente de la aplicación según el sistema operativo donde corra, entonces necesitarás añadir instrucciones que verifiquen en qué versión de Windows (http://msdn.microsoft.com/en-us/library/windows/desktop/ms724439%28v=vs.85%29.aspx) se encuentra y, mediante tradicionales "Ifs", separar las sentencias que deben ser ejecutadas en unas versiones del sistema operativo de las que deben ser ejecutadas en otras.

Una alternativa a lo anterior sería definir un símbolo condicional en las opciones del proyecto (entrada Conditional defines), sin dejar de usar directivas de compilación $IfDef. El símbolo lo pondrías o lo quitarías, según desees generar un ejecutable para unas versiones de Windows o para otras.

No ando muy lúcido este día, pero ojalá te haya servido de algo mi intervención.

Un cordial saludo. :)

nlsgarcia
26-06-2014, 07:45:12
santiago14,


...tengo que incluir una unit si el ejecutable está corriendo en Win7 o Win8...


Revisa este código:

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}

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
ShowMessage(GetWindowsVersion);
end;

end.

El código anterior en Delphi 7 permite obtener por medio de WMI (Windows Management Instrumentation) el nombre y la versión del Sistema Operativo Windows instalado.

Revisa este código:

unit Unit1;

interface

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

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

var
Form1: TForm1;

implementation

{$R *.dfm}

function GetWindowsVersion : String;
var
OSVersionInfo: TOSVersionInfo;
MajorVersion, MinorVersion: Integer;

begin

Result := 'Windows Unknown';

OSVersionInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);

if GetVersionEx(OSVersionInfo) then
begin

MajorVersion := OSVersionInfo.dwMajorVersion;
MinorVersion := OSVersionInfo.dwMinorVersion;

if OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then
begin
if MajorVersion <= 4 then
Result := Format('%s %d',['Windows NT',MajorVersion])
else if (MajorVersion = 5) and (MinorVersion = 0) then
Result := Format('%s %d.%d',['Windows 2000',MajorVersion,MinorVersion])
else if (MajorVersion = 5) and (MinorVersion = 1) then
Result := Format('%s %d.%d',['Windows XP',MajorVersion,MinorVersion])
else if (MajorVersion = 6) and (MinorVersion = 0) then
Result := Format('%s %d.%d',['Windows Vista',MajorVersion,MinorVersion])
else if (MajorVersion = 6) and (MinorVersion = 1) then
Result := Format('%s %d.%d',['Windows 7',MajorVersion,MinorVersion])
else if (MajorVersion = 6) and (MinorVersion = 2) then
Result := Format('%s %d.%d',['Windows 8',MajorVersion,MinorVersion])
end;

end;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(GetWindowsVersion);
end;

end.

El código anterior en Delphi 2010 permite obtener el nombre y la versión del Sistema Operativo Windows instalado.

Nota: En Delphi 7, el código propuesto identifica erróneamente el SO Windows 7 x32 y x64 como Windows XP.

Revisa este código:

unit Unit1;

interface

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

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

var
Form1: TForm1;

implementation

{$R *.dfm}

function GetWindowsVersion : String;
var
OSVersion : TOSVersion;
begin
Result := Format('%s %d.%d Build %d',[OSVersion.Name,
OSVersion.Major,
OSVersion.Minor,
OSVersion.Build]);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(GetWindowsVersion);
end;

end.

El código anterior en Delphi XE6 permite obtener el nombre y la versión del Sistema Operativo Windows instalado.

Revisa esta información:

1- Conditional compilation (Delphi) (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/compdirsconditionalcompilation_xml.html)

2- Delphi Compiler Version Directives (http://delphi.about.com/od/objectpascalide/a/compiler_ver.htm)

3- DelphiBasics : $IfDef (http://www.delphibasics.co.uk/RTL.asp?Name=$IfDef)

Espero sea útil :)

Nelson.

santiago14
26-06-2014, 15:20:47
Gracias nlsgarcia, yo creo que sí sirve.
Me explico mejor.

Hay una unit que uso, pero solamente ha sido desarrollada para Win8, si compilo en DelphiXE5 sobre Win8 y lo ejecuto , lo hace sin problemas.
Cuando llevo ese ejecutable a otra máquina (XP, Win7), no se ejecuta y devuelve un error.
La idea es que cuando esté corriendo en cierto sistema operativo, Win8, le dé bolilla a esa unit, que está en uses claro, y cuando esté corriendo en otro, no. No se si entiende. Lo mismo vale para los objetos, que están dentro del código, que son de esa unit.
Ahora que lo veo, no se si por el lado de las condicionales la cosa se encamina.

Supongo que se puede combinar lo que pusiste con esta explicación.
Un detalle mas, a esa unit la debo poner en la lista de unit del program. :mad::(

duilioisola
26-06-2014, 18:35:40
Con lo que te han explicado, supongo que sería algo así:

unit CosasParaWindows8;
...
implementatin
funtion DevuelveCosaEspecial(...);
begin
if (EsWindows8) then
begin
...
end
else
Return -1; // error
end;


La otra opción es:


funtion EstoUtilizaAlgoDeWindows8(...);
begin
...
if (EsWindows8) then
VariableEspeciaal := DevuelveCosaEspecial(...)...
else
VariableEspeciaal := Obtengo_el_valor_de_otra_manera;
...
end;

nlsgarcia
26-06-2014, 20:50:07
santiago14,


...Hay una unit que uso, pero solamente ha sido desarrollada para Win8...en Delphi XE5 sobre Win8...sin problemas...Cuando llevo ese ejecutable a otra máquina (XP, Win7), no se ejecuta...


Revisa este código:

unit Unit1;

interface

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

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

var
Form1: TForm1;

implementation

{$R *.dfm}

uses UWindowsX, UWindows8;

function GetWindowsVersion : Boolean;
var
OSVersion : TOSVersion;
begin
if Copy(OSVersion.Name,1,9) = 'Windows 8' then
Result := True
else
Result := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if GetWindowsVersion then
UWindows8.Msg // Se ejecuta si el OS es Windows 8
else
UWindowsX.Msg; // Se ejecuta si el OS es una versión diferente a Windows 8
end;

end.

El código anterior en Delphi XE6, ejecuta el procedimiento Msg en función de si el Sistema Operativo es Windows 8 o es otro Sistema Operativo Windows.

Espero sea útil :)

Nelson.

escafandra
26-06-2014, 22:50:38
Para dar más información, revisa la API GetVersionEx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms724451%28v=vs.85%29.aspx) y la estructura OSVERSIONINFO (http://msdn.microsoft.com/en-us/library/windows/desktop/ms724834%28v=vs.85%29.aspx)



function IsWin8: boolean;
var
VerInfo: TOSVersioninfo;
begin
VerInfo.dwOSVersionInfoSize:= SizeOf(TOSVersionInfo);
GetVersionEx(VerInfo);
Result:= (VerInfo.dwMajorVersion >= 6) and (VerInfo.dwMinorVersion >= 2);
end;


Nota importante:
El código anterior dará WinXP(5.1) si corres por ejemplo delphi7 en Win8 en modo de compatibilidad WinXP durante el debug, pero la aplicación ya compilada reconocerá Win8 sin error

Saludos.

nlsgarcia
27-06-2014, 02:54:29
santiago14,

Nota: El segundo código del Msg #3 (Basado en la API GetVersionEx) si es ejecutado en Delphi 7 en modo Debug, identifica erróneamente el SO Windows Vista, Windows 7 y Windows 8 como Windows XP, si es ejecutado directamente desde el ejecutable funcionara correctamente según lo esperado.

Nelson.