Wednesday, February 19, 2020

EVENTS scan powershell

Bonjour,

Ceci est une formation pour utiliser un script powershell qui scanne les événements, locaux ou distants, avec un filterxpath ou avec une recherche par chaîne.

Requis:
windows, server ou client
savoir le nom du log à scanner
windows à jour 2020-02
powershell ISE

Requis:
Pour lire un log à distance, le port suivant doit être ouvert dans le firewall windows:
Donc sur l'ordinateur client distant (dans le même réseau local), appliquer la commande powershell suivante:
Enable-NetFirewallRule -DisplayGroup 'Remote Event Log Management'


Comment trouver un log d'événements quand on ne sait pas le nom du log:
Pour trouver par nom un log, exemple: applocker (utilitaire qui bloque les application louches comme les crypto lockers)
Commande à faire dans powershell ISE:
Get-WinEvent -ListLog *exe* -force | select logname

Résultat:
LogName                                           
-------                                           
Microsoft-Windows-AppLocker/EXE and DLL           
Microsoft-Windows-AppLocker/Packaged app-Execution

PS C:\Users\serge.fournier\DÉVICOM INC\Prog Devicom - Document Prog\event_list_ps>

Le log voulu s'appelle donc:
Microsoft-Windows-AppLocker/EXE and DLL 

Au début du script, plusieurs object powershell ont été créé en tant que paramètres pour l'exécution du script:
# what events to check   0 = not check, 1 =check
$events_log_to_check01 = New-Object PsObject
$events_log_to_check01 | Add-Member NoteProperty -Name system -value '1'     # hardware
$events_log_to_check01 | Add-Member NoteProperty -Name security -value '0'   # logins
$events_log_to_check01 | Add-Member NoteProperty -Name updates -value '0'    # windows update
$events_log_to_check01 | Add-Member NoteProperty -Name dpmbackups -value '0' # backup azure microsoft
$events_log_to_check01 | Add-Member NoteProperty -Name applocker -value '0'  # bloqueur d'applications contre crypto virus

Par défaut, dans le script, plusieurs events log sont déjà prévu pour être scannés.
C'est-à-dire qu'il y a déjà des paramètres pour les scanner, mais ils sont à "off"
Pour qu'un log soit scanné, il faut que sa variable soit à 1.
Exemple:
$events_log_to_check01 | Add-Member NoteProperty -Name system -value '1'     # hardware

Le log system sera scanné

Par la suite une matrice (array) de paramètres est définie pour chaque log voulu:
Première matrice, les ordinateurs à scanner:
################################################################
# computers
################################################################
[string[]]$eventlogs_name_device_arr01 = "localhost"   # computer name to scan
#[string[]]$eventlogs_name_device_arr01+= "sql2008" # computer name to scan

Dans le rapport, chaque log sera un après l'autre, séparé par une ligne orange
Et chaque ordinateur scanné à la suite, à la fin du premier log
Ainsi, avec le bon id ou mot clef, on peut scanner les erreurs hardware d'un parc complet d'ordinateurs.

Deuxième matrice, les paramètres pour un log à scanner:
le nom du log
le provider (utilisé rarement)
le niveau d'erreur (en chiffre)
un mot à chercher qu'il faut mettre entre *. Exemple: *shut*, va trouver les shutdown
le nombre maximum d'événements
le nombre de jours à mettre dans le rapport
des filtres de ID à inclure (parfois on veut juste les login dans security)
des filtres de ID à NE PAS inclure (parfois il y a des id qui reviennent trop souvent pour rien (erreur com))


if($events_log_to_check01.system -eq 1)
{
    $n++
    [string[]]$eventslog_name_arr01[$n] = "system"
    [string[]]$eventslog_provider_arr01[$n] = "*"
    [string[]]$eventslog_level_arr01[$n] = "2"         # -1 = all 2 = ERROR, 3 = warning 4 = information
    [string[]]$eventslog_keywordtosearch01[$n] = "*"   # always use *word* (asterix at start and end)
    [string[]]$eventslog_maxevents_arr01[$n] = 100
    [string[]]$eventslog_daysback_arr01[$n] = 30       # -1 = no datetime filter

    [string[]]$eventslog_idtoget_arr01 = @()    # put other line in comment # for all events (0 count = no search by id)
    #[string[]]$eventslog_idtoget_arr01+= "107" # system wake from sleep
    #[string[]]$eventslog_idtoget_arr01+= "19"  # system update and description
    #[string[]]$eventslog_idtoget_arr01+= "22"  # system network loss
    #[string[]]$eventslog_idtoget_arr01+= "13"  # system shutdown
    $eventslog_idtoget_jarr01[$n] = $eventslog_idtoget_arr01

    $eventslog_idtoignore_arr01 = @()          # put other line in comment # for all events
    $eventslog_idtoignore_arr01+= "10016"      # com object error
    $eventslog_idtoignore_arr01+= "10028"      # com object error
    $eventslog_idtoignore_arr01+= "103"        # connectwise
    $eventslog_idtoignore_jarr01[$n] = $eventslog_idtoignore_arr01

    if($eventslog_daysback_arr01 -ne -1)
    {
        [DateTime[]]$eventslog_datetime_min_arr01[$n] = (Get-Date).AddDays(-$eventslog_daysback_arr01[$n])
        [DateTime[]]$eventslog_datetime_max_arr01[$n] = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    }
}

Résultat du scan:

event search by keyword mot recherché:

timecreatedMachineNamelognamelevelLeveldisplaynameuserididmessage
GoBackDays: 30MaxEvents: 100system2StringSearch: *IdNotWanted: 10016 10028 103IDWanted:system orange01
2020-02-19 09:56:23dev47.ad.devicom.comsystem2Erreur7000Le service IntelHaxm n'a pas pu démarrer en raison de l'erreur : Un périphérique attaché au système ne fonctionne pas correctement.

Script complet:

####################################################################################################################
$Title01 = "Event search with filterxpath (level, date) and string search multiple computers multiple event log"
####################################################################################################################
cls; write-host $title01 -ForegroundColor green
###############################
# requis
###############################
# security powershell execution
# windows 7  #   Set-ExecutionPolicy RemoteSigned
# windows 10 #   Set-ExecutionPolicy -scope currentuser RemoteSigned #   Set-ExecutionPolicy -scope localmachine RemoteSigned
################## find an event log by keyword
# Enable-NetFirewallRule -DisplayGroup 'Remote Event Log Management'
### search for an event log in all logs
# Get-WinEvent -ListLog *exe* -force | select logname

################### parameters
$method01 = 0   # 0 = use xfilterpath   1 = use string search in xml (outdated)

# what events to check   0 = not check, 1 =check
$events_log_to_check01 = New-Object PsObject
$events_log_to_check01 | Add-Member NoteProperty -Name system -value '1'     # hardware
$events_log_to_check01 | Add-Member NoteProperty -Name security -value '0'   # logins
$events_log_to_check01 | Add-Member NoteProperty -Name updates -value '0'    # windows update
$events_log_to_check01 | Add-Member NoteProperty -Name dpmbackups -value '0' # backup azure microsoft
$events_log_to_check01 | Add-Member NoteProperty -Name applocker -value '0'  # bloqueur d'applications contre crypto virus

# get the total of array we need to store events
[int]$log_tot = 0
foreach($object_properties in $events_log_to_check01.PsObject.Properties)
{
    #$object_properties.Name
    $log_tot += $object_properties.Value
}

$eventslog_name_arr01 = New-Object 'string[]' $log_tot
$eventslog_provider_arr01 = New-Object 'string[]' $log_tot
$eventslog_level_arr01 = New-Object 'string[]' $log_tot
$eventslog_keywordtosearch01 = New-Object 'string[]' $log_tot
$eventslog_maxevents_arr01 = New-Object 'string[]' $log_tot
$eventslog_daysback_arr01 = New-Object 'string[]' $log_tot
$eventslog_idtoget_jarr01 = New-Object 'object[]' $log_tot
$eventslog_idtoignore_jarr01 = New-Object 'Object[]' $log_tot
$eventslog_datetime_min_arr01 = New-Object 'string[]' $log_tot
$eventslog_datetime_max_arr01 = New-Object 'string[]' $log_tot

#Installation events can have an Event ID of 11707 or 1033. The InstallOperation field of these events indicate Installation completed.
#Uninstallation events can have an Event ID of 11724 or 1034. The InstallOperation field of these events indicate Removal completed.
#http://juventusitprofessional.blogspot.com/2015/07/windows-2012-dfs-dfs-r-part-5-list-of.html

################################################################
# computers
################################################################
[string[]]$eventlogs_name_device_arr01 = "localhost"   # computer name to scan
#[string[]]$eventlogs_name_device_arr01+= "sql2008" # computer name to scan
$n = -1

if($events_log_to_check01.system -eq 1)
{
    $n++
    [string[]]$eventslog_name_arr01[$n] = "system"
    [string[]]$eventslog_provider_arr01[$n] = "*"
    [string[]]$eventslog_level_arr01[$n] = "2"         # -1 = all 2 = ERROR, 3 = warning 4 = information
    [string[]]$eventslog_keywordtosearch01[$n] = "*"   # always use *word* (asterix at start and end)
    [string[]]$eventslog_maxevents_arr01[$n] = 100
    [string[]]$eventslog_daysback_arr01[$n] = 30       # -1 = no datetime filter

    [string[]]$eventslog_idtoget_arr01 = @()    # put other line in comment # for all events (0 count = no search by id)
    #[string[]]$eventslog_idtoget_arr01+= "107" # system wake from sleep
    #[string[]]$eventslog_idtoget_arr01+= "19"  # system update and description
    #[string[]]$eventslog_idtoget_arr01+= "22"  # system network loss
    #[string[]]$eventslog_idtoget_arr01+= "13"  # system shutdown
    $eventslog_idtoget_jarr01[$n] = $eventslog_idtoget_arr01

    $eventslog_idtoignore_arr01 = @()          # put other line in comment # for all events
    $eventslog_idtoignore_arr01+= "10016"      # com object error
    $eventslog_idtoignore_arr01+= "10028"      # com object error
    $eventslog_idtoignore_arr01+= "103"        # connectwise
    $eventslog_idtoignore_jarr01[$n] = $eventslog_idtoignore_arr01

    if($eventslog_daysback_arr01 -ne -1)
    {
        [DateTime[]]$eventslog_datetime_min_arr01[$n] = (Get-Date).AddDays(-$eventslog_daysback_arr01[$n])
        [DateTime[]]$eventslog_datetime_max_arr01[$n] = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    }
}
##############################
if($events_log_to_check01.security -eq 1)
{
   
    $n++
    [string[]]$eventslog_name_arr01[$n] = "security"
    [string[]]$eventslog_provider_arr01[$n] = "*"
    [string[]]$eventslog_level_arr01[$n] = "*"         # -1 = all 2 = ERROR, 3 = warning 4 = information
    [string[]]$eventslog_keywordtosearch01[$n] = "*serge*"   # always use *word* (asterix at start and end)
    [string[]]$eventslog_maxevents_arr01[$n] = 100
    [string[]]$eventslog_daysback_arr01[$n] = 30       # -1 = no datetime filter

    [string[]]$eventslog_idtoget_arr01 = @()    # put other line in comment # for all events (0 count = no search by id)
    #[string[]]$eventslog_idtoget_arr01+= "4624" # logon
    $eventslog_idtoget_jarr01[$n] = $eventslog_idtoget_arr01

    $eventslog_idtoignore_arr01 = @()          # put other line in comment # for all events
    #$eventslog_idtoignore_arr01+= "10016"      # com object error
    $eventslog_idtoignore_jarr01[$n] = $eventslog_idtoignore_arr01

    if($eventslog_daysback_arr01 -ne -1)
    {
        [DateTime[]]$eventslog_datetime_min_arr01[$n] = (Get-Date).AddDays(-$eventslog_daysback_arr01[$n])
        [DateTime[]]$eventslog_datetime_max_arr01[$n] = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    }
}
##############################
if($events_log_to_check01.updates -eq 1)
{
    #[string[]]$log_arr01+= "setup (installation, updates)"
    #[string[]]$eventid00 = "2 (update windows sans description, voir system pour celui avec description)"
   
    $n++
    [string[]]$eventslog_name_arr01[$n] = "setup (installation, updates)"
    [string[]]$eventslog_provider_arr01[$n] = "*"
    [string[]]$eventslog_level_arr01[$n] = "*"         # -1 = all 2 = ERROR, 3 = warning 4 = information
    [string[]]$eventslog_keywordtosearch01[$n] = "*"   # always use *word* (asterix at start and end)
    [string[]]$eventslog_maxevents_arr01[$n] = 25
    [string[]]$eventslog_daysback_arr01[$n] = 30       # -1 = no datetime filter

    [string[]]$eventslog_idtoget_arr01 = @()    # put other line in comment # for all events (0 count = no search by id)
    #[string[]]$eventslog_idtoget_arr01+= "4624" # logon
    $eventslog_idtoget_jarr01[$n] = $eventslog_idtoget_arr01

    $eventslog_idtoignore_arr01 = @()          # put other line in comment # for all events
    #$eventslog_idtoignore_arr01+= "10016"      # com object error
    $eventslog_idtoignore_jarr01[$n] = $eventslog_idtoignore_arr01

    if($eventslog_daysback_arr01 -ne -1)
    {
        [DateTime[]]$eventslog_datetime_min_arr01[$n] = (Get-Date).AddDays(-$eventslog_daysback_arr01[$n])
        [DateTime[]]$eventslog_datetime_max_arr01[$n] = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    }
}
###################################
if($events_log_to_check01.dpmbackups -eq 1)
{
    $n++
    [string[]]$eventslog_name_arr01[$n] = "dpm backup events"
    [string[]]$eventslog_provider_arr01[$n] = "*"
    [string[]]$eventslog_level_arr01[$n] = "3"         # -1 = all 2 = ERROR, 3 = warning 4 = information
    [string[]]$eventslog_keywordtosearch01[$n] = "*"   # always use *word* (asterix at start and end)
    [string[]]$eventslog_maxevents_arr01[$n] = 25
    [string[]]$eventslog_daysback_arr01[$n] = 14       # -1 = no datetime filter

    [string[]]$eventslog_idtoget_arr01 = @()    # put other line in comment # for all events (0 count = no search by id)
    #[string[]]$eventslog_idtoget_arr01+= "4624" # logon
    $eventslog_idtoget_jarr01[$n] = $eventslog_idtoget_arr01

    $eventslog_idtoignore_arr01 = @()          # put other line in comment # for all events
    #$eventslog_idtoignore_arr01+= "10016"      # com object error
    $eventslog_idtoignore_jarr01[$n] = $eventslog_idtoignore_arr01

    if($eventslog_daysback_arr01 -ne -1)
    {
        [DateTime[]]$eventslog_datetime_min_arr01[$n] = (Get-Date).AddDays(-$eventslog_daysback_arr01[$n])
        [DateTime[]]$eventslog_datetime_max_arr01[$n] = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    }
}

# reference ID for events
[string[]]$log_arr01 = "application (msi installer)"
[string[]]$eventid00 = "11707 (install completed)"
[string[]]$eventid00+= "1033 (install completed)"
[string[]]$eventid00+= "11724 (uninstall completed)"
[string[]]$eventid00+= "1034 (uninstall completed)"

############################################### display date
$date = get-date $eventslog_datetime_min_arr01[$n] -Format "yyyy-MM-dd HH:mm:ss"

########################################
# know events that are recurrents
########################################
# http://www.eventid.net/display-eventid-36887-source-Schannel-eventno-10676-phase-1.htm

########################################
# log file
########################################
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$scriptname = split-path -leaf $MyInvocation.MyCommand.Definition
$Logfilename = $scriptname + "_log.txt"
$logfile = $scriptPath + "\" + $Logfilename
$logall = 1

####################################
# color for thml report
####################################
[string[]]$error_message_arr = "WARNING"
[string[]]$error_color_arr = "yellow" # yellow
[string[]]$error_message_arr+= "avertissement"
[string[]]$error_color_arr+= "yellow" # yellow
[string[]]$error_message_Arr+= "ERROR"
[string[]]$error_color_arr+= "red" # red
[string[]]$error_message_Arr+= "ERReuR"
[string[]]$error_color_arr+= "red" # red
[string[]]$error_message_arr += "1900-01-01 00:00:00"
[string[]]$error_color_arr += "yellow" # yellow
[string[]]$error_message_arr += "00:00:00"
[string[]]$error_color_arr += "yellow" # yellow
[string[]]$error_message_arr += "inprogress"
[string[]]$error_color_arr += "yellow" # yellow
[string[]]$error_message_arr += "pending"
[string[]]$error_color_arr += "yellow" # yellow
[string[]]$error_message_Arr+= "failed"
[string[]]$error_color_arr+= "red" # red
[string[]]$error_message_Arr+= "true"
[string[]]$error_color_arr+= "red" # red
[string[]]$error_message_Arr+= "orange01"
[string[]]$error_color_arr+= "orange" # red

# if we search a keyword, the result cell will be orange if found
if($keywordtosearch01 -ne "*")
{
    #[string[]]$error_message_arr += "$keywordtosearch01"
    #[string[]]$error_color_arr += "orange" # yellow
}

#################################
# HTML formatting
#################################
$header = @"
<style>
BODY{background-color:white;}
TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: LightBlue}
TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: white}
.green{background-color:#d5f2d5}
.blue{background-color:#e0eaf1}
.red{background-color:#ffd7de}
.yellow{background-color:#ffff00}
.orange{background-color:#ffa500}
</style>
"@

$msg01 = $title01
if ($logall=1) {try{(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile}catch{}}

# loop computers

# agregation of all computers and logs for each computers
$events_jobs_arr01 = @()

foreach($eventlog_computer in $eventlogs_name_device_arr01)
{
    $msg01 = "Loop computers: " + $eventlog_computer
    write-host  -ForegroundColor Cyan
    if ($logall=1) {try{(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}catch{}}
   
    # loop logs (ex: system, application etc.)
    for($log_cnt =0; $log_cnt -lt $log_tot; $log_cnt++)
    {
        $msg01 = "Log: " + $eventslog_name_arr01[$log_cnt]
        if ($logall=1) {try{(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}catch{}}

        ##########################################
        # FILTERXPATH fabrication (faster filter)
        ##########################################
        #$eventid01 = @()
   
        #[DateTime]$date_time_max00 = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        #[DateTime]$date_time_min00 = (Get-Date).AddDays(-$gobackdays01)

        # using filterxpath to filter stuff is faster, the event are filtered BEFORE the result is sent to powershell
        # http://www.powershellish.com/blog/2014-12-09-get-winevent-filterxpath

        # filter datetime at source for filterxpath parameter
        $milliseconds01 = New-TimeSpan -Days $eventslog_daysback_arr01[$log_cnt] | Select-Object -ExpandProperty TotalMilliseconds

        #"*[System[EventID=4624 and TimeCreated[timediff(@SystemTime) <= 86400000]] and EventData[Data[@Name='TargetUserName']='jdoe']]"
   
        $filterxpath01 = "*[System["
        $filterxpath01+= "TimeCreated[timediff(@SystemTime) <= $milliseconds01]"
   
        # level of error
        if($eventslog_level_arr01[$log_cnt] -ne -1 -and $eventslog_level_arr01[$log_cnt] -ne "*")
        {
            $level01 = $eventslog_level_arr01[$log_cnt]
            $filterxpath01+= " and Level=$level01"
        }

        # id wanted
        if($eventslog_idtoget_jarr01[$log_cnt].count -gt 1) { $filterxpath01+= " and (" }
        if($eventslog_idtoget_jarr01[$log_cnt].count -eq 1) { $filterxpath01+= " and" }
        for($idcnt=0;$idcnt -lt $eventslog_idtoget_jarr01[$log_cnt].count; $idcnt++)
        {
            $id01 = $eventslog_idtoget_jarr01[$log_cnt][$idcnt]
            if ($id01.length -gt 0)
            {
                # add OR at second element and more
                if($idcnt -gt 0) {$filterxpath01+= " or " }
                $filterxpath01+= " EventID=$id01"
            }
        }
        if($eventslog_idtoget_jarr01[$log_cnt].count -gt 1) { $filterxpath01+= ")" }

        # id NOT wanted
        for($idcnt=0;$idcnt -lt $eventslog_idtoignore_jarr01[$log_cnt].count; $idcnt++)
        {
            $id01 = $eventslog_idtoignore_jarr01[$log_cnt][$idcnt]
            if ($id01.length -gt 0)
            {
                $filterxpath01+= " and EventID!=$id01" # com error
            }
        }
       
        $filterxpath01+= "]" # close system related variable group
        #$filterxpath01+= " and EventData[Data[@Name='Utilisateur']='devicom']"
        #[EventData[Data='Sens' and Data='Logoff']]
        #$filterxpath01+= " and EventData[Data='windows']"
        $filterxpath01+= "]" # close main

        ###########################
        # main
        ###########################

        #[string]$date_time_min = $date_time_min00.tostring("yyyy-MM-dd HH:mm:ss")
        #[string]$date_time_max = $date_time_max00.tostring("yyyy-MM-dd HH:mm:ss")
        write-host "------------------------------------"
        write-host "Computer.........: " $eventlog_computer
        write-host "log..............: " $eventslog_name_arr01[$log_cnt]
        write-host "provider01.......: " $eventslog_provider_arr01[$log_cnt]
        write-host "level............: " $eventslog_level_arr01[$log_cnt]
        write-host "id to get........: " $eventslog_idtoget_jarr01[$log_cnt]
        write-host "id to ignore.....: " $eventslog_idtoignore_jarr01[$log_cnt]
        write-host "keywordtosearch01: " $eventslog_keywordtosearch01[$log_cnt]
        write-host "date_time_min....: " $eventslog_datetime_min_arr01[$log_cnt] #.tostring("yyyy-MM-dd HH:mm:ss")
        write-host "date_time_max....: " $eventslog_datetime_max_arr01[$log_cnt] #.tostring("yyyy-MM-dd HH:mm:ss")
        write-host "maxevents........: " $eventslog_maxevents_arr01[$log_cnt]

        #############################################
        # result psobject
        #############################################
        $events_job_obj01 = New-Object PsObject
        $events_job_obj01 | Add-Member NoteProperty -Name timecreated -value ''
        $events_job_obj01 | Add-Member NoteProperty -Name MachineName -value ''
        $events_job_obj01 | Add-Member NoteProperty -Name logname -value ''
        $events_job_obj01 | Add-Member NoteProperty -Name level -value ''
        $events_job_obj01 | Add-Member NoteProperty -Name Leveldisplayname -value ''
        $events_job_obj01 | Add-Member NoteProperty -Name userid -value ''
        $events_job_obj01 | Add-Member NoteProperty -Name id -value ''
        $events_job_obj01 | Add-Member NoteProperty -Name message -value ''

        ########################################
        # second header 1st line for each log
        ########################################
        $events_job_obj01.timecreated = "GoBackDays: " + $eventslog_daysback_arr01[$log_cnt]
        $events_job_obj01.MachineName = "MaxEvents: " + $eventslog_maxevents_arr01[$log_cnt]
        $events_job_obj01.logname = $eventslog_name_arr01[$log_cnt]
        $events_job_obj01.level = $eventslog_level_arr01[$log_cnt]
        $events_job_obj01.Leveldisplayname = "StringSearch: " + $eventslog_keywordtosearch01[$log_cnt]
        $events_job_obj01.userid = "IdNotWanted: " + $eventslog_idtoignore_jarr01[$log_cnt]
        $events_job_obj01.id = "IDWanted: " + $eventslog_idtoget_jarr01[$log_cnt]
        $events_job_obj01.message = $eventslog_name_arr01[$log_cnt] + " orange01"
        $events_jobs_arr01 += $events_job_obj01.PSObject.Copy()

        $usefilterxpath01 = 1
        if($usefilterxpath01 -eq 1)
        {
            [psobject]$global:events_report01 = $null
           
            if($eventslog_keywordtosearch01[$log_cnt] -ne "*")
            {
                # string search
                $command01 = {[psobject]$global:events_report01 = Get-WinEvent -ComputerName $eventlog_computer -LogName $eventslog_name_arr01[$log_cnt] `
                -MaxEvents $eventslog_maxevents_arr01[$log_cnt] -FilterXPath $FilterXPath01 -ErrorAction Stop | Where-Object {$_.Message -like $eventslog_keywordtosearch01[$log_cnt]}}
            }
            else
            {
                # no string search
                $command01 = {[psobject]$global:events_report01 = Get-WinEvent -ComputerName $eventlog_computer -LogName $eventslog_name_arr01[$log_cnt] `
                -MaxEvents $eventslog_maxevents_arr01[$log_cnt] -FilterXPath $FilterXPath01 -ErrorAction Stop}
            }
           
            write-host "Filterxpath...: $FilterXPath01" -ForegroundColor Yellow
            #write-host $command01 -ForegroundColor Yellow
            #$command02 = [scriptblock]::Create($command01)
           
            try
            {
                &$command01
                #[psobject]$events_report01 = Get-WinEvent -ComputerName $eventlog_computer -LogName $eventslog_name_arr01[$log_cnt] `
                #-MaxEvents $eventslog_maxevents_arr01[$log_cnt] -FilterXPath $FilterXPath01 -ErrorAction Stop
                $events_job_obj01 = $global:events_report01 | select Timecreated, MachineName, @{Name = 'Logname'; Expression = {$eventslog_name_arr01[$log_cnt]}} , level, Leveldisplayname,  userid, id, message
            }
            catch
            {
                write-host "error 0 results" -ForegroundColor Red
                $events_job_obj01.logname = $eventslog_name_arr01[$log_cnt]
               
                $msg01 = "ERROR getting events"
                $msg01+= $eventslog_name_arr01[$log_cnt]
                $msg01+= $_.exception.message

                $events_job_obj01.message = $msg01
                #write-host $_.ScriptStackTrace
                write-host $_.exception.message -ForegroundColor Red
            }
            #$global:events_report01
            #| format-table Timecreated, Leveldisplayname, message, id #-auto -wrap #| Out-String
        }
        else
        {
            # OLD search by TEXT, no xfilter
            [psobject]$events_report01 = Get-WinEvent -ComputerName $eventlog_computer -LogName $log01 -MaxEvents $maxevents01 `
            | Where-Object {`
            $_.providername -like $provider01 `
            -and $_.Message -like $keywordtosearch01 `
            -and $_.timecreated -gt $date_time_min `
            -and $_.level -eq 2 `
            -and $_.id -ne 10016 `
            -and $_.timecreated -le $date_time_max}
            #-and $_.Message -notlike "*Group Policy failed*" `
            #-and $_.level -eq 2 `
        }
        #$events_job_obj01 = $global:events_report01 | select Timecreated, MachineName, @{Name = 'Logname'; Expression = {$eventslog_name_arr01[$log_cnt]}} , level, Leveldisplayname,  userid, id, message

        $events_jobs_arr01 += $events_job_obj01.PSObject.Copy()
        #$events_jobs_arr01
    } # loop logs

} # loop computers

[xml]$event_xml01 = $events_jobs_arr01 | ConvertTo-Html -fragment

# xml for futur database
#$event_xml02 = ConvertTo-Xml -As "Document" -InputObject ($events_jobs_arr01  | select Timecreated, level, Leveldisplayname, MachineName, userid, message, id) #-Depth 3

# Parse XML object and set colour class according to value in last column ("Age")

$msg01 = "xml loop start"
if ($logall=1) {try{(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}catch{}}

for($trcnt=1;$trcnt -le $event_xml01.table.tr.count-1;$trcnt++)
{
    ################################################################
    # change color if certain keywords are found in html cell
    ################################################################
   
    for($tdcnt=1;$tdcnt -le $event_xml01.table.tr[$trcnt].ChildNodes.Count-1;$tdcnt++)
    {
        #write-host $tdcnt "   " $event_xml01.table.tr[$trcnt].td[$tdcnt]
        $item02 = $event_xml01.table.tr[$trcnt].td[$tdcnt]
        for($errorcnt = 0; $errorcnt -lt $error_message_arr.count; $errorcnt++)
        {
            $error_message = $error_message_arr[$errorcnt]
            if($item02 -like "*$error_message*")
            {
                $event_xml01.table.tr[$trcnt].ChildNodes[$tdcnt].SetAttribute('class',$error_color_arr[$errorcnt])
            }
        }
    }
}
$msg01 = "xml loop end"
if ($logall=1) {try{(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}catch{}}

# Define body and append the modified XML object
$body = @"
<H2>event search by keyword mot recherché: $keywordtosearch01</H2>
$($event_xml01.innerxml)
"@

#####################
# html
#####################
$file03 = $scriptPath + "\event_list_array.htm"
# Convert to HTML and save the file
ConvertTo-Html -Head $header -Body $body | Out-File $file03

#########################
# xml
#########################
#$file04 = $scriptPath + "\event_list.xml"
#$event_xml02.save($file04)

if($events_jobs_arr01.count -gt 0)
{
    & $file03
}
Write-Host "Saved to:" $file03 -ForegroundColor Green



Sunday, August 11, 2019

utf-8 conversion in VBS script

this will read utf-8 in a while converting it for windows 1252 codepage

Source:
WScript.Arguments(0) contain the full path of the utf-8 file to convert

Destination:
strData

Set objStream = CreateObject("ADODB.Stream")

objStream.CharSet = "utf-8"
objStream.Open
objStream.LoadFromFile(WScript.Arguments(0))

strData = objStream.ReadText()

objStream.Close
Set objStream = Nothing

Friday, July 12, 2019

ms access mdb to ms sql express

Hi,

I had to convert a database access to Microsoft sql express
I wanted to keep the forms in access to minimize the work

Whatever i did, the search from access was always slower in mssql than it was with a simple access file (.mdb)

I used linked tables, 13 seconds to go to the end of the 13000 records with ms access search
I used a query (in access) directly to the sql server with a dsn, 3-4 seconds to search last recordm and sometimes, even with an index, my form became readonly...

I had to use a mixed technique, to fill a recordset from ms sql, then push it as source in the ms access form

Here the precious VBA code to do that in a form:

-------------- vba macro in access --------------------------

Private Sub form_open(cancel As Integer)

    sql01 = 1
 
    If sql01 = 1 Then
        db_Server01 = "mssqlipaddressorservername\sqlexpress,1533"
        database01 = "databasename"
        db_login01 = "sa"
        db_password01 = "password"
     
        Dim Conn1 As New ADODB.Connection
     
        x = 0
        Dim arrcon01()
        con01 = ""
 
        '=== mssql express 2017 connection build
        ReDim Preserve arrcon01(x): arrcon01(x) = "Provider=SQLOLEDB": x = x + 1
        ReDim Preserve arrcon01(x): arrcon01(x) = "Data Source=" & db_Server01: x = x + 1
     
        If Len(db_login01) = 0 And Len(db_password01) = 0 Then
            '=== use windows login if no login adn password
            ReDim Preserve arrcon01(x): arrcon01(x) = "Integrated Security=SSPI": x = x + 1
            ReDim Preserve arrcon01(x): arrcon01(x) = "Persist Security Info=True": x = x + 1
        Else
            '=== adodb login and pass (sqlserver is different syntax)
            ReDim Preserve arrcon01(x): arrcon01(x) = "user id=" & db_login01: x = x + 1
            ReDim Preserve arrcon01(x): arrcon01(x) = "password=" & db_password01: x = x + 1
        End If
     
        '=== ref code
        'ReDim Preserve arrcon01(x): arrcon01(x) = "Initial Catalog=" & db_name01: x = x + 1
 
        For i = 0 To UBound(arrcon01)
            If i < UBound(arrcon01) Then
                con01 = con01 & arrcon01(i) & ";"
            Else
                con01 = con01 & arrcon01(i)
            End If
        Next
     
        Conn1.ConnectionTimeout = 3
        'Conn1.CommandTimeout = 3600
        Conn1.ConnectionString = con01
        Conn1.Open
     
        Set Rs01 = CreateObject("ADODB.Recordset")  ' recordset
        'Rs01.LockType = adLockOptimistic
        'Rs01.CursorType = adOpenKeyset
     
        method01 = 1
        If method01 = 0 Then

        ElseIf method01 = 1 Then
            'https://sourcedaddy.com/ms-access/working-with-ado-recordsets.html
            Dim cmd1 As New ADODB.Command
            Set cmd1.ActiveConnection = Conn1
         
            s = "SELECT * "
            s = s & " FROM database.dbo.table order by no"
         
            'MsgBox ("sql access cmd: " & s)
         
            cmd1.CommandText = s
            cmd1.CommandType = adCmdText ' adCmdStoredProc
            Rs01.Index = "id"
            Rs01.CursorLocation = adUseClient
            Rs01.CursorType = adOpenStatic
            Rs01.LockType = adLockBatchOptimistic
         
            Rs01.Open cmd1, , adOpenKeyset, adLockPessimistic

        ElseIf method01 = 2 Then
            '=== method 2
            'https://stackoverflow.com/questions/37013322/receiving-an-error-the-object-you-entered-is-not-a-valid-record-set-property
            ' was slow, removed
         
        End If
    ElseIf sql01 = 0 Then

    End If
 
 
 
    If Not Rs01.EOF Then
        'stDocName = "principal"
        'Me.RecordSource = rs01
        'MsgBox ("query: " & s)
        'DoCmd.OpenForm stDocName, OpenArgs:=""
        'DoCmd.OpenForm stDocName, RecordSource:=s
        '=== reference from florida
        'Me.RResidentContrat_sous_formulaire1.Form.RecordSource = sql
        'Me.RResidentContrat_sous_formulaire1.Form.Requery
        'MsgBox ("query" & s)
        'DoCmd.OpenForm (stDocName), OpenArgs:=s
        'Forms(stDocName).RecordSource = s
        'Me.RecordSource = s
        Set Me.Recordset = Rs01
     
    Else
        msg01 = "ERROR" & vbCrLf
        msg01 = msg01 & "Il n'y a aucun enregistrement dans dbo.dos" & vbCrLf
        msg01 = msg01 & "Base de donnee SQL non disponible" & vbCrLf
        MsgBox (msg01)
    End If
 
 
Exit_Procedure:
    Exit Sub

End Sub

Sunday, July 7, 2019

vm hyperv windows 10 1903 with powershell

Hello,

I had to recreate a vm often with a virtual hard disk, because exporting a vm was quite long
So i started storing my virtual disk on a removable usb3 drive

Since hyperv is a service, I needed to recreate the vm on any computer to work with
Only the hard disk was important to restart the vm on another computer quickly

I found code in powershell on internet and adapted it to my needs

I added powershell code references at the end for futur use

2019-08-03 added the state of hyper-v service

################# powershell ####################
# create a vm from a vistual disk
# windows or maybe anything
# 2 cpu
# 4 gig ram

# windows 7
#   Set-ExecutionPolicy RemoteSigned
# windows 10
#   Set-ExecutionPolicy -scope currentuser RemoteSigned

$test01 = 0
#$test01 = 0

# logfile
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$scriptname = split-path -leaf $MyInvocation.MyCommand.Definition
$Logfilename = $scriptname + "_log.txt"
$logfile = $scriptPath + "\" + $Logfilename
$logall = 1

$msg01 = "START hyper-v vm creation from disk image with same name"
write-host $msg01
if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile}

# error management object
$error01 = New-Object PsObject
$error01 | Add-Member NoteProperty -Name number -value ''
$error01 | Add-Member NoteProperty -Name description -value ''
$error01 | Add-Member NoteProperty -Name error02 -value ''

function error_display($error01)
{
    write-host "===== " $error01.description
    write-host "===== " $error01.error02
    write-host "===== " $error01.error02.InvocationInfo.PositionMessage
    if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + "===== " + $error01.description | Out-File $logfile -append}
    if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + "===== " + $error01.error02 | Out-File $logfile -append}
    if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + "===== " + $error01.error02.InvocationInfo.PositionMessage  | Out-File $logfile -append}
    #if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " error02.Exception.itemname: " + $error01.error02.Exception.itemname | Out-File $filnamfull_log01 -append}
    #if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " error02.InvocationInfo.MyCommand.Name: " + $error01.error02.InvocationInfo.MyCommand.Name | Out-File $filnamfull_log01 -append}
    #if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " error02.ErrorDetails.Message : " + $error01.error02.ErrorDetails.Message | Out-File $filnamfull_log01 -append}
    #if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " error02.InvocationInfo.PositionMessage: " + $error01.error02.InvocationInfo.PositionMessage | Out-File $filnamfull_log01 -append}
    #if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " error02.CategoryInfo.ToString: " + $error01.error02.CategoryInfo.ToString() | Out-File $filnamfull_log01 -append}
    #if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " error02.FullyQualifiedErrorId: " + $error01.error02.FullyQualifiedErrorId | Out-File $filnamfull_log01 -append}
       
}

# hyper-v requis
# Windows 10 Enterprise, Pro, or Education
# 64-bit Processor with Second Level Address Translation (SLAT).
# CPU support for VM Monitor Mode Extension (VT-c on Intel CPUs).
# Minimum of 4 GB memory.
# The Hyper-V role cannot be installed on Windows 10 Home.

#Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
#Install-WindowsFeature -Name Hyper-V -IncludeManagementTools -Restart
#Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

# check if hyper-v optionnal feature is installed
cls

write-host ""
write-host "Checking if hyper-v is installed..."

$features01 = Get-WindowsOptionalFeature -online

[string[]]$arr_optionnal_feature = "Microsoft-Hyper-V-All" #State       : Enabled
          $arr_optionnal_feature+= "Microsoft-Hyper-V"
          $arr_optionnal_feature+= "Microsoft-Hyper-V-Tools-All"
          $arr_optionnal_feature+= "Microsoft-Hyper-V-Management-PowerShell"
          $arr_optionnal_feature+= "Microsoft-Hyper-V-Hypervisor"
          $arr_optionnal_feature+= "Microsoft-Hyper-V-Services"
          $arr_optionnal_feature+= "Microsoft-Hyper-V-Management-Clients"

$found01 = 0
foreach ($feature01 in $features01)
{
    if ($feature01.FeatureName -eq $arr_optionnal_feature[0])
    {
        if ($feature01.State.tostring() -eq "Enabled")
        {
            #write-host $arr_optionnal_feature[1]
            $found01 = 1
            $feature01.FeatureName
            $feature01.State

        }
        else
        {
            $feature01.FeatureName
            $feature01.State
        }
    }
}

if($found01 -eq 1)
{
    write-host "--> OK hyper-v is installed"
    ####################################################
    # disk path to create vm from with same name
    ####################################################
    write-host ""
    write-host "Getting all virtual disk in current folder..."

    # scan file in this folder

    $filelist01 = Get-ChildItem -Path $scriptPath -Filter "*.vhd*"

    [System.Int32]$i_max = ( $filelist01 | Measure-Object ).Count + 1

    write-host ""
    write-host "Liste des disques virtuels dans le dossier actuel: "

    write-host ""
    for($i=1; $i -lt $i_max; $i++)
    {
        write-host ($i) ($filelist01[$i-1].name)
    }
   
    write-host ""
    $choice01 = Read-Host -Prompt 'Entrez le choix du disque virtuel'

    if (($choice01 -gt 0) -and ($choice01 -lt ($i_max)))
    {
       write-host ""
       $msg01 = "--> Choice: " + $choice01 + " " + $filelist01[$choice01 -1]
       if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}
       write-host $msg01

        $filename01 = $filelist01[$choice01 -1]
        $vhd_path01 = $scriptPath + "\" + $filename01

        # extract vm name from disk image name (we want it to be the same)
        $vm_name_arr01 = $vhd_path01.split("\")
        $vm_name01 = $vm_name_arr01[$vm_name_arr01.GetUpperBound(0)]
        # remove extension after .
        $vm_name01 = $vm_name01.Substring(0,$vm_name01.LastIndexOf('.'))

        write-host ""
        write-host "virtual disk full path: " $vhd_path01
        write-host "virtual machine name..: " $vm_name01

        if ($vm_name01.length -gt 0)
        {
            $vm01 = Get-VM| where {$_.name -eq $vm_name01}
            if ($vm01.count -eq 0)
            {
                write-host ""
                write-host "Getting switch list, finding any external switch... (so we can patch windows on internet)"
               
                $switchs01 = Get-VMSwitch

                $found01 = 0
                $switch_name01 = ""

                foreach ($switch01 in $switchs01)
                {
                    if ($switch01.switchtype.tostring().tolower() -eq "external")
                    {
                        write-host "External switch found: " $switch01.name
                        $switch_name01 = $switch01.name
                        $found01 = 1 # caca
                    }
                }
               
                if($found01 -eq 0)
                {
                    ################################
                    # create external v-switch
                    ################################
                    $netadapters01 = Get-NetAdapter

                    $found01 = 0
                   
                    foreach($netadapter01 in $netadapters01)
                    {
                        if($netadapter01.name.tostring().tolower() -eq "ethernet")
                        {
                            write-host "found ethernet"
                            $found01 = 1
                        }
                    }

                    if($found01 -eq 1)
                    {
                        $switch_name01 = "external01"
                       
                        $msg01 = "Creating external switch, network might get disrupted"
                        write-host $msg01
                        if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}

                        New-VMSwitch -name $switch_name01 -NetAdapterName Ethernet -AllowManagementOS $true
                    }
                }
                else
                {
                    # an external v-switch was found
                    # we dont create one
                }

                ############################## futur dev ############################
                ## futur multiple vm creation from array
       
                #[string[]]$arr_vmname = ""
                #[string[]]$arr_vmMemoryStartupBytes = 2147483648*2
                #[string[]]$arr_Generation = 1
                #[string[]]$arr_VHDPath = $vhd_path01
                #[string[]]$arr_NewVHDSizeBytes = 120687091200
                #[string[]]$arr_BootDevice = "VHD"
                #[string[]]$arr_path = Path = $scriptPath + "\" + $vm_name01
                #[string[]]$arr_SwitchName = "Nouveau commutateur virtuel"

                ## parameter number 2 to inputbox

                #$arr_vmname += "vm2"
                #$arr_vmMemoryStartupBytes += 2147483648*2
                #$arr_Generation += $vhd_path01
                #$arr_VHDPath += "textbox"
                #$arr_NewVHDSizeBytes += 120687091200
                #$arr_BootDevice += "VHD"
                #$arr_path += $scriptPath + "\" + $vm_name01
                #$arr_SwitchName += "Nouveau commutateur virtuel"

                # array of parameters
                    #=== vm parameters
                    #https://docs.microsoft.com/en-us/powershell/module/hyper-v/set-vm?view=win10-ps

                    $VM = @{
                    Name = $vm_name01
                    MemoryStartupBytes = 2147483648*2
                    Generation = 1
                    VHDPath = $vhd_path01
                    #NewVHDSizeBytes = 53687091200
                    BootDevice = "VHD"
                    Path = $scriptPath
                    SwitchName = $switch_name01 #(Get-VMSwitch).Name
                    }

                try
                {
                    $error01.number = 0
                    New-VM @VM | out-null
                    $msg01 = "creating vm: " + $vm_name01
                    if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}
                }
                catch
                {
                    $error01.number = 1
                    $error01.description = "ERROR " + $msg01
                    $error01.error02 = $_
                }
               
                if ($error01.number -eq 0)
                {
                   
                    $msg01 = "vm created: " + $vm_name01
                    write-host $msg01
                    if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}

                    try
                    {
                        $error01.number = 0
                        set-vmprocessor -vmname $vm_name01 -count 2
                       
                        $msg01 = "vm processors set to 2: " + $vm_name01
                        write-host $msg01
                        if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}
                    }
                    catch
                    {
                        $error01.number = 1
                        $error01.description = "ERROR " + $msg01
                        $error01.error02 = $_
                    }
               
                    if ($error01.number -eq 0)
                    {
                        # checkpoints off
                       
                        $msg01 = "vm checkpoints: disabled"
                        write-host $msg01
                        if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}
                        set-vm -vmname $vm_name01 -CheckpointType disabled
                    }
                    else
                    {
                        error_display($error01)
                    }
                   
                    ###############################
                    # start hyper-v manager
                    ###############################
                    & (Get-Command "$($env:systemroot)\system32\mmc.exe") @("$($env:systemroot)\System32\virtmgmt.msc")

                }
                else
                {
                    error_display($error01)
                }

                #Set-VMNetworkAdapterVlan -VMName vmfrompowershell1 -Access -VlanId 121

            }
            else
            {
                $error01.number = 1
                $error01.description = "ERROR vm already exist, name: " + $vm_name01
                $error01.error02 = ""
                error_display($error01)
               
                ###############################
                # start hyper-v manager
                ###############################
                & (Get-Command "$($env:systemroot)\system32\mmc.exe") @("$($env:systemroot)\System32\virtmgmt.msc")

            }
        }
        else
        {
            $error01.number = 1
            $error01.description = "ERROR vm_name01 empty"
            $error01.error02 = ""
            error_display($error01)
        }
    }
    else
    {
        $error01.number = 1
        $error01.description = "ERROR bad choice"
        $error01.error02 = ""
        error_display($error01) 
    }

    write-host ""
    $msg01 = "END hyper-v vm creation from disk image"
    write-host $msg01
    if ($logall=1) {(Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $msg01 | Out-File $logfile -append}

    #ref code:
    #& (Get-Command "$($env:systemroot)\system32\robocopy.exe") @("$($folder_source_c_01)", "$($folder_destination_here_01)", '/XJ', '/s', '/e', '/R:0', '/W:0', $log01)
   


    # check if it's already existing

    # reference:
    # vm details
    # Get-VM -Name VMWEB01 | Format-List *

    # vm disks
    #(Get-VM –VMName VMTest | Select-Object VMId | Get-VHD).Path

    # vm memory
    #Set-VMMemory "VMTest" -DynamicMemoryEnabled $true -MaximumBytes 1GB

    # vm start
    # Start-VM -name VMTest

    #vm stop forced (not gracefull)
    # Stop-VM -name VMTest -Force

    # vm add checkpoint
    # Get-VM -Name VMTest | Checkpoint-VM -SnapshotName “Before Upgrade”

    # vm get checkpoints
    # Remove-VMCheckpoint -VMName VMTest -Name "Before Upgrade"

    # vm list all checkpoints
    #Get-VM | Get-VMCheckpoint

    #######################
    # vm backup
    #######################

    ## Backup Folder
    #$Backup = "C:\Backup"
    ## Get VMs Name
    #$VMs = Get-VM | select name

    # vm backuo Delete Backup Folder and create it again

    ## Backup Folder
    #$Backup = "C:\Backup"
    ## Get VMs Name
    #$VMs = Get-VM | select name
    #if((Test-Path -Path $Backup)){
    #    Remove-Item $Backup -force -recurse -erroraction:SilentlyContinue
    #} else {
    #    New-Item $Backup -type directory
    #}
    ## Export all the VMs
    #foreach ($VM in $VMs)
    #{
    #    Export-VM -Name $VM.Name -Path $Backup
    #}

    # vm backup schedule
    #$trigger = New-JobTrigger -Weekly -DaysOfWeek Sunday -WeeksInterval 2 -At 12:00AM
    #$options = New-ScheduledJobOption -RunElevated

    #############################################
    # vmsnapshot
    #############################################
    #get-VMSnapshot forea-demox-win10-avantage
    #Remove-VMSnapshot

    ##################################################
    # vm management advanced (server)
    ##################################################

    #scvmm console commands
    # https://docs.microsoft.com/en-us/powershell/module/virtualmachinemanager/?view=systemcenter-ps-2019

    #Import-Module -Name "virtualmachinemanager"

    # scvmm
    # add console
    #SCVMM Management console

    # load pssnapin
    #Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager
}
else
{

    $error01.number = 1
    $error01.description = "ERROR Hyper-v is not installed"
    $error01.error02 = ""
    error_display($error01)

    write-host ""
    $choice01 = Read-Host -Prompt "Do you want to install all hyper-v features? (y = yes, n=no, you will have to reboot if it was not installed)"

    if($choice01.ToString().ToLower() -eq "y")
    {
        write-host ""
        write-host "Installting all hyper-v features online"
        write-host "Executing: Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All..."

        Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
    }
    else
    {
        write-host "ok bye!"
    }



}

Thursday, March 14, 2019

Automatic login in office 365 / sharepoint with powershell

Automatic login in office 365 / sharepoint with powershell

powershell, sharepoint online

Requis:
try
    {Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking}
    catch{}
#Get-Module SharePointPnPPowerShell* -ListAvailable | Select-Object Name,Version | Sort-Object Version -Descending
Install-Module SharePointPnPPowerShellOnline

Avec le login actuel
$env:UserName

Je vais chercher dans les crédentials, le login et password windows du user actuel ($env:UserName)
$cred = Get-PnPStoredCredential -Name $env:UserName -Type PSCredential

J’ajoute « @domain.com » car il est obligatoire dans office 365 (reste à faire : le .com n’est pas dynamique)
$username = $cred.UserName + "@" + $env:UserDomain + ".com"

Je le met dans un login office 365 :
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $cred.Password)

Que j’utilise avec le context : (client mode in sharepoint)

$Context01 = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)

$Context01.Credentials = $Credentials

$site01 = $context01.Web
$context01.Load($site01)

try
    {
    $Context01.executeQuery()
    }
catch
    {
    write-host "ERROR: $($_.Exception.Message) $($_.InvocationInfo.PositionMessage)" -foregroundcolor RED
    }



Et voilà!

Tuesday, November 6, 2018

Google Authenticator siteweb visual studio


Google 2FA with authenticator

Package
https://www.nuget.org/packages/GoogleAuthenticator/

Nuget console in visual studio:
Install-Package GoogleAuthenticator -Version 1.2.1

Source of Google.Authenticator.dll:
https://github.com/brandonpotter/GoogleAuthenticator

------------------ code visual studio.net c#----------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using System.Security.Cryptography;
using System.Text;
using System.Web.Profile;
using System.Web.Security;
using Google.Authenticator;

public partial class _Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ////////////////////////////////////////////////
        // if user do not have a code, we generate one
        ////////////////////////////////////////////////
     


        ////////////////////////////////////////
        // get qrcode
        ////////////////////////////////////////
        TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();

        //the width and height of the Qr Code in pixels
        var setupInfo = tfa.GenerateSetupCode("Name of the app", "More info ABout the App", "SuperSecretKeyGoesHere22", 300, 300);

        // assigning the Qr code information + URL to string
        string qrCodeImageUrl = setupInfo.QrCodeSetupImageUrl;
        // show the Manual Entry Key for the users that don't have app or phone
        string manualEntrySetupCode = setupInfo.ManualEntryKey;

        // showing the qr code on the page "linking the string to image element"
        Image1.ImageUrl = qrCodeImageUrl;

        // showing the manual Entry setup code for the users
        Label1.Text = manualEntrySetupCode;
    }

    protected void Button1_Click(object sender, EventArgs e)
    {

        // login
        string login01 = txtlogin01.Text.Trim();
        string password01 = txtpassword01.Text.Trim();
        string passcode01 = txtpasscode01.Text.Trim();

        // check sql if the user have a passcodekey01



        ////////////////////////////////////////
        // validate google code
        ////////////////////////////////////////
     
        TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
        bool isCorrectPIN = tfa.ValidateTwoFactorPIN("SuperSecretKeyGoesHere22", passcode01);
        if (isCorrectPIN == true)
        {
            Label2.Text = "i am cool";
        }
        else
        {
            Label2.Text = "i am Fool";
        }

    }

    protected void TextBox1_TextChanged(object sender, EventArgs e)
    {

    }
}

Friday, October 26, 2018

Object Programming Level 1

Object Programming Level 1

I never saw the use of object programming until we could make an object with a sql query.
Of course it is because i never had a program that needed it.

Doing a class with a get and set (wich is simply a variable with extra code) is superfluous, because you can do that with a variable in procedural mode. Without having to include your sub class in your main class and typing 10 lines of extra code just to have an object as a variable.

Most poeple create objects instead of variables and think it's cool. But what about the extra time you charge your client just so your variable are now objects, but the need for it was not there?

Programmer analyst must be analyse first. Do you need an object for a simple variable never used again? That do not need parent property? That does not have childrens?

So a procedural code with a variable is: (csharp)

--- code start csharp visual studio console app -------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace application_obejct_test
{
    class Program
    {
        static void Main(string[] args)
        {
            string variable01 = "hello";
            Console.WriteLine(variable01);

            variable01 = "not hello";
            Console.WriteLine(variable01);

            Thread.Sleep(3000);
        }
    }
}

--- end code ---

Now let's the same with an object

--- code start csharp visual studio console app -------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace application_obejct_test
{
    class Program
    {
       

        static void Main(string[] args)
        {
            string01 variable01 = new string01();
            variable01.text01 = "hello";
            Console.WriteLine(variable01.text01);

            variable01.text01 = "not hello";
            Console.WriteLine(variable01.text01);

            Thread.Sleep(3000);
        }
    }

    public class string01
    {
        // here i will not give the same name to the field and the property with a case difference (uppercase the first letter)
        // it's just a pain to always use the SHIFT key to type uppercases letters

        private string text02; // field, just a variable used to get and set value
        public string text01   // property, the thingy after the . in the name of your new object
        {
            get
            {
                return text02;
            }
            set
            {
                text02 = value; // value is an object property, it's always there
            }
        }
    }
}
------- code end --------

Now, as you can see, for a simple string, making an object to manage it, is really of no use
Poeple doing that with a string, have too much time to loose

BUT, object can be much more
You can validate the length before setting the value of the string object

That changes things, because your object now free you of validating every input from your client
But it would still cut the value without warning...
To add a warning you have to manage error that can happen in your object

--- code start csharp visual studio console app -------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace application_obejct_test
{
    class Program
    {
       

        static void Main(string[] args)
        {
            string01 variable01 = new string01();
            variable01.text01 = "hello";
            Console.WriteLine(variable01.text01);

            variable01.text01 = "not hello";
            if (variable01.errorcode01 == 99)
            {
                Console.WriteLine("ERROR " + variable01.errorcode01);
                Console.WriteLine("ERROR " + variable01.errormessage01);
                Console.WriteLine(variable01.text01);
            }
            else
            {
                Console.WriteLine(variable01.text01);
            }

            Thread.Sleep(3000);
        }
    }

    public class string01
    {
        // here i will not give the same name to the field and the property with a case difference (uppercase the first letter)
        // it's just a pain to always use the SHIFT key to type uppercases letters

        private int err01;
        private string err02;

        private string text02; // field, just a variable used to get and set value
        public string text01   // property, the thingy after the . in the name of your new object
        {
            get
            {
                return text02;
            }
            set
            {
                // validate the value before assigning it to the object
                int maxvalue01 = 7;
                if (value.Length > maxvalue01)
                {
                    text02 = value.Substring(0, maxvalue01);
                    err01 = 99;
                    err02 = "string was cut";
                }
                else
                {
                    text02 = value; // value is an object property, it's always there
                }
            }
        }

        public int errorcode01
        {
            get { return err01; }
        }

        public string errormessage01
        {
            get { return err02; }
        }

    }
}
--- code end ---

Until now, the difference is we can get and set the object variable WITH a validation on the set

We could do this with a struct passed to a function byref, but we would have to include the action to do on each variable in the struct.

So the difference with an object variable, is the actions are defined in it, and the validation too.

But can we access the object variables dynamically? (by name)
Yes we can:

--- code start ---
            // set with dynamic name
            typeof(string01).GetProperty("text01").SetValue(variable01, "hello");
            // get with dynamic name
            object value01 = typeof(string01).GetProperty("text01").GetValue(variable01);

            Console.WriteLine(value01);

--- code end ---

Of course, without hardcoding your object, you loose the warning the compiler will give you if you try to give a bad type of value to your object (string to an int etc.), but that is for amateur programmers. Real pro would trap that inside the object, and validate any get or set with an error returned by the object.

That's it for level 1 object programming.