Cosmin3 Posted October 2, 2010 Author Share Posted October 2, 2010 (edited) @Cosmin3That would sure help some people around hereI look forward to testing it ;-)Ok First version. Only for tests!The code (compiled in Delphi 7):program SetVM;uses Windows, SysUtils;{$R *.res}type TMemoryStatusEx = packed record dwLength: DWORD; dwMemoryLoad: DWORD; ullTotalPhys: Int64; ullAvailPhys: Int64; ullTotalPageFile: Int64; ullAvailPageFile: Int64; ullTotalVirtual: Int64; ullAvailVirtual: Int64; ullAvailExtendedVirtual: Int64; end;function GlobalMemoryStatusEx(var lpBuffer: TMemoryStatusEx): BOOL; stdcall; external kernel32;var MS: TMemoryStatusEx; CurrStr, StrToChg: AnsiString; hTemp: HKEY; WinPath: array[0..MAX_PATH + 1] of char; Result: Boolean; FreeAv, TotalAv, VMSize, CurrVal: Int64; p: Integer; Buf: Pointer; BufSize: Cardinal; ValType: DWORD; sr: TSearchRec;begin Result := False; CurrVal := 0; try MS.dwLength := SizEof(TMemoryStatusEx); GlobalMemoryStatusEx(MS); if MS.ullTotalPhys < 134217728 then VMSize := 201326592 else VMSize := Round(1.5 * MS.ullTotalPhys); WinPath[0] := #0; if GetWindowsDirectory(WinPath, MAX_PATH) = 0 then Exit; if not GetDiskFreeSpaceEx(PChar(WinPath[0] + ':\'), FreeAv, TotalAv, nil) then Exit; if FreeAv = 0 then Exit; try if RegOpenKeyEx(HKEY_LOCAL_MACHINE, PChar('SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management'), 0, KEY_READ, hTemp) = ERROR_SUCCESS then begin if RegQueryValueEx(hTemp, PChar('PagingFiles'), nil, @ValType, nil, @BufSize) = ERROR_SUCCESS then begin GetMem(Buf, BufSize); try if RegQueryValueEx(hTemp, PChar('PagingFiles'), nil, @ValType, Buf, @BufSize) = ERROR_SUCCESS then if BufSize > 0 then begin CurrStr := PChar(Buf); p := Pos(' ', CurrStr); Delete(CurrStr, p, Length(CurrStr) - p + 1); if CurrStr <> '' then if CharLower(PChar(CurrStr[1])) = CharLower(PChar(WinPath[0])) then begin if FindFirst(CurrStr, faAnyFile, sr) = 0 then CurrVal := Int64(sr.FindData.nFileSizeHigh) shl Int64(32) + Int64(sr.FindData.nFileSizeLow); FindClose(sr); end; end; finally FreeMem(Buf); end; end; RegCloseKey(hTemp); end; except end; if (FreeAv + CurrVal) <= VMSize then Exit; StrToChg := WinPath[0] + ':\pagefile.sys ' + IntToStr(Round(VMSize / 1048576)) + ' ' + IntToStr(Round(VMSize / 1048576)); try if RegCreateKeyEx(HKEY_LOCAL_MACHINE, PChar('SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management'), 0, nil, REG_OPTION_NON_VOLATILE, KEY_WRITE, nil, hTemp, nil) = ERROR_SUCCESS then begin Result := RegSetValueEx(hTemp, PChar('PagingFiles'), 0, REG_MULTI_SZ, PChar(StrToChg + #0#0), Length(StrToChg) + 2) = ERROR_SUCCESS; RegCloseKey(hTemp); end; except end; finally if not Result then MessageBox(0, 'Unable to set Virtual Memory values automatically'#13#10'Please set them manually!', 'SetVM', MB_ICONERROR or MB_OK); end;end.I attached the exe file. Just run it and if there is no error message restart Windows.Remember to backup your registry first, just in case Anyway, on my computer works fine.Later edit: I made 2 small changes:- The VM size is no longer limited to 4 GB;- The exe file is a little smaller (I removed Math Unit).Unfortunatelly, for now, this program can be used in 64 bit operating system only when the size of Ram is < 4 GB.It is a limitation of GlobalMemoryStatus function (from kernel32.dll) who can return a 32 bit value (4 GB - 1).I will try to find a better function.Later later edit: I solved also the problem with GlobalMemoryStatus: I used GlobalMemoryStatusEx. Microsoft says that it should work fine.But I can't test it, because I have only 2 GB.Oh, and I also made the code to get the size of the current virtual memory file on the system drive.SetVM.zip Edited October 2, 2010 by Cosmin3 Link to comment Share on other sites More sharing options...
Sp0iLedBrAt Posted October 2, 2010 Share Posted October 2, 2010 So, from what I see, you have set pagefile size to be constructed as physically available RAM x 1.5.In numbers: I have 768MB, but 751 are usable (shared video card) So, 751x1.5=1126.5, and I got 1127.Conclusion: Congrats! It worked for meP.S. A small insight on how some other members do it; for example, cluberti has posted this http://www.cluberti.com/blog/2010/06/17/pagefile-vbs-for-vistawin7-systems-may-work-on-xp2003-not-tested/ in .vbs to be run with cscript.Now, pagefile.sys is set by default to be created on the system drive (normally c:\), but I wonder if it could also be split on two drives, like I normally do it. Link to comment Share on other sites More sharing options...
Cosmin3 Posted October 2, 2010 Author Share Posted October 2, 2010 So, from what I see, you have set pagefile size to be constructed as physically available RAM x 1.5.In numbers: I have 768MB, but 751 are usable (shared video card) So, 751x1.5=1126.5, and I got 1127.Conclusion: Congrats! It worked for meYou're welcome.Now, pagefile.sys is set by default to be created on the system drive (normally c:\), but I wonder if it could also be split on two drives, like I normally do it.When you say "two drives" you mean two physical drives or 2 logical drives (on the same physical drive)..? Link to comment Share on other sites More sharing options...
Sp0iLedBrAt Posted October 2, 2010 Share Posted October 2, 2010 (edited) When you say "two drives" you mean two physical drives or 2 logical drives (on the same physical drive)..? In my case, I have one primary partition on one HDD (apart from the system drive), but will it be any different if there are two separate HDDs? If more explanation is needed, I mainly divide pagefile.sys because of free space; a small amount (256MB, for example) on C:\ and the rest on D:\Cheers Edited October 2, 2010 by Sp0iLedBrAt Link to comment Share on other sites More sharing options...
Cosmin3 Posted October 2, 2010 Author Share Posted October 2, 2010 In my case, I have one primary partition on one HDD (apart from the system drive), but will it be any different if there are two separate HDDs? If more explanation is needed, I mainly divide pagefile.sys because of free space; a small amount (256MB, for example) on C:\ and the rest on D:\CheersFor my program no, I asked only because having 2 or more pagefiles on the same physical drive is not good (slower access).Ok, I'll let you choose a way to implement (configuration file or command line parameters) and the "syntax" to be used It should be easy to understand and use... Link to comment Share on other sites More sharing options...
Cosmin3 Posted October 2, 2010 Author Share Posted October 2, 2010 (edited) Version 2.0 program SetVM;uses Windows, SysUtils, StrUtils;{$R *.res}type TMemoryStatusEx = packed record dwLength: DWORD; dwMemoryLoad: DWORD; ullTotalPhys: Int64; ullAvailPhys: Int64; ullTotalPageFile: Int64; ullAvailPageFile: Int64; ullTotalVirtual: Int64; ullAvailVirtual: Int64; ullAvailExtendedVirtual: Int64; end;type TCurrVal = record Drive: Char; Size: Int64; end;function GlobalMemoryStatusEx(var lpBuffer: TMemoryStatusEx): BOOL; stdcall; external kernel32;var MS: TMemoryStatusEx; CurrStr, StrToChg, IniName, s: AnsiString; hTemp: HKEY; WinPath: array[0..MAX_PATH + 1] of char; Result: Boolean; FreeAv, TotalAv, VMSize, CurrVal: Int64; i, j, p, l, NrDefVal: Integer; Buf: Pointer; BufSize: Cardinal; ValType: DWORD; sr: TSearchRec; CurrValA, FtValA: array of TCurrVal; t: TextFile;begin Result := False; try try //tries to read the current configuration if RegOpenKeyEx(HKEY_LOCAL_MACHINE, PChar('SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management'), 0, KEY_READ, hTemp) = ERROR_SUCCESS then begin if RegQueryValueEx(hTemp, PChar('PagingFiles'), nil, @ValType, nil, @BufSize) = ERROR_SUCCESS then //query buffer size begin GetMem(Buf, BufSize); try if RegQueryValueEx(hTemp, PChar('PagingFiles'), nil, @ValType, Buf, @BufSize) = ERROR_SUCCESS then if BufSize > 0 then begin CurrStr := AnsiLowerCase(string(Buf)); SetLength(CurrValA, 0); i := -1; p := Pos('pagefile.sys', CurrStr); while p > 0 do //recursive search for each pagefile begin Inc(i); SetLength(CurrValA, i + 1); CurrValA[i].Drive := CurrStr[p - 3]; //get the actual size of the pagefiles if FindFirst(Copy(CurrStr, p - 3, 15), faAnyFile, sr) = 0 then CurrValA[i].Size := Int64(sr.FindData.nFileSizeHigh) shl Int64(32) + Int64(sr.FindData.nFileSizeLow); FindClose(sr); p := PosEx('pagefile.sys', CurrStr, p + 12); end; end; finally FreeMem(Buf); end; end; RegCloseKey(hTemp); end; except end; StrToChg := ''; //get the Ram informations MS.dwLength := SizEof(TMemoryStatusEx); GlobalMemoryStatusEx(MS); if MS.ullTotalPhys < 134217728 then // if RAM size is lower than 128 MB (most probably a reading bug) VMSize := 201326592 else VMSize := Round(1.5 * MS.ullTotalPhys); IniName := Copy(ParamStr(0), 1, Length(ParamStr(0)) - 3) + 'ini'; if FileExists(IniName) then //if configuration file exists begin //reads the configuration file AssignFile(t, IniName); FileMode := 0; i := -1; NrDefVal := 0; SetLength(FtValA, 0); try Reset(t); while not Eof(t) do begin Readln(t, s); if Pos('#', s) = 1 then Continue; l := Length(s); if l > 2 then if (s[1] in ['a'..'z']) or (s[1] in ['A'..'Z']) then if s[2] = '=' then begin Inc(i); SetLength(FtValA, i + 1); if s[1] in ['a'..'z'] then FtValA[i].Drive := s[1] else FtValA[i].Drive := Char(Byte(s[1]) + 32); if s[3] = '*' then begin FtValA[i].Size := -1; Inc(NrDefVal); end else FtValA[i].Size := StrToInt64def(Copy(s, 3, l - 2), 0) * 1048576; end; end; except end; CloseFile(t); if i = -1 then Exit; if NrDefVal > 0 then //if the number of * is at least 1 begin for i := 0 to High(FtValA) do if FtValA[i].Size <> -1 then VMSize := VMSize - FtValA[i].Size; //calculate the default size for i := 0 to High(FtValA) do begin //assignes default values when * is used if FtValA[i].Size = -1 then FtValA[i].Size := Round(VMSize / NrDefVal); //if assigned value is 0 or negative then it's a problem if Round(FtValA[i].Size / 1048576) < 1 then Exit; end; end; for i := 0 to High(FtValA) do //for each drive begin if not GetDiskFreeSpaceEx(PChar(FtValA[i].Drive + ':\'), FreeAv, TotalAv, nil) then //can't read free disk space (drive/OS error) Exit; if FreeAv = 0 then //no free space on that drive; most probably a drive error or a read-only one... Exit; j := 0; while j < Length(CurrValA) do //search for records about current pagefile on that drive begin if CurrValA[j].Drive = FtValA[i].Drive then Break; Inc(j); end; //tests if the new pagefile fits if j < Length(CurrValA) then begin if (FreeAv + CurrValA[i].Size) <= FtValA[i].Size then Exit; end else if FreeAv <= FtValA[i].Size then Exit; //text to change in registry StrToChg := StrToChg + FtValA[i].Drive + ':\pagefile.sys ' + IntToStr(Round(FtValA[i].Size / 1048576)) + ' ' + IntToStr(Round(FtValA[i].Size / 1048576)) + #0; end; Delete(StrToChg, Length(StrToChg), 1); //delete unused #0 at the end end else begin //no configuration found so it sets one file on Windows drive WinPath[0] := #0; if GetWindowsDirectory(WinPath, MAX_PATH) = 0 then //can't read the name of Windows folder (drive/OS error) Exit; if not GetDiskFreeSpaceEx(PChar(WinPath[0] + ':\'), FreeAv, TotalAv, nil) then //can't read free disk space (drive/OS error) Exit; if FreeAv = 0 then //no free space on that drive; most probably a drive error or a read-only one... Exit; WinPath[0] := Char(CharLower(PChar(WinPath[0]))); i := 0; CurrVal := 0; while i < Length(CurrValA) do //search for records about current pagefile on Windows drive begin if CurrValA[i].Drive = WinPath[0] then begin CurrVal := CurrValA[i].Size; Break; end; Inc(i); end; //tests if the new pagefile fits if (FreeAv + CurrVal) <= VMSize then Exit; //text to change in registry StrToChg := WinPath[0] + ':\pagefile.sys ' + IntToStr(Round(VMSize / 1048576)) + ' ' + IntToStr(Round(VMSize / 1048576)); end; //tries to write in registry try if RegCreateKeyEx(HKEY_LOCAL_MACHINE, PChar('SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management'), 0, nil, REG_OPTION_NON_VOLATILE, KEY_WRITE, nil, hTemp, nil) = ERROR_SUCCESS then begin Result := RegSetValueEx(hTemp, PChar('PagingFiles'), 0, REG_MULTI_SZ, PChar(StrToChg + #0#0), Length(StrToChg) + 2) = ERROR_SUCCESS; RegCloseKey(hTemp); end; except end; finally if not Result then //some error happened so it shows a message MessageBox(0, 'Unable to set Virtual Memory values automatically'#13#10'Please set them manually!', 'SetVM', MB_ICONERROR or MB_OK); end;end.Configuration is set in SetVM.ini:C=300D=*The user can set the size directly (in MB) or * for the default value.If the ini file is missing it sets like in previous version.SetVM.zip Edited October 3, 2010 by Cosmin3 Link to comment Share on other sites More sharing options...
Sp0iLedBrAt Posted October 3, 2010 Share Posted October 3, 2010 You were right, it just can't get any simpler that this All we need now is someone with more understanding of the XP install process to tell us if it can be run through RunOnce.Keep up the good work Link to comment Share on other sites More sharing options...
Cosmin3 Posted October 3, 2010 Author Share Posted October 3, 2010 You were right, it just can't get any simpler that this All we need now is someone with more understanding of the XP install process to tell us if it can be run through RunOnce.Keep up the good work I tested it...I made an $OEM$\$$\Temp\ folder on XP installation CD and I copied the files in it.At Unattended >> RunOnce section in nlite I added %windir%\Temp\SetVM.exe.During installation I didn't see any error message.It seems it worked: Link to comment Share on other sites More sharing options...
Sp0iLedBrAt Posted October 3, 2010 Share Posted October 3, 2010 Cool!I was thinking of putting in a batch file and doing something likeREM Setting virtual memorystart /wait %source%$OEM$\VM\setVM.exe because I was interested whether it would work if it was run before the actual first logon.I'll test this too and get back.Cheers Link to comment Share on other sites More sharing options...
Cosmin3 Posted October 3, 2010 Author Share Posted October 3, 2010 Cool!I was thinking of putting in a batch file and doing something likeREM Setting virtual memorystart /wait %source%$OEM$\VM\setVM.exe because I was interested whether it would work if it was run before the actual first logon.I'll test this too and get back.CheersI tried myself with "%source%" a few weeks ago (for other program) but this environment variable isn't recognized after the installation is over.Anyway, even if it works when installing from CD, surely it won't work when installing from USB stick. Link to comment Share on other sites More sharing options...
johnhc Posted October 4, 2010 Share Posted October 4, 2010 I tried myself with "%source%" a few weeks ago (for other program) but this environment variable isn't recognized after the installation is over.Anyway, even if it works when installing from CD, surely it won't work when installing from USB stick.Cosmin3, please see nLite.cmd (compressed into NLITE.CM_) for how nLite determines %Source%. An even more transparent way is common around here that I copied:for %%i in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if exist %%i:\sources\install.wim set CDROM=%%i: Just change the file name to something unique on the drive you are interesting on getting the letter. Enjoy, John. Link to comment Share on other sites More sharing options...
Cosmin3 Posted October 4, 2010 Author Share Posted October 4, 2010 (edited) Cosmin3, please see nLite.cmd (compressed into NLITE.CM_) for how nLite determines %Source%.I found it only as "c:\WINDOWS\system32\nlite.cmd". I couldn't find it in installation files as nlite.cm_ (or anywhere else for that matter).I kept only the first line:for /f "tokens=3" %%i IN ('reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup /v "SourcePath" ^| findstr "REG_SZ"') do set SOURCE=%%iIt gives me a temporary %source% variable (set on my system as "E:"). But soon as I close cmd window, it's gone.Anyway it doesn't work with USB stick installation because, obviously, the CD ain't there...An even more transparent way is common around here that I copied:for %%i in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if exist %%i:\sources\install.wim set CDROM=%%i: Just change the file name to something unique on the drive you are interesting on getting the letter. Enjoy, John.I will use it like this:for %%i in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if exist %%i:\SetVM\SetVM.exe %%i:\SetVM\SetVM.exeBut the problem is that I have to use a *.cmd file for this command, which I have to place it in a $OEM$ folder so I can run it. This is what I tried to avoid in the first place...But thank you. Edited October 4, 2010 by Cosmin3 Link to comment Share on other sites More sharing options...
Sp0iLedBrAt Posted October 4, 2010 Share Posted October 4, 2010 (edited) I got it to work from RunOnce! The biggest problem I had was to create a partition and name it D:\ in VirtualBox, which I did by splitting the VHD, formatting one partition into NTFS (Quick) and then hitting restart. The procedure began again. This time I formatted the second partition (which was already in FAT32) into NTFS (Quick) and the newly formatted partition took drive letter C:\ when I installed on it. The recommended amount was 388MB, and I got 389MB.This is a snapshot of the end result Edited October 4, 2010 by Sp0iLedBrAt Link to comment Share on other sites More sharing options...
Cosmin3 Posted October 4, 2010 Author Share Posted October 4, 2010 I got it to work from RunOnce! The biggest problem I had was to create a partition and name it D:\ in VirtualBox, which I did by splitting the VHD, formatting one partition into NTFS (Quick) and then hitting restart. The procedure began again. This time I formatted the second partition (which was already in FAT32) into NTFS (Quick) and the newly formatted partition took drive letter C:\ when I installed on it. The recommended amount was 388MB, and I got 389MB.This is a snapshot of the end resultGlad to hear this Link to comment Share on other sites More sharing options...
Cosmin3 Posted November 2, 2010 Author Share Posted November 2, 2010 I'm back I have set Automatic Updates to "Notify me but don't automatically download or install them".When I install, in oobe is asking me to enable Automatic updates, which is pointless.How can I set it not to ask this, but keeping oobe...? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now