Sign in to follow this  
Followers 0
PsaltyDS

Edit boot.ini failed?

20 posts in this topic

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.

:D


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

Share this post


Link to post
Share on other sites



; 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 :D


Share this post


Link to post
Share on other sites

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 :D

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

Share this post


Link to post
Share on other sites

Isn't boot.ini read only?

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

#7 ·  Posted (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 :D

Edit: Here is an unaltered version of the UDF

;===============================================================================
;
; 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 by Nomad

Share this post


Link to post
Share on other sites

I wanted to do this also, so I modified your code. Your error went away when I changed the System and Archive Attributes.

;--------------------------------------
; 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")

Share this post


Link to post
Share on other sites

#9 ·  Posted (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 by Jimbeau

Share this post


Link to post
Share on other sites

It looks like I lost CRLF when writing back to file? :D

Share this post


Link to post
Share on other sites

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... :D

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.

:D


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

Share this post


Link to post
Share on other sites

YOUR MACHINE WILL NOT BOOT IF YOU DON"T FIX THE CRLF PROBLEM......

BE Careful

Share this post


Link to post
Share on other sites

#13 ·  Posted (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:

#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

:D

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 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

Share this post


Link to post
Share on other sites

hmmm mine put things on the same line like default line was followed by [operating systems]on one line?

Share this post


Link to post
Share on other sites

The error seems to occur only if I run the script multiple times? I think maybe you need to clear the array on exit?

Share this post


Link to post
Share on other sites

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.

:D


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

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites

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):

#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! :D


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

Share this post


Link to post
Share on other sites

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]

Share this post


Link to post
Share on other sites

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.

:D


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

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0