Jump to content
t0nZ

Password Expiration Guardian

Recommended Posts

t0nZ

Today I want to share this little project made to check and  notify the expiration of domain users password, in a Microsoft domain.

Briefly, the script check users domain password expiration and takes actions.
The script can work on multiple domain groups, taking different actions for every group, there is an .ini file with some options.

Groups to be checked are defined in the .ini, and the groups must contain only users no other groups.
The list of users of every group is obtained and if the password expiration in (remaining) days is matched (two possibilities) an email is sent.
It can be a mail sent directly to the user (ini file : tomail=user) or it can be a mail sent to only one address (ini file : tomail=the@mail.it) (like domain admins...) and in this case the mail contains a report with the users approaching expiration.

An operation log is always generated.

In the ini (also the posted one) you can set to have no mail sent (for testing) and/or to have a GUI, but also the GUI is intended only for test, this script is scheduled on a server not logged in, so normally no GUI .

Update 2018/03/16 : added switch to reset the password expiration, useful if you have for example an user (or 500) with psw expiration withing 3 days and you want to restore expiration within 90 days WITHOUT changing password.

Used the way as advised by Microsoft  (see the link), but with sth AD.au3 , the fantastic Active Directory UDF

# First change the pwdlastset to 0 because Microsoft wants it this way 
    $todouser.pwdLastSet = 0 
    Set-ADUser -Instance $todouser 
     
    # Change the pwdlastset to the current date/time of the associate DC 
    $todouser.pwdLastSet = -1 
    Set-ADUser -Instance $todouser

Why you should act this way ? Big companies have strange policies listen to me :shifty:...

The code:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=Icone\Faenza\117.ico
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
; PEG
; Password Expiration Guardian
; (C) NSC 2018
; check user domain password expiration and takes actions
; the script can work on multiple domain groups, taking differente actions for every group.
; the groups must contains only users no other groups
; the list of users of every group is obtained and if the password expiration in day is matched (two possibilities) an email is sent.
; It can be a mail sent directly to the user (ini file : tomail=user)
; or it can be a mail sent to only one address (ini file : tomail=the@mail.it)
; and in this case the mail contains a report with the users approaching expiration
; V.0.5 check based on one domain group
; V.1.0 ini file and check based on multiple domain groups
; V.1.5 ini file with general section to activate "test" GUI, and to enable disable mail send
; V.1.6 march 2018 italian "home made" translation of days and months in date
; V.1.7 added flag pwdLastSet to reset pass expiration - intended to use like a one time on/off switch to reset psw expiration

#include <AD.au3>
#include <File.au3>
#include <GuiEdit.au3>
#include <_zip.au3>
#include <Date.au3>
#include <Inet.au3>
#include <GUIConstantsEx.au3>
#include <GuiEdit.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Debug.au3>

Global $appname = "PEG", $appver = "V.1.7"
Global $inifile = @ScriptDir & "\" & $appname & ".ini"
Global $geleft = 5, $getop = 5, $gewidth = 790, $geheight = 540
Global $gollogcount = 0, $lastlog = "sicrlf", $cachelog = "", $guititle = "PEG " & $appver, $Gollogedit, $logfile = @ScriptDir & "\" & $appname & "_LOG_", $months2NOTzip = 3
Global $INIgroup, $INItomail, $INImailsubject, $INIsmpt, $INIfromname, $INIfromaddress, $INIdays1, $INIdays2, $INItosend, $arrayINIsections, $guiactive, $flagITA, $flagpwdLastSet

; START program
GOLLOG(">>>>>> " & $appname & " " & $appver & " START >>>>>>")

CFGctrl()

If $guiactive = 1 Then GUI()

$groupnumber = 0
While $groupnumber < $arrayINIsections[0]
    $groupnumber += 1
    If $arrayINIsections[$groupnumber] <> "general" Then

        CFGload($arrayINIsections[$groupnumber])
        loaduserS()
    EndIf
WEnd

If $guiactive = 1 Then
    While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE
                GOLLOG("<<<< STOP <<<<")
                Exit
        EndSwitch
    WEnd
EndIf

GOLLOG("<<<<<< PEG STOP <<<<<<<")
Exit
;STOP program

Func GUI()
    GUICreate($guititle, 800, 560, 100, 200, -1)
    GUISetBkColor(0x693F54) ; will change background color
    $Gollogedit = GUICtrlCreateEdit("", $geleft, $getop, $gewidth, $geheight, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_WANTRETURN, $WS_BORDER, $WS_VSCROLL))
    GUICtrlSetBkColor(-1, 0xC7BBC1)
    GUICtrlSetData(-1, "" & @CRLF)
    GUICtrlSetFont(-1, 9, 800, 0, "consolas")
    GUICtrlSetColor(-1, 0x090608)

    GUISetState(@SW_SHOW)
    GOLLOG("PEG " & $appver & " gui STARTED")

EndFunc   ;==>GUI

Func loaduserS()
    GOLLOG("workin on group: " & $INIgroup)

    Local $Nscad = 0
    Dim $report[1] = ["Report:"]
    Local $singlereport = ""
    Local $usermail = ""
    Local $username = ""
    Local $datediff = ""
    Local $arrayuserpsw
    Local $iErr
    _AD_Open()

    $search1 = _AD_GetGroupMembers($INIgroup)
    ;$search1 = _AD_RecursiveGetGroupMembers($INIgroup); testing recursive .. in the future maybe
    If @error = 0 Then
        Local $conta1 = 0
        While $search1[0] > $conta1
            $conta1 += 1
            $arrayuserpsw = _AD_GetPasswordInfo($search1[$conta1])
            $datediff = _DateDiff("D", _NowCalc(), $arrayuserpsw[9])
            GOLLOG("USER: " & $search1[$conta1])
            GOLLOG("Password expires on: " & $arrayuserpsw[9] & " in " & $datediff & " days")
            If $datediff = $INIdays1 Or $datediff = $INIdays2 Then
                GOLLOG("expiration match !")
                If $INItomail = "user" Then ; this IF is relative to .ini file parameter TOSEND
                    $usermail = _AD_GetObjectAttribute($search1[$conta1], "mail")
                    GOLLOG("sending mail to: " & $usermail)
                    If $flagITA = 1 Then
                        $dataITA = dataITA($arrayuserpsw[9])
                    Else
                        $dataITA = _DateTimeFormat($arrayuserpsw[9], 1)
                    EndIf
                    Dim $report[1] = ["La tua password scadra' " & $dataITA & ", entro " & $datediff & " giorni."]
                    _ArrayAdd($report, "Modificala per tempo !")
                    If $INItosend = 0 Then
                        GOLLOG("Not sent mail " & $Nscad & ": ")
                        GOLLOG("from :" & $INIfromname & " | " & $INIfromaddress)
                        GOLLOG("to   :" & $usermail & " | subject: " & $INImailsubject)
                        Local $reporttext = _ArrayToString($report)
                        GOLLOG("text :" & $reporttext)
                    Else
                        Local $iResponse = _INetSmtpMail($INIsmpt, $INIfromname, $INIfromaddress, $usermail, $INImailsubject, $report, "EHLO " & @ComputerName, "-1") ; perla pearl mail send HS smtp (ehlo required)
                        $iErr = @error
                        If $iResponse = 1 Then
                            GOLLOG("Success! " & "Mail to user sent")
                        Else
                            GOLLOG("Error! " & "Mail failed with error code " & $iErr)
                        EndIf
                    EndIf
                Else
                    $username = _AD_GetObjectAttribute($search1[$conta1], "displayname")
                    _ArrayAdd($report, "USER: " & $username)
                    _ArrayAdd($report, "Password expires on: " & $arrayuserpsw[9] & " in " & $datediff & " days")
                    $Nscad += 1
                    If $flagpwdLastSet = 1 Then ; warning : auto pass set
                        GOLLOG("Re-set password expiration for " & $search1[$conta1])
                        If _AD_ModifyAttribute($search1[$conta1], "pwdLastSet", "0") Then
                            GOLLOG("pwdLastSet to 0 - OK")
                        Else
                            GOLLOG("pwdLastSet to 0 - ERROR " & @error)
                        EndIf

                        If _AD_ModifyAttribute($search1[$conta1], "pwdLastSet", "-1") Then
                            GOLLOG("pwdLastSet to -1 - OK")
                        Else
                            GOLLOG("pwdLastSet to -1 - ERROR " & @error)
                        EndIf

                    EndIf
                EndIf
            EndIf
        WEnd

        If $Nscad > 0 And $INItomail <> "user" Then
            _ArrayAdd($report, $Nscad & " user passwords near expiration")
            If $INItosend = 0 Then
                GOLLOG("Not sent mail " & $Nscad & ": ")
                GOLLOG("from :" & $INIfromname & " | " & $INIfromaddress)
                GOLLOG("to   :" & $INItomail & " | subject: " & $INImailsubject)
                Local $reporttext = _ArrayToString($report)
                GOLLOG("text :" & $reporttext)
            Else
                Local $iResponse = _INetSmtpMail($INIsmpt, $INIfromname, $INIfromaddress, $INItomail, $INImailsubject, $report, "EHLO " & @ComputerName, "-1") ; perla pearl mail send HS smtp (ehlo required)
                Local $iErr = @error
                If $iResponse = 1 Then
                    GOLLOG("Success! " & "Mail sent")
                Else
                    GOLLOG("Error! " & "Mail failed with error code " & $iErr)
                EndIf
            EndIf
        EndIf

        GOLLOG("checked n° " & $conta1 & " users")
    Else
        GOLLOG("error in user search " & @error)
    EndIf
    _AD_Close()
EndFunc   ;==>loaduserS

Func dataITA($inputdate) ; Input date in the format "YYYY/MM/DD[ HH:MM:SS]", and translates Tuesday 8 May 2018 -> Martedì 8 maggio 2018 - perla pearl
    Local $stringaDATAita = _DateTimeFormat($inputdate, 1)
    Select
        Case StringInStr($stringaDATAita, "Monday")
            $stringaDATAita = StringReplace($stringaDATAita, "Monday", "lunedi'")
        Case StringInStr($stringaDATAita, "Tuesday")
            $stringaDATAita = StringReplace($stringaDATAita, "Tuesday", "martedi'")
        Case StringInStr($stringaDATAita, "Wednesday")
            $stringaDATAita = StringReplace($stringaDATAita, "Wednesday", "mercoledi'")
        Case StringInStr($stringaDATAita, "Thursday")
            $stringaDATAita = StringReplace($stringaDATAita, "Thursday", "giovedi'")
        Case StringInStr($stringaDATAita, "Friday")
            $stringaDATAita = StringReplace($stringaDATAita, "Friday", "venerdi'")
        Case StringInStr($stringaDATAita, "Saturday")
            $stringaDATAita = StringReplace($stringaDATAita, "Saturday", "sabato")
        Case StringInStr($stringaDATAita, "Sunday")
            $stringaDATAita = StringReplace($stringaDATAita, "Sunday", "Domenica")
    EndSelect

    Select
        Case StringInStr($stringaDATAita, "January")
            $stringaDATAita = StringReplace($stringaDATAita, "January", "gennaio")
        Case StringInStr($stringaDATAita, "February")
            $stringaDATAita = StringReplace($stringaDATAita, "February", "febbraio")
        Case StringInStr($stringaDATAita, "March")
            $stringaDATAita = StringReplace($stringaDATAita, "March", "marzo")
        Case StringInStr($stringaDATAita, "April")
            $stringaDATAita = StringReplace($stringaDATAita, "April", "aprile")
        Case StringInStr($stringaDATAita, "May")
            $stringaDATAita = StringReplace($stringaDATAita, "May", "maggio")
        Case StringInStr($stringaDATAita, "June")
            $stringaDATAita = StringReplace($stringaDATAita, "June", "giugno")
        Case StringInStr($stringaDATAita, "July")
            $stringaDATAita = StringReplace($stringaDATAita, "July", "luglio")
        Case StringInStr($stringaDATAita, "August")
            $stringaDATAita = StringReplace($stringaDATAita, "August", "agosto")
        Case StringInStr($stringaDATAita, "September")
            $stringaDATAita = StringReplace($stringaDATAita, "September", "settembre")
        Case StringInStr($stringaDATAita, "October")
            $stringaDATAita = StringReplace($stringaDATAita, "October", "ottobre")
        Case StringInStr($stringaDATAita, "November")
            $stringaDATAita = StringReplace($stringaDATAita, "November", "novembre")
        Case StringInStr($stringaDATAita, "December")
            $stringaDATAita = StringReplace($stringaDATAita, "December", "dicembre")

    EndSelect

    Return ($stringaDATAita)

EndFunc   ;==>dataITA



Func GOLLOG($logtext) ; Gollog V.2.3 gestione CRLF si o no ; gestione a capo automatico oltre i xx caratteri; gestione pulitura ogni totmila char  Perla pearl
    ; basta aggiungere |nocrlf50 a fine stringa, dove 50 sono gli xx caratteri, conta la prima riga dove si supera quel limite.
    ; to declare $gollogcount = 0,$lastlog="sicrlf",$cachelog="",$guititle = "nomegui",$Gollogedit,$logfile = @ScriptDir & "\GOLLOG_LOG_", $months2NOTzip = 3
    ; e anche le misure dell'edit: $geleft = 32, $getop = 32, $gewidth = 553, $geheight = 377
    ; #include <File.au3> #include <GuiEdit.au3> #include <_zip.au3>
    ; to insert FUNCs:  GOLLOG CLEANEDIT GOLzipZIP

    $gollogcount += StringLen($logtext)
    ;Local $logfile = @ScriptDir & "\GOLLOG_LOG_" ; now global
    Local $logfiletimerange = @YEAR & @MON
    Local $linelimit = StringRight($logtext, 2)
    If StringRight($logtext, 9) = "|nocrlf" & $linelimit Then

        $logtext = StringTrimRight($logtext, 9)
        Local $acapo = "no"
    Else
        Local $acapo = "si"
        $gollogcount += 4
        If $gollogcount > 13000 Then
            Sleep(3000)
            cleanedit()
            ;   MsgBox(64, "debug", $conta)
            $gollogcount = 0
        EndIf
    EndIf

    If $acapo = "no" And (StringLen($cachelog) <= $linelimit) Then ;pearl perla non a capo se

        If $lastlog = "nocrlf" Then
            If WinExists($guititle) Then ; per non scrivere in gui se questa non esiste
                _GUICtrlEdit_AppendText($Gollogedit, $logtext)
            EndIf
        Else

            If WinExists($guititle) Then ; per non scrivere in gui se questa non esiste
                _GUICtrlEdit_AppendText($Gollogedit, @MDAY & "/" & @MON & "_" & @HOUR & ":" & @MIN & " " & $logtext)
            EndIf
        EndIf
        $cachelog = $cachelog & $logtext
        $lastlog = "nocrlf"
    Else
        If $lastlog = "nocrlf" Then
            If WinExists($guititle) Then ; per non scrivere in gui se questa non esiste
                _GUICtrlEdit_AppendText($Gollogedit, $logtext & @CRLF)
            EndIf
            $cachelog = $cachelog & $logtext
            _FileWriteLog($logfile & $logfiletimerange & ".txt", $cachelog)
            $cachelog = ""
        Else
            If WinExists($guititle) Then ; per non scrivere in gui se questa non esiste
                _GUICtrlEdit_AppendText($Gollogedit, @MDAY & "/" & @MON & "_" & @HOUR & ":" & @MIN & " " & $logtext & @CRLF)
            EndIf
            _FileWriteLog($logfile & $logfiletimerange & ".txt", $logtext)
        EndIf

        $lastlog = "sicrlf"
    EndIf
EndFunc   ;==>GOLLOG

Func cleanedit() ; cleaning of edit every n° lines (in program put if $nlines > xlines then this function)
    GUICtrlDelete($Gollogedit)
    $Gollogedit = GUICtrlCreateEdit("", $geleft, $getop, $gewidth, $geheight) ;, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_WANTRETURN, $WS_BORDER))
    GUICtrlSetData(-1, "" & @CRLF)
    GUICtrlSetFont(-1, 9, 800, 0, "consolas")
    GUICtrlSetColor(-1, 0090608)
    GUICtrlSetBkColor(-1, 0xF0DAE5)
    GUICtrlSetCursor(-1, 3)
EndFunc   ;==>cleanedit

Func GOLzipLOG($months2NOTzip) ; zipping old log leaving unzipped only n months
    GOLLOG("Starting old logs zipping..")

    ; path extraction zone
    Local $logfiletimerange = @YEAR & @MON
    Local $sDrive = "", $sDir = "", $sFileName = "", $sExtension = ""
    Local $arraylogpath = _PathSplit($logfile & $logfiletimerange & ".txt", $sDrive, $sDir, $sFileName, $sExtension)
    Local $logpath = $arraylogpath[1] & $arraylogpath[2]

    Local $hSearch = FileFindFirstFile($logfile & "*.txt") ; searching for logs
    Local $logconta = 0

    While 1 ; single file processing cycle
        Local $sFileName = FileFindNextFile($hSearch)
        ; If there is no more file matching the search.
        If @error Then ExitLoop

        Local $stringtime = StringTrimRight(StringRight($sFileName, 10), 4) ;obtaining year-month like 201609

        If $logfiletimerange - $stringtime > $months2NOTzip Then ;zipping

            If Not FileExists($logfile & ".zip") Then
                If Not _Zip_Create($logfile & ".zip", 1) Then
                    GOLLOG("Error " & @error & " creating " & $logfile & ".zip")
                Else
                    GOLLOG("Created new log archive: " & $logfile & ".zip")
                EndIf
            Else
                GOLLOG("adding to archive: " & $logfile & ".zip")
            EndIf
            If Not _zip_additem($logfile & ".zip", $logpath & $sFileName) Then
                GOLLOG("Error " & @error & " zipping:  " & $logpath & $sFileName)
            Else
                GOLLOG("Added: " & $logpath & $sFileName)
                $logconta += 1
                If Not FileDelete($logpath & $sFileName) Then
                    GOLLOG("ERROR - Unable to DELETE log file " & $logpath & $sFileName)
                EndIf

            EndIf
        EndIf
    WEnd
    GOLLOG("Finished = " & $logconta & " log files zipped")
EndFunc   ;==>GOLzipLOG

Func CFGctrl()
    ; check ini files and load section names
    GOLLOG("checkin' INI file..|nocrlf50")
    If FileExists($inifile) Then
        $guiactive = IniRead($inifile, "general", "GUI", "?")
        If $guiactive = "?" Then
            GOLLOG("INI incomplete, missing section 'general', value GUI")
            ExitwithError()
        EndIf

        $flagITA = IniRead($inifile, "general", "dataITA", "?")
        If $flagITA = "?" Then
            GOLLOG("INI incomplete, missing section 'general', value dataITA")
            ExitwithError()
        EndIf

        $flagpwdLastSet = IniRead($inifile, "general", "pwdLastSet", "?")
        If $flagpwdLastSet = "?" Then
            GOLLOG("INI incomplete, missing section 'general', value pwdLastSet")
            ExitwithError()
        EndIf


        GOLLOG("reading section names...|nocrlf50")
        $arrayINIsections = IniReadSectionNames($inifile)
        GOLLOG("N°" & $arrayINIsections[0] - 1 & " groups to process")
    Else
        $message1 = "error: no saved settings !?"
        GOLLOG($message1)
        ExitwithError()
    EndIf
    GOLLOG("..completed")
EndFunc   ;==>CFGctrl

Func CFGload($section) ; load single ini file section values
    $INIgroup = IniRead($inifile, $section, "group", "?")
    $INItomail = IniRead($inifile, $section, "tomail", "?")
    $INItosend = IniRead($inifile, $section, "tosend", "?")
    $INIdays1 = IniRead($inifile, $section, "days1", "?")
    $INIdays2 = IniRead($inifile, $section, "days2", "?")
    $INImailsubject = IniRead($inifile, $section, "mailsubject", "?")
    $INIsmpt = IniRead($inifile, $section, "smtp", "?")
    $INIfromname = IniRead($inifile, $section, "fromname", "?")
    $INIfromaddress = IniRead($inifile, $section, "fromaddress", "?")
EndFunc   ;==>CFGload

Func ExitwithError()
    GOLLOG("**********ERROR and STOP****************")
    Exit
EndFunc   ;==>ExitwithError

The example .ini:

 

[group1]
group=G_IT_PASSWORD_MONITORED
days1=5
days2=2
tomail=yourgroup@yourdomain.it
;tosend=user; send mails to the domain user mail address, otherwise send to specified address
tosend=0
;tosend ;1 send mails,  0 disable mails for testing 
mailsubject=Domain users going to expire passwords
smtp=smtp.your.own.server
fromname=Password Expiration Guardian
fromaddress=PEG@NSC.it

[group2]
group=G_IT_PASSWORD_NOTIFIED
days1=5
days2=2
tomail=user
;tosend=user; send mails to the domain user mail address, otherwise send to specified address
tosend=0
;tosend ;1 send mails,  0 disable mails for testing 
mailsubject=Password is expiring !
smtp=smtp.your.own.server
fromname=Password Expiration Guardian
fromaddress=PEG@NSC.it

[general]
GUI=1
;1 gui ON for testing, 0 gui disabled
dataITA = 1
;1 translates datetime in italian, 0 for ENG
pwdLastSet = 0
;1 tries to reset the 'pwdLastSet' attribute (you must have permissions), 0 do nothing

 

 

Edited by t0nZ
Added password expiration reset
  • Like 1

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

    • Blois
      By Blois
      Hey Guys,
      Good?
      I'm ned help to consult in other domain. My three domain contains any domains.
      How do I get this query done?
       
      Tks for the Help!
       
    • Gowrisankar
      By Gowrisankar
      Dear members of the forum,
      I need to open excel files that may or may not need a password and finally move the files that needs password to manual queue.
      Is there a fastest way to do this?
       
      PS: I have a huge respect for the rules of this forum. I am not asking assistance to override any security measure. I just need to segregate the files that needs passwords.
    • bouzzi
      By bouzzi
      Hi guys,
      I'm trying to make a script that could tell me, from a username list file,  if the username is active, inactive or not existant  in a multi-domain Active Directory....
      I found a few scripts giving me hints but I found nothing to help me to accomplish this task...
      Do you have any ideas !
      Thanks
      Bouzzi!
       
    • t0nZ
      By t0nZ
      This time I want to share this utility I developed to speed-up the helpdesk activity in our windows domain, used every day by my collegues.
      Our windows machines have no simple to remember name, and when a user calls it's good to quick find a set of informations about the user, the machine, the account and so on.
      In our domain every user and machine has a well made description, and many fields are completed.
      So, based on the fantastic UDF AD.au3 for active directory, I have this script that can:
      search both on user name - machine description, retrieving account name, name/surname, phone number , and for the machine the machine name, the description, the operating system.
      You can check if an account is locked, the domain group membership of an user, the expiration date of the password, you can connect via VNC (tightvnc 64bit please), you can even call the user (but this is based on a particular setup in our environment, we have another script to send commands to the desktop IPphone).
      The code:
      #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=Icone\glaze\kcontrol.ico #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ;UMD User.Machine.Domain ; (c) NSC 2017-2018 ; V.0.3 december 2017 ; V.0.4 english translated and phone fiel added ; V.0.6 autodeploy and update ; V.0.61 support for old vnc 32bit ; V.0.65 search on machine name with radio button ; V.0.66 search on machine name added to default search, removed radio buttons ; V.0.67 radio buttons restored ; V.0.70 VNC connect with no checkbox if only 1 machine found, VNC called with vnconf file, added call functionality via DTdial key combo, user password info ; V.0.71 bugfix ; V.0.75 added ip retrieval, ping if online, reverse host lookup, added tips on every command. ; V.0.76 code cleaned ;#RequireAdmin #include <WinAPISys.au3> #include <GUIConstantsEx.au3> #include <GuiEdit.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <MsgBoxConstants.au3> #include "GUIListViewEx.au3" #include <Array.au3> #include <File.au3> #include <AD.au3> #include <_zip.au3> #include <Inet.au3> #Cs ------- notes ------------------ https://social.technet.microsoft.com/wiki/contents/articles/12037.active-directory-get-aduser-default-and-extended-properties.aspx https://social.technet.microsoft.com/wiki/contents/articles/12056.active-directory-get-adcomputer-default-and-extended-properties.aspx #CE Global $idListview, $id2Listview, $Icercato, $search1, $search2, $List_lines_Index, $List2_lines_Index, $trovati1, $trovatiPHONE1, $trovati2, $umdver = "V.0.76" Global $gollogcount = 0, $lastlog = "sicrlf", $cachelog = "", $guititle = "UMD - Users-Machines-Domain " & $umdver & " NSC 2017-2018", $Gollogedit, $logfile = @ScriptDir & "\UMD_", $months2NOTzip = 1 Global $geleft = 590, $getop = 15, $gewidth = 400, $geheight = 550 Global $prgname = "umd.exe", $umddir = "c:\autoit\UMD\", $sourceexepath = "\\yourpath", $toping = ("your ip to ping") ; environment related: $sourceexepath is for autodeploy/autoupdate, these operations depend on pinging $toping Global $OU1 = "OU=Users,OU=IT,DC=??,DC=???,DC=local", $OU2 = "OU=Clients,OU=IT,DC=??,DC=???,DC=local" ;domain related, the first is the domain OU (organizational unit) where to search for users, the second the OU for machines Global $only1machine = 0, $lastmachinefound = "", $only1user = 0, $lastphonefound = "" Global $idchkbox1, $idchkbox2, $idchkbox3 GuiGO() Func GuiGO() Local $guiheight = 620 ; gui height GUICreate($guititle, 1000, $guiheight, 100, 200, -1, $WS_EX_ACCEPTFILES) GUISetBkColor(0x6FA8DC) GUICtrlCreateLabel("Search on Users", 5, 1, 150, 15) CLVW() GUICtrlCreateLabel("Search on Machines", 5, 286, 150, 15) $idradio1 = GUICtrlCreateRadio("on user name / machine description", 180, 286, 200, 15) GUICtrlSetState(-1, $gui_checked) GUICtrlSetTip(-1, "search in both user name - machine description, populate both lists") $idradio2 = GUICtrlCreateRadio("only on machine name", 400, 286, 150, 15) GUICtrlSetState(-1, $gui_unchecked) GUICtrlSetTip(-1, "search only in the machine name field, populates only the list below") CLVW2() $Bcerca = GUICtrlCreateButton("Search (or enter)", 5, 570, 90, 30) GUICtrlSetTip(-1, "search the string in the yellow input box") $Block = GUICtrlCreateButton("User locked? ", 95, 570, 90, 30) GUICtrlSetTip(-1, "check if selected user account is locked, only an admin can unlock it") $Busergroups = GUICtrlCreateButton("User Groups", 185, 570, 90, 30) GUICtrlSetTip(-1, "list the domain groups for the selected user") $Buserpsw = GUICtrlCreateButton("User Password", 275, 570, 90, 30) GUICtrlSetTip(-1, "retrieve password expiration") $idchkbox2 = GUICtrlCreateCheckbox("psw extra info", 275, 600, 150, 15) GUICtrlSetFont(-1, 8, 400, 0, "consolas") GUICtrlSetState(-1, $gui_unchecked) GUICtrlSetTip(-1, "all the domain info about password") $Bcall = GUICtrlCreateButton("CALL", 495, 570, 40, 30) GUICtrlSetTip(-1, "phone CALL number") $Bvnc = GUICtrlCreateButton("VNC", 535, 570, 40, 30) GUICtrlSetFont(-1, 12, 800, 0, "consolas") GUICtrlSetTip(-1, "launch VNC, if one machine no need to check it") $idchkbox1 = GUICtrlCreateCheckbox("VNC readOnly", 495, 600, 90, 15) GUICtrlSetFont(-1, 8, 400, 0, "consolas") GUICtrlSetState(-1, $gui_unchecked) GUICtrlSetTip(-1, "launch VNC in read only mode") $Icercato = GUICtrlCreateInput("", 590, 570, 400, 30, BitOR($GUI_SS_DEFAULT_INPUT, $WS_BORDER)) GUICtrlSetBkColor(-1, 0xffff4d) GUICtrlSetFont(-1, 12, 800, 0, "consolas") GUICtrlSetColor(-1, 0x000099) GUICtrlSetTip(-1, "insert here a string to search...") $idchkbox3 = GUICtrlCreateCheckbox("ip check / nslookup", 590, 600, 150, 15) GUICtrlSetFont(-1, 8, 400, 0, "consolas") GUICtrlSetState(-1, $gui_unchecked) GUICtrlSetTip(-1, "retrieve IP, check online and performs a reverse check 'nslookup', warning can slow down operations !") GUICtrlCreateLabel("Operation LOG", 590, 1) $Gollogedit = GUICtrlCreateEdit("", $geleft, $getop, $gewidth, $geheight, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_WANTRETURN, $WS_BORDER, $WS_VSCROLL)) GUICtrlSetBkColor(-1, 0x3333ff) GUICtrlSetData(-1, "" & @CRLF) GUICtrlSetFont(-1, 9, 800, 0, "consolas") GUICtrlSetColor(-1, 0xffff4d) GUISetState(@SW_SHOW) GOLLOG("UMD " & $umdver & " STARTED") autodeploy() While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE GOLLOG("<<<< STOP <<<<") Exit Case $Bcerca If BitAND(GUICtrlRead($idradio1), $GUI_CHECKED) = $GUI_CHECKED Then Multisearch("username-machinedescription") If BitAND(GUICtrlRead($idradio2), $GUI_CHECKED) = $GUI_CHECKED Then Multisearch("machinename-username") Case $Block lock() Case $Busergroups usergroups() Case $Buserpsw userpsw() Case $Bcall DTdialCALL() Case $Bvnc VNC() Case $Icercato If BitAND(GUICtrlRead($idradio1), $GUI_CHECKED) = $GUI_CHECKED Then Multisearch("username-machinedescription") If BitAND(GUICtrlRead($idradio2), $GUI_CHECKED) = $GUI_CHECKED Then Multisearch("machinename-username") EndSwitch WEnd EndFunc ;==>GuiGO Func userpsw() _AD_Open() Local $checked_List = _GUIListViewEx_ReturnArray($List_lines_Index, 1) If Not @error Then For $i = 0 To UBound($checked_List) - 1 If $checked_List[$i] = "true" Then GOLLOG("PSW info for " & $trovati1[$i + 1]) Local $arrayuserpsw = _AD_GetPasswordInfo($trovati1[$i + 1]) If BitAND(GUICtrlRead($idchkbox2), $GUI_CHECKED) = $GUI_CHECKED Then Local $arraydesk[13] = [" ", "max psw age:", "min psw age:", "n° enforced psw:", "min lenght:", "lock duration:", "lock attempts:", "lock reset", "psw last changed:", "psw expires on:", "UTC last changed:", "UTC expires on:", "psw properties:"] For $i = 1 To UBound($arrayuserpsw) - 1 GOLLOG($arraydesk[$i] & " " & $arrayuserpsw[$i]) Next Else GOLLOG("Password expires on: " & $arrayuserpsw[9]) EndIf EndIf Next Else MsgBox(0, "nothing selected", "Empty Check Array") EndIf _AD_Close() EndFunc ;==>userpsw Func usergroups() _AD_Open() Local $checked_List = _GUIListViewEx_ReturnArray($List_lines_Index, 1) If Not @error Then For $i = 0 To UBound($checked_List) - 1 If $checked_List[$i] = "true" Then GOLLOG("Query groups of " & $trovati1[$i + 1]) Local $arrayusergroups = _AD_GetUserGroups($trovati1[$i + 1], False) _ArrayDisplay($arrayusergroups) EndIf Next Else MsgBox(0, "nothing selected", "Empty Check Array") EndIf _AD_Close() EndFunc ;==>usergroups Func VNCcall($machine) IniWrite("C:\autoit\UMD\vncconf.vnc", "connection", "host", $machine) If BitAND(GUICtrlRead($idchkbox1), $GUI_CHECKED) = $GUI_CHECKED Then IniWrite("C:\autoit\UMD\vncconf.vnc", "options", "viewonly", "1") Else IniWrite("C:\autoit\UMD\vncconf.vnc", "options", "viewonly", "0") EndIf Run("c:\program files\tightvnc\tvnviewer.exe -optionsfile=C:\autoit\UMD\vncconf.vnc -password=apollo") EndFunc ;==>VNCcall Func VNC() If $only1machine = 1 Then GOLLOG("VNC to :" & $lastmachinefound) VNCcall($lastmachinefound) Else Local $checked_List = _GUIListViewEx_ReturnArray($List2_lines_Index, 1) If Not @error Then For $i = 0 To UBound($checked_List) - 1 If $checked_List[$i] = "true" Then GOLLOG("connecting to :" & $trovati2[$i + 1]) VNCcall($trovati2[$i + 1]) EndIf Next Else MsgBox(0, "multiple machines and nothing selected", "Empty Check Array") EndIf EndIf EndFunc ;==>VNC Func CALLnow($number2call) ; Create a subGUI Local $callGUI = GUICreate("calling", 200, 40) Local $callinput = GUICtrlCreateInput($number2call, 10, 5, 180, 20) GUISetState(@SW_SHOW, $callGUI) GUICtrlSetState($callinput, $GUI_FOCUS) Sleep(500) Send("+{END}") Sleep(200) If @OSVersion = "WIN_8" Or @OSVersion = "WIN_81" Or @OSVersion = "WIN_10" Then Send("{LWINdown}<") Else Send("{LWINdown}z") EndIf Sleep(100) Send("{LWINup}") Sleep(1000) ; Delete the previous subGUI GUIDelete($callGUI) EndFunc ;==>CALLnow Func DTdialCALL() If ProcessExists("dtdial.exe") Then If $only1user = 1 Then GOLLOG("to call :" & $lastphonefound) Local $number2call = InputBox("UMD calling", "modify the number", $lastphonefound) CALLnow($number2call) Else Local $checked_List = _GUIListViewEx_ReturnArray($List_lines_Index, 1) If Not @error Then For $i = 0 To UBound($checked_List) - 1 If $checked_List[$i] = "true" Then GOLLOG("call selected :" & $trovatiPHONE1[$i + 1]) Local $number2call = InputBox("UMD calling", "modify the number", $trovatiPHONE1[$i + 1]) If $number2call = "" Then GOLLOG("nothing to call") Else CALLnow($number2call) EndIf EndIf Next Else MsgBox(0, "multiple machines and nothing selected", "Empty Check Array") EndIf EndIf Else GOLLOG("*** call function") GOLLOG("*** not available") GOLLOG("*** outside DT phone system") EndIf EndFunc ;==>DTdialCALL Func lock() _AD_Open() Local $checked_List = _GUIListViewEx_ReturnArray($List_lines_Index, 1) If Not @error Then For $i = 0 To UBound($checked_List) - 1 If $checked_List[$i] = "true" Then If _AD_IsObjectLocked($trovati1[$i + 1]) = 1 Then GOLLOG($trovati1[$i + 1]) GOLLOG("account is LOCKED !") If MsgBox(36, "Unlock ?", "Do you want to unlock account " & $trovati1[$i + 1] & " ?") = $idyes Then If _AD_UnlockObject($trovati1[$i + 1]) = 0 Then GOLLOG("error " & @error) Else GOLLOG("Unlock DONE !") EndIf Else GOLLOG("not unlocked...") EndIf Else GOLLOG($trovati1[$i + 1]) GOLLOG("account is UNlocked.") EndIf EndIf Next Else MsgBox(0, "nothing selected", "Empty Check Array") EndIf _AD_Close() EndFunc ;==>lock Func Multisearch($searchtype) GOLLOG("_____Load domain data_____") renewlistview() Local $cercato = GUICtrlRead($Icercato) Local $List_lines = '', $List2_lines = '', $string2search = '' $trovatiPHONE1 = 0 Dim $trovati1[1] = ["zero"] Dim $trovatiPHONE1[1] Dim $trovati2[1] = ["zero"] _AD_Open() GOLLOG("Searched for " & $cercato) If $searchtype = "username-machinedescription" Then $search1 = _AD_GetObjectsInOu($OU1, "", 2, "SamAccountName,name,ipphone,telephonenumber") If @error = 0 Then Local $conta1 = 0 Local $conta1trovati = 0 $string2search = '' While $search1[0][0] > $conta1 $conta1 += 1 If StringInStr($search1[$conta1][0], $cercato) <> 0 Then $List_lines = $search1[$conta1][0] & "|" & $search1[$conta1][1] & "|" & $search1[$conta1][2] & " " & $search1[$conta1][3] $lastphonefound = $search1[$conta1][2] & " " & $search1[$conta1][3] ; to save last machine found GUICtrlCreateListViewItem($List_lines, $idListview) _ArrayAdd($trovati1, $search1[$conta1][0]) _ArrayAdd($trovatiPHONE1, $search1[$conta1][2] & " " & $search1[$conta1][3]) $conta1trovati += 1 EndIf WEnd ; Initiate LVEx - use filling array - no count parameter - default insert mark colour (black) - drag image - sortable + not select all text + editable headers $List_lines_Index = _GUIListViewEx_Init($idListview, $List_lines, 0, 0, True, 1 + 2 + 8) GOLLOG("checked n° " & $conta1 & " users") GOLLOG("Found n° " & $conta1trovati & " users") If $conta1trovati = 1 Then $only1user = 1 Else $only1user = 0 EndIf Else GOLLOG("error in user search " & @error) EndIf $search2 = _AD_GetObjectsInOu($OU2, "", 2, "name,description,operatingSystem") ;search in machines If @error = 0 Then Local $conta2 = 0 Local $conta2trovati = 0 $string2search = '' While $search2[0][0] > $conta2 $conta2 += 1 If StringInStr($search2[$conta2][1], $cercato) <> 0 Or StringInStr($search2[$conta2][0], $cercato) <> 0 Then $List2_lines = $search2[$conta2][0] & "|" & $search2[$conta2][1] & "|" & $search2[$conta2][2] $lastmachinefound = $search2[$conta2][0] ; to save last machine found GUICtrlCreateListViewItem($List2_lines, $id2Listview) If BitAND(GUICtrlRead($idchkbox3), $GUI_CHECKED) = $GUI_CHECKED Then ; V.0.75 IPrelated($search2[$conta2][0]) EndIf _ArrayAdd($trovati2, $search2[$conta2][0]) $conta2trovati += 1 EndIf WEnd ; Initiate LVEx - use filling array - no count parameter - default insert mark colour (black) - drag image - sortable + not select all text + editable headers $List2_lines_Index = _GUIListViewEx_Init($id2Listview, $List2_lines, 0, 0, True, 1 + 2 + 8) GOLLOG("Checked n° " & $conta2 & " machines") GOLLOG("Found n° " & $conta2trovati & " machines") If $conta2trovati = 1 Then $only1machine = 1 Else $only1machine = 0 EndIf Else GOLLOG("error in machines search " & @error) EndIf EndIf ; second searchtype----------------------------------------------------------------------_-_--------------------------- If $searchtype = "machinename-username" Then $search2 = _AD_GetObjectsInOu($OU2, "", 2, "name,description,operatingSystem") ;search in machines If @error = 0 Then Local $conta2 = 0 Local $conta2trovati = 0 $string2search = '' While $search2[0][0] > $conta2 $conta2 += 1 If StringInStr($search2[$conta2][0], $cercato) <> 0 Then $List2_lines = $search2[$conta2][0] & "|" & $search2[$conta2][1] & "|" & $search2[$conta2][2] GUICtrlCreateListViewItem($List2_lines, $id2Listview) If BitAND(GUICtrlRead($idchkbox3), $GUI_CHECKED) = $GUI_CHECKED Then ; V.0.75 IPrelated($search2[$conta2][0]) EndIf _ArrayAdd($trovati2, $search2[$conta2][0]) $conta2trovati += 1 EndIf WEnd ; Initiate LVEx - use filling array - no count parameter - default insert mark colour (black) - drag image - sortable + not select all text + editable headers $List2_lines_Index = _GUIListViewEx_Init($id2Listview, $List2_lines, 0, 0, True, 1 + 2 + 8) GOLLOG("Checked n° " & $conta2 & " machines") GOLLOG("Found n° " & $conta2trovati & " machines") Else GOLLOG("error in machines search " & @error) EndIf EndIf _AD_Close() EndFunc ;==>Multisearch Func IPrelated($pinghost) Local $sIPAddress = "" Local $shostname = "" Local $pcping = Ping($pinghost) If $pcping = 0 Then Select Case @error = 1 Local $errorping = "host is offline" Case @error = 2 Local $errorping = "host is unreachable" Case @error = 3 Local $errorping = "bad destination" Case @error = 4 Local $errorping = "not found for other errors" EndSelect GOLLOG($pinghost & " " & $errorping) Else GOLLOG($pinghost & " ping in " & $pcping & " ms") ; Start the TCP service. TCPStartup() $sIPAddress = TCPNameToIP($pinghost) $shostname = _TCPIpToName($sIPAddress, 0) TCPShutdown() ; Close the TCP service. GOLLOG("IP address is: " & $sIPAddress) GOLLOG("reverse lookup:" & $shostname) EndIf EndFunc ;==>IPrelated Func autodeploy() ; pensato per la prima installazione e update Local $TipDT = Ping($toping) Local $ntest = 1 While $TipDT = 0 And $ntest < 3 Sleep(200) $TipDT = Ping($toping) $ntest += 1 WEnd If $TipDT = 0 Then GOLLOG("unable to check updates") Else If Not FileExists($umddir) Then GOLLOG("Procedo con Autodeploy") If DirCreate($umddir) Then GOLLOG("-> creata cartella " & $umddir) Else GOLLOG("-> problema ! non creata cartella " & $umddir) EndIf GOLLOG("posiziono eseguibile in " & $umddir) FileCopy(@ScriptDir & "\umd.exe", $umddir & "umd.exe", 1) If Not FileExists(@DesktopDir & "\umd.lnk") Then GOLLOG("desktop link creation...") FileCreateShortcut($umddir & "\" & $prgname, @DesktopDir & "\umd.lnk") EndIf GOLLOG("posiziono VNConf in " & $umddir) FileCopy($sourceexepath & "\vncconf.vnc", $umddir & "\" & "vncconf.vnc", 1) GOLLOG("AutoDeploy completato") ; ora devo spegnere e riavviare quello in \cpa_da Local $sCmdFile ; phoenix modificata NON è quella standard di autoupdate FileDelete(@TempDir & "\phoenix.bat") $sCmdFile = 'ping 127.0.0.1 -n 2 > NUL' & @CRLF _ & ':loop' & @CRLF _ & 'if exist "' & @ScriptFullPath & '" goto loop' & @CRLF _ & 'start c:\autoit\umd\umd.exe' & @CRLF _ & 'del %0' FileWrite(@TempDir & "\phoenix.bat", $sCmdFile) GOLLOG("program is closing, see ya in deployed version...") Sleep(1000) Run(@TempDir & "\phoenix.bat", @TempDir, @SW_HIDE) Exit ; exit and real update EndIf Local $currtime = FileGetTime(@ScriptDir & "\" & $prgname, $FT_MODIFIED, 1) Local $newtime = FileGetTime($sourceexepath & "\" & $prgname, $FT_MODIFIED, 1) If $newtime > $currtime Then GOLLOG("update available!") If Not FileExists(@DesktopDir & "\umd.lnk") Then GOLLOG("desktop link creation...") FileCreateShortcut($umddir & "\" & $prgname, @DesktopDir & "\umd.lnk") EndIf Local $sCmdFile GOLLOG("posiziono VNConf in " & $umddir) FileCopy($sourceexepath & "\vncconf.vnc", $umddir & "\" & "vncconf.vnc", 1) FileDelete(@TempDir & "\phoenix.bat") $sCmdFile = 'ping 127.0.0.1 -n 2 > NUL' & @CRLF _ & ':loop' & @CRLF _ & 'del "' & @ScriptFullPath & '"' & @CRLF _ & 'if exist "' & @ScriptFullPath & '" goto loop' & @CRLF _ & 'copy "' & $sourceexepath & '"\"' & $prgname & '" "' & @ScriptFullPath & @CRLF _ & 'start ' & @ScriptFullPath & @CRLF _ & 'del %0' FileWrite(@TempDir & "\phoenix.bat", $sCmdFile) GOLLOG("program is closing, see ya in next version..") Sleep(1000) Run(@TempDir & "\phoenix.bat", @TempDir, @SW_HIDE) Exit ; exit and real update Else GOLLOG("UMD already updated") EndIf EndIf EndFunc ;==>autodeploy Func renewlistview() ; cancella e ricrea GUICtrlDelete($idListview) GUICtrlDelete($id2Listview) CLVW() CLVW2() EndFunc ;==>renewlistview Func CLVW() ;crea listview utenti $idListview = GUICtrlCreateListView("SamAccountName|Name|phone", 5, 15, 570, 265, $LVS_SHOWSELALWAYS) _GUICtrlListView_SetExtendedListViewStyle($idListview, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_CHECKBOXES)) _GUICtrlListView_SetColumnWidth($idListview, 0, 175) _GUICtrlListView_SetColumnWidth($idListview, 1, 175) _GUICtrlListView_SetColumnWidth($idListview, 2, 150) GUICtrlSetFont(-1, 9, 800, 0, "consolas") EndFunc ;==>CLVW Func CLVW2() ;crea listview macchine $id2Listview = GUICtrlCreateListView("Name|Description|Operating System", 5, 300, 570, 265, $LVS_SHOWSELALWAYS) _GUICtrlListView_SetExtendedListViewStyle($id2Listview, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_CHECKBOXES)) _GUICtrlListView_SetColumnWidth($id2Listview, 0, 120) _GUICtrlListView_SetColumnWidth($id2Listview, 1, 180) _GUICtrlListView_SetColumnWidth($id2Listview, 2, 230) GUICtrlSetFont(-1, 9, 800, 0, "consolas") EndFunc ;==>CLVW2 Func GOLLOG($logtext) ; Gollog V.2.3 gestione CRLF si o no ; gestione a capo automatico oltre i xx caratteri; gestione pulitura ogni totmila char Perla pearl ; basta aggiungere |nocrlf50 a fine stringa, dove 50 sono gli xx caratteri, conta la prima riga dove si supera quel limite. ; to declare $gollogcount = 0,$lastlog="sicrlf",$cachelog="",$guititle = "nomegui",$Gollogedit,$logfile = @ScriptDir & "\GOLLOG_LOG_", $months2NOTzip = 3 ; e anche le misure dell'edit: $geleft = 32, $getop = 32, $gewidth = 553, $geheight = 377 ; #include <File.au3> #include <GuiEdit.au3> #include <_zip.au3> ; to insert FUNCs: GOLLOG CLEANEDIT GOLzipZIP $gollogcount += StringLen($logtext) Local $logfiletimerange = @YEAR & @MON Local $linelimit = StringRight($logtext, 2) If StringRight($logtext, 9) = "|nocrlf" & $linelimit Then $logtext = StringTrimRight($logtext, 9) Local $acapo = "no" Else Local $acapo = "si" $gollogcount += 4 If $gollogcount > 13000 Then Sleep(3000) cleanedit() $gollogcount = 0 EndIf EndIf If $acapo = "no" And (StringLen($cachelog) <= $linelimit) Then ;pearl perla non a capo se If $lastlog = "nocrlf" Then If WinExists($guititle) Then ; per non scrivere in gui se questa non esiste _GUICtrlEdit_AppendText($Gollogedit, $logtext) EndIf Else If WinExists($guititle) Then ; per non scrivere in gui se questa non esiste _GUICtrlEdit_AppendText($Gollogedit, @MDAY & "/" & @MON & "_" & @HOUR & ":" & @MIN & " " & $logtext) EndIf EndIf $cachelog = $cachelog & $logtext $lastlog = "nocrlf" Else If $lastlog = "nocrlf" Then If WinExists($guititle) Then ; per non scrivere in gui se questa non esiste _GUICtrlEdit_AppendText($Gollogedit, $logtext & @CRLF) EndIf $cachelog = $cachelog & $logtext _FileWriteLog($logfile & $logfiletimerange & ".txt", $cachelog) $cachelog = "" Else If WinExists($guititle) Then ; per non scrivere in gui se questa non esiste _GUICtrlEdit_AppendText($Gollogedit, @MDAY & "/" & @MON & "_" & @HOUR & ":" & @MIN & " " & $logtext & @CRLF) EndIf _FileWriteLog($logfile & $logfiletimerange & ".txt", $logtext) EndIf $lastlog = "sicrlf" EndIf EndFunc ;==>GOLLOG Func cleanedit() ; cleaning of edit every n° lines (in program put if $nlines > xlines then this function) GUICtrlDelete($Gollogedit) $Gollogedit = GUICtrlCreateEdit("", $geleft, $getop, $gewidth, $geheight) ;, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_WANTRETURN, $WS_BORDER)) GUICtrlSetData(-1, "" & @CRLF) GUICtrlSetFont(-1, 9, 800, 0, "consolas") GUICtrlSetColor(-1, 0xffff4d) GUICtrlSetBkColor(-1, 0x3333ff) GUICtrlSetCursor(-1, 3) EndFunc ;==>cleanedit Func GOLzipLOG($months2NOTzip) ; zipping old log leaving unzipped only n months GOLLOG("Starting old logs zipping..") ; path extraction zone Local $logfiletimerange = @YEAR & @MON Local $sDrive = "", $sDir = "", $sFileName = "", $sExtension = "" Local $arraylogpath = _PathSplit($logfile & $logfiletimerange & ".txt", $sDrive, $sDir, $sFileName, $sExtension) Local $logpath = $arraylogpath[1] & $arraylogpath[2] Local $hSearch = FileFindFirstFile($logfile & "*.txt") ; searching for logs Local $logconta = 0 While 1 ; single file processing cycle Local $sFileName = FileFindNextFile($hSearch) ; If there is no more file matching the search. If @error Then ExitLoop Local $stringtime = StringTrimRight(StringRight($sFileName, 10), 4) ;obtaining year-month like 201609 If $logfiletimerange - $stringtime > $months2NOTzip Then ;zipping If Not FileExists($logfile & ".zip") Then If Not _Zip_Create($logfile & ".zip", 1) Then GOLLOG("Error " & @error & " creating " & $logfile & ".zip") Else GOLLOG("Created new log archive: " & $logfile & ".zip") EndIf Else GOLLOG("adding to archive: " & $logfile & ".zip") EndIf If Not _zip_additem($logfile & ".zip", $logpath & $sFileName) Then GOLLOG("Error " & @error & " zipping: " & $logpath & $sFileName) Else GOLLOG("Added: " & $logpath & $sFileName) $logconta += 1 If Not FileDelete($logpath & $sFileName) Then GOLLOG("ERROR - Unable to DELETE log file " & $logpath & $sFileName) EndIf EndIf EndIf WEnd GOLLOG("Finished = " & $logconta & " log files zipped") EndFunc ;==>GOLzipLOG The minimum for make it work in your domain  (no admin rights required, no writing on domain performed) is to modify these globals:
      Global $prgname = "umd.exe", $umddir = "c:\autoit\UMD\", $sourceexepath = "\\the .exe path for autodeploy", $toping = ("ip to ping") ; environment related: $sourceexepath is for autodeploy/autoupdate, these operations depend on pinging $toping
      Global $OU1 = "OU=Users,OU=IT,DC=??,DC=???,DC=local", $OU2 = "OU=Clients,OU=IT,DC=??,DC=???,DC=local" ;domain related, the first is the domain OU (organizational unit) where to search for users, the second the OU for machines.
      You have to recompile modifying at minimum $toping with a NON pingable IP (to disable auto deploy - update) and certainly the domain OU for your users and machines.
      The vncconf.vnc is to be modified with the standard (I hope for you..) VNC password in your company, OR you can remove the line and VNC will request the psw every time.
      After, Just copy the executable and the other file (vncconf.vnc) in a folder in your PC and try it.
      The autodeploy/update feature work in this way: if the script can ping $toping value, then pick the executable from $sourceexepath, and perform
      "installation" (link and copying .exe, no win register involved) or updating.
      Let me know your experience..

      vncconf.vnc
      UMD.au3
    • Overkill
      By Overkill
      Hi all,
      I am working on a GUI program to update Google's Dynamic DNS (API at https://support.google.com/domains/answer/6147083?authuser=1&hl=en if you scroll to bottom). I am not a programmer by any means - just a sysadmin who has picked up on some things along the way. I am sure that there's better ways to do a lot of things in this script; I'm just going with what I know.
      My challenge right now is that I'd like a better way to store the credentials both in memory as well as in system registry or INI file (not sure which way I want to go for local storage). How should I convert the passwords to a secure string in a manner that can't be easily reversed, yet is still accessible to the script? Is that even an option in AutoIt?
      Can anybody provide me with links to good reference posts, or coding suggestions for how best to achieve this in the script below? I am using the WinHTTP UDF (https://github.com/dragana-r/autoit-winhttp/releases) to make my API calls.
      #include<WinHTTP.au3> #include<GUIConstantsEx.au3> #include<EditConstants.au3> #include<iNet.au3> #include<Array.au3> DIM $aDomainList[1][4] $aDomainList[0][0] = 0 $gMainGUI = GUICreate("Overkill's Google DNS Updater",800,800) $gDomainLabel = GUICtrlCreateLabel("FQDN",21,8) $gDomainInput = GUICtrlCreateInput("",60,5,300) $gUserLabel = GUICtrlCreateLabel("Username",5,36) $gUserInput = GUICtrlCreateInput("",60,32,130,Default,BitOR($GUI_SS_DEFAULT_INPUT,$ES_PASSWORD)) $gPasswordLabel = GUICtrlCreateLabel("Password",6,64) $gPassInput = GUICtrlCreateInput("",60,60,130,Default,BitOR($GUI_SS_DEFAULT_INPUT,$ES_PASSWORD)) $gAddButton = GUICtrlCreateButton("ADD DOMAIN",200,31,160,52) $gCurrentIP = GUICtrlCreateLabel("Current IP: " & _CheckIP(),5,780) $gDomainList = GUICtrlCreateListView("Domain | Resolved IP | Update Status",5,120,600,600) GUISetState(@SW_SHOW,$gMainGUI) while 1 $m = GUIGetMsg() IF $M = $GUI_EVENT_CLOSE then Exit IF $M = $gAddButton Then $sAddDomain = GUICtrlRead($gDomainInput) $sAddUser = GUICtrlRead($gUserInput) $sAddPass = GUICtrlRead($gPassInput) $sResolveIP = _DNSCheck($sAddDomain) ;Google wants you to avoid sending updates when there are no changes If StringCompare($sResolveIP,_CheckIP()) = 0 Then $sStatus = "No change, not sending update" Else $sStatus = _DNSUpdate($sAddDomain,$sAddUser,$sAddPass) EndIf ;Check to make sure all fields are completed before continuing IF StringLen($sAddDomain) = 0 OR StringLen($sAddUser) = 0 OR StringLen($sAddPass) = 0 Then MsgBox(0,"","Please complete all fields") Else ; If the fields all have data, then continue ;Check to see if the entry exists in the array already $iSanity = _ArraySearch($aDomainList,$sAddDomain) IF $iSanity = 0 Then _ArrayAdd($aDomainList,$sAddDomain & "|" & $sAddUser & "|" & $sAddPass ) If @error = 0 Then $aDomainList[0][0] += 1 $aDomainList[$aDomainList[0][0]][3] = GUICtrlCreateListViewItem($sAddDomain & "|" & $sResolveIP & "|" & $sStatus,$gDomainList) Else MsgBox(0,"","Error adding input to list") EndIf Else ; If $iSanity <> 0 ; Update existing info in array and listviewitem $aDomainList[$iSanity][0] = $sAddDomain $aDomainList[$iSanity][1] = $sAddUser $aDomainList[$iSanity][2] = $sAddPass GUICtrlSetData($aDomainList[$iSanity][3],$sAddDomain & "|" & $sResolveIP & "|" & $sStatus) EndIf ; If $iSanity = 0 EndIf ; If StringLen... EndIf ; If $m = $gaddbutton WEnd ;---------------------------------------------------------------------------------------- Func _DNSCheck($sFQDN) $sJSON = _INetGetSource("https://dns.google.com/resolve?name=" & $sFQDN & "&cd=1") ConsoleWrite($sJSON & @CRLF) $sIPAddress = StringRegExpReplace($sJSON,'^.*data": "(.*?)".*?$',"\1") Return $sIPAddress EndFunc ;---------------------------------------------------------------------------------------- Func _DNSUpdate($sFQDN,$sUser,$sPass) Local $sGoogleAPIURI = "https://domains.google.com" Local $hOpen = _WinHttpOpen() Local $hConnect = _WinHttpConnect($hOpen, $sGoogleAPIURI) Local $sHeader = _ 'Authorization: Basic ' & _Base64Encode($sUser & ":" & $sPass) & @CRLF & _ 'Accept: */*' & @CRLF & _ 'User-Agent: AutoITScript/' & @AutoItVersion & @CRLF & _ 'Content-Type: application/x-www-form-urlencoded' Local $aHTTPResponse = _WinHttpSimpleSSLRequest($hConnect, "POST", "/nic/update", Default, "hostname=" & $sFQDN, $sHeader, True, Default, Default, Default, True) _WinHttpCloseHandle($hConnect) _WinHttpCloseHandle($hOpen) If IsArray($aHTTPResponse) Then $sHTTPResponse = "Header:" & @CRLF & $aHTTPResponse[0] & @CRLF & "Data:" & @CRLF & $aHTTPResponse[1] & @CRLF & @CRLF & @CRLF Return $aHTTPResponse[1] Else $sHTTPResponse = "NO REPLY" Return "No reply from " & $sGoogleAPIURI EndIf EndFunc ;---------------------------------------------------------------------------------------- Func _Base64Encode($sData) Local $oXml = ObjCreate("Msxml2.DOMDocument") If Not IsObj($oXml) Then SetError(1, 1, 0) EndIf Local $oElement = $oXml.createElement("b64") If Not IsObj($oElement) Then SetError(2, 2, 0) EndIf $oElement.dataType = "bin.base64" $oElement.nodeTypedValue = Binary($sData) Local $sReturn = $oElement.Text If StringLen($sReturn) = 0 Then SetError(3, 3, 0) EndIf Return $sReturn EndFunc ;---------------------------------------------------------------------------------------- Func _CheckIP() Return _INetGetSource("https://domains.google.com/checkip") EndFunc ;----------------------------------------------------------------------------------------  
×