Jump to content
zorphnog

Registry Policy File Editor

Recommended Posts

I needed a tool that would allow me to edit local group policy files. Registry policy files contain registry information used by the local group policy. Editing these files, followed by a `gpupdate /force` command allows you to enforce the modified local group policy. To my surprise, there aren't many editors out there for this type of file. I found a few implementations across the net, but none of them did everything I wanted or they were not free. Mainly I wanted a tool that provided read/write capabilities for the registry policy file format (.pol) via GUI and command line interface.

So I created 'GPO Registry Editor' to solve this problem and I thought I would share it with the community. The script provides read/write access .pol file through GUI and CLI. I created the editor to be compliant with the Registry Policy File Format. However, in my testing the special values **DeleteKeys and **SecureKey do not conform the the format specification (at least not on Windows XP). Although I did implement these features, they do not perform the expected results when updated via gpupdate.
 

GRE_Screen_Cap.PNG


The CLI has the following usage:

GPO Registry Editor
v1.0.0.0
Provides read and write capabilities for registry policy files.

   Usage:
    -a  --add              Add the entry specified by the key, value, type, and data parameters.
    -r  --remove           Remove the entry specified by the key and value parameters.
    -d  --data             Specifies the data of the registry entry.
    -f  --file             Specifies the registry file to load or modify. Use `computer` or `user` to specify the system policy files.
    -k  --key              Specifies the key of the registry entry.
    -s  --silent           Perform the operation silently (no GUI).
    -t  --type             Specifies the type of the registry entry.
    -v  --value            Specifies the value of the registry entry.
    -h  --help             Display this message.
    -?  --?                Display this message.

Example: Add a value to the system Computer/Machine registry file.

gre --add -f=computer -k=Software\Policies\Microsoft\MyTestKey -v="My Test Value" -t REG_SZ -d="Registry Policy File editing"

Example: Remove a value from the system User registry file and suppress GUI error messages.

gre --remove -f user -k Software\Policies\Microsoft\MyTestKey -v "My Test Value" -s

Example: Delete all values of a key from a local file.

gre --add -f=C:\Registry.pol -k=Software\Policies\Microsoft\MyTestKey -v=**DelVals

Source code:

#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_UseX64=y
#AutoIt3Wrapper_Res_Description=Provides read and write capabilities for registry policy files.
#AutoIt3Wrapper_Res_Fileversion=1.0.0.0
#AutoIt3Wrapper_Res_Language=1033
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#cs ----------------------------------------------------------------------------

Title:        GPO Registry Editor
AutoIt Version: 3.3.8.1
Author:      Michael Mims (zorphnog)

Script Function:
    Provides read/write capabilities for the registry policy file format (.pol) via GUI or command line interface.
    Registry policy files contain registry information used by the local group policy. Editing these files, followed
    by a `gpupdate /force` command will update the local group policy.

    **Note: On Windows Vista and above, administrator rights are required to save to the system group policy folder.
            Compile with the requestedExecutionLevel=requireAdministrator directive to ensure administrator access.

Reference(s):
    Registry Policy File Format - http://msdn.microsoft.com/en-us/library/windows/desktop/aa374407(v=vs.85).aspx

#ce ----------------------------------------------------------------------------


#include <EditConstants.au3>
#include <File.au3>
#include <GuiComboBox.au3>
#include <GuiConstants.au3>
#include <GuiListView.au3>
#include <Misc.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include "_OptParse.au3"

; Set Options
Opt("GUICloseOnESC", 0)
Opt("GUIOnEventMode", 1)
Opt("MustDeclareVars", 1)

; Create mutex
If @AutoItX64 And @Compiled Then
    _Singleton("GPO64_RE")
Else
    _Singleton("GPO_RE")
EndIf


; Application globals
Global Const $GRE_TITLE = "GPO Registry Editor"
Global Const $GRE_VERSION = "1.0.0.0"
Global Const $GRE_DESC = "Provides read and write capabilities for registry policy files."

; File globals
Global Const $GRE_LOG_FILE = @ScriptDir & "gre.log"
Global Const $USER_REGISTRY_FILE = @SystemDir & "GroupPolicyUserRegistry.pol"
Global Const $MACHINE_REGISTRY_FILE = @SystemDir & "GroupPolicyMachineRegistry.pol"

; Policy file format globals
Global Const $REGISTRY_FILE_SIGNATURE = 0x67655250
Global Const $REGISTRY_FILE_VERSION = 0x00000001
Global Const $REGISTRY_FILE_ENCODING = 2  ; 1 - ANSI, 2 - UTF16 LE, 3 - UTF16 BE, 4 - UTF8

; $g_aEntries array indices
Global Enum $POLENTRY_KEY, $POLENTRY_VALUE, $POLENTRY_TYPE, $POLENTRY_SIZE, $POLENTRY_DATA

; Registry globals
Global Enum $REG_NONE,$REG_SZ,$REG_EXPAND_SZ,$REG_BINARY,$REG_DWORD,$REG_DWORD_BIG_ENDIAN,$REG_LINK,$REG_MULTI_SZ, _
    $REG_RESOURCE_LIST,$REG_FULL_RESOURCE_DESCRIPTOR,$REG_RESOURCE_REQUIREMENTS_LIST,$REG_QWORD
Global Const $g_REGTYPES[12] = [ "REG_NONE", "REG_SZ", "REG_EXPAND_SZ", "REG_BINARY", _
    "REG_DWORD", "REG_DWORD_BIG_ENDIAN", "REG_LINK", "REG_MULTI_SZ", "REG_RESOURCE_LIST", _
    "REG_FULL_RESOURCE_DESCRIPTOR", "REG_RESOURCE_REQUIREMENTS_LIST", "REG_QWORD"]
Global Const $g_ENTRYREGTYPE_CONV[4] = [$REG_SZ,$REG_EXPAND_SZ,$REG_BINARY,$REG_DWORD]
Global Const $g_ENTRYREGTYPES[4] = [$g_REGTYPES[$g_ENTRYREGTYPE_CONV[0]],$g_REGTYPES[$g_ENTRYREGTYPE_CONV[1]], _
    $g_REGTYPES[$g_ENTRYREGTYPE_CONV[2]], $g_REGTYPES[$g_ENTRYREGTYPE_CONV[3]]]

; Policy entry type globals
Global Enum $ENTRY_TYPE_NORM,$ENTRY_TYPE_DEL,$ENTRY_TYPE_DELMULVALS,$ENTRY_TYPE_DELALLVALS,$ENTRY_TYPE_DELKEYS, _
    $ENTRY_TYPE_SECKEY,$_ENTRY_TYPE_SIZE
Global Const $g_ENTRYTYPES[$_ENTRY_TYPE_SIZE] = ["Normal Entry", "Delete Value", "Delete Multiple Values", _
    "Delete All Values", "Delete Subkeys", "Secure Key"]

; $g_MainCtrl array indices
Global Enum $ENT_GUI,$ENT_CBENTR,$ENT_LBKEY,$ENT_INKEY,$ENT_LBVALU,$ENT_INVALU,$ENT_LBTYPE,$ENT_CBTYPE,$ENT_LBDATA, _
    $ENT_INDATA,$ENT_LBDESC,$ENT_ILASTENTR,$_ENT_SIZE

; $g_EntryCtrl array indices
Global Enum $MAIN_GUI,$MAIN_LVENTR,$MAIN_BTNEW,$MAIN_BTEDIT,$MAIN_BTDEL,$MAIN_MIMPOL,$MAIN_MIUPOL,$MAIN_MISAVE, _
    $MAIN_MISAVA,$_MAIN_SIZE

; Command line option array indices
Global Enum $GRE_OPT_ACTION,$GRE_OPT_FILE,$GRE_OPT_KEY,$GRE_OPT_VALUE,$GRE_OPT_TYPE,$GRE_OPT_DATA,$_GRE_OPT_SIZE
Global Enum $GRE_ACTION_ADD,$GRE_ACTION_REMOVE

; Error code globals
Global Enum Step *2 $GRE_ERROR_NONE=0,$GRE_ERROR_NOFILE=1,$GRE_ERROR_NOACTION,$GRE_ERROR_NOKEY,$GRE_ERROR_NOVALUE, _
    $GRE_ERROR_NOTYPE,$GRE_ERROR_INVALIDTYPE,$GRE_ERROR_NODATA,$GRE_ERROR_FILENOTEXIST,$GRE_ERROR_INVALIDARG, _
    $GRE_ERROR_DUPLICATEARG,$GRE_ERROR_INVALIDSWITCH,$GRE_ERROR_FILEWRITE,$GRE_ERROR_INVALIDREGISTRYSIG, _
    $GRE_ERROR_INVALIDREGISTRYVERSION,$GRE_ERROR_ENTRYNOTFOUND,$GRE_ERROR_DELETEENTRY,$GRE_ERROR_INVALIDSPECVAL

Global $g_aEntries[1][5], $g_MainCtrl[$_MAIN_SIZE], $g_EntryCtrl[$_ENT_SIZE]
Global $g_sRegFile, $g_iEditLVIndex = -1, $g_bOpen = False, $g_bChanged = False, $g_bDebug = False, $g_bSilent = False

_Main()

Func _AddEntry($sKey, $sValue, $iType = 1, $vData = "")
    Local $iIndex = _FindEntry($sKey, $sValue)
    If @error Then
        $iIndex = UBound($g_aEntries)
        ReDim $g_aEntries[$iIndex + 1][5]
        $g_aEntries[$iIndex][$POLENTRY_KEY] = $sKey & ChrW(0)
        $g_aEntries[$iIndex][$POLENTRY_VALUE] = $sValue & ChrW(0)
    EndIf

    ; Force type for special values
    If StringLeft($sValue, 2) == "**" Then
        __DebugPrint("Special value; forcing REG_SZ", "_AddEntry")
        $iType = $REG_SZ
    EndIf
    $g_aEntries[$iIndex][$POLENTRY_TYPE] = Binary(Int($iType))

    ; Determine if value is string data and convert properly
    Switch $iType
        Case $REG_SZ, $REG_EXPAND_SZ
            ; Check for special values
            If StringLeft($sValue, 2) == "**" Then
                Select
                    Case StringMid($sValue, 3, 12) = "DeleteValues" Or StringMid($sValue, 3, 10) = "DeleteKeys"
                        $vData = StringToBinary(StringRegExpReplace(StringStripWS($vData, 3), "(s*;s*)", ";") & _
                            ChrW(0), $REGISTRY_FILE_ENCODING)
                    Case Else
                        $vData = StringToBinary(ChrW(0x20) & ChrW(0), $REGISTRY_FILE_ENCODING)
                EndSelect
            Else
                $vData = StringToBinary($vData & ChrW(0), $REGISTRY_FILE_ENCODING)
            EndIf
        Case $REG_DWORD
            $vData = Binary(Int($vData))
        Case Else
            $vData = Binary($vData)
    EndSwitch

    $g_aEntries[$iIndex][$POLENTRY_SIZE] = BinaryLen($vData)
    $g_aEntries[$iIndex][$POLENTRY_DATA] = $vData

    Return $iIndex
EndFunc   ;==>_AddEntry

Func _CloseFile()
    If Not $g_bOpen Then Return True
    If $g_bOpen And $g_bChanged Then
        Local $iRet = MsgBox(0x1033, $GRE_TITLE, "The current registry file has been modified. Would you like to save the changes?", 0, $g_MainCtrl[$MAIN_GUI])
        If $iRet = 2 Then  ; CANCEL
            Return False
        ElseIf $iRet = 6 Then  ; YES
            _SaveFile()
        EndIf
    EndIf
    _GUICtrlListView_DeleteAllItems($g_MainCtrl[$MAIN_LVENTR])
    _ModifyFile(False, False)
    $g_aEntries = 0
    Dim $g_aEntries[1][5]
    $g_sRegFile = ""
    Return True
EndFunc   ;==>_CloseFile

Func _CreateEntryGUI($bIsNew = True)
    Local $sTitle = "Add"
    If Not $bIsNew Then $sTitle = "Edit"
    $g_EntryCtrl[$ENT_GUI] = GUICreate($sTitle & " Registry Entry", 520, 240, -1, -1, BitOR($WS_POPUP, $WS_CAPTION), $WS_EX_TOOLWINDOW, $g_MainCtrl[$MAIN_GUI])
    GUICtrlCreateGroup("", 10, 10, 500, 185)
    $g_EntryCtrl[$ENT_CBENTR] = GUICtrlCreateCombo("", 20, 6, 135, 25, BitOR($CBS_DROPDOWNLIST,$CBS_AUTOHSCROLL))
    GUICtrlSetData(-1, _ArrayToString($g_ENTRYTYPES), $g_ENTRYTYPES[0])
    GUICtrlSetOnEvent(-1, "_Ev_cbEntryType")
    $g_EntryCtrl[$ENT_ILASTENTR] = 0
    $g_EntryCtrl[$ENT_LBKEY] = GUICtrlCreateLabel("Key:", 20, 44, 45, 17, $SS_RIGHT)
    $g_EntryCtrl[$ENT_INKEY] = GUICtrlCreateInput("", 70, 41, 430, 21)
    $g_EntryCtrl[$ENT_LBVALU] = GUICtrlCreateLabel("Value:", 20, 76, 45, 17, $SS_RIGHT)
    $g_EntryCtrl[$ENT_INVALU] = GUICtrlCreateInput("", 70, 73, 430, 21)
    $g_EntryCtrl[$ENT_LBTYPE] = GUICtrlCreateLabel("Type:", 20, 108, 45, 17, $SS_RIGHT)
    $g_EntryCtrl[$ENT_CBTYPE] = GUICtrlCreateCombo("", 70, 105, 240, 25, BitOR($CBS_DROPDOWNLIST,$CBS_AUTOHSCROLL))
    GUICtrlSetData(-1, _ArrayToString($g_ENTRYREGTYPES), $g_ENTRYREGTYPES[0])
    $g_EntryCtrl[$ENT_LBDATA] = GUICtrlCreateLabel("Data:", 20, 140, 45, 17, $SS_RIGHT)
    $g_EntryCtrl[$ENT_INDATA] = GUICtrlCreateInput("", 70, 137, 430, 42, $ES_MULTILINE)
    $g_EntryCtrl[$ENT_LBDESC] = GUICtrlCreateLabel("", 70, 100, 430, 68)
    GUICtrlSetFont(-1, Default, Default, 2)
    GUICtrlSetState(-1, $GUI_HIDE)
    GUICtrlCreateGroup("", -99, -99, 1, 1)
    GUICtrlCreateButton("OK", 350, 205, 75, 25)
    GUICtrlSetOnEvent(-1, "_Ev_btEntryOk")
    GUICtrlCreateButton("Cancel", 435, 205, 75, 25)
    GUICtrlSetOnEvent(-1, "_Ev_btEntryCancel")
EndFunc   ;==>_CreateEntryGUI

Func _CreateGUI()
    $g_MainCtrl[$MAIN_GUI] = GUICreate($GRE_TITLE, 770, 475, -1, -1, BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU, $WS_MAXIMIZEBOX, $WS_SIZEBOX))
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Ev_miFileClose")
    GUICtrlCreateListView("Registry Key|Value|Type|Data", 10, 10, 750, 400)
    $g_MainCtrl[$MAIN_LVENTR] = GUICtrlGetHandle(-1)
    GUICtrlSendMsg(-1, 0x101E, 0, 350)
    GUICtrlSendMsg(-1, 0x101E, 1, 150)
    GUICtrlSendMsg(-1, 0x101E, 2, 100)
    GUICtrlSendMsg(-1, 0x101E, 3, 100)
    GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)
    $g_MainCtrl[$MAIN_BTNEW] = GUICtrlCreateButton("New...", 10, 420, 75, 25, 0)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlSetOnEvent(-1, "_Ev_btNew")
    GUICtrlSetResizing(-1, BitOR($GUI_DOCKLEFT,$GUI_DOCKBOTTOM,$GUI_DOCKSIZE))
    $g_MainCtrl[$MAIN_BTEDIT] = GUICtrlCreateButton("Edit...", 95, 420, 75, 25, 0)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlSetOnEvent(-1, "_Ev_btEdit")
    GUICtrlSetResizing(-1, BitOR($GUI_DOCKLEFT,$GUI_DOCKBOTTOM,$GUI_DOCKSIZE))
    $g_MainCtrl[$MAIN_BTDEL] = GUICtrlCreateButton("Delete", 180, 420, 75, 25, 0)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlSetOnEvent(-1, "_Ev_btDelete")
    GUICtrlSetResizing(-1, BitOR($GUI_DOCKLEFT,$GUI_DOCKBOTTOM,$GUI_DOCKSIZE))

    ; Menu items
    Local $muFile, $muOpen
    $muFile = GUICtrlCreateMenu("File")
    GUICtrlCreateMenuItem("New", $muFile)
    GUICtrlSetOnEvent(-1, "_Ev_miFileNew")
    $muOpen = GUICtrlCreateMenu("Open", $muFile)
    $g_MainCtrl[$MAIN_MIMPOL] = GUICtrlCreateMenuItem("Machine Policy", $muOpen)
    GUICtrlSetOnEvent(-1, "_Ev_miFileOpenSystem")
    $g_MainCtrl[$MAIN_MIUPOL] = GUICtrlCreateMenuItem("User Policy", $muOpen)
    GUICtrlSetOnEvent(-1, "_Ev_miFileOpenSystem")
    GUICtrlCreateMenuItem("", $muOpen)
    GUICtrlCreateMenuItem("File...", $muOpen)
    GUICtrlSetOnEvent(-1, "_Ev_miFileOpenFile")
    $g_MainCtrl[$MAIN_MISAVE] = GUICtrlCreateMenuItem("Save", $muFile)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlSetOnEvent(-1, "_Ev_miFileSave")
    $g_MainCtrl[$MAIN_MISAVA] = GUICtrlCreateMenuItem("Save As...", $muFile)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlSetOnEvent(-1, "_Ev_miFileSave")
    GUICtrlCreateMenuItem("", $muFile)
    GUICtrlCreateMenuItem("Exit", $muFile)
    GUICtrlSetOnEvent(-1, "_Ev_miFileClose")

    GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")
    GUISetState(@SW_SHOW)
EndFunc   ;==>_CreateGUI

Func _DeleteEntry($sKey, $sValue)
    Local $iIndex = _FindEntry($sKey, $sValue)
    If @error Then Return SetError(@error, 0, -1)
    __DebugPrint("--key=" & $sKey & " --value=" & $sValue, "_DeleteEntry")
    _ArrayDelete($g_aEntries, $iIndex)
    If @error Then Return SetError($GRE_ERROR_DELETEENTRY, 0, -1)
    Return 1
EndFunc   ;==>_DeleteEntry

Func _EditEntry($iEntry = -1)
    If $iEntry == -1 Then
        $g_iEditLVIndex = $iEntry
        _CreateEntryGUI()
    Else
        _CreateEntryGUI(False)
        _LoadEntryValues($iEntry)
    EndIf

    GUISetState(@SW_DISABLE, $g_MainCtrl[$MAIN_GUI])
    GUISetState(@SW_SHOW, $g_EntryCtrl[$ENT_GUI])
EndFunc   ;==>_EditEntry

Func _FindEntry($sKey, $sValue)
    Local $iCurrent, $iIndex, $iSize
    $iCurrent = 0
    $iSize = UBound($g_aEntries)

    While $iCurrent < $iSize
        $iIndex = _ArraySearch($g_aEntries, $sValue, $iCurrent, 0, 0, 0, 1, $POLENTRY_VALUE)
        If @error Then ExitLoop
        If $g_aEntries[$iIndex][$POLENTRY_KEY] = $sKey Then
            __DebugPrint($iIndex & " " & $g_aEntries[$iIndex][$POLENTRY_KEY], "_FindEntry")
            Return $iIndex
        EndIf
        $iCurrent = $iIndex + 1
    WEnd

    Return SetError($GRE_ERROR_ENTRYNOTFOUND, 0, -1)
EndFunc   ;==>_FindEntry

Func _GetFormattedData($iIndex, $bHex = True)
    Switch $g_aEntries[$iIndex][$POLENTRY_TYPE]
        Case $REG_SZ, $REG_EXPAND_SZ
            Return BinaryToString($g_aEntries[$iIndex][$POLENTRY_DATA], $REGISTRY_FILE_ENCODING)
        Case $REG_BINARY
            Return "0x" & Hex(Int($g_aEntries[$iIndex][$POLENTRY_DATA]), 8)
        Case $REG_DWORD
            If $bHex Then Return "0x" & Hex(Int($g_aEntries[$iIndex][$POLENTRY_DATA]), 8)
            Return Int($g_aEntries[$iIndex][$POLENTRY_DATA])
        Case Else
            Return $g_aEntries[$iIndex][4]
    EndSwitch
EndFunc   ;==>_GetFormattedData

Func _LoadEntryValues($iEntry)
    Local $iEntryType, $sKey, $sValue, $iRegType, $sValue
    $iEntryType = 0
    $sKey = $g_aEntries[$iEntry][$POLENTRY_KEY]
    $sValue = $g_aEntries[$iEntry][$POLENTRY_VALUE]

    If StringLeft($sValue, 2) == "**" Then
        Select
            Case StringMid($sValue, 3, 12) = "DeleteValues"
                $iEntryType = $ENTRY_TYPE_DELMULVALS
                $sValue = BinaryToString($g_aEntries[$iEntry][$POLENTRY_DATA], $REGISTRY_FILE_ENCODING)
                $iRegType = 0
            Case StringMid($sValue, 3, 4) = "Del."
                $iEntryType = $ENTRY_TYPE_DEL
                $sValue = StringMid($sValue, 7)
                $iRegType = 0
            Case StringMid($sValue, 3, 7) = "DelVals"
                $iEntryType = $ENTRY_TYPE_DELALLVALS
                $sValue = ""
                $iRegType = 0
            Case StringMid($sValue, 3, 10) = "DeleteKeys"
                $iEntryType = $ENTRY_TYPE_DELKEYS
                $sValue = BinaryToString($g_aEntries[$iEntry][$POLENTRY_DATA], $REGISTRY_FILE_ENCODING)
                $iRegType = 0
            Case StringMid($sValue, 3, 9) = "SecureKey"
                $iEntryType = $ENTRY_TYPE_SECKEY
                $iRegType = Int(StringMid($sValue, 13, 1))
                $sValue = ""
        EndSelect
        _GUICtrlComboBox_SetCurSel($g_EntryCtrl[$ENT_CBENTR], $iEntryType)
        _Ev_cbEntryType()
        GUICtrlSetData($g_EntryCtrl[$ENT_INKEY], $sKey)
        GUICtrlSetData($g_EntryCtrl[$ENT_INVALU], $sValue)
        _GUICtrlComboBox_SetCurSel($g_EntryCtrl[$ENT_CBTYPE], $iRegType)
    Else
        $iRegType = _ArraySearch($g_ENTRYREGTYPE_CONV, $g_aEntries[$iEntry][$POLENTRY_TYPE])
        GUICtrlSetData($g_EntryCtrl[$ENT_INKEY], $sKey)
        GUICtrlSetData($g_EntryCtrl[$ENT_INVALU], $sValue)
        _GUICtrlComboBox_SetCurSel($g_EntryCtrl[$ENT_CBTYPE], $iRegType)
        GUICtrlSetData($g_EntryCtrl[$ENT_INDATA], _GetFormattedData($iEntry, False))
    EndIf
EndFunc   ;==>_LoadEntryValues

Func _Main()
    Local $aValidOpts, $aOptions, $sFilename = ""

    If @CPUArch = "X64" And Not @AutoItX64 Then
;~       __DebugPrint("X64 architecture detected.", "_Main", True)
        Local $sDrive, $sDir, $sFile, $sExt, $sExec
        _PathSplit(@ScriptFullPath, $sDrive, $sDir, $sFile, $sExt)
        $sExec = @ScriptDir & "" & $sFile & "_x64" & $sExt
;~       __DebugPrint("Attempting 64 bit launch: " & $sExec, "_Main", True)
        If FileExists($sExec) Then Exit(RunWait($sExec & " " & _ArrayToString($CmdLine, " ", 1), @WorkingDir))
    EndIf

    If _ParseOptions($aValidOpts, $aOptions) Then
        Local $iOption, $iMatches = 0

        If _OptParse_MatchOption("h,help,?", $aOptions, $iOption) Then
            _OptParse_ShowUsage($aValidOpts, 1)
            Exit($GRE_ERROR_NONE)
        EndIf

        If _OptParse_MatchOption("D,debug", $aOptions, $iOption) Then
            $iMatches += 1
            $g_bDebug = True
            __PrintEnvironment()
        EndIf

        If _OptParse_MatchOption("s,silent", $aOptions, $iOption) Then
            __DebugPrint("Silent mode set", "_Main")
            $iMatches += 1
            $g_bSilent = True
            _OptParse_SetDisplay(0)
        EndIf

        If _OptParse_MatchOption("f,file", $aOptions, $iOption) Then
            $iMatches += 1
            Switch StringLower($aOptions[$iOption][1])
                Case "c","comp","computer","m","machine"
                    $sFilename = $MACHINE_REGISTRY_FILE
                Case "u","user"
                    $sFilename = $USER_REGISTRY_FILE
                Case Else
                    $sFilename = _PathFull($aOptions[$iOption][1])
            EndSwitch
            __DebugPrint("[file] " & $sFilename, "_Main")
        EndIf

        ; Some command line parameters for testing
        ; --add -f Registry.pol -k SoftwareMyTestKey -v TestMe -t REG_SZ -d "test, test, test"
        ; --remove -f Registry.pol -k SoftwareMyTestKey -v TestMe
        If _OptParse_MatchOption("a,add,r,remove", $aOptions, $iOption) Then
            Local $iReturn, $aValidated = _ValidateOptions($aOptions)

            _ReadPolFile($sFilename)
            If @error Then Exit(@error)

            If $aValidated[$GRE_OPT_ACTION] == $GRE_ACTION_ADD Then
                _AddEntry($aValidated[$GRE_OPT_KEY], $aValidated[$GRE_OPT_VALUE], $aValidated[$GRE_OPT_TYPE], _
                    $aValidated[$GRE_OPT_DATA])
            ElseIf $aValidated[$GRE_OPT_ACTION] == $GRE_ACTION_REMOVE Then
                _DeleteEntry($aValidated[$GRE_OPT_KEY], $aValidated[$GRE_OPT_VALUE])
                If @error Then Exit(@error)
            EndIf

            _WritePolFile($sFilename)
            If @error Then Exit(@error)

            Exit($GRE_ERROR_NONE)
        ElseIf $iMatches < $aOptions[0][0] Then
            _OptParse_Display("No action specified. Use --add or --remove to modify a policy file.", "Error")
            Exit($GRE_ERROR_NOACTION)
        EndIf
    EndIf

    _CreateGUI()
    If $sFilename <> "" Then _OpenFile($sFilename)

    While 1
        Sleep(10)
    WEnd
EndFunc   ;==>_Main

Func _ModifyFile($bNewOpen, $bNewChanged)
    Local $sTitle, $aClientSize, $a_iCall
    __DebugPrint(StringFormat("[%s, %s] => [%s, %s]", $g_bOpen, $g_bChanged, $bNewOpen, $bNewChanged), "_ModifyFile")
    If $bNewOpen <> $g_bOpen Then
        If $bNewOpen Then
            If $g_sRegFile == "" Then
                $sTitle = "New Policy File - " & $GRE_TITLE
            Else
                $sTitle = $g_sRegFile & " - " & $GRE_TITLE
            EndIf
            $aClientSize = WinGetClientSize($g_MainCtrl[$MAIN_GUI])
            $a_iCall = DllCall("shlwapi.dll", "int", "PathCompactPathW", _
                    "hwnd", 0, _
                    "wstr", $sTitle, _
                    "dword", $aClientSize[0] - 100)
            If Not @error Then $sTitle = $a_iCall[2]
            WinSetTitle($g_MainCtrl[$MAIN_GUI], 0, $sTitle)
            GUICtrlSetState($g_MainCtrl[$MAIN_MISAVA], $GUI_ENABLE)
            GUICtrlSetState($g_MainCtrl[$MAIN_BTNEW], $GUI_ENABLE)
            GUICtrlSetState($g_MainCtrl[$MAIN_BTEDIT], $GUI_ENABLE)
            GUICtrlSetState($g_MainCtrl[$MAIN_BTDEL], $GUI_ENABLE)
        Else
            WinSetTitle($g_MainCtrl[$MAIN_GUI], 0, $GRE_TITLE)
            GUICtrlSetState($g_MainCtrl[$MAIN_MISAVE], $GUI_DISABLE)
            GUICtrlSetState($g_MainCtrl[$MAIN_MISAVA], $GUI_DISABLE)
            GUICtrlSetState($g_MainCtrl[$MAIN_BTNEW], $GUI_DISABLE)
            GUICtrlSetState($g_MainCtrl[$MAIN_BTEDIT], $GUI_DISABLE)
            GUICtrlSetState($g_MainCtrl[$MAIN_BTDEL], $GUI_DISABLE)
            $g_bChanged = False
        EndIf
        $g_bOpen = $bNewOpen
        Return
    EndIf
    If $bNewChanged <> $g_bChanged And $g_bOpen Then
        If $bNewChanged Then
            If $g_sRegFile == "" Then
                $sTitle = "New Policy File* - " & $GRE_TITLE
            Else
                $sTitle = $g_sRegFile & "* - " & $GRE_TITLE
            EndIf
            $aClientSize = WinGetClientSize($g_MainCtrl[$MAIN_GUI])
            $a_iCall = DllCall("shlwapi.dll", "int", "PathCompactPathW", _
                    "hwnd", 0, _
                    "wstr", $sTitle, _
                    "dword", $aClientSize[0] - 100)
            If Not @error Then $sTitle = $a_iCall[2]
            WinSetTitle($g_MainCtrl[$MAIN_GUI], 0, $sTitle)
            GUICtrlSetState($g_MainCtrl[$MAIN_MISAVE], $GUI_ENABLE)
        Else
            If $g_sRegFile == "" Then
                $sTitle = "New Policy File - " & $GRE_TITLE
            Else
                $sTitle = $g_sRegFile & " - " & $GRE_TITLE
            EndIf
            $aClientSize = WinGetClientSize($g_MainCtrl[$MAIN_GUI])
            $a_iCall = DllCall("shlwapi.dll", "int", "PathCompactPathW", _
                    "hwnd", 0, _
                    "wstr", $sTitle, _
                    "dword", $aClientSize[0] - 100)
            If Not @error Then $sTitle = $a_iCall[2]
            WinSetTitle($g_MainCtrl[$MAIN_GUI], 0, $sTitle)
            GUICtrlSetState($g_MainCtrl[$MAIN_MISAVE], $GUI_DISABLE)
        EndIf
    EndIf
    $g_bChanged = $bNewChanged
EndFunc   ;==>_ModifyFile

Func _OpenFile($sFilename = "")
    If Not _CloseFile() Then Return
    If $sFilename <> "" Then
        GUISetCursor(15, 1, $g_MainCtrl[$MAIN_GUI])
        _ReadPolFile($sFilename)
        If @error Then
            GUISetCursor()
            Return
        EndIf
        _UpdateListView()
        GUISetCursor()
    EndIf
    $g_sRegFile = $sFilename
    _ModifyFile(True, False)
EndFunc   ;==>_OpenFile

Func _ParseOptions(ByRef $aValidOpts, ByRef $aOptions)
    Local $local_CmdLine = $CmdLine
    $aValidOpts = 0
    $aOptions = 0

    ; Create the valid options list
    _OptParse_Init($aValidOpts, $GRE_TITLE & "n", "v" & $GRE_VERSION & "n", $GRE_DESC & "n")
    _OptParse_Add($aValidOpts, "a", "add", $OPT_ARG_NONE, "Add the entry specified by the key, value, type, and data parameters.")
    _OptParse_Add($aValidOpts, "r", "remove", $OPT_ARG_NONE, "Remove the entry specified by the key and value parameters.")
    _OptParse_Add($aValidOpts, "D", "debug", BitOR($OPT_ARG_NONE,$OPT_ARG_HIDDEN), "Record debugging information.")
    _OptParse_Add($aValidOpts, "d", "data", $OPT_ARG_REQ, "Specifies the data of the registry entry.")
    _OptParse_Add($aValidOpts, "f", "file", $OPT_ARG_REQ, "Specifies the registry file to load or modify. Use `computer` or `user` to specify the system policy files.")
    _OptParse_Add($aValidOpts, "k", "key", $OPT_ARG_REQ, "Specifies the key of the registry entry.")
    _OptParse_Add($aValidOpts, "s", "silent", $OPT_ARG_NONE, "Perform the operation silently (no GUI).")
    _OptParse_Add($aValidOpts, "t", "type", $OPT_ARG_REQ, "Specifies the type of the registry entry.")
    _OptParse_Add($aValidOpts, "v", "value", $OPT_ARG_REQ, "Specifies the value of the registry entry.")
    _OptParse_Add($aValidOpts, "h", "help", $OPT_ARG_NONE, "Display this message.")
    _OptParse_Add($aValidOpts, "?", "?", $OPT_ARG_NONE, "Display this message.")

    $aOptions = _OptParse_GetOpts($local_CmdLine, $aValidOpts)
    Switch @error
        Case 0
            _OptParse_SetDisplay(1)  ; Display via MsgBox
            Return True
        Case 1
            _OptParse_SetDisplay(1)  ; Display via MsgBox
            Return False
        Case 2
            Exit($GRE_ERROR_INVALIDARG)
        Case 3
            Exit($GRE_ERROR_DUPLICATEARG)
        Case 4
            Exit($GRE_ERROR_INVALIDSWITCH)
    EndSwitch
EndFunc   ;==>_ParseOptions

Func _ReadPolFile($sFilename)
    Local $hInfile, $bBuffer, $iStart, $iCurrent, $iLength, $iColon, $iNumEntries, $bTemp

    If Not FileExists($sFilename) Then
        If Not $g_bSilent Then MsgBox(0x1010, $GRE_TITLE, "ERROR: File not found: " & $sFilename)
        Return SetError($GRE_ERROR_FILENOTEXIST, 0, -1)
    EndIf
    $hInfile = FileOpen($sFilename, 16)
    $bBuffer = FileRead($hInfile)
    FileClose($hInfile)
    $iLength = BinaryLen($bBuffer)

    If BinaryMid($bBuffer, 1, 4) <> Binary($REGISTRY_FILE_SIGNATURE) Then
        If Not $g_bSilent Then MsgBox(0x1010, $GRE_TITLE, "ERROR: Invalid file signature. File will not be processed.")
        Return SetError($GRE_ERROR_INVALIDREGISTRYSIG, 0, -1)
    EndIf
    If BinaryMid($bBuffer, 5, 4) <> Binary($REGISTRY_FILE_VERSION) Then
        If Not $g_bSilent Then MsgBox(0x1010, $GRE_TITLE, "ERROR: Invalid registry file version. File will not be processed.")
        Return SetError($GRE_ERROR_INVALIDREGISTRYVERSION, 0, -1)
    EndIf
    $iStart = 9
    $iCurrent = 9
    $iColon = 0
    $iNumEntries = 0
    $g_aEntries = 0
    Dim $g_aEntries[1][5]

    ; The body consists of registry values in the following format.
    ; [key;value;type;size;data]
    While $iCurrent < $iLength
        $bTemp = BinaryMid($bBuffer, $iCurrent, 2)
        Switch $bTemp
            Case 0x005B ; Unicode => [
                ReDim $g_aEntries[$iNumEntries+1][5]
                $iColon = 0
                $iStart = $iCurrent + 2
            Case 0x005D ; Unicode => ]
                $iStart = $iCurrent + 2
                $iNumEntries += 1
            Case 0x003B ; Unicode => ;
                Switch $iColon
                    Case 0
                        $g_aEntries[$iNumEntries][$POLENTRY_KEY] = BinaryToString(BinaryMid($bBuffer, $iStart, $iCurrent - $iStart), $REGISTRY_FILE_ENCODING)
                        $iColon += 1
                        $iStart = $iCurrent + 2
                    Case 1
                        $g_aEntries[$iNumEntries][$POLENTRY_VALUE] = BinaryToString(BinaryMid($bBuffer, $iStart, $iCurrent - $iStart), $REGISTRY_FILE_ENCODING)
                        $iColon += 1
                        $iStart = $iCurrent + 2
                    Case 2
;~                       _ArrayDisplay($g_aEntries)
                        $g_aEntries[$iNumEntries][$POLENTRY_TYPE] = Int(BinaryMid($bBuffer, $iStart, $iCurrent - $iStart))
                        $iColon += 1
                        $iStart = $iCurrent + 2
                    Case 3
                        $g_aEntries[$iNumEntries][$POLENTRY_SIZE] = Int(BinaryMid($bBuffer, $iStart, $iCurrent - $iStart))
                        $iColon += 1
                        $iStart = $iCurrent + 2
                        $g_aEntries[$iNumEntries][$POLENTRY_DATA] = BinaryMid($bBuffer, $iStart, $g_aEntries[$iNumEntries][$POLENTRY_SIZE])
                        $iCurrent = $iStart + $g_aEntries[$iNumEntries][$POLENTRY_SIZE] - 2
                    Case Else
                        $iColon += 1
                        $iStart = $iCurrent + 2
                EndSwitch
        EndSwitch
        $iCurrent += 2
    WEnd
EndFunc   ;==>_ReadPolFile

Func _SaveFile($bSaveAs = False)
    If $bSaveAs Or Not FileExists($g_sRegFile) Then
        Local $sFilename = FileSaveDialog("Save GPO Registry File...", "", "GPO Registry Files (*.pol)", 18, "", $g_MainCtrl[$MAIN_GUI])
        If @error Then Return False
        If StringRight($sFilename, 4) <> ".pol" Then $sFilename &= ".pol"
        $g_sRegFile = $sFilename
    EndIf
    _WritePolFile($g_sRegFile)
    If @error Then Return False
    _ModifyFile($g_bOpen, False)
EndFunc   ;==>_SaveFile

Func _UpdateListView()
    Local $i, $iMax
    _GUICtrlListView_BeginUpdate($g_MainCtrl[$MAIN_LVENTR])
    _GUICtrlListView_DeleteAllItems($g_MainCtrl[$MAIN_LVENTR])
    $iMax = UBound($g_aEntries) - 1
    For $i=0 To $iMax
        _GUICtrlListView_AddItem($g_MainCtrl[$MAIN_LVENTR], $g_aEntries[$i][$POLENTRY_KEY])
        _GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $i, $g_aEntries[$i][$POLENTRY_VALUE], 1)
        _GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $i, $g_REGTYPES[$g_aEntries[$i][$POLENTRY_TYPE]], 2)
        _GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $i, _GetFormattedData($i), 3)
    Next
    _GUICtrlListView_EndUpdate($g_MainCtrl[$MAIN_LVENTR])
EndFunc   ;==>_UpdateListView

Func _ValidateOptions($aOptions)
    Local $aReturn[$_GRE_OPT_SIZE], $iOption

    ; Check for policy file definition
    If Not _OptParse_MatchOption("f,file", $aOptions, $iOption) Then
        _OptParse_Display("File required. Use --file to specify the policy file to modify.", "Error")
        Exit($GRE_ERROR_NOFILE)
    EndIf

    ; Check for key definition
    If _OptParse_MatchOption("k,key", $aOptions, $iOption) Then
        __DebugPrint("[key] " & $aOptions[$iOption][1], "_ValidateOptions")
        $aReturn[$GRE_OPT_KEY] = $aOptions[$iOption][1]
    Else
        _OptParse_Display("Key required. Use --key to specify the registry key to modify.", "Error")
        Exit($GRE_ERROR_NOKEY)
    EndIf

    ; Check for value definition
    If _OptParse_MatchOption("v,value", $aOptions, $iOption) Then
        __DebugPrint("[value] " & $aOptions[$iOption][1], "_ValidateOptions")
        $aReturn[$GRE_OPT_VALUE] = $aOptions[$iOption][1]
    Else
        _OptParse_Display("Value required. Use --value to specify the registry value to modify.", "Error")
        Exit($GRE_ERROR_NOVALUE)
    EndIf

    If _OptParse_MatchOption("r,remove", $aOptions, $iOption) Then
        __DebugPrint("[action] remove", "_ValidateOptions")
        $aReturn[$GRE_OPT_ACTION] = $GRE_ACTION_REMOVE

        Return $aReturn
    ElseIf _OptParse_MatchOption("a,add", $aOptions, $iOption) Then
        Local $sType, $sData, $bTypeRequired = True, $bDataRequired = True
        __DebugPrint("[action] add", "_ValidateOptions")
        $aReturn[$GRE_OPT_ACTION] = $GRE_ACTION_ADD

        ; Handle special values and determine whether data is required
        If StringLeft($aReturn[$GRE_OPT_VALUE], "2") == "**" Then
            Select
                Case StringMid($aReturn[$GRE_OPT_VALUE], 3, 4) = "Del." Or _
                     StringMid($aReturn[$GRE_OPT_VALUE], 3, 7) = "DelVals" Or _
                     StringMid($aReturn[$GRE_OPT_VALUE], 3, 9) = "SecureKey"
                    __DebugPrint("Special value detected; data not required.", "_ValidateOptions")
                    $bTypeRequired = False
                    $bDataRequired = False
                Case StringMid($aReturn[$GRE_OPT_VALUE], 3, 12) = "DeleteValues" Or _
                     StringMid($aReturn[$GRE_OPT_VALUE], 3, 10) = "DeleteKeys"
                    __DebugPrint("Special value detected; data required.", "_ValidateOptions")
                    $bTypeRequired = False
                Case Else
                    _OptParse_Display("Invalid special value: " & $aReturn[$GRE_OPT_VALUE], "Error")
                    Exit($GRE_ERROR_INVALIDSPECVAL)
            EndSelect
        EndIf

        ; Check for type definition
        If _OptParse_MatchOption("t,type", $aOptions, $iOption) Then
            __DebugPrint("[type] " & $aOptions[$iOption][1], "_ValidateOptions")
            $aReturn[$GRE_OPT_TYPE] = StringUpper($aOptions[$iOption][1])
            $aReturn[$GRE_OPT_TYPE] = _ArraySearch($g_REGTYPES, $aReturn[$GRE_OPT_TYPE])
            If @error Then
                _OptParse_Display("Invalid type argument: " & $aOptions[$iOption][1], "Error")
                Exit($GRE_ERROR_INVALIDTYPE)
            EndIf
        ElseIf $bTypeRequired Then
            _OptParse_Display("Type required. Use --type to specify the registry type to add.", "Error")
            Exit($GRE_ERROR_NOTYPE)
        EndIf

        ; Check for data definition
        If _OptParse_MatchOption("d,data", $aOptions, $iOption) Then
            __DebugPrint("[data] " & $aOptions[$iOption][1], "_ValidateOptions")
            $aReturn[$GRE_OPT_DATA] = $aOptions[$iOption][1]
        ElseIf $bDataRequired Then
            _OptParse_Display("Data required. Use --data to specify the registry data to add.", "Error")
            Exit($GRE_ERROR_NODATA)
        EndIf

        Return $aReturn
    EndIf
EndFunc   ;==>_ValidateOptions

Func _WritePolFile($sFilename)
    Local $hOutfile, $iMax

    ; Open file for writing
    __DebugPrint("Writing output file...", "_WritePolFile")
    $hOutfile = FileOpen($sFilename, 26)
    If $hOutfile = -1 Then
        If Not $g_bSilent Then MsgBox(0x1010, $GRE_TITLE, "ERROR: File could not be created [" & $sFilename & "].")
        Return SetError($GRE_ERROR_FILEWRITE, 0, -1)
    EndIf

    ; Write header information
    FileWrite($hOutfile, Binary($REGISTRY_FILE_SIGNATURE))
    FileWrite($hOutfile, Binary($REGISTRY_FILE_VERSION))

    ; Write entries
    $iMax = UBound($g_aEntries) - 1
    For $i = 0 To $iMax
        FileWrite($hOutfile, StringToBinary("[" & $g_aEntries[$i][$POLENTRY_KEY], $REGISTRY_FILE_ENCODING))
        FileWrite($hOutfile, StringToBinary(";", $REGISTRY_FILE_ENCODING))
        FileWrite($hOutfile, StringToBinary($g_aEntries[$i][$POLENTRY_VALUE], $REGISTRY_FILE_ENCODING))
        FileWrite($hOutfile, StringToBinary(";", $REGISTRY_FILE_ENCODING))
        FileWrite($hOutfile, $g_aEntries[$i][$POLENTRY_TYPE])
        FileWrite($hOutfile, StringToBinary(";", $REGISTRY_FILE_ENCODING))
        FileWrite($hOutfile, $g_aEntries[$i][$POLENTRY_SIZE])
        FileWrite($hOutfile, StringToBinary(";", $REGISTRY_FILE_ENCODING))
        FileWrite($hOutfile, $g_aEntries[$i][$POLENTRY_DATA])
        FileWrite($hOutfile, StringToBinary("]", $REGISTRY_FILE_ENCODING))
    Next

    ; Close file
    FileClose($hOutfile)
EndFunc   ;==>_WritePolFile

Func _Ev_btDelete()
    Local $iIndex = _GUICtrlListView_GetSelectedIndices($g_MainCtrl[$MAIN_LVENTR])
    If $iIndex <> "" Then
        _DeleteEntry(_GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $iIndex), _GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $iIndex, 1))
        If Not @error Then
            _GUICtrlListView_DeleteItem($g_MainCtrl[$MAIN_LVENTR], $iIndex)
            _ModifyFile($g_bOpen, True)
        EndIf
    EndIf
EndFunc   ;==>_Ev_btDelete

Func _Ev_btEdit()
    Local $iEntry, $iIndex = _GUICtrlListView_GetSelectedIndices($g_MainCtrl[$MAIN_LVENTR])
    If $iIndex <> "" Then
        $iEntry = _FindEntry(_GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $iIndex), _GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $iIndex, 1))
        If Not @error Then
            $g_iEditLVIndex = $iIndex
            _EditEntry($iEntry)
        EndIf
    EndIf
EndFunc   ;==>_Ev_btEdit

Func _Ev_btEntryCancel()
    GUISetState(@SW_ENABLE, $g_MainCtrl[$MAIN_GUI])
    GUIDelete($g_EntryCtrl[$ENT_GUI])
EndFunc   ;==>_Ev_btEntryCancel

Func _Ev_btEntryOk()
    Local $iIndex, $iEntry, $sKey, $sValue, $iType, $vData

    $sKey = GUICtrlRead($g_EntryCtrl[$ENT_INKEY])
    $sValue = GUICtrlRead($g_EntryCtrl[$ENT_INVALU])
    $iType = $g_ENTRYREGTYPE_CONV[_GUICtrlComboBox_GetCurSel($g_EntryCtrl[$ENT_CBTYPE])]
    $vData = GUICtrlRead($g_EntryCtrl[$ENT_INDATA])

    Switch _GUICtrlComboBox_GetCurSel($g_EntryCtrl[$ENT_CBENTR])
        Case $ENTRY_TYPE_DEL
            $sValue = "**Del." & $sValue
            $iType = $REG_SZ
        Case $ENTRY_TYPE_DELMULVALS
            $vData = $sValue
            $sValue = "**DeleteValues"
            $iType = $REG_SZ
        Case $ENTRY_TYPE_DELALLVALS
            $sValue = "**DelVals."
            $iType = $REG_SZ
        Case $ENTRY_TYPE_DELKEYS
            $vData = $sValue
            $sValue = "**DeleteKeys" & ChrW(0)
            $iType = $REG_SZ
        Case $ENTRY_TYPE_SECKEY
            $sValue = "**SecureKey=" & _GUICtrlComboBox_GetCurSel($g_EntryCtrl[$ENT_CBTYPE])
            $iType = $REG_SZ
    EndSwitch

    $iEntry = _AddEntry($sKey, $sValue, $iType, $vData)
    If $g_iEditLVIndex == -1 Then
        $iIndex = _GUICtrlListView_AddItem($g_MainCtrl[$MAIN_LVENTR], $g_aEntries[$iEntry][$POLENTRY_KEY])
        If $iIndex <> -1 Then
            _GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $iIndex, $g_aEntries[$iEntry][$POLENTRY_VALUE], 1)
            _GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $iIndex, $g_REGTYPES[$g_aEntries[$iEntry][$POLENTRY_TYPE]], 2)
            _GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $iIndex, _GetFormattedData($iEntry), 3)
        EndIf
    Else
        Local $sLVKey, $sLVValue
        $sLVKey = _GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex)
        $sLVValue = _GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, 1)

        ; Update list view entry
        _GUICtrlListView_SetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, $g_aEntries[$iEntry][$POLENTRY_KEY])
        _GUICtrlListView_SetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, $g_aEntries[$iEntry][$POLENTRY_VALUE], 1)
        _GUICtrlListView_SetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, $g_REGTYPES[$g_aEntries[$iEntry][$POLENTRY_TYPE]], 2)
        _GUICtrlListView_SetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, _GetFormattedData($iEntry), 3)

        ; Delete old entry if necessary
        If $sLVKey <> $sKey Or $sLVValue <> $sValue Then _DeleteEntry($sLVKey, $sLVValue)
    EndIf

    _ModifyFile($g_bOpen, True)
    GUISetState(@SW_ENABLE, $g_MainCtrl[$MAIN_GUI])
    GUIDelete($g_EntryCtrl[$ENT_GUI])
EndFunc   ;==>_Ev_btEntryOk

Func _Ev_btNew()
    _EditEntry()
EndFunc   ;==>_Ev_btNew

Func _Ev_cbEntryType()
    Local $iSelected = _GUICtrlComboBox_GetCurSel($g_EntryCtrl[$ENT_CBENTR])
    If $iSelected = $g_EntryCtrl[$ENT_ILASTENTR] Then Return
    Switch $iSelected
        Case $ENTRY_TYPE_NORM
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_HIDE)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBVALU], "Value:")
            GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_SHOW)
            GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_SHOW)
            GUICtrlSetPos($g_EntryCtrl[$ENT_LBTYPE], 20, 108)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBTYPE], "Type:")
            GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_SHOW)
            GUICtrlSetPos($g_EntryCtrl[$ENT_CBTYPE], 70, 105, 240)
            _GUICtrlComboBox_ResetContent($g_EntryCtrl[$ENT_CBTYPE])
            GUICtrlSetData($g_EntryCtrl[$ENT_CBTYPE], _ArrayToString($g_ENTRYREGTYPES), $g_ENTRYREGTYPES[0])
            GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_SHOW)
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_SHOW)
            GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_SHOW)
        Case $ENTRY_TYPE_DEL
            GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBVALU], "Value:")
            GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_SHOW)
            GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_SHOW)
            GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 100)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], "Deletes the value from the associated key.")
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
        Case $ENTRY_TYPE_DELMULVALS
            GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBVALU], "Values:")
            GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_SHOW)
            GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_SHOW)
            GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 100)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], _
                StringFormat("Deletes multiple values from the associated key. Specify multiple values using a " & _
                "semicolon-delimited list.rnExample: type;size;NoRun;NoFind"))
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
        Case $ENTRY_TYPE_DELALLVALS
            GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
            GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 68)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], "Deletes all values from the associated key.")
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
        Case $ENTRY_TYPE_DELKEYS
            GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBVALU], "Subkeys:")
            GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_SHOW)
            GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_SHOW)
            GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 100)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], _
                StringFormat("Deletes multiple subkeys from the associated key. Specify multiple subkeys using a " & _
                "semicolon-delimited list.rnExample: type;size;NoRun;NoFind"))
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
        Case $ENTRY_TYPE_SECKEY
            GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
            GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
            GUICtrlSetPos($g_EntryCtrl[$ENT_LBTYPE], 20, 76)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBTYPE], "Secure:")
            GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_SHOW)
            GUICtrlSetPos($g_EntryCtrl[$ENT_CBTYPE], 70, 73, 50)
            _GUICtrlComboBox_ResetContent($g_EntryCtrl[$ENT_CBTYPE])
            GUICtrlSetData($g_EntryCtrl[$ENT_CBTYPE], "False|True", "True")
            GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_SHOW)
            GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 100)
            GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], _
                "Secures the associated key, giving administrators and the system full control, and giving " & _
                "users read-only access. If set to False, access to the key resets to whatever is set on the root.")
            GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
    EndSwitch
    $g_EntryCtrl[$ENT_ILASTENTR] = $iSelected
EndFunc   ;==>_Ev_cbEntryType

Func _Ev_miFileClose()
    If Not _CloseFile() Then Return
    Exit($GRE_ERROR_NONE)
EndFunc   ;==>_Ev_miFileClose

Func _Ev_miFileNew()
    If Not _CloseFile() Then Return
    _OpenFile()
EndFunc   ;==>_Ev_miFileNew

Func _Ev_miFileOpenFile()
    If Not _CloseFile() Then Return
    Local $sFilename = FileOpenDialog("Select GPO Registry File", "", "GPO Registry Files (*.pol)|All Files (*.*)", 3, "", $g_MainCtrl[$MAIN_GUI])
    If @error Then Return
    _OpenFile($sFilename)
EndFunc   ;==>_Ev_miFileOpenFile

Func _Ev_miFileOpenSystem()
    If Not _CloseFile() Then Return
    Switch @GUI_CtrlId
        Case $g_MainCtrl[$MAIN_MIMPOL]
            _OpenFile($MACHINE_REGISTRY_FILE)
        Case $g_MainCtrl[$MAIN_MIUPOL]
            _OpenFile($USER_REGISTRY_FILE)
    EndSwitch
EndFunc   ;==>_Ev_miFileOpenSystem

Func _Ev_miFileSave()
    Switch @GUI_CtrlId
        Case $g_MainCtrl[$MAIN_MISAVE]
            _SaveFile()
        Case $g_MainCtrl[$MAIN_MISAVA]
            _SaveFile(True)
    EndSwitch
EndFunc   ;==>_Ev_miFileSave

Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $tNMHDR, $hWndFrom, $iCode

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    If $hWndFrom = $g_MainCtrl[$MAIN_LVENTR] And $iCode == $NM_DBLCLK Then _Ev_btEdit()

    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_NOTIFY

Func __DebugPrint($sMessage, $sSource = "Info", $bOverride = False)
    If Not $g_bDebug And Not $bOverride Then Return
    Local $sLine = StringFormat("%02d%02d%04d %02d:%02d:%02d   %-20s %srn", _
        @MON, @MDAY, @YEAR, @HOUR, @MIN, @SEC, $sSource, $sMessage)
    If @Compiled Then
        FileWrite($GRE_LOG_FILE, $sLine)
    Else
        ConsoleWrite($sLine)
    EndIf
EndFunc   ;==>__DebugPrint

Func __PrintEnvironment()
    Local $sEnv = @CRLF
    $sEnv &= StringFormat("  OSVersion:    %srn", @OSVersion)
    $sEnv &= StringFormat("  OSArch:          %srn", @OSArch)
    $sEnv &= StringFormat("  AutoItX64:    %srn", @AutoItX64)
    $sEnv &= StringFormat("  WindowsDir:      %srn", @WindowsDir)
    $sEnv &= StringFormat("  SystemDir:    %srn", @SystemDir)
    $sEnv &= StringFormat("  TempDir:        %srn", @TempDir)
    $sEnv &= StringFormat("  ComSpec:        %srn", @ComSpec)
    $sEnv &= StringFormat("  ProgramFilesDir: %s", @ProgramFilesDir)

    __DebugPrint($sEnv, "__PrintEnvironment", True)
EndFunc   ;==>__PrintEnvironment

Enjoy and please let me know if there are any issues.

GRE_source.zip

**Note: On Windows Vista and above, administrator rights are required to save to the system group policy folder. Compile with the requestedExecutionLevel=requireAdministrator directive to ensure administrator access.

Edited by zorphnog

Share this post


Link to post
Share on other sites

Its very usefull! I always find a way to script it do like block executable/script on USB stick. If you do it manually you will have to create new path rules for each targetted drive letter. One question, is this tool already have export/import feature builtin?

Share this post


Link to post
Share on other sites

One question, is this tool already have export/import feature builtin?

Currently, there is not an import/export feature. It would certainly be a nice feature to implement, and I may try to add it when I have some free time.

Share this post


Link to post
Share on other sites

THANK YOU!  This was exactly what I was looking for.  I also wanted to add a couple of notes.

1. When specifying the key with -k, you need to add in the '' which isn't listed in your example.

2. If you will be using this on both x86 and x64 computers, you will need to compile 2 versions.  One for each architecture.

Share this post


Link to post
Share on other sites

Hello, I'm brand new on script compiling etc.

So when I'm running this script I'm getting an error:

line 73 cannot assign values to constants

Do you have an idea ?

thank you

Share this post


Link to post
Share on other sites

This example is 5 years old and the languages has seen many changes.
Doing a au3check on this source gives many errors, so there is some work to check all of those.

Jos

 

Share this post


Link to post
Share on other sites

danielqc,

Welcome to the AutoIt forums.

Those values are obviously now defined in one of the included files - try commenting out lines 73 & 74 and see if that helps.

M23


Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Thank you Jos an Melba23,

I commented out these line and script runs. Now I need to figure why there is no registry.pol file in /windows/system32/grouppolicy/user/

Dan

Share this post


Link to post
Share on other sites

Thank you for the tool zorphnog, and for the update Melba23.

I recently altered the local machine zone policy in such a way to render access to group policy editor impossible.

This tool help me down all the zone info the local machine, keep the rest of my group policy and give me back access to group policy editor.

However, I had to delete many entries one at a time, totaling about 100 entries.

Is there an easy way to add multiple selection for delete?

 

Thank you,

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

  • Similar Content

    • By joseLB
      Hi
      This piece of code creates and reads OK a key at  "HKEY_LOCAL_MACHINE" and can be changed for a key at "HKEY_CURRENT_USER"
      $sta= RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor", "wav", "REG_SZ", "5555") MsgBox(4096,"wrote", $sta &@cr& @error) $zz= RegRead ("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor", "wav") MsgBox(4096,"readed","="&$zz &@cr& @error) Exit With  HKEY_CURRENT_USER, in RegEdit we can see the created key, and we can create the key by hand/RegEdit and everything Works OK.
      At  HKEY_LOCAL_MACHINE we can´t see the created key above  thru RegEdit, but it Works (even not seeing, I can read). But  if I create "by hand"/RegEdit  the key,  it can´t read it with   $zz= RegRead  ("HKEY_LOCAL_MACHINE.... above.
      I´m the PC´s WIN.7 administrator. Even so I ran RegEdit as administrator and also the compiled AU3 and also plain. No changes.
      edit: even if Try   "HKEY_LOCAL_MACHINE\SOFTWARE\AAA", "wav", the same holds true.
      $sta= RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\AAA", "wav", "REG_SZ", "4444") MsgBox(4096,"wrote", $sta &@cr& @error) $zz= RegRead ("HKEY_LOCAL_MACHINE\SOFTWARE\AAA", "wav") MsgBox(4096,"readed","="&$zz &@cr& @error) Exit Seems that it creates this key at another place.... I can read the above value ("4444"), even after a boot, even the key not showing in regedit. And if I create it by hand key AAA/wav with a distinct value (666), t, it continues Reading the old value = 444.
      Thanks
      Jose
       
    • By nacerbaaziz
      good morning everybody.
      today i liked to share an small example with you
      which it an function to read the registry values as an array
      the result array is 2d array witch
      $a_array[n][0] = value name
      $a_array[n][1] = value Data
      $a_array[0][0] = values count
      here's the function

      #include <Array.au3> #include <WinAPIReg.au3> #include <APIRegConstants.au3> Local $a_array = _RegReadToArray("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run") If @error Then     MsgBox(16, "error", @error)     Exit EndIf _ArrayDisplay($a_array) Func _RegReadToArray($s_RegKey)     Local $a_KeySplitInfo = StringSplit($s_RegKey, "\\", 2)     If UBound($a_KeySplitInfo) <= 1 Then         $a_KeySplitInfo = StringSplit($s_RegKey, "\", 2)         If UBound($a_KeySplitInfo) <= 1 Then Return (1, 1, 0)     EndIf     Local $H_KeyInfo = "", $s_RegKeyInfo = ""     Switch $a_KeySplitInfo[0]         Case "hklm", "HKEY_LOCAL_MACHINE", "hklm64", "HKEY_LOCAL_MACHINE64"             $H_KeyInfo = $HKEY_LOCAL_MACHINE         Case "hkCu", "HKEY_CURRENT_USER", "hkCU64", "HKEY_CURRENT_USER64"             $H_KeyInfo = $HKEY_CURRENT_USER         Case "hkCr", "HKEY_CLASSES_ROOT", "HKCR64", "HKEY_CLASSES_ROOT64"             $H_KeyInfo = $HKEY_CLASSES_ROOT         Case "HKU", "HKEY_USERS", "HKU64", "HKEY_USERS64"             $H_KeyInfo = $HKEY_USERS         Case Else             Return SetError(2, 2, 0)     EndSwitch     _ArrayDelete($a_KeySplitInfo, 0)     $s_RegKeyInfo = _ArrayToString($a_KeySplitInfo, "\")     Local $H_KeyInfoOpen = _WinAPI_RegOpenKey($H_KeyInfo, $s_RegKeyInfo, $KEY_READ)     Local $A_KeyInfo = _WinAPI_RegQueryInfoKey($H_KeyInfoOpen)     If @error Then Return SetError(1, 1, 0)     _WinAPI_RegCloseKey($H_KeyInfoOpen)     Local $A_RegVal[$A_KeyInfo[2] + 1][2]     Local $iV = 1, $s_RegRead = ""     While 1         $s_RegVal = RegEnumVal($s_RegKey, $iV)         If @error <> 0 Then ExitLoop         $s_RegRead = RegRead($s_RegKey, $s_RegVal)         If Not (@error) Then             $A_RegVal[$iV][0] = $s_RegVal             $A_RegVal[$iV][1] = $s_RegRead         EndIf         $iV += 1     WEnd     $A_RegVal[0][0] = UBound($A_RegVal) - 1     If $A_RegVal[0][0] >= 1 Then         Return $A_RegVal     Else         Return SetError(3, 3, 0)     EndIf EndFunc   ;==>_RegReadToArray
      i hope you benefit from it
      with my greetings
    • By Xandy
      What's new section:
      Snowman_Sky is game using MapIt engine.  MapIt will evolve here for a little bit.
      Download: [ http://songersoft.com/programming/Snowman_Sky.zip ]
      Video demonstrating new sprite_sheet class and weather effect.
      Working on the Class section of the Character Sheet.
      Which is what makes multiclassing possible.

      Changing the value of Class will load the stored value for XP.  Lvl will be updated to the XP tier.
      Hit points are then rolled for each level of all learned classes.  Hit dice are specific to each class and a Constitution modifier is added to each roll of hit die.
       
    • By Simpel
      Hi,
      I wondered why negative integers I wrote into registry (e.g. negative x-coordinates of a gui if using two monitors and the right one is the main one) wouldn't return right when reading. Now I know: it is saved as an unsigned integer (without algebraic sign). So here is a snippet that is changing unsigned to signed integer:
      Global Const $g_sRegKey = "HKEY_CURRENT_USER\Software\" & @ScriptName ; path to registry RegWrite($g_sRegKey, "Value", "REG_DWORD", -2147483647) ; write some negative integer into registry; -2147483647 highest possible negative integer , 2147483648 highest possible positive integer if talking of 32bit Local $sValue = RegRead($g_sRegKey, "Value") ; read out registry ConsoleWrite("Value: " & $sValue & @CRLF) ; show real value in console Local $sResult = _SignedInteger($sValue) ; change to signed value ConsoleWrite("Result: " & $sResult & @CRLF) ; and show it in console Func _SignedInteger($iUnsignedInteger) Local $iSignedInteger If $iUnsignedInteger > (2^31) Then ; then it means a negative integer $iSignedInteger = $iUnsignedInteger - (2^32) Else $iSignedInteger = $iUnsignedInteger EndIf Return $iSignedInteger EndFunc It took me some time to find out the problem and so I hope I can help somebody with this.
      Regards, Conrad
    • By AdamUL
      Below are some functions that I created when I needed to get some Group Policy information via script.  The quickest way I found to get this information was using the Group Policy Module for PowerShell.  This is not a full UDF for the Group Policy Module.  There are a lot more options available with the cmdlets, and this only touches on a few.  To use the functions below, for a Windows client, you will need to install Remote Server Administration Tools (RSAT).  For Windows Server 2012 or later, you will need to install the Group Policy Management Console.  
      Remote Server Administration Tools (RSAT)
      Installing the Group Policy Management Console via PowerShell for Windows Server 2012 or later.  Run in an Admin PowerShell prompt.
      Install-WindowsFeature –Name GPMC PowerShell Group Policy Module Documentation
      For the example below, the AD UDF is only required to query GPO names, but is not required to use the functions.  
      #include <AD.au3> #include <WinAPIFiles.au3> Global $sLDAPFilter = "(name=*)" Global $sExcludeFilter = "" Global $sIncludeFilter = "" Global $sBaseDN = "DC=ad,DC=university,DC=edu" Global $sDataToRetrieve = "sAMAccountName" $sIncludeFilter = "(&(displayName=LIBS-*))" ;GPO Names. $sLDAPFilter = "(&(objectClass=groupPolicyContainer)" & $sExcludeFilter & $sIncludeFilter & ")" $sDataToRetrieve = "displayName,name" _AD_Open() Global $aGPONames = _AD_GetObjectsInOU($sBaseDN, $sLDAPFilter, 2, $sDataToRetrieve) If @error Then MsgBox(64, "Active Directory Functions", "No objects found") Exit _AD_Close() EndIf _AD_Close() ;Add column headers to the output array. Global $aDataToRetrieve = StringSplit($sDataToRetrieve, ",", 2) For $i = 0 To UBound($aGPONames, 2) - 1 Step 1 $aGPONames[0][$i] = $aDataToRetrieve[$i] Next _ArraySort($aGPONames) _ArrayDisplay($aGPONames, "LIBS GPOs") ;For Testing. Global $aGPOPermissions = _AD_GetGPOPermissionsPS($aGPONames[1][0]) If @error Then Exit 1 _ArrayDisplay($aGPOPermissions, $aGPONames[1][0]) Global $sOU = "OU=libs,OU=active,DC=ad,DC=university,DC=edu" Global $aGPOLinks = _AD_GetGPOLinksPS($sOU) If @error Then Exit 2 _ArrayDisplay($aGPOLinks, $sOU) Global $aGPOInheritedLinks = _AD_GetGPOInheritedLinksPS($sOU) If @error Then Exit 2 _ArrayDisplay($aGPOInheritedLinks, $sOU) Global $aGPOs = _AD_GetAllGPOsPS() If @error Then Exit 3 _ArraySort($aGPOs) _ArrayDisplay($aGPOs, "GPOs") Global $aGPOName = _AD_GetGPOByNamePS($aGPONames[1][0]) If @error Then Exit 4 _ArrayDisplay($aGPOName, $aGPONames[1][0]) Global $aGPOGuid = _AD_GetGPOByGuidPS($aGPONames[1][1]) If @error Then Exit 5 _ArrayDisplay($aGPOGuid, $aGPONames[1][1]) Global $sReportName = "C:\Users\adamul\Desktop\Group Policy Object (GPO) PowerShell\Reports\" & $aGPONames[1][0] & ".html" _AD_GetGPOReportByNamePS($aGPONames[1][0], $sReportName) If @error Then Exit 6 Global $sReportGUID = "C:\Users\adamul\Desktop\Group Policy Object (GPO) PowerShell\Reports\" & $aGPONames[1][1] & ".html" _AD_GetGPOReportByGuidPS($aGPONames[1][1], $sReportGUID) If @error Then Exit 6 Func _AD_GetGPOPermissionsPS($sGPOName) ;An array of permission level for one or more security principals on a specified GPO. Local $sGPOCmd = 'powershell "Import-Module GroupPolicy; Get-GPPermissions -Name ''' & $sGPOName & ''' -All"' ConsoleWrite($sGPOCmd & @CRLF) ;Turn off redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(False) Local $iPIDGPOCmd = Run($sGPOCmd, @SystemDir, @SW_HIDE, $STDERR_MERGED) ProcessWaitClose($iPIDGPOCmd) ;Turn on redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(True) Local $sGPOCmdOutput = StringStripWS(StdoutRead($iPIDGPOCmd), 3) ;~ ConsoleWrite($sGPOCmdOutput & @CRLF & @CRLF) ;For testing. Local $iGPOCmdOutputSS = StringInStr($sGPOCmdOutput, @CRLF & @CRLF) If $iGPOCmdOutputSS = 0 Then Return SetError(1, 0, 0) Local $sGPOCmdOutputSS = StringMid($sGPOCmdOutput, 1, $iGPOCmdOutputSS) ;~ ConsoleWrite(@CRLF & @CRLF & $sGPOCmdOutputSS & @CRLF) Local $sRegEx = "([^:\r\n]*):.*" Local $aProperties = StringRegExp($sGPOCmdOutputSS, $sRegEx, 3) ;~ _ArrayDisplay($aProperties) ;For testing. If StringInStr($sGPOCmdOutput, "ArgumentException") Then Return SetError(2, 0, 0) ;Get data on multiple lines to a single line. $sGPOCmdOutput = StringRegExpReplace($sGPOCmdOutput, "(\r\n\h{2,})", "") Local $aGPOCmdOutput = StringSplit($sGPOCmdOutput, @CRLF & @CRLF, 1) ;~ _ArrayDisplay($aGPOCmdOutput) ;For testing. ;Convert from a list output to a 2D array. Local $aGPOCmdOutput2D[$aGPOCmdOutput[0]][UBound($aProperties)] Local $aTemp For $i = 1 To $aGPOCmdOutput[0] Step 1 $aTemp = StringSplit($aGPOCmdOutput[$i], @CRLF, 1) For $j = 1 To $aTemp[0] Step 1 For $k = 0 To UBound($aProperties) - 1 Step 1 If StringInStr($aTemp[$j], $aProperties[$k]) Then $aGPOCmdOutput2D[$i - 1][$k] = StringStripWS(StringReplace($aTemp[$j], $aProperties[$k] & ":", ""), 3) EndIf Next Next Next ;~ _ArrayDisplay($aGPOCmdOutput2D) ;For testing. For $i = 0 To UBound($aProperties) - 1 Step 1 $aProperties[$i] = StringStripWS($aProperties[$i], 3) Next _ArrayTranspose($aProperties) _ArrayConcatenate($aProperties, $aGPOCmdOutput2D) Return $aProperties EndFunc ;==>_AD_GetGPOPermissionsPS Func _AD_GetGPOLinksPS($sOUName) ;An array of GPOs that are linked directly to the location. Local $sGPOCmd = 'powershell "Import-Module GroupPolicy; (Get-GPInheritance -Target ''' & $sOUName & "').GpoLinks" ConsoleWrite($sGPOCmd & @CRLF) ;Turn off redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(False) Local $iPIDGPOCmd = Run($sGPOCmd, @SystemDir, @SW_HIDE, $STDERR_MERGED) ProcessWaitClose($iPIDGPOCmd) ;Turn on redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(True) Local $sGPOCmdOutput = StringStripWS(StdoutRead($iPIDGPOCmd), 3) ;~ ConsoleWrite($sGPOCmdOutput & @CRLF & @CRLF) ;For testing. Local $iGPOCmdOutputSS = StringInStr($sGPOCmdOutput, @CRLF & @CRLF) If $iGPOCmdOutputSS = 0 Then Return SetError(1, 0, 0) Local $sGPOCmdOutputSS = StringMid($sGPOCmdOutput, 1, $iGPOCmdOutputSS) ;~ ConsoleWrite(@CRLF & @CRLF & $sGPOCmdOutputSS & @CRLF) ;For testing. Local $sRegEx = "([^:\r\n]*):.*" Local $aProperties = StringRegExp($sGPOCmdOutputSS, $sRegEx, 3) ;~ _ArrayDisplay($aProperties) ;For testing. If StringInStr($sGPOCmdOutput, "ArgumentException") Then Return SetError(1, 0, 0) ;Get data on multiple lines to a single line. $sGPOCmdOutput = StringRegExpReplace($sGPOCmdOutput, "(\r\n\h{2,})", "") Local $aGPOCmdOutput = StringSplit($sGPOCmdOutput, @CRLF & @CRLF, 1) ;~ _ArrayDisplay($aGPOCmdOutput) ;For testing. ;Convert from a list output to a 2D array. Local $aGPOCmdOutput2D[$aGPOCmdOutput[0]][UBound($aProperties)] Local $aTemp For $i = 1 To $aGPOCmdOutput[0] Step 1 $aTemp = StringSplit($aGPOCmdOutput[$i], @CRLF, 1) For $j = 1 To $aTemp[0] Step 1 For $k = 0 To UBound($aProperties) - 1 Step 1 If StringInStr($aTemp[$j], $aProperties[$k]) Then $aGPOCmdOutput2D[$i - 1][$k] = StringStripWS(StringReplace($aTemp[$j], $aProperties[$k] & ":", ""), 3) EndIf Next Next Next ;~ _ArrayDisplay($aGPOCmdOutput2D) ;For testing. For $i = 0 To UBound($aProperties) - 1 Step 1 $aProperties[$i] = StringStripWS($aProperties[$i], 3) Next _ArrayTranspose($aProperties) _ArrayConcatenate($aProperties, $aGPOCmdOutput2D) Return $aProperties EndFunc ;==>_AD_GetGPOLinksPS Func _AD_GetGPOInheritedLinksPS($sOUName) ;An array of GPOs that are applied to the location when Group Policy is processed on a client. Local $sGPOCmd = 'powershell "Import-Module GroupPolicy; (Get-GPInheritance -Target ''' & $sOUName & "').InheritedGpoLinks" ConsoleWrite($sGPOCmd & @CRLF) ;Turn off redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(False) Local $iPIDGPOCmd = Run($sGPOCmd, @SystemDir, @SW_HIDE, $STDERR_MERGED) ProcessWaitClose($iPIDGPOCmd) ;Turn on redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(True) Local $sGPOCmdOutput = StringStripWS(StdoutRead($iPIDGPOCmd), 3) ;~ ConsoleWrite($sGPOCmdOutput & @CRLF & @CRLF) ;For testing. Local $iGPOCmdOutputSS = StringInStr($sGPOCmdOutput, @CRLF & @CRLF) If $iGPOCmdOutputSS = 0 Then Return SetError(1, 0, 0) Local $sGPOCmdOutputSS = StringMid($sGPOCmdOutput, 1, $iGPOCmdOutputSS) ;~ ConsoleWrite(@CRLF & @CRLF & $sGPOCmdOutputSS & @CRLF) ;For testing. Local $sRegEx = "([^:\r\n]*):.*" Local $aProperties = StringRegExp($sGPOCmdOutputSS, $sRegEx, 3) ;~ _ArrayDisplay($aProperties) ;For testing. If StringInStr($sGPOCmdOutput, "ArgumentException") Then Return SetError(1, 0, 0) ;Get data on multiple lines to a single line. $sGPOCmdOutput = StringRegExpReplace($sGPOCmdOutput, "(\r\n\h{2,})", "") Local $aGPOCmdOutput = StringSplit($sGPOCmdOutput, @CRLF & @CRLF, 1) ;~ _ArrayDisplay($aGPOCmdOutput) ;For testing. ;Convert from a list output to a 2D array. Local $aGPOCmdOutput2D[$aGPOCmdOutput[0]][UBound($aProperties)] Local $aTemp For $i = 1 To $aGPOCmdOutput[0] Step 1 $aTemp = StringSplit($aGPOCmdOutput[$i], @CRLF, 1) For $j = 1 To $aTemp[0] Step 1 For $k = 0 To UBound($aProperties) - 1 Step 1 If StringInStr($aTemp[$j], $aProperties[$k]) Then $aGPOCmdOutput2D[$i - 1][$k] = StringStripWS(StringReplace($aTemp[$j], $aProperties[$k] & ":", ""), 3) EndIf Next Next Next ;~ _ArrayDisplay($aGPOCmdOutput2D) ;For testing. For $i = 0 To UBound($aProperties) - 1 Step 1 $aProperties[$i] = StringStripWS($aProperties[$i], 3) Next _ArrayTranspose($aProperties) _ArrayConcatenate($aProperties, $aGPOCmdOutput2D) Return $aProperties EndFunc ;==>_AD_GetGPOInheritedLinksPS Func _AD_GetAllGPOsPS() ;An array of information on all the GPOs in a domain. Local $sGPOCmd = 'powershell "Import-Module GroupPolicy; Get-GPO -All"' ConsoleWrite($sGPOCmd & @CRLF) ;Turn off redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(False) Local $iPIDGPOCmd = Run($sGPOCmd, @SystemDir, @SW_HIDE, $STDERR_MERGED) ProcessWaitClose($iPIDGPOCmd) ;Turn on redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(True) Local $sGPOCmdOutput = StringStripWS(StdoutRead($iPIDGPOCmd), 3) ;~ ConsoleWrite($sGPOCmdOutput & @CRLF & @CRLF) ;For testing. Local $iGPOCmdOutputSS = StringInStr($sGPOCmdOutput, @CRLF & @CRLF) If $iGPOCmdOutputSS = 0 Then Return SetError(1, 0, 0) Local $sGPOCmdOutputSS = StringMid($sGPOCmdOutput, 1, $iGPOCmdOutputSS) ;~ ConsoleWrite(@CRLF & @CRLF & $sGPOCmdOutputSS & @CRLF) ;For testing. Local $sRegEx = "([^:\r\n]*):.*" Local $aProperties = StringRegExp($sGPOCmdOutputSS, $sRegEx, 3) ;~ _ArrayDisplay($aProperties) If StringInStr($sGPOCmdOutput, "ArgumentException") Then Return SetError(1, 0, 0) ;Get data on multiple lines to a single line. $sGPOCmdOutput = StringRegExpReplace($sGPOCmdOutput, "(\r\n\h{2,})", "") Local $aGPOCmdOutput = StringSplit($sGPOCmdOutput, @CRLF & @CRLF, 1) ;~ _ArrayDisplay($aGPOCmdOutput) ;For testing. ;Convert from a list output to a 2D array. Local $aGPOCmdOutput2D[$aGPOCmdOutput[0]][UBound($aProperties)] Local $aTemp For $i = 1 To $aGPOCmdOutput[0] Step 1 $aTemp = StringSplit($aGPOCmdOutput[$i], @CRLF, 1) For $j = 1 To $aTemp[0] Step 1 For $k = 0 To UBound($aProperties) - 1 Step 1 If StringInStr($aTemp[$j], $aProperties[$k]) Then $aGPOCmdOutput2D[$i - 1][$k] = StringStripWS(StringReplace($aTemp[$j], $aProperties[$k] & ":", ""), 3) EndIf Next Next Next ;~ _ArrayDisplay($aGPOCmdOutput2D) ;For testing. For $i = 0 To UBound($aProperties) - 1 Step 1 $aProperties[$i] = StringStripWS($aProperties[$i], 3) Next _ArrayTranspose($aProperties) _ArrayConcatenate($aProperties, $aGPOCmdOutput2D) Return $aProperties EndFunc ;==>_AD_GetAllGPOsPS Func _AD_GetGPOByNamePS($sGPOName) ;An array of information on one Group Policy Object (GPO) in a domain by Display Name. Local $sGPOCmd = 'powershell "Import-Module GroupPolicy; Get-GPO -Name ''' & $sGPOName & '''"' ConsoleWrite($sGPOCmd & @CRLF) ;Turn off redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(False) Local $iPIDGPOCmd = Run($sGPOCmd, @SystemDir, @SW_HIDE, $STDERR_MERGED) ProcessWaitClose($iPIDGPOCmd) ;Turn on redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(True) Local $sGPOCmdOutput = StringStripWS(StdoutRead($iPIDGPOCmd), 3) ;~ ConsoleWrite($sGPOCmdOutput & @CRLF & @CRLF) ;For testing. ;Add end of line characters for single return group to be processed. $sGPOCmdOutput = $sGPOCmdOutput & @CRLF & @CRLF Local $iGPOCmdOutputSS = StringInStr($sGPOCmdOutput, @CRLF & @CRLF) If $iGPOCmdOutputSS = 0 Then Return SetError(1, 0, 0) Local $sGPOCmdOutputSS = StringMid($sGPOCmdOutput, 1, $iGPOCmdOutputSS) ConsoleWrite(@CRLF & @CRLF & $sGPOCmdOutputSS & @CRLF) Local $sRegEx = "([^:\r\n]*):.*" Local $aProperties = StringRegExp($sGPOCmdOutputSS, $sRegEx, 3) ;~ _ArrayDisplay($aProperties) ;For testing. If StringInStr($sGPOCmdOutput, "ArgumentException") Then Return SetError(1, 0, 0) ;Get data on multiple lines to a single line. $sGPOCmdOutput = StringRegExpReplace($sGPOCmdOutput, "(\r\n\h{2,})", "") ;Remove last @CRLF to prevent blank row in return array. $sGPOCmdOutput = StringTrimRight($sGPOCmdOutput, 2) Local $aGPOCmdOutput = StringSplit($sGPOCmdOutput, @CRLF & @CRLF, 1) ;~ _ArrayDisplay($aGPOCmdOutput) ;For testing. ;Convert from a list output to a 2D array. Local $aGPOCmdOutput2D[$aGPOCmdOutput[0]][UBound($aProperties)] ;~ _ArrayDisplay($aGPOCmdOutput2D) ;For testing. Local $aTemp For $i = 1 To $aGPOCmdOutput[0] Step 1 $aTemp = StringSplit($aGPOCmdOutput[$i], @CRLF, 1) For $j = 1 To $aTemp[0] Step 1 For $k = 0 To UBound($aProperties) - 1 Step 1 If StringInStr($aTemp[$j], $aProperties[$k]) Then $aGPOCmdOutput2D[$i - 1][$k] = StringStripWS(StringReplace($aTemp[$j], $aProperties[$k] & ":", ""), 3) EndIf Next Next Next ;~ _ArrayDisplay($aGPOCmdOutput2D) ;For testing. For $i = 0 To UBound($aProperties) - 1 Step 1 $aProperties[$i] = StringStripWS($aProperties[$i], 3) Next _ArrayTranspose($aProperties) _ArrayConcatenate($aProperties, $aGPOCmdOutput2D) Return $aProperties EndFunc ;==>_AD_GetGPOByNamePS Func _AD_GetGPOByGuidPS($sGPOGuid) ;An array of information on one Group Policy Object (GPO) in a domain by GUID. Local $sGPOCmd = 'powershell "Import-Module GroupPolicy; Get-GPO -Guid ''' & $sGPOGuid & '''"' ConsoleWrite($sGPOCmd & @CRLF) ;Turn off redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(False) Local $iPIDGPOCmd = Run($sGPOCmd, @SystemDir, @SW_HIDE, $STDERR_MERGED) ProcessWaitClose($iPIDGPOCmd) ;Turn on redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(True) Local $sGPOCmdOutput = StringStripWS(StdoutRead($iPIDGPOCmd), 3) ;~ ConsoleWrite($sGPOCmdOutput & @CRLF & @CRLF) ;For testing. ;Add end of line characters for single return group to be processed. $sGPOCmdOutput = $sGPOCmdOutput & @CRLF & @CRLF Local $iGPOCmdOutputSS = StringInStr($sGPOCmdOutput, @CRLF & @CRLF) If $iGPOCmdOutputSS = 0 Then Return SetError(1, 0, 0) Local $sGPOCmdOutputSS = StringMid($sGPOCmdOutput, 1, $iGPOCmdOutputSS) ;~ ConsoleWrite(@CRLF & @CRLF & $sGPOCmdOutputSS & @CRLF) ;For testing. Local $sRegEx = "([^:\r\n]*):.*" Local $aProperties = StringRegExp($sGPOCmdOutputSS, $sRegEx, 3) ;~ _ArrayDisplay($aProperties) ;For testing. If StringInStr($sGPOCmdOutput, "ArgumentException") Then Return SetError(1, 0, 0) ;Get data on multiple lines to a single line. $sGPOCmdOutput = StringRegExpReplace($sGPOCmdOutput, "(\r\n\h{2,})", "") ;Remove last @CRLF to prevent blank row in return array. $sGPOCmdOutput = StringTrimRight($sGPOCmdOutput, 2) Local $aGPOCmdOutput = StringSplit($sGPOCmdOutput, @CRLF & @CRLF, 1) ;~ _ArrayDisplay($aGPOCmdOutput) ;For testing. ;Convert from a list output to a 2D array. Local $aGPOCmdOutput2D[$aGPOCmdOutput[0]][UBound($aProperties)] ;~ _ArrayDisplay($aGPOCmdOutput2D) Local $aTemp For $i = 1 To $aGPOCmdOutput[0] Step 1 $aTemp = StringSplit($aGPOCmdOutput[$i], @CRLF, 1) For $j = 1 To $aTemp[0] Step 1 For $k = 0 To UBound($aProperties) - 1 Step 1 If StringInStr($aTemp[$j], $aProperties[$k]) Then $aGPOCmdOutput2D[$i - 1][$k] = StringStripWS(StringReplace($aTemp[$j], $aProperties[$k] & ":", ""), 3) EndIf Next Next Next ;~ _ArrayDisplay($aGPOCmdOutput2D) ;For testing. For $i = 0 To UBound($aProperties) - 1 Step 1 $aProperties[$i] = StringStripWS($aProperties[$i], 3) Next _ArrayTranspose($aProperties) _ArrayConcatenate($aProperties, $aGPOCmdOutput2D) Return $aProperties EndFunc ;==>_AD_GetGPOByGuidPS Func _AD_GetGPOReportByNamePS($sGPOName, $sReportFullPath, $sReportType = "HTML") ;Generates a report either in XML or HTML format for a specified GPO by name in a domain. Switch $sReportType Case "HTML", "XML" Case Else Return SetError(1, 0, False) EndSwitch Local $sPath = StringRegExpReplace($sReportFullPath, "(^.*\\)(.*)", "$1") ;~ ConsoleWrite($sPath & @CRLF) ;For testing. ;~ If Not FileExists($sPath) Then Return SetError(2, 0, False) Local $sGPOCmd = 'powershell "Get-GPOReport -Name ''' & $sGPOName & ''' -ReportType ' & $sReportType & ' -Path ''' & $sReportFullPath & '''"' ConsoleWrite($sGPOCmd & @CRLF) ;Turn off redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(False) Local $iPIDGPOCmd = Run($sGPOCmd, @SystemDir, @SW_HIDE, $STDERR_MERGED) ProcessWaitClose($iPIDGPOCmd) ;Turn on redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(True) Local $sGPOCmdOutput = StringStripWS(StdoutRead($iPIDGPOCmd), 3) ;~ ConsoleWrite($sGPOCmdOutput & @CRLF & @CRLF) ;For testing. If $sGPOCmdOutput <> "" Then SetError(3, 0, False) Return True EndFunc ;==>_AD_GetGPOReportByNamePS Func _AD_GetGPOReportByGuidPS($sGPOGuid, $sReportFullPath, $sReportType = "HTML") ;Generates a report either in XML or HTML format for a specified GPO by GUID in a domain. Switch $sReportType Case "HTML", "XML" Case Else Return SetError(1, 0, False) EndSwitch Local $sPath = StringRegExpReplace($sReportFullPath, "(^.*\\)(.*)", "$1") ;~ ConsoleWrite($sPath & @CRLF) ;For testing. ;~ If Not FileExists($sPath) Then Return SetError(2, 0, False) Local $sGPOCmd = 'powershell "Get-GPOReport -GUID ''' & $sGPOGuid & ''' -ReportType ' & $sReportType & ' -Path ''' & $sReportFullPath & '''"' ConsoleWrite($sGPOCmd & @CRLF) ;Turn off redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(False) Local $iPIDGPOCmd = Run($sGPOCmd, @SystemDir, @SW_HIDE, $STDERR_MERGED) ProcessWaitClose($iPIDGPOCmd) ;Turn on redirection for a 32-bit script on 64-bit system. If @OSArch = "X64" And Not @AutoItX64 Then _WinAPI_Wow64EnableWow64FsRedirection(True) Local $sGPOCmdOutput = StringStripWS(StdoutRead($iPIDGPOCmd), 3) ;~ ConsoleWrite($sGPOCmdOutput & @CRLF & @CRLF) ;For testing. If $sGPOCmdOutput <> "" Then SetError(3, 0, False) Return True EndFunc ;==>_AD_GetGPOReportByGuidPS  
      Adam
       
×
×
  • Create New...