Witam. Tworząc program chciałbym, aby w menu Pomoc->O programie wyświetlała mi się aktualna wersja programu w formacie np. 0.1.2.3. Wersję taką ustawiam w oknie Version Info w Opcjach projektu. Czy jest jakiś sposób na zapisanie wersji programu do zmiennej, którą mogę później wykorzystać?
- Rejestracja:około 13 lat
- Ostatnio:ponad 12 lat
- Postów:4
Znalazłem taką funkcję:
{
Usage:
VersionInformation(ListBox1)
}
{Pads or truncates a String and
Justifies Left if StrJustify=True}
Function StringPad(
InputStr,
FillChar: String;
StrLen: Integer;
StrJustify: Boolean): String;
Var
TempFill: String;
Counter : Integer;
Begin
If Not (Length(InputStr) = StrLen) Then
Begin
If Length(InputStr) > StrLen Then
Begin
InputStr := Copy(InputStr,1,StrLen) ;
End
Else
Begin
TempFill := '';
For Counter := 1 To StrLen-Length(InputStr) Do
Begin
TempFill := TempFill + FillChar;
End;
If StrJustify Then
Begin
{Left Justified}
InputStr := InputStr + TempFill;
End
Else
Begin
{Right Justified}
InputStr := TempFill + InputStr ;
End;
End;
End;
Result := InputStr;
End;
Function VersionInformation(
ListBox : TListBox): Boolean;
const
InfoNum = 11;
InfoStr : array [1..InfoNum] of String =
('CompanyName', 'FileDescription', 'FileVersion',
'InternalName', 'LegalCopyright', 'LegalTradeMarks',
'OriginalFilename', 'ProductName', 'ProductVersion',
'Comments', 'Author') ;
LabelStr : array [1..InfoNum] of String =
('Company Name', 'Description', 'File Version',
'Internal Name', 'Copyright', 'TradeMarks',
'Original File Name', 'Product Name',
'Product Version', 'Comments', 'Author') ;
var
S : String;
j : Integer;
Len, n: Cardinal;
Buf : PChar;
Value : PChar;
begin
Try
S := Application.ExeName;
ListBox.Items.Clear; <----------------------- Tu wywala błąd
ListBox.Sorted := True;
ListBox.Font.Name := 'Courier New';
n := GetFileVersionInfoSize(PChar(S),n) ;
If n > 0 Then Begin
Buf := AllocMem(n) ;
ListBox.Items.Add
(StringPad('Size',' ',20,True)+' = '+IntToStr(n)) ;
GetFileVersionInfo(PChar(S),0,n,Buf) ;
For j:=1 To InfoNum Do Begin
If VerQueryValue(Buf,PChar('StringFileInfo\040904E4\'+
InfoStr[j]),Pointer(Value),Len) Then
Begin
Value := PChar(Trim(Value)) ;
If Length(Value) > 0 Then
Begin
ListBox.Items.Add
(StringPad(labelStr,' ',20,True)+' = '+Value) ;
End;
End;
End;
FreeMem(Buf,n) ;
End
Else Begin
ListBox.Items.Add
('No FileVersionInfo found') ;
End;
Result := True;
Except
Result := False;
End;
End;
Nie znam dobrze elementów typu TListBox, więc proszę o pomoc co może powodować błąd.
- Rejestracja:około 13 lat
- Ostatnio:ponad 12 lat
- Postów:4
TListBox był przekazywany jako parametr... Zresztą znalazłem o wiele mniejszy kod kilka stron dalej ;] oto on:
procedure GetBuildInfo(var V1, V2, V3, V4: word);
var
VerInfoSize, VerValueSize, Dummy: DWORD;
VerInfo: Pointer;
VerValue: PVSFixedFileInfo;
begin
VerInfoSize := GetFileVersionInfoSize(PChar(ParamStr(0)), Dummy);
if VerInfoSize > 0 then
begin
GetMem(VerInfo, VerInfoSize);
try
if GetFileVersionInfo(PChar(sFileName), 0, VerInfoSize, VerInfo) then
begin
VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize);
with VerValue^ do
begin
V1 := dwFileVersionMS shr 16;
V2 := dwFileVersionMS and $FFFF;
V3 := dwFileVersionLS shr 16;
V4 := dwFileVersionLS and $FFFF;
end;
end;
finally
FreeMem(VerInfo, VerInfoSize);
end;
end;
end;
Dzięki niemu można uzyskać każdą cyferkę oddzielnie co jest pomocne przy formatowaniu, np. v2.1.3 build 5 :D
marcin412 napisał(a)
Dzięki niemu można uzyskać każdą cyferkę oddzielnie co jest pomocne przy formatowaniu
Przecież podzielić łańcuch na kawałki według jakichś znaków nie jest problem; Kilka funkcji do tego istnieje, także łatwo samemu taką napisac;
const
IV_CompanyName = 0;
IV_FileDescription = 1;
IV_FileVersion = 2;
IV_InternalName = 3;
IV_LegalCopyRight = 4;
IV_LegalTradeMark = 5;
IV_OriginalFileName = 6;
IV_ProductName = 7;
IV_ProductVersion = 8;
IV_Comments = 9;
function GetAppVersionInfo(const FileName: String; InfoValue: Byte): String;
var
VerSize: Integer;
VerBuf: PChar;
VerBufValue: Pointer;
VerHandle: Cardinal;
VerBufLen: Cardinal;
VerKey: String;
function GetInfo(ThisKey: String): String;
begin
Result := '';
VerKey := '\StringFileInfo\' + IntToHex(LoWord(Integer(VerBufValue^)), 4) +
IntToHex(HiWord(Integer(VerBufValue^)), 4) + '\' + ThisKey;
if VerQueryValue(VerBuf, PChar(VerKey), VerBufValue, VerBufLen) then
Result := StrPas(VerBufValue);
end;
function QueryValue(ThisValue: string): string;
begin
Result := '';
if GetFileVersionInfo(PChar(FileName), VerHandle, VerSize, VerBuf) and
VerQueryValue(VerBuf, '\VarFileInfo\Translation', VerBufValue, VerBufLen) then
Result := GetInfo(ThisValue);
end;
begin
VerSize := GetFileVersionInfoSize(PChar(FileName), VerHandle);
VerBuf := AllocMem(VerSize);
try
case InfoValue of
IV_CompanyName: Result := QueryValue('CompanyName');
IV_FileDescription: Result := QueryValue('FileDescription');
IV_FileVersion: Result := QueryValue('FileVersion');
IV_InternalName: Result := QueryValue('InternalName');
IV_LegalCopyRight: Result := QueryValue('LegalCopyRight');
IV_LegalTradeMark: Result := QueryValue('LegalTradeMark');
IV_OriginalFileName: Result := QueryValue('OriginalFileName');
IV_ProductName: Result := QueryValue('ProductName');
IV_ProductVersion: Result := QueryValue('ProductVersion');
IV_Comments: Result := QueryValue('Comments');
end;
finally
FreeMem(VerBuf, VerSize);
end;
end;
Dzięki temu kodowi możesz pobrać wiele informacji z pliku wykonywalnego; Podobny do tego kod napisał dla mnie kiedyś @Opi, ten jest przerobiony na własne potrzeby; Myślę, że @Opi nie będzie miał nic przeciwko, jak udostępnię go :)
- Rejestracja:około 13 lat
- Ostatnio:ponad 12 lat
- Postów:4
Mam jeszcze jeden problem tyle, że w C++. Otóż funkcja (której kod przedstawiam poniżej) zamiast ustawionego przeze mnie numeru wersji zawraca (zawsze) wartości odpowiednio:
V1 = 65535
V2 = 65534
V3 = 0
V4 = 0
W opcjach projektu miałem ustawione 3.3.3.3
Oto kod funkcji:
void GetAppVersion(DWORD &V1, DWORD &V2, DWORD &V3, DWORD &V4)
{
//give your application full path
LPTSTR lpszFilePath = g_CmdLine;
DWORD dwDummy;
DWORD dwFVISize = GetFileVersionInfoSize( lpszFilePath , &dwDummy );
LPBYTE lpVersionInfo = new BYTE[dwFVISize];
GetFileVersionInfo( lpszFilePath , 0 , dwFVISize , lpVersionInfo );
UINT uLen;
VS_FIXEDFILEINFO *lpFfi;
VerQueryValue( lpVersionInfo , _T("\\") , (LPVOID *)&lpFfi , &uLen );
DWORD dwFileVersionMS = lpFfi->dwFileVersionMS;
DWORD dwFileVersionLS = lpFfi->dwFileVersionLS;
delete [] lpVersionInfo;
V1 = HIWORD(dwFileVersionMS);
V2 = LOWORD(dwFileVersionMS);
V3 = HIWORD(dwFileVersionLS);
V4 = LOWORD(dwFileVersionLS);
}
Wrzuć ten kod do działu 4programmers.net » Forum » C/C++ to może Ci ktoś pomoże; W tym dziale rozwiązuje się problemy w języku Object Pascal & Pascal;
Jeśli nie wiesz co się dzieje - uruchom debuger;
- Rejestracja:ponad 16 lat
- Ostatnio:12 dni
oksik napisał(a):
Witam wszystkich
Mam takie pytanko każdy zamieszcza jak można odczytać wersję, COmpanyName itp
A jak zmienić w pliku np dll CompanyName?
http://www.wilsonc.demon.co.uk/files/d10/ResourceUtils100.zip

- Rejestracja:około 13 lat
- Ostatnio:2 miesiące
- Lokalizacja:Łódź
- Postów:648
A nie możesz sobie zrobić stałej z wersją programu? Jak i tak wpisujesz to w środowisku to zamiast w środowisku wpisz do stałej.
program qwer;
const
version = '1.2.3.4';
begin
end.
- Rejestracja:ponad 21 lat
- Ostatnio:ponad rok
Widzicie budowa w resourcach wersji i innych właściwości wygląda mniej więcej tak:
1 VERSIONINFO
FILEVERSION 1,9,0,29
PRODUCTVERSION 1,9,0,29
FILEOS 0x4
FILETYPE 0x1
FILESUBTYPE 0x0L
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE "CompanyName", ""
VALUE "FileDescription", ""
VALUE "FileVersion", ""
VALUE "InternalName", ""
VALUE "LegalCopyright", ""
VALUE "LegalTrademarks", ""
VALUE "OriginalFilename", ""
VALUE "ProductName", ""
VALUE "ProductVersion", "1.9.0\0"
VALUE "Comments",""
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409, 1252
}
}
chodzi mi o to żeby się dobrać do tego blocku BLOCK "040904E4" a konkretnie do której kolwiek wartości. To co mówicie jest jak najbardziej ok ale potrzebuje zmieniać wersję DLL z kodu programu.
dodanie znacznika <code> - fp