diff --git a/extra/SetVersion/SetVersion.dpr b/extra/SetVersion/SetVersion.dpr new file mode 100644 index 00000000..fbaa843a --- /dev/null +++ b/extra/SetVersion/SetVersion.dpr @@ -0,0 +1,164 @@ +program SetVersion; + +{$APPTYPE CONSOLE} + +uses + SysUtils, Windows, SynRegExpr, Classes; + +var + FileName, FileContent, Line, Revision, CurDir, SvnOutput, Cmd: String; + FileHandle: TextFile; + rx: TRegExpr; + SvnOutputLines: TStringList; + + +function RunConsoleAppWaitAndCapture(const cConsoleApp, cParameters, + cWorkingDir: string; aResults: TStringList): DWord; +var + SA: TSecurityAttributes; + SI: TStartupInfo; + PI: TProcessInformation; + hStdOut, hAppProcess, hAppThread: THandle; + cTemp, cTempFile: String; + aBuffer: Array[0..255] of Char; +begin + Result := 0; + hAppProcess := 0; + hAppThread := 0; + aResults.Clear; + + GetTempPath( 255, aBuffer ); + cTemp := StrPas( aBuffer ); + cTempFile := cTemp + 'stdout.tmp'; + if FileExists(cTempFile) then + SysUtils.DeleteFile( cTempFile ); + + // Initialize output file security attributes + FillChar(SA, SizeOf(SA), #0 ); + SA.nLength := SizeOf(SA); + SA.lpSecurityDescriptor := nil; + SA.bInheritHandle := true; + + // Create Output File + hStdOut := CreateFile(PChar(cTempFile), + GENERIC_READ or GENERIC_WRITE, + FILE_SHARE_READ or FILE_SHARE_WRITE, + @SA, + CREATE_ALWAYS, // Always create it + FILE_ATTRIBUTE_TEMPORARY or // Will cache in memory if possible + FILE_FLAG_WRITE_THROUGH, + 0); + if hStdOut = INVALID_HANDLE_VALUE then begin + ExitCode := 103; + Raise Exception.CreateFmt('Creating temporary stdout "'+cTempFile+'" file failed.', [cConsoleApp]); + end; + + // Initialize Startup Info + FillChar(SI, SizeOf(SI), #0); + with SI do begin + cb := SizeOf(SI); + dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; + wShowWindow := SW_HIDE; + hStdInput := GetStdHandle(STD_INPUT_HANDLE); + hStdError := hStdOut; + hStdOutput := hStdOut; + end; + + try + // Create the process + cTemp := cConsoleApp + ' ' + cParameters; + if CreateProcess(nil, + PChar( cTemp ), + nil, + nil, + true, + 0, + nil, + PChar(cWorkingDir), + SI, + PI + ) then begin + WaitforSingleObject( PI.hProcess, INFINITE ); + hAppProcess := PI.hProcess; + hAppThread := PI.hThread; + GetExitCodeProcess( hAppProcess, result ); + end else begin + ExitCode := 104; + Raise Exception.CreateFmt('CreateProcess() failed!'#10#13'Command line = %s', [cConsoleApp]); + end; + CloseHandle( hStdOut ); + + if FileExists(cTempFile) then begin + try + aResults.LoadFromFile(cTempFile); + except + on e:Exception do + WriteLn(e.Message); + end; + SysUtils.DeleteFile(cTempFile); + end; + + finally + if hAppProcess <> 0 then + CloseHandle(hAppProcess); + if hAppThread <> 0 then + CloseHandle(hAppThread); + end; +end; + + +begin + try + FileName := Paramstr(1); + if not FileExists(FileName) then begin + raise Exception.Create('File "'+FileName+'" is not a valid resource file.'); + ExitCode := 101; + end; + + // Read resource file + AssignFile(FileHandle, FileName); + Reset(FileHandle); + while not Eof(FileHandle) do begin + ReadLn(FileHandle, Line); + FileContent := FileContent + Line + #13#10; + end; + Delete(FileContent, Length(FileContent)-1, 2); + CloseFile(FileHandle); + + // Regular expression object + rx := TRegExpr.Create; + rx.ModifierI := True; + + // Find Subversion revision number + CurDir := ExtractFilePath(paramStr(0)); + SvnOutputLines := TStringList.Create; + Cmd := 'svnversion.exe'; + RunConsoleAppWaitAndCapture(Cmd, ExtractFilePath(ExpandFileName(FileName)), CurDir, SvnOutputLines); + SvnOutput := Trim(SvnOutputLines.Text); + // 123:123M + // 123M + // 123 + rx.Expression := '^(\d+\:)?(\d+)M?$'; + if rx.Exec(SvnOutput) then + Revision := rx.Match[2] + else begin + ExitCode := 102; + raise Exception.Create('Could not find SVN revision'); + end; + + // Inject revision into file content + rx.Expression := '(\bFILEVERSION\s\d+,\d+,\d+,)\d+(\b)'; + FileContent := rx.Replace(FileContent, '${1}'+Revision+'${2}', True); + rx.Free; + + // Save modified file + Rewrite(FileHandle); + WriteLn(FileHandle, FileContent); + CloseFile(FileHandle); + except + on E: Exception do + Writeln(E.ClassName, ': ', E.Message); + end; + +end. + diff --git a/extra/SetVersion/SetVersion.dproj b/extra/SetVersion/SetVersion.dproj new file mode 100644 index 00000000..57e987b1 --- /dev/null +++ b/extra/SetVersion/SetVersion.dproj @@ -0,0 +1,107 @@ + + + {2E249C21-5A3E-430F-AC5A-E8BAAF56C3FC} + 12.0 + SetVersion.dpr + Debug + DCC32 + + + true + + + true + Base + true + + + true + Base + true + + + SetVersion.exe + 00400000 + false + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias) + x86 + false + 0 + false + false + false + false + false + false + + + false + RELEASE;$(DCC_Define) + 0 + false + + + DEBUG;$(DCC_Define) + + + + MainSource + + + Base + + + Cfg_2 + Base + + + Cfg_1 + Base + + + + + Delphi.Personality.12 + + + + + SetVersion.dpr + + + False + True + False + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1031 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + 12 + + diff --git a/extra/SetVersion/SetVersion.exe b/extra/SetVersion/SetVersion.exe new file mode 100644 index 00000000..067e31a7 Binary files /dev/null and b/extra/SetVersion/SetVersion.exe differ diff --git a/extra/build_everything.cmd b/extra/build_everything.cmd index ba8e8e89..f9a4e825 100644 --- a/extra/build_everything.cmd +++ b/extra/build_everything.cmd @@ -25,7 +25,7 @@ echo. :test_dcc32 dcc32.exe --version >NUL: 2>NUL: -if %errorlevel% == 0 goto test_svn +if %errorlevel% == 0 goto test_libs :dcc32_not_found echo Error: Delphi compiler 'dcc32.exe' was not found in PATH. @@ -39,22 +39,6 @@ echo. pause > NUL: goto :eof -:test_svn -svnversion.exe --version >NUL: 2>NUL: -if %errorlevel% == 0 goto test_libs - -:svn_not_found -echo Error: Subversion executable 'svnversion.exe' was not found in PATH. -echo. -echo Please install Subversion. When installing, Subversion should modify -echo your system path to include the location of this file. -echo. -echo See also: -echo http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91^&filter=setup.exe -echo. -pause > NUL: -goto :eof - :locate_dcc32 if not "%compiler_dir%" == "none" goto :eof pushd %~f1 @@ -124,34 +108,8 @@ goto param_loop :param_done echo Base directory: %base_dir% echo Compiler directory: %compiler_dir% - -:find_wcver -rem Unix tool, may not handle Windows paths well, so go to base directory and use dot. -cd /d "%base_dir%" -for /f "usebackq" %%s in (`svnversion.exe . ^|^| ECHO unknown`) DO SET wcver=WC %%s -if "%wcver%" == "WC unknown" (set wcver=unknown) else (goto insert_wcver) - -:svnversion_failure -rem Non-fatal, continue if this happens. -echo. -echo Error: svnversion failed - run this step manually to see what went wrong? -echo. - -:insert_wcver -echo Version: %WCVER% -echo. -rem Put WC version or "unknown" into main.pas -"%base_dir%\extra\sed\sed.exe" "s/\$Revision.*\$/\$Revision: %WCVER% \$/g" -i "%base_dir%\source\main.pas" -if not %errorlevel% == 0 goto sedfail -"%base_dir%\extra\sed\sed.exe" "s/\$Rev[^i].*\$/\$Rev: %WCVER% \$/g" -i "%base_dir%\source\main.pas" -if not %errorlevel% == 0 goto sedfail goto start -:sedfail -echo Error: SED failure - run this step manually to see what went wrong? -echo. -goto end - :start rem Delete old binaries echo Cleaning build directories. @@ -198,6 +156,7 @@ if not %err% == 0 goto end rem Build main executable echo Compiling main project. cd /d "%base_dir%\packages\%package_dir%\" +..\..\extra\SetVersion\SetVersion.exe ..\..\res\version.rc brcc32 ..\..\res\version.rc brcc32 ..\..\res\icon.rc brcc32 ..\..\res\manifest.rc diff --git a/extra/sed/libiconv2.dll b/extra/sed/libiconv2.dll deleted file mode 100644 index 747073f1..00000000 Binary files a/extra/sed/libiconv2.dll and /dev/null differ diff --git a/extra/sed/libintl3.dll b/extra/sed/libintl3.dll deleted file mode 100644 index ec11e6b1..00000000 Binary files a/extra/sed/libintl3.dll and /dev/null differ diff --git a/extra/sed/sed.exe b/extra/sed/sed.exe deleted file mode 100644 index 6a1f9fd0..00000000 Binary files a/extra/sed/sed.exe and /dev/null differ diff --git a/packages/delphi2010/heidisql.dproj b/packages/delphi2010/heidisql.dproj index c03e63a5..6a9432a0 100644 --- a/packages/delphi2010/heidisql.dproj +++ b/packages/delphi2010/heidisql.dproj @@ -47,6 +47,7 @@ False + ..\..\res 3 ..\..\out\heidisql.exe 7.0 diff --git a/source/about.pas b/source/about.pas index 57e24516..52c7464d 100644 --- a/source/about.pas +++ b/source/about.pas @@ -100,7 +100,7 @@ begin MemoAuthors.Text := TrimRight(MemoAuthors.Text); // App-Version - LabelVersion.Caption := FullAppVersion; + LabelVersion.Caption := 'Version '+AppVersion; // Compile-date FileAge(ParamStr(0), Compiled); diff --git a/source/helpers.pas b/source/helpers.pas index bd90331f..a6cc654d 100644 --- a/source/helpers.pas +++ b/source/helpers.pas @@ -846,7 +846,7 @@ begin else NodeCount := Grid.RootNodeCount; EnableProgressBar(NodeCount); - Generator := APPNAME+' '+FullAppVersion; + Generator := APPNAME+' '+AppVersion; tmp := '' + CRLF + CRLF + diff --git a/source/main.pas b/source/main.pas index d2610f9c..272eded2 100644 --- a/source/main.pas +++ b/source/main.pas @@ -864,9 +864,8 @@ end; var MainForm : TMainForm; - AppVersion : String = '4.0'; - AppRevision : String = '$Rev$'; - FullAppVersion : String; + AppVerMajor, AppVerMinor, AppVerRelease, AppVerRevision: Integer; + AppVersion : String; DirnameCommonAppData, DirnameUserAppData, DirnameSnippets, @@ -1143,6 +1142,11 @@ var DisableProcessWindowsGhostingProc: procedure; QueryTab: TQueryTab; Action: TAction; + dwInfoSize, // Size of VERSIONINFO structure + dwVerSize, // Size of Version Info Data + dwWnd: DWORD; // Handle for the size call. + FI: PVSFixedFileInfo; // Delphi structure; see WINDOWS.PAS + ptrVerBuf: Pointer; // pointer to a version buffer begin caption := APPNAME; setLocales; @@ -1156,16 +1160,17 @@ begin refreshMonitorConfig; loadWindowConfig; - // Beautify AppRevision - if Pos('$Rev: WC', AppRevision) < 1 then - AppRevision := 'unknown' - else begin - AppRevision := StringReplace( AppRevision, '$Rev: WC', '', [rfIgnoreCase] ); - AppRevision := StringReplace( AppRevision, '$', '', [] ); - AppRevision := Trim( AppRevision ); - end; - // Compose full version string - FullAppVersion := 'Version ' + AppVersion + ', Revision ' + AppRevision; + // Detect version + dwInfoSize := GetFileVersionInfoSize(PChar(Application.ExeName), dwWnd); + GetMem(ptrVerBuf, dwInfoSize); + GetFileVersionInfo(PChar(Application.ExeName), dwWnd, dwInfoSize, ptrVerBuf); + VerQueryValue(ptrVerBuf, '\', Pointer(FI), dwVerSize ); + AppVerMajor := HiWord(FI.dwFileVersionMS); + AppVerMinor := LoWord(FI.dwFileVersionMS); + AppVerRelease := HiWord(FI.dwFileVersionLS); + AppVerRevision := LoWord(FI.dwFileVersionLS); + FreeMem(ptrVerBuf); + AppVersion := Format('%d.%d.%d.%d', [AppVerMajor, AppVerMinor, AppVerRelease, AppVerRevision]); // "All users" folder for HeidiSQL's data (All Users\Application Data) DirnameCommonAppData := GetShellFolder(CSIDL_COMMON_APPDATA) + '\' + APPNAME + '\'; @@ -1394,7 +1399,7 @@ begin end; if DaysBetween(Now, LastStatsCall) >= 30 then begin // Report used SVN revision - StatsURL := APPDOMAIN + 'savestats.php?c=' + AppRevision; + StatsURL := APPDOMAIN + 'savestats.php?c=' + IntToStr(AppVerRevision); // Enumerate actively used server versions SessionNames := TStringlist.Create; if MainReg.OpenKey(REGPATH + REGKEY_SESSIONS, true) then @@ -1411,7 +1416,7 @@ begin end; StatsCall := TDownloadUrl2.Create(Self); StatsCall.URL := StatsURL; - StatsCall.SetUserAgent(APPNAME + ' ' + FullAppVersion); + StatsCall.SetUserAgent(APPNAME + ' ' + AppVersion); try StatsCall.ExecuteTarget(nil); OpenRegistry; @@ -8488,7 +8493,7 @@ begin Cap := Cap + ' /' + ActiveDatabase; if SelectedTable.Name <> '' then Cap := Cap + '/' + SelectedTable.Name; - Cap := Cap + ' - ' + APPNAME + ' ' + FullAppVersion; + Cap := Cap + ' - ' + APPNAME + ' ' + AppVersion; Caption := Cap; Application.Title := Cap; end; diff --git a/source/tabletools.pas b/source/tabletools.pas index b056996f..458869f7 100644 --- a/source/tabletools.pas +++ b/source/tabletools.pas @@ -961,7 +961,7 @@ begin WideFormat('# %-30s%s', ['Database:', DBObj.Database]) + CRLF + WideFormat('# %-30s%s', ['Server version:', Mainform.Connection.ServerVersionUntouched]) + CRLF + WideFormat('# %-30s%s', ['Server OS:', Mainform.Connection.GetVar('SHOW VARIABLES LIKE ' + esc('version_compile_os'), 1)]) + CRLF + - WideFormat('# %-30s%s', [APPNAME + ' version:', FullAppVersion]) + CRLF + + WideFormat('# %-30s%s', [APPNAME + ' version:', AppVersion]) + CRLF + WideFormat('# %-30s%s', ['Date/time:', DateTimeToStr(Now)]) + CRLF + '# --------------------------------------------------------' + CRLF + CRLF + '/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;' + CRLF + diff --git a/source/updatecheck.pas b/source/updatecheck.pas index c25b5c36..a9a0a88c 100644 --- a/source/updatecheck.pas +++ b/source/updatecheck.pas @@ -37,7 +37,7 @@ type public { Public declarations } AutoClose: Boolean; // Automatically close dialog after detecting no available downloads - CurrentRevision, BuildRevision: Integer; + BuildRevision: Integer; CheckForBuildsInAutoMode: Boolean; BuildSize: Integer; end; @@ -95,7 +95,6 @@ procedure TfrmUpdateCheck.FormShow(Sender: TObject); begin Status('Initiating ... '); Caption := 'Check for '+APPNAME+' updates ...'; - CurrentRevision := StrToIntDef(AppRevision, 0); // Init GUI controls btnRelease.Enabled := False; @@ -105,8 +104,8 @@ begin // Prepare download CheckfileDownload := TDownLoadURL2.Create(Self); - CheckfileDownload.SetUserAgent(APPNAME + ' ' + APPVERSION + ' ' + APPREVISION + ' update checker tool'); - CheckfileDownload.URL := APPDOMAIN + 'updatecheck.php?r='+APPREVISION; + CheckfileDownload.SetUserAgent(APPNAME + ' ' + AppVersion + ' update checker tool'); + CheckfileDownload.URL := APPDOMAIN + 'updatecheck.php?r='+IntToStr(AppVerRevision); CheckfileDownload.Filename := GetTempDir + APPNAME + '_updatecheck.ini'; // Download the check file @@ -118,9 +117,9 @@ begin ReadCheckFile; // Developer versions probably have "unknown" (0) as revision, // which makes it impossible to compare the revisions. - if CurrentRevision = 0 then + if AppVerRevision = 0 then Status('Error: Cannot determine current revision. Using a developer version?') - else if CurrentRevision = BuildRevision then + else if AppVerRevision = BuildRevision then Status('Your '+APPNAME+' is up-to-date (no update available).') else if groupRelease.Enabled or btnBuild.Enabled then Status('Updates available.'); @@ -174,7 +173,7 @@ begin memoRelease.Lines.Add( 'Note: ' + Note ); btnRelease.Caption := 'Download version ' + ReleaseVersion; // Enable the download button if the current version is outdated - groupRelease.Enabled := ReleaseRevision > CurrentRevision; + groupRelease.Enabled := ReleaseRevision > AppVerRevision; btnRelease.Enabled := groupRelease.Enabled; memoRelease.Enabled := groupRelease.Enabled; if not memoRelease.Enabled then @@ -188,7 +187,7 @@ begin BuildRevision := Ini.ReadInteger(INISECT_BUILD, 'Revision', 0); BuildURL := Ini.ReadString(INISECT_BUILD, 'URL', ''); BuildSize := Ini.ReadInteger(INISECT_BUILD, 'Size', 0); - memoBuild.Lines.Add( 'Revision ' + IntToStr(BuildRevision) + ' (yours: '+AppRevision+')' ); + memoBuild.Lines.Add( 'Revision ' + IntToStr(BuildRevision) + ' (yours: '+IntToStr(AppVerRevision)+')' ); FileAge(ParamStr(0), Compiled); memoBuild.Lines.Add( 'Compiled: ' + Ini.ReadString(INISECT_BUILD, 'Date', '') + ' (yours: '+DateToStr(Compiled)+')' ); Note := Ini.ReadString(INISECT_BUILD, 'Note', ''); @@ -198,7 +197,7 @@ begin // A new release should have priority over a new nightly build. // So the user should not be able to download a newer build here // before having installed the new release. - btnBuild.Enabled := (CurrentRevision = 0) or ((BuildRevision > CurrentRevision) and (not btnRelease.Enabled)); + btnBuild.Enabled := (AppVerRevision = 0) or ((BuildRevision > AppVerRevision) and (not btnRelease.Enabled)); end; end;