PsaltyDS Posted June 6, 2006 Share Posted June 6, 2006 I have a simple function that is part of a much larger install script. I have to change the 'noexecute' option in boot.ini from AlwaysOff to OptOut. I get errors everytime I try to write to the boot.ini file at the end of the function. The attributes are changed (no longer hidden or read only), but the script still gets an error and I have to edit it manualy. Anyone got an idea on why this doesn't work? ;-------------------------------------- ; Function _BootIni() ; Edit Boot.ini for noexecute option ;-------------------------------------- Func _BootIni() Local $avBootIni[1] Local $n, $iChange = 0 ; Remove Hidden and Readonly attributes of boot.ini file If Not FileSetAttrib("C:\Boot.ini", "-HR") Then MsgBox(16, "Error!", "Error changing attributes of C:\Boot.ini!") ; Read Boot.ini into array If _FileReadToArray("C:\Boot.ini", $avBootIni) Then ; Edit noexecute line For $n = 1 To $avBootIni[0] If StringInStr($avBootIni[$n], "noexecute=AlwaysOff") Then $avBootIni[$n] = StringReplace($avBootIni[$n], "noexecute=AlwaysOff", "noexecute=OptOut") $iChange = 1 EndIf Next Else MsgBox(16, "Error!", "Error reading C:\Boot.ini to array! Edit '/noexecute=OptOut' manualy!") Return 0 EndIf ; Write change, if required If $iChange Then If Not _FileWriteFromArray("C:\Boot.ini", $avBootIni, 1) Then MsgBox(16, "Error!", "Error writing to C:\Boot.ini! Edit '/noexecute=OptOut' manualy!") EndIf EndIf EndFunc ;==>_BootIni Sample boot.ini: [boot loader] timeout=3 default=multi(0)disk(0)rdisk(0)partition(1)\WINNT [operating systems] multi(0)disk(0)rdisk(0)partition(1)\WINNT="Windows Server 2003, Standard" /noexecute=AlwaysOff /fastdetect I get the message for "Error writing to C:\Boot.ini!" every time, but then have no trouble editing it with notepad after the script is done. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 7, 2006 Author Share Posted June 7, 2006 Bump... anybody? Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Nomad Posted June 7, 2006 Share Posted June 7, 2006 ; Write change, if required If $iChange Then If Not _FileWriteFromArray("C:\Boot.ini", $avBootIni, 1) Then MsgBox(16, "Error!", "Error writing to C:\Boot.ini! Edit '/noexecute=OptOut' manualy!") EndIf EndIf EndFunc ;==>_BootIni Well, obviously the error must be occuring somewhere inside this UDF, and you have thissetup as a boolean type function where it is either true or false. If it is false then the file did not write and your msgbox pops up. You should first eliminate the possibility that $avBootIni is not an array with IsArray(). If it is not an array then it will return a false message causing the UDF to terminate and popping up your msgbox. If it is in fact an array, then I would try removing the 1 at the end of: If Not _FileWriteFromArray("C:\Boot.ini", $avBootIni, 1) and make it like this: If Not _FileWriteFromArray("C:\Boot.ini", $avBootIni) See if that works. If that doesn't work then I don't know what else it could be, but it has to have something to do with the UDF or the info being sent to it. There is no other reason for the msgbox to pop up, the function must return false to make it pop up. I hope this helps, Nomad Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 7, 2006 Author Share Posted June 7, 2006 Well, obviously the error must be occuring somewhere inside this UDF, and you have thissetup as a boolean type function where it is either true or false. If it is false then the file did not write and your msgbox pops up. You should first eliminate the possibility that $avBootIni is not an array with IsArray(). If it is not an array then it will return a false message causing the UDF to terminate and popping up your msgbox. If it is in fact an array, then I would try removing the 1 at the end of: If Not _FileWriteFromArray("C:\Boot.ini", $avBootIni, 1) and make it like this: If Not _FileWriteFromArray("C:\Boot.ini", $avBootIni) See if that works. If that doesn't work then I don't know what else it could be, but it has to have something to do with the UDF or the info being sent to it. There is no other reason for the msgbox to pop up, the function must return false to make it pop up. I hope this helps, Nomad Thanks for looking, but I'm pretty satisfied that the array reference is straight. $avBootIni is declared as a local 1D array by the first active line of the function. It is then populated six lines later by _FileReadToArray(), which puts the line count at index [0], therefor starting at index [1] for the _FileWriteFromArray() function. You did give me an idea though. When I get to work (and windows box) tomorrow, I'll crack open the _FileWriteFromArray() function itself and see if I can tease out some more info on why it returns 0. The boot.ini is being modified for the first time at this point in the script, and the function does change the attributes correctly with FileSetAttrib(), but when it comes time to write from the array it acts as though still readonly... :-( Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
gamepin126 Posted June 7, 2006 Share Posted June 7, 2006 Isn't boot.ini read only? Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 7, 2006 Author Share Posted June 7, 2006 Isn't boot.ini read only?...and hidden, but the FileSetAttrib() function removes those attributes. And that part works, because I go straight in after the script fails to write it and view the changed attributes and make the change manually with Notepad. :-( Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Nomad Posted June 7, 2006 Share Posted June 7, 2006 (edited) I've tried it myself and it appears to be working correctly as far as I can tell. If the Boot.ini contains the string, "/noexecute=AlwaysOff" the function rewrites it to, "/noexecute=OptOut". I assume that this is what this function should be doing. If it is then it works flawlessly for me. Maybe there is a different problem on your end, like the file is open or something. I get a "true" return from the _FileWriteFromArray UDF. I'd check elsewhere besides your function, I see nothing wrong with it. Or maybe make sure the UDF's haven't been modified from their original syntax. Nomad Edit: Here is an unaltered version of the UDF expandcollapse popup;=============================================================================== ; ; Description: Write array to File. ; Syntax: _FileWriteFromArray( $sFilePath, $aArray ) ; Parameter(s): $sFilePath - Path and filename of the file to be written ; $a_Array - The array to retrieve the contents ; $i_Base - Start reading at this Array entry. ; $I_Ubound - End reading at this Array entry. ; Default UBound($a_Array) - 1 ; Requirement(s): None ; Return Value(s): On Success - Returns 1 ; On Failure - Returns 0 and sets @error = 1 ; Author(s): Jos van der Zande <jdeb at autoitscript dot com> ; Note(s): None ; ;=============================================================================== Func _FileWriteFromArray($sFilePath, $a_Array, $i_Base = 0, $i_UBound = 0) ;============================================== ; Local Constant/Variable Declaration Section ;============================================== Local $hFile ; Check if we have a valid array as input If Not IsArray($a_Array) Then SetError(2) Return 0 EndIf ; determine last entry Local $last = UBound($a_Array) - 1 If $i_UBound < 1 Or $i_UBound > $last Then $i_UBound = $last If $i_Base < 0 Or $i_Base > $last Then $i_Base = 0 ; Open output file $hFile = FileOpen($sFilePath, 2) If $hFile = -1 Then SetError(1) Return 0 EndIf ; FileWrite($hFile, $a_Array[$i_Base]) For $x = $i_Base + 1 To $i_UBound FileWrite($hFile, @CRLF & $a_Array[$x]) Next FileClose($hFile) Return 1 EndFunc ;==>_FileWriteFromArray It's also possible that the write protection is not being removed for another reason. As you can see, if the write fails, it also returns a "false". But like I said, I had no problems. Edited June 7, 2006 by Nomad Link to comment Share on other sites More sharing options...
Jimbeau Posted June 19, 2006 Share Posted June 19, 2006 I wanted to do this also, so I modified your code. Your error went away when I changed the System and Archive Attributes. expandcollapse popup;-------------------------------------- ; Function _BootIni() ; Edit Boot.ini for noexecute option ;-------------------------------------- #include <File.au3> #include <Array.au3> Func _FileWriteFromArray($sFilePath, $a_Array, $i_Base = 0, $i_UBound = 0) ;============================================== ; Local Constant/Variable Declaration Section ;============================================== Local $hFile ; Check if we have a valid array as input If Not IsArray($a_Array) Then SetError(2) Return 0 EndIf ; determine last entry Local $last = UBound($a_Array) - 1 If $i_UBound < 1 Or $i_UBound > $last Then $i_UBound = $last If $i_Base < 0 Or $i_Base > $last Then $i_Base = 0 ; Open output file $hFile = FileOpen($sFilePath, 2) If $hFile = -1 Then SetError(1) Return 0 EndIf ; FileWrite($hFile, $a_Array[$i_Base]) For $x = $i_Base + 1 To $i_UBound FileWrite($hFile, @CRLF & $a_Array[$x]) Next FileClose($hFile) Return 1 EndFunc ;==>_FileWriteFromArray Func _BootIni() Local $avBootIni[1] Local $n, $iChange = 0 ; Remove Hidden and Readonly attributes of boot.ini file If Not FileSetAttrib("C:\Boot.ini", "-AHRS") Then MsgBox(16, "Error!", "Error changing attributes of C:\Boot.ini!") ; Read Boot.ini into array If _FileReadToArray("C:\Boot.ini", $avBootIni) Then ; Edit noexecute line For $n = 1 To $avBootIni[0] If StringInStr($avBootIni[$n], "noexecute=OptOut") Then $avBootIni[$n] = StringReplace($avBootIni[$n], "noexecute=OptOut", "noexecute=AlwaysOff") $iChange = 1 EndIf If StringInStr($avBootIni[$n], "noexecute=OptIn") Then $avBootIni[$n] = StringReplace($avBootIni[$n], "noexecute=OptIn", "noexecute=AlwaysOff") $iChange = 1 EndIf If StringInStr($avBootIni[$n], "noexecute=AlwaysOn") Then $avBootIni[$n] = StringReplace($avBootIni[$n], "noexecute=AlwaysOn", "noexecute=AlwaysOff") $iChange = 1 EndIf Next Else MsgBox(16, "Error!", "Error reading C:\Boot.ini to array! Edit '/noexecute=AlwaysOff' manually!") Return 0 EndIf ; Write change, if required If $iChange Then If Not _FileWriteFromArray('C:\Boot.ini', $avBootIni, 1) Then MsgBox(16, "Error!", "Error writing to C:\Boot.ini! Edit '/noexecute=AlwaysOff' manually!") EndIf EndIf EndFunc ;==>_BootIni call ("_BootIni") Link to comment Share on other sites More sharing options...
Jimbeau Posted June 19, 2006 Share Posted June 19, 2006 (edited) Just for fun housecleaning I added this to the end If FileSetAttrib("C:\Boot.ini", "+AHRS") Then MsgBox(16, "Done!", "Reboot For Changes to Take Effect!") EndIf Also notice that I changed the no execute option to do what I needed, you will need to change it back..... Edited June 19, 2006 by Jimbeau Link to comment Share on other sites More sharing options...
Jimbeau Posted June 19, 2006 Share Posted June 19, 2006 It looks like I lost CRLF when writing back to file? Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 19, 2006 Author Share Posted June 19, 2006 Just for fun housecleaning I added this to the end If FileSetAttrib("C:\Boot.ini", "+AHRS") Then MsgBox(16, "Done!", "Reboot For Changes to Take Effect!") EndIf Also notice that I changed the no execute option to do what I needed, you will need to change it back..... Duh... I hadn't looked at the System attribute. I made the change to FileSetAttrib("C:\Boot.ini", "-HSR"), and also added the part to put the attibs back at the end. I'll post when I get a chance to test it. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Jimbeau Posted June 19, 2006 Share Posted June 19, 2006 YOUR MACHINE WILL NOT BOOT IF YOU DON"T FIX THE CRLF PROBLEM...... BE Careful Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 19, 2006 Author Share Posted June 19, 2006 (edited) YOUR MACHINE WILL NOT BOOT IF YOU DON"T FIX THE CRLF PROBLEM...... BE Careful I tested it on XP Pro SP2 and Win2003 Server, and it works fine on both now, thanks for the reminder about the system attribute. Don't know what you are seeing with the CRLF, I don't have a problem. Here's the resulting log: 2006-06-19 18:24:35 : Successfully removed Hidden and Readonly attributes from C:\Boot.ini. 2006-06-19 18:24:35 : Successfully wrote modified C:\Boot.ini file. 2006-06-19 18:24:35 : Successfully restored Hidden and Readonly attributes to C:\Boot.ini. From running the following code: expandcollapse popup#include <file.au3> #include <array.au3> $LogFile = @ScriptDir & "\TestLogging.log" _BootIni() ;-------------------------------------- ; Function _BootIni() ; Edit Boot.ini for /noexecute=OptOut ;-------------------------------------- Func _BootIni() Local $avBootIni[1] Local $n, $iChange = 0 ; Read Boot.ini into array If _FileReadToArray("C:\Boot.ini", $avBootIni) Then ; Edit noexecute line For $n = 1 To $avBootIni[0] If StringInStr($avBootIni[$n], "noexecute=AlwaysOff") Then $avBootIni[$n] = StringReplace($avBootIni[$n], "noexecute=AlwaysOff", "noexecute=OptOut") $iChange = 1 EndIf Next Else _FileWriteLog($LogFile, "Error reading C:\Boot.ini to array, operator will have to edit '/noexecute=OptOut' manualy!") MsgBox(16, "Error!", "Error reading C:\Boot.ini to array! Edit '/noexecute=OptOut' manualy!") Return 0 EndIf ; Write change, if required If $iChange Then ; Remove Hidden and Readonly attributes of boot.ini file If FileSetAttrib("C:\Boot.ini", "-HSR") Then _FileWriteLog($LogFile, "Successfully removed Hidden and Readonly attributes from C:\Boot.ini.") Else _FileWriteLog($LogFile, "Error changing attributes of C:\Boot.ini!") MsgBox(16, "Error!", "Error changing attributes of C:\Boot.ini!") EndIf ; Write changes to file If _FileWriteFromArray("C:\Boot.ini", $avBootIni, 1) Then _FileWriteLog($LogFile, "Successfully wrote modified C:\Boot.ini file.") Else _FileWriteLog($LogFile, "Error writing to C:\Boot.ini! Operator will have to edit '/noexecute=OptOut' manualy!") MsgBox(16, "Error!", "Error writing to C:\Boot.ini! Edit '/noexecute=OptOut' manualy!") EndIf ; Put back the file attributes If FileSetAttrib("C:\Boot.ini", "+HSR") Then _FileWriteLog($LogFile, "Successfully restored Hidden and Readonly attributes to C:\Boot.ini.") Else _FileWriteLog($LogFile, "Error restoring attributes of C:\Boot.ini!") MsgBox(16, "Error!", "Error restoring attributes of C:\Boot.ini!") EndIf Else _FileWriteLog($LogFile, "Boot.ini /noexecute=OptOut was already set, no changes made.") EndIf EndFunc ;==>_BootIni Edit: First time I tried it the write was: If _FileWriteFromArray("C:\Boot.new.ini", $avBootIni, 1) Then So I didn't throw caution completely to the wind! Edited June 19, 2006 by PsaltyDS Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Jimbeau Posted June 19, 2006 Share Posted June 19, 2006 hmmm mine put things on the same line like default line was followed by [operating systems]on one line? Link to comment Share on other sites More sharing options...
Jimbeau Posted June 20, 2006 Share Posted June 20, 2006 The error seems to occur only if I run the script multiple times? I think maybe you need to clear the array on exit? Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 20, 2006 Author Share Posted June 20, 2006 The error seems to occur only if I run the script multiple times? I think maybe you need to clear the array on exit? The array is declared by "Local $avBootIni[1]", so it is local to the function and should be recreated fresh each time the fuction is called. Even if it wasn't, the line "_FileReadToArray("C:\Boot.ini", $avBootIni)" would overwrite any previous contents in the array, not append them. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
CyberSlug Posted June 20, 2006 Share Posted June 20, 2006 Being lazy, I would try the following approach--untested, use at own risk: Dim $ini = "C:\boot.ini" FileCopy($ini, "C:\BackupJustInCaseThisScriptIsBuggy.ini") Dim $data = FileRead($ini, FileGetSize($ini)) $data = StringReplace($data, "noexecute=AlwaysOff", "noexecute=OptOut") FileDelete($ini); Might want to check the return value... FileWrite($ini, $data) Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig! Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 20, 2006 Author Share Posted June 20, 2006 Being lazy, I would try the following approach--untested, use at own risk: Dim $ini = "C:\boot.ini" FileCopy($ini, "C:\BackupJustInCaseThisScriptIsBuggy.ini") Dim $data = FileRead($ini, FileGetSize($ini)) $data = StringReplace($data, "noexecute=AlwaysOff", "noexecute=OptOut") FileDelete($ini); Might want to check the return value... FileWrite($ini, $data) Well, it doesn't come out that slim, trim, and racy when I add all my logging, but I like it, and it works. Here's the new code (note it works on a faux boot.test.ini for testing): expandcollapse popup#include <file.au3> $LogFile = @ScriptDir & "\TestLogging.log" _BootIni() ;-------------------------------------- ; Function _BootIni() ; Edit Boot.ini for /noexecute=OptOut ;-------------------------------------- Func _BootIni() Local $BootIni = "C:\Boot.test.ini", $Changes = 0 Local $BootBak = $BootIni & ".bak" ; Remove Hidden and Readonly attributes of boot.ini file If FileSetAttrib($BootIni, "-HSR") Then ; Backup old boot.ini file If FileCopy($BootIni, $BootBak, 1) Then _FileWriteLog($LogFile, "Successfully backed up " & $BootIni & " to " & $BootBak) ; Read old boot.ini data Local $BootData = FileRead($BootBak, FileGetSize($BootBak)) ; Modify NoExecute parameter(s) $BootData = StringReplace($BootData, "noexecute=AlwaysOff", "noexecute=OptOut") $Changes += @extended $BootData = StringReplace($BootData, "noexecute=AlwaysOn", "noexecute=OptOut") $Changes += @extended $BootData = StringReplace($BootData, "noexecute=OptIn", "noexecute=OptOut") $Changes += @extended ; Record changes, if any If $Changes = 0 Then _FileWriteLog($LogFile, "No changes were required to /noexecute in: " & $BootIni) Else _FileWriteLog($LogFile, "Found " & $Changes & " change(s) to /noexecute option in: " & $BootIni) ; Delete old boot.ini file If FileDelete($BootIni) Then ; Write new boot.ini file If Not FileWrite($BootIni, $BootData) Then _FileWriteLog($LogFile, "Error writing new file: " & $BootIni) Return 0 EndIf Else _FileWriteLog($LogFile, "Error deleting old file: " & $BootIni) Return 0 EndIf EndIf ; Put back the file attributes If FileSetAttrib($BootIni, "+HSR") Then Return 1 Else _FileWriteLog($LogFile, "Error restoring Hidden and Readonly attributes of: " & $BootIni) Return 0 EndIf Else _FileWriteLog($LogFile, "Error backing up file: " & $BootIni & " to " & $BootBak) Return 0 EndIf Else _FileWriteLog($LogFile, "Error removing Hidden and Readonly attributes of: " & $BootIni) Return 0 EndIf EndFunc ;==>_BootIni This the resulting log file: 2006-06-20 15:32:08 : Successfully removed Hidden and Readonly attributes from: C:\Boot.test.ini 2006-06-20 15:32:08 : Successfully backed up C:\Boot.test.ini to C:\Boot.test.ini.bak 2006-06-20 15:32:08 : Found 1 changes to /noexecute option in: C:\Boot.test.ini Thanks for the pointer! Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Skruge Posted June 21, 2006 Share Posted June 21, 2006 This is what I used a while back (I did the opposite... we needed to set "AlwaysOff") Local $sFindText = "OptOut" Local $sReplaceText = "AlwaysOff" Local $sBootINI = EnvGet("SYSTEMDRIVE") & "\boot.ini" Local $sAttribs = FileGetAttrib($sBootINI); Save attributes Local $aOSList = IniReadSection($sBootINI, "operating systems") ; Remove Attributes FileSetAttrib($sBootINI, "-RSH") ; Replace Text For $iX = 1 To $aOSList[0][0] If StringInStr($aOSList[$iX][1], $sFindText) Then IniWrite($sBootINI, "operating systems", $aOSList[$iX][0], StringReplace($aOSList[$iX][1], $sFindText, $sReplaceText)) Next ; Restore Attributes FileSetAttrib($sBootINI, $sAttribs) [font="Tahoma"]"Tougher than the toughies and smarter than the smarties"[/font] Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 21, 2006 Author Share Posted June 21, 2006 This is what I used a while back (I did the opposite... we needed to set "AlwaysOff") Local $sFindText = "OptOut" Local $sReplaceText = "AlwaysOff" Local $sBootINI = EnvGet("SYSTEMDRIVE") & "\boot.ini" Local $sAttribs = FileGetAttrib($sBootINI); Save attributes Local $aOSList = IniReadSection($sBootINI, "operating systems") ; Remove Attributes FileSetAttrib($sBootINI, "-RSH") ; Replace Text For $iX = 1 To $aOSList[0][0] If StringInStr($aOSList[$iX][1], $sFindText) Then IniWrite($sBootINI, "operating systems", $aOSList[$iX][0], StringReplace($aOSList[$iX][1], $sFindText, $sReplaceText)) Next ; Restore Attributes FileSetAttrib($sBootINI, $sAttribs) That's cool. I struck me a while back that the boot.ini is, after all, an .ini. I think CyberSlug's method was even easier though, because you treat the entire contents of the file as a string. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law 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