Windows profile deletion tool

Post your working scripts, libraries and tools for AHK v1.1 and older
skoliver1
Posts: 10
Joined: 18 Jun 2014, 08:35

Windows profile deletion tool

10 Jul 2019, 22:25

I was looking for a quicker way to delete Windows profiles than manually deleting the user folder and registry entries. So I created this to compile a list of valid users from the registry, excluding system profiles and those who are currently logged on. It also lists any extra user profile folders that don't exist in the registry anymore, for whatever reason, and marks them as such.

So it deletes the user folder and these associated registry entries via WMI:
"HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\{SID of User}"
"HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileGuid\{GUID}" SidString = {SID of User}
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\{SID of User}"

I'm self-taught and I'm sure there are tons of ways to simplify/improve this, but here you go.

Code: Select all

; created by skoliver1
; [email protected]
; inspired by Remove-UserProfile.ps1  Developer: Andrew Saraceni ([email protected])
; http gallery.technet.microsoft.com /scriptcenter/Remove-UserProfile-Remove-96e27a3b  Broken Link for safety

#SingleInstance force

if A_OSVersion in WIN_XP
{
   MsgBox, 262160, Profile Remover, This is not compatible with XP.`n`nThis script will now exit.
   ExitApp
}

if not A_IsAdmin
{
   Run *RunAs "%A_AhkPath%" "%A_ScriptFullPath%"
   ExitApp
}

OnExit("Cleanup")
OnExit(ObjBindMethod(MyObject, "Exiting"))
SetBatchLines, -1

TempFolder = %A_Temp%\ProfileKiller
FileCreateDir %TempFolder%

Gui, Margin, 10, 10
Gui, Add, ListView, r10 w260 h180 Grid vVLV hwndHLV gColClick
   , User Profiles|Last Modified|Size|SSID|Extra
Gui Add, Text, x276 y5, Select the profiles to remove and click Go.
Gui Add, Text, x276 y25 w220, Any rows highlighted in yellow are user folders that are invalid and are not in the registry.
Gui Add, Button, x276 y60 w50 gEngage, Go
gosub UserList

; Create a new instance of LV_Colors
CLV := New LV_Colors(HLV)
; Set the colors for selected rows
CLV.SelectionColors(0x0000FF, 0xFFFFFF)
If !IsObject(CLV) {
   MsgBox, 0, ERROR, Couldn't create a new LV_Colors object!
   ExitApp
}

; ======  Adjusting column widths  ======
LV_ModifyCol(1, AutoHdr)
LV_ModifyCol(3, 80)
LV_ModifyCol(4, 0)
LV_ModifyCol(5, 0)


Gui Show, xCenter YCenter, Profile Remover
; Redraw the ListView after the first Gui, Show command to show the colors, if any.
WinSet, Redraw, , ahk_id %HLV%
gosub ExtraFolders
gosub FolderSize
Return

GuiClose:
GuiEscape:
ExitApp




UserList:
; ==============  get list of logged in users to exclude from list  ==================
RunWait cmd.exe /c quser > %TempFolder%\quser.txt,, Hide
FileRead LoadedProfiles, %TempFolder%\quser.txt

; ==============  this piece gets the list of existing profiles from registry  ==================
ProfileRegList = HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

Loop Reg, %ProfileRegList%, KR
{
	if (A_LoopRegName = "S-1-5-18" or A_LoopRegName = "S-1-5-19" or A_LoopRegName = "S-1-5-20")
		continue ; skip the above system accounts
	SIDNames = %SIDNames%%A_LoopRegName%`n ; add the SID #s of these reg entries to a list
}

; ======  parse the SID list and get the username each corresponds to  ======
Loop Parse, SIDNames, `n
{
	if A_LoopField = ; if empty, move on
		continue
	RegRead LocalPath, %ProfileRegList%\%A_LoopField%, ProfileImagePath
	LocalPath := StrReplace(LocalPath, "C:\Users\") ; remove the beginning of the path so it's just the username
	Needle = %LocalPath%%A_Space% ; Username plus a space
	
	if InStr(LoadedProfiles, Needle) ; if the Username+Space is found in the list of loaded users
		continue ; skip it
	LV_Add("",LocalPath,,, A_LoopField) ; this gives me a username and SID
	NewLocalPath = %NewLocalPath%%LocalPath%`n
}
myUserList = %NewLocalPath%

; ======  get last modified time for folders  ======
Loop Parse, myUserList, `n
{
	if A_LoopField =
		continue
	FileGetTime LastMod, C:\Users\%A_LoopField%
	FormatTime LastMod, %LastMod%, yyyy/M/d
	LV_Modify(A_Index, , , LastMod, "<calculating>")
}
return


ExtraFolders:
CLV.OnMessage()
GuiControl, Focus, %HLV%
GuiControl, -Redraw, %HLV%
CLV.Clear(1, 1)

Loop Files, C:\Users\*, D
{
	Needle = %A_LoopFileName%%A_Space% ; Username plus a space
	if InStr(LoadedProfiles, Needle) ; if the Username+Space is found in the list of loaded users
		continue ; skip it
	
	if (A_LoopFileName = "All Users" or A_LoopFileName = "Default" or A_LoopFileName = "Default User" or A_LoopFileName = "Public" or A_LoopFileName = "Administrator")
		continue
		
	if !InStr(NewLocalPath, A_LoopFileName . "`n")
	{
		FileGetTime LastMod, C:\Users\%A_LoopFileName%
		FormatTime LastMod, %LastMod%, yyyy/M/d
        LV_Add("", A_LoopFileName, LastMod, "<calculating>",, "1")
		Row := LV_GetCount()
		CLV.Row(Row, 0xFFFF00, 0x000000) ; make it yellow
	}
}
CLV.NoSort(False) ; this enables column re-sorting
GuiControl, +Redraw, %HLV%
return



; ======  calculate user folder sizes  ======
FolderSize:
Loop
{
   LV_GetText(Name, A_Index)  ; Resume the search at the row after that found by the previous iteration.
   if Name =
      break
   
   ; ======  calculate the size.  No offline files, directories or system files.  The last two don't make much diff for size but speeds it up  ======
   if A_OSVersion in WIN_7,WIN_8,WIN_8.1,WIN_VISTA
		RunWait cmd.exe /c dir C:\Users\%Name% /a:-D-S /S > %TempFolder%\%Name%-Size.txt,, Hide
	
    else if (A_OSVersion >= "10.0.17763")
		; the Offline file attribute was introduced in version 1809 of Windows 10, which is preferred, as it 
		; lets me calculate the actual "on disk" file size.  Not just what is allocated by offline files in cloud-syncing programs.
		RunWait cmd.exe /c dir C:\Users\%Name% /a:-O-D-S /S > %TempFolder%\%Name%-Size.txt,, Hide
	
    else ; if W10 and lower than 1809
		RunWait cmd.exe /c dir C:\Users\%Name% /a:-D-S /S > %TempFolder%\%Name%-Size.txt,, Hide
   
   FileRead theText, %TempFolder%\%Name%-Size.txt
   
   ; ======  get beginning of location from bottom and trim  ======
   FileLineNum := InStr(theText, "File", , 0, 1)
   Replacement1 := SubStr(theText, FileLineNum)
   
   ; ======  get end of byte #'s and trim  ======
   0Dir := InStr(Replacement1, "0 Dir",, 0) - 1
   Replacement1 := SubStr(Replacement1, 1, 0Dir)
   
   ; ======  get rid of extra stuff  ======
   Replacement1 := StrReplace(Replacement1, "bytes", "")
   Replacement1 := StrReplace(Replacement1, ",", "")
   Replacement1 := StrReplace(Replacement1, "File(s) ", "")
   Replacement1 := StrReplace(Replacement1, "`r`n", "")
   Replacement1 := StrReplace(Replacement1, " ", "")
   
   ; ======  converstion from bytes to xxx.x MB or xx.xx GB  ======
   if (Replacement1 <= 1073741824) ; if < 1GB
   {
      Replacement1 := Replacement1 // 1024 / 1024 ; the individual "/" is not a mistake
      Replacement1 := Round(Replacement1, 1)
      LV_Modify(A_Index, , , , Replacement1 . "  MB") ; modify the size field with calculated value
   }
   else
   {
      Replacement1 := Replacement1 // 1024 // 1024 / 1024
      Replacement1 := Round(Replacement1, 2)
      LV_Modify(A_Index, , , , Replacement1 . "  GB")
   }
}
return




; ======  this section is to re-color the "extra" user profiles if the columns are re-sorted  ======
ColClick:
CLV.OnMessage()
GuiControl, Focus, %HLV%
GuiControl, -Redraw, %HLV%
CLV.Clear(1, 1)

Loop
{
   LV_GetText(Name, A_Index)  ; Resume the search at the row after that found by the previous iteration.
   if Name =
      break
   
   LV_GetText(Extra, A_Index, 5)
   if Extra = 1
      CLV.Row(A_Index, 0xFFFF00, 0x000000)
   else
      CLV.Row(A_Index)
}
GuiControl, +Redraw, %HLV%
return



; ======  kill the profile  ======
Engage:
RowNumber = 0  ; This causes the first loop iteration to start the search at the top of the list.
Loop
{
    RowNumber := LV_GetNext(RowNumber)  ; Resume the search at the row after that found by the previous iteration.
    if not RowNumber  
        break ; The above returned zero, so there are no more selected rows.	
	LV_GetText(ListUserName, RowNumber)
	LV_GetText(SSID, RowNumber, 4)
	Profile = C:\Users\%ListUserName%
    Gui, 2:add, progress, xCenter yCenter w500 h20 Range0-2
	
	; ======  remove C:\Users\ folder  ======
	Gui, 2:Show,, Removing User folder
	RunWait cmd /c "rmdir %Profile% /S /Q",, Hide
	IfExist %Profile%
		RunWait cmd /c "rmdir %Profile% /S /Q",, Hide
	GuiControl, 2:, msctls_progress321, +1
	
	; ======  use PS to remove profile from registry  ======
	Gui, 2:Show,, Removing Profile
    RunWait Powershell -command "& {Get-WmiObject win32_userprofile | Where-Object {!$_.Special -and !$_.Loaded -and $_.LocalPath -like '%Profile%'} | RWMI}",, Hide
	
	; ======  see if it's still there  ======
	RegRead LocalPath, %ProfileRegList%\%SSID%, ProfileImagePath
	if !ErrorLevel ; and try again if it is
		RunWait Powershell -command "& {Get-WmiObject win32_userprofile | Where-Object {!$_.Special -and !$_.Loaded -and $_.LocalPath -like '%Profile%'} | RWMI}",, Hide
	
	Gui, 2:Destroy
	
	IfExist %Profile%
	{
		Failure = 1
		FolderMessage = %Profile% was not deleted
	}
	
	RegRead LocalPath, %ProfileRegList%\%SSID%, ProfileImagePath
	if !ErrorLevel
	{
		Failure = 1
		RegMessage = Registry profile was not removed
	}
	
	if Failure = 1
		MsgBox %FolderMessage%`n%RegMessage%
	else
		LV_Delete(RowNumber)
}
gosub ColClick ; re-color the rows
return



; ======  cleanup the Temp folder  ======
Cleanup(ExitReason, ExitCode)
{
   
}


class MyObject
{
   Exiting()
   {
		Run cmd.exe /c rmdir "%LocalAppData%\Temp\ProfileKiller" /S /Q,, Hide
   }
}



; ======  do not modify below this line  ======
; credit to "just me",  https://www.autohotkey.com/boards/memberlist.php?mode=viewprofile&u=148
; posting: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=1081
; ======================================================================================================================
; Namespace:      LV_Colors
; Function:       Individual row and cell coloring for AHK ListView controls.
; Tested with:    AHK 1.1.23.05 (A32/U32/U64)
; Tested on:      Win 10 (x64)
; Changelog:
;     1.1.04.01/2016-05-03/just me - added change to remove the focus rectangle from focused rows
;     1.1.04.00/2016-05-03/just me - added SelectionColors method
;     1.1.03.00/2015-04-11/just me - bugfix for StaticMode
;     1.1.02.00/2015-04-07/just me - bugfixes for StaticMode, NoSort, and NoSizing
;     1.1.01.00/2015-03-31/just me - removed option OnMessage from __New(), restructured code
;     1.1.00.00/2015-03-27/just me - added AlternateRows and AlternateCols, revised code.
;     1.0.00.00/2015-03-23/just me - new version using new AHK 1.1.20+ features
;     0.5.00.00/2014-08-13/just me - changed 'static mode' handling
;     0.4.01.00/2013-12-30/just me - minor bug fix
;     0.4.00.00/2013-12-30/just me - added static mode
;     0.3.00.00/2013-06-15/just me - added "Critical, 100" to avoid drawing issues
;     0.2.00.00/2013-01-12/just me - bugfixes and minor changes
;     0.1.00.00/2012-10-27/just me - initial release
; ======================================================================================================================
; CLASS LV_Colors
;
; The class provides six public methods to set individual colors for rows and/or cells, to clear all colors, to
; prevent/allow sorting and rezising of columns dynamically, and to deactivate/activate the message handler for
; WM_NOTIFY messages (see below).
;
; The message handler for WM_NOTIFY messages will be activated for the specified ListView whenever a new instance is
; created. If you want to temporarily disable coloring call MyInstance.OnMessage(False). This must be done also before
; you try to destroy the instance. To enable it again, call MyInstance.OnMessage().
;
; To avoid the loss of Gui events and messages the message handler might need to be set 'critical'. This can be
; achieved by setting the instance property 'Critical' ti the required value (e.g. MyInstance.Critical := 100).
; New instances default to 'Critical, Off'. Though sometimes needed, ListViews or the whole Gui may become
; unresponsive under certain circumstances if Critical is set and the ListView has a g-label.
; ======================================================================================================================
Class LV_Colors {
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; META FUNCTIONS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; ===================================================================================================================
   ; __New()         Create a new LV_Colors instance for the given ListView
   ; Parameters:     HWND        -  ListView's HWND.
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 StaticMode  -  Static color assignment, i.e. the colors will be assigned permanently to the row
   ;                                contents rather than to the row number.
   ;                                Values:  True/False
   ;                                Default: False
   ;                 NoSort      -  Prevent sorting by click on a header item.
   ;                                Values:  True/False
   ;                                Default: True
   ;                 NoSizing    -  Prevent resizing of columns.
   ;                                Values:  True/False
   ;                                Default: True
   ; ===================================================================================================================
   __New(HWND, StaticMode := False, NoSort := True, NoSizing := True) {
      If (This.Base.Base.__Class) ; do not instantiate instances
         Return False
      If This.Attached[HWND] ; HWND is already attached
         Return False
      If !DllCall("IsWindow", "Ptr", HWND) ; invalid HWND
         Return False
      VarSetCapacity(Class, 512, 0)
      DllCall("GetClassName", "Ptr", HWND, "Str", Class, "Int", 256)
      If (Class <> "SysListView32") ; HWND doesn't belong to a ListView
         Return False
      ; ----------------------------------------------------------------------------------------------------------------
      ; Set LVS_EX_DOUBLEBUFFER (0x010000) style to avoid drawing issues.
      SendMessage, 0x1036, 0x010000, 0x010000, , % "ahk_id " . HWND ; LVM_SETEXTENDEDLISTVIEWSTYLE
      ; Get the default colors
      SendMessage, 0x1025, 0, 0, , % "ahk_id " . HWND ; LVM_GETTEXTBKCOLOR
      This.BkClr := ErrorLevel
      SendMessage, 0x1023, 0, 0, , % "ahk_id " . HWND ; LVM_GETTEXTCOLOR
      This.TxClr := ErrorLevel
      ; Get the header control
      SendMessage, 0x101F, 0, 0, , % "ahk_id " . HWND ; LVM_GETHEADER
      This.Header := ErrorLevel
      ; Set other properties
      This.HWND := HWND
      This.IsStatic := !!StaticMode
      This.AltCols := False
      This.AltRows := False
      This.NoSort(!!NoSort)
      This.NoSizing(!!NoSizing)
      This.OnMessage()
      This.Critical := "Off"
      This.Attached[HWND] := True
   }
   ; ===================================================================================================================
   __Delete() {
      This.Attached.Remove(HWND, "")
      This.OnMessage(False)
      WinSet, Redraw, , % "ahk_id " . This.HWND
   }
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; PUBLIC METHODS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; ===================================================================================================================
   ; Clear()         Clears all row and cell colors.
   ; Parameters:     AltRows     -  Reset alternate row coloring (True / False)
   ;                                Default: False
   ;                 AltCols     -  Reset alternate column coloring (True / False)
   ;                                Default: False
   ; Return Value:   Always True.
   ; ===================================================================================================================
   Clear(AltRows := False, AltCols := False) {
      If (AltCols)
         This.AltCols := False
      If (AltRows)
         This.AltRows := False
      This.Remove("Rows")
      This.Remove("Cells")
      Return True
   }
   ; ===================================================================================================================
   ; AlternateRows() Sets background and/or text color for even row numbers.
   ; Parameters:     BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   AlternateRows(BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      This.AltRows := False
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["ARB"] := (BkBGR <> "") ? BkBGR : This.BkClr
      This["ART"] := (TxBGR <> "") ? TxBGR : This.TxClr
      This.AltRows := True
      Return True
   }
   ; ===================================================================================================================
   ; AlternateCols() Sets background and/or text color for even column numbers.
   ; Parameters:     BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   AlternateCols(BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      This.AltCols := False
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["ACB"] := (BkBGR <> "") ? BkBGR : This.BkClr
      This["ACT"] := (TxBGR <> "") ? TxBGR : This.TxClr
      This.AltCols := True
      Return True
   }
   ; ===================================================================================================================
   ; SelectionColors() Sets background and/or text color for selected rows.
   ; Parameters:     BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default selected background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default selected text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   SelectionColors(BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      This.SelColors := False
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["SELB"] := BkBGR
      This["SELT"] := TxBGR
      This.SelColors := True
      Return True
   }
   ; ===================================================================================================================
   ; Row()           Sets background and/or text color for the specified row.
   ; Parameters:     Row         -  Row number
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   Row(Row, BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      This["Rows"].Remove(Row, "")
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["Rows", Row, "B"] := (BkBGR <> "") ? BkBGR : This.BkClr
      This["Rows", Row, "T"] := (TxBGR <> "") ? TxBGR : This.TxClr
      Return True
   }
   ; ===================================================================================================================
   ; Cell()          Sets background and/or text color for the specified cell.
   ; Parameters:     Row         -  Row number
   ;                 Col         -  Column number
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> row's background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> row's text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   Cell(Row, Col, BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      This["Cells", Row].Remove(Col, "")
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      If (BkBGR <> "")
         This["Cells", Row, Col, "B"] := BkBGR
      If (TxBGR <> "")
         This["Cells", Row, Col, "T"] := TxBGR
      Return True
   }
   ; ===================================================================================================================
   ; NoSort()        Prevents/allows sorting by click on a header item for this ListView.
   ; Parameters:     Apply       -  True/False
   ;                                Default: True
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   NoSort(Apply := True) {
      If !(This.HWND)
         Return False
      If (Apply)
         This.SortColumns := False
      Else
         This.SortColumns := True
      Return True
   }
   ; ===================================================================================================================
   ; NoSizing()      Prevents/allows resizing of columns for this ListView.
   ; Parameters:     Apply       -  True/False
   ;                                Default: True
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   NoSizing(Apply := True) {
      Static OSVersion := DllCall("GetVersion", "UChar")
      If !(This.Header)
         Return False
      If (Apply) {
         If (OSVersion > 5)
            Control, Style, +0x0800, , % "ahk_id " . This.Header ; HDS_NOSIZING = 0x0800
         This.ResizeColumns := False
      }
      Else {
         If (OSVersion > 5)
            Control, Style, -0x0800, , % "ahk_id " . This.Header ; HDS_NOSIZING
         This.ResizeColumns := True
      }
      Return True
   }
   ; ===================================================================================================================
   ; OnMessage()     Adds/removes a message handler for WM_NOTIFY messages for this ListView.
   ; Parameters:     Apply       -  True/False
   ;                                Default: True
   ; Return Value:   Always True
   ; ===================================================================================================================
   OnMessage(Apply := True) {
      If (Apply) && !This.HasKey("OnMessageFunc") {
         This.OnMessageFunc := ObjBindMethod(This, "On_WM_Notify")
         OnMessage(0x004E, This.OnMessageFunc) ; add the WM_NOTIFY message handler
      }
      Else If !(Apply) && This.HasKey("OnMessageFunc") {
         OnMessage(0x004E, This.OnMessageFunc, 0) ; remove the WM_NOTIFY message handler
         This.OnMessageFunc := ""
         This.Remove("OnMessageFunc")
      }
      WinSet, Redraw, , % "ahk_id " . This.HWND
      Return True
   }
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; PRIVATE PROPERTIES  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Static Attached := {}
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; PRIVATE METHODS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   On_WM_NOTIFY(W, L, M, H) {
      ; Notifications: NM_CUSTOMDRAW = -12, LVN_COLUMNCLICK = -108, HDN_BEGINTRACKA = -306, HDN_BEGINTRACKW = -326
      Critical, % This.Critical
      If ((HCTL := NumGet(L + 0, 0, "UPtr")) = This.HWND) || (HCTL = This.Header) {
         Code := NumGet(L + (A_PtrSize * 2), 0, "Int")
         If (Code = -12)
            Return This.NM_CUSTOMDRAW(This.HWND, L)
         If !This.SortColumns && (Code = -108)
            Return 0
         If !This.ResizeColumns && ((Code = -306) || (Code = -326))
            Return True
      }
   }
   ; -------------------------------------------------------------------------------------------------------------------
   NM_CUSTOMDRAW(H, L) {
      ; Return values: 0x00 (CDRF_DODEFAULT), 0x20 (CDRF_NOTIFYITEMDRAW / CDRF_NOTIFYSUBITEMDRAW)
      Static SizeNMHDR := A_PtrSize * 3                  ; Size of NMHDR structure
      Static SizeNCD := SizeNMHDR + 16 + (A_PtrSize * 5) ; Size of NMCUSTOMDRAW structure
      Static OffItem := SizeNMHDR + 16 + (A_PtrSize * 2) ; Offset of dwItemSpec (NMCUSTOMDRAW)
      Static OffItemState := OffItem + A_PtrSize         ; Offset of uItemState  (NMCUSTOMDRAW)
      Static OffCT :=  SizeNCD                           ; Offset of clrText (NMLVCUSTOMDRAW)
      Static OffCB := OffCT + 4                          ; Offset of clrTextBk (NMLVCUSTOMDRAW)
      Static OffSubItem := OffCB + 4                     ; Offset of iSubItem (NMLVCUSTOMDRAW)
      ; ----------------------------------------------------------------------------------------------------------------
      DrawStage := NumGet(L + SizeNMHDR, 0, "UInt")
      , Row := NumGet(L + OffItem, "UPtr") + 1
      , Col := NumGet(L + OffSubItem, "Int") + 1
      , Item := Row - 1
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      ; CDDS_SUBITEMPREPAINT = 0x030001 --------------------------------------------------------------------------------
      If (DrawStage = 0x030001) {
         UseAltCol := !(Col & 1) && (This.AltCols)
         , ColColors := This["Cells", Row, Col]
         , ColB := (ColColors.B <> "") ? ColColors.B : UseAltCol ? This.ACB : This.RowB
         , ColT := (ColColors.T <> "") ? ColColors.T : UseAltCol ? This.ACT : This.RowT
         , NumPut(ColT, L + OffCT, "UInt"), NumPut(ColB, L + OffCB, "UInt")
         Return (!This.AltCols && !This.HasKey(Row) && (Col > This["Cells", Row].MaxIndex())) ? 0x00 : 0x20
      }
      ; CDDS_ITEMPREPAINT = 0x010001 -----------------------------------------------------------------------------------
      If (DrawStage = 0x010001) {
         ; LVM_GETITEMSTATE = 0x102C, LVIS_SELECTED = 0x0002
         If (This.SelColors) && DllCall("SendMessage", "Ptr", H, "UInt", 0x102C, "Ptr", Item, "Ptr", 0x0002, "UInt") {
            ; Remove the CDIS_SELECTED (0x0001) and CDIS_FOCUS (0x0010) states from uItemState and set the colors.
            NumPut(NumGet(L + OffItemState, "UInt") & ~0x0011, L + OffItemState, "UInt")
            If (This.SELB <> "")
               NumPut(This.SELB, L + OffCB, "UInt")
            If (This.SELT <> "")
               NumPut(This.SELT, L + OffCT, "UInt")
            Return 0x02 ; CDRF_NEWFONT
         }
         UseAltRow := (Item & 1) && (This.AltRows)
         , RowColors := This["Rows", Row]
         , This.RowB := RowColors ? RowColors.B : UseAltRow ? This.ARB : This.BkClr
         , This.RowT := RowColors ? RowColors.T : UseAltRow ? This.ART : This.TxClr
         If (This.AltCols || This["Cells"].HasKey(Row))
            Return 0x20
         NumPut(This.RowT, L + OffCT, "UInt"), NumPut(This.RowB, L + OffCB, "UInt")
         Return 0x00
      }
      ; CDDS_PREPAINT = 0x000001 ---------------------------------------------------------------------------------------
      Return (DrawStage = 0x000001) ? 0x20 : 0x00
   }
   ; -------------------------------------------------------------------------------------------------------------------
   MapIndexToID(Row) { ; provides the unique internal ID of the given row number
      SendMessage, 0x10B4, % (Row - 1), 0, , % "ahk_id " . This.HWND ; LVM_MAPINDEXTOID
      Return ErrorLevel
   }
   ; -------------------------------------------------------------------------------------------------------------------
   BGR(Color, Default := "") { ; converts colors to BGR
      Static Integer := "Integer" ; v2
      ; HTML Colors (BGR)
      Static HTML := {AQUA: 0x00FFFF, BLACK: 0x000000, RED: 0xFF0000, FUCHSIA: 0xFF00FF, GRAY: 0x808080, GREEN: 0x008000
                    , LIME: 0x00FF00, MAROON: 0x800000, NAVY: 0x000080, OLIVE: 0x808000, PURPLE: 0x800080, BLUE: 0x0000FF
                    , SILVER: 0xC0C0C0, TEAL: 0x008080, WHITE: 0xFFFFFF, YELLOW: 0xFFFF00}
      If Color Is Integer
         Return ((Color >> 16) & 0xFF) | (Color & 0x00FF00) | ((Color & 0xFF) << 16)
      Return (HTML.HasKey(Color) ? HTML[Color] : Default)
   }
}
robodesign
Posts: 934
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: Windows profile deletion tool

11 Jul 2019, 06:13

This is why compiled scripts often get labeled as viruses I suppose.... ^_^ (due to such scripts)
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
User avatar
Delta Pythagorean
Posts: 627
Joined: 13 Feb 2017, 13:44
Location: Somewhere in the US
Contact:

Re: Windows profile deletion tool

15 Jul 2019, 16:50

It's pretty well done for being self-taught, I was the same and over time I learned more tricks and ideas along the way.
One suggestion I would make is to have some sort of way of moving any files that might have been in those folders and moving them into a "mass folder" on the main drive.

[AHK]......: v2.0.12 | 64-bit
[OS].......: Windows 11 | 23H2 (OS Build: 22621.3296)
[GITHUB]...: github.com/DelPyth
[PAYPAL]...: paypal.me/DelPyth
[DISCORD]..: tophatcat


Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: vysmaty and 234 guests