CMD-tips and utils for files and folders

For updating folder dates, the utility "FolderTimeUpdate" can be used (developed by NirSoft).
 Search-words: bat cmd batch script
 

Comments

Permalink

Script below is a sample of calling another CMD-file and redirecting screen output (including errors) to a logfile with current time.

@echo off
echo *** Ready to run other cmd-file ?
pause
echo.
echo *** Started running.. check logfile for the progress..

REM *** Get current date and time in the desired format
REM *** Script assumes swedish date and time format. (YYYY-MM-DD and HH:mm:ss,xx)

for /f "tokens=1-3 delims=-" %%a in ('echo %date%') do (
    set "year=%%a"
    set "datestamp=!year:~-2!%%b%%c"
)

for /f "tokens=1-3 delims=:," %%a in ('echo %time%') do (
    set "hour=%%a"
    set "minute=%%b"
    set "seconds=%%c"
)
set "secdig=%seconds:~0,2%"

REM *** Add leading zero to hour if it is a single digit
if 1%hour% lss 110 set "hour=0%hour%"


call othercmdfile.cmd > "logfile-%datestamp%-%hour%%minute%%secdig%.txt" 2>&1
echo.
echo *** Completed! See status in the generated log-file.
pause

Permalink

The batch-script below can be used to rename files, it will ask for search and replace strings.

@echo off
setlocal enabledelayedexpansion

set /p "search=Enter the string to search for: "
set /p "replace=Enter the string to replace with: "

for %%F in (*%search%*.txt) do (
    set "filename=%%~nF"
    set "newname=!filename:%search%=%replace%!"
    ren "%%F" "!newname!%%~xF"
)

endlocal
Permalink

The Powershell-script below can be used to search for and remove an XML-element from all XML-files in chosen folder.
Running the script it will ask for folder and name of XML-element.

Default value for XML-element is "sheetProtection" as it primary use was to remove sheet-passwords in Excel-documents.
 (rename xlsx-files to "zip", extract zip into folder, and then use powershell-script on folder ".\xl\worksheets"

Suggested name for powershell-file: "remove-xml-elem.ps1" 

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName Microsoft.VisualBasic

# Function to show File Browser Dialog as a folder selector
function Select-FolderDialog {
    $fileDialog = New-Object System.Windows.Forms.OpenFileDialog
    $fileDialog.Title = "Select a folder or paste a path"
    $fileDialog.Filter = "Folders|nonesuch"
    $fileDialog.CheckFileExists = $false
    $fileDialog.ValidateNames = $false
    $fileDialog.FileName = "Folder Selection"
    
    if ($fileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
        return [System.IO.Path]::GetDirectoryName($fileDialog.FileName)
    } else {
        return $null
    }
}

# Function to get the encoding of an XML file
function Get-Encoding {
    param (
        [string]$filePath
    )
    $encoding = [System.Text.Encoding]::Default
    $reader = New-Object System.IO.StreamReader($filePath, $encoding, $true)
    $reader.Read() | Out-Null  # Read to detect encoding
    $detectedEncoding = $reader.CurrentEncoding
    $reader.Close()
    return $detectedEncoding
}

# Step 1: Select the Folder
$folderPath = Select-FolderDialog

if (-not $folderPath) {
    Write-Host "No folder selected. Exiting script."
    exit
}

# Step 2: Enter the XML element to remove with default value
$elementToRemove = [Microsoft.VisualBasic.Interaction]::InputBox(
    "Enter the name of the XML element to remove:", 
    "XML Element Remover", 
    "sheetProtection"  # Default value
)

if ([string]::IsNullOrWhiteSpace($elementToRemove)) {
    Write-Host "No XML element name entered. Exiting script."
    exit
}

# Step 3: Process the XML files
$xmlFiles = Get-ChildItem -Path $folderPath -Filter *.xml
$fileCount = 0

foreach ($file in $xmlFiles) {
    $originalEncoding = Get-Encoding -filePath $file.FullName

    # Read the file content using StreamReader
    $reader = New-Object System.IO.StreamReader($file.FullName, $originalEncoding)
    $xmlContent = $reader.ReadToEnd()
    $reader.Close()

    $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.PreserveWhitespace = $true

    try {
        $xmlDoc.LoadXml($xmlContent)
    } catch {
        Write-Host "Failed to load XML file: $($file.FullName). Error: $($_.Exception.Message)"
        continue
    }

    $nodes = $xmlDoc.SelectNodes("//*[local-name()='$elementToRemove']")
    if ($nodes.Count -eq 0) {
        Write-Host "No elements named '$elementToRemove' found in $($file.FullName)."
    } else {
        foreach ($node in $nodes) {
            $node.ParentNode.RemoveChild($node) | Out-Null
        }

        # Save the updated content with the original encoding using StreamWriter
        $writer = New-Object System.IO.StringWriter
        $xmlTextWriter = New-Object System.Xml.XmlTextWriter($writer)
        $xmlTextWriter.Formatting = 'None'
        $xmlDoc.WriteContentTo($xmlTextWriter)
        $xmlTextWriter.Flush()

        $streamWriter = New-Object System.IO.StreamWriter($file.FullName, $false, $originalEncoding)
        $streamWriter.Write($writer.ToString())
        $streamWriter.Close()

        $fileCount++
    }
}

# Step 4: Show completion message
[System.Windows.Forms.MessageBox]::Show("Processed $fileCount XML file(s). XML elements removed successfully!", "Success", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)

Search-words: excel powershell

Permalink

Simple Powershell-script that will create a log file with current date and time. 

$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition # Get the current directory (where the script is located)
$logDir = Join-Path -Path $scriptDir -ChildPath "log" # Define the path for the log folder

if (-not (Test-Path -Path $logDir)) {
    New-Item -Path $logDir -ItemType Directory # Create the log directory if it doesn't exist
}

$currentDateTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "The logged date and time is: " + [Environment]::NewLine + "$currentDateTime"

$outputFile = Join-Path -Path $logDir -ChildPath "script-log.txt" # Define the output file path inside the log folder
$logMessage | Out-File -FilePath $outputFile -Encoding UTF8 # Write the message to the text file

# Optional: Print confirmation to console
Write-Host "Date and time logged to $outputFile"
Permalink

schtasks /Delete /TN "KeePassXC-elevated" /F

Try using the command below to create a Scheduled Task that will run "on logon":
 (Use XML-sample below instead, as this will stop when running a laptop on battery..)

schtasks /create /tn "KeePassXC-elevated"  /tr "\"C:\Prg\KeePassXC\KeePassXC.exe\"" /sc ONLOGON  /rl HIGHEST /f


Show info for scheduled task with name "keepassxc-elevated":

schtasks /Query /TN "KeePassXC-elevated" /V /FO LIST

Delete a scheduled task:

schtasks /Delete /TN "KeePassXC-elevated" /F


Register scheduled task using XML:

schtasks /Create /TN "KeePassXC-elevated" /XML "C:\Prg\KeePassXC\keepassxc-startup.xml" /F

Sample-XML for the file "keepassxc-startup.xml":

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <Triggers>
    <LogonTrigger>
      <Enabled>true</Enabled>
    </LogonTrigger>
  </Triggers>

  <Principals>
    <Principal id="Author">
      <!-- Modify COMPUTERNAME\USERNAME on the line below -->
      <UserId>COMPUTERNAME\USERNAME</UserId>
      <LogonType>InteractiveToken</LogonType>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>

  <Settings>
    <Enabled>true</Enabled>

    <!-- "Stop Task If Runs X Hours and X Mins" -->
    <!-- 72 hours = P3D. Use PT0S for "no limit". -->
    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
  </Settings>

  <Actions Context="Author">
    <Exec>
      <Command>C:\Prg\KeePassXC\KeePassXC.exe</Command>
    </Exec>
  </Actions>
</Task>
Permalink

Processes by memory use, sorted descending:

Get-Process |
Sort-Object WorkingSet64 -Descending |
Format-Table ProcessName, Id,
    @{Label='WorkingSetMB'; Expression={[math]::Round($_.WorkingSet64 / 1MB, 2)}},
    @{Label='PrivateMB'; Expression={[math]::Round($_.PrivateMemorySize64 / 1MB, 2)}} -AutoSize
Permalink

Powershell-script that will list all code-files in a Visual Studio solution.
Useful for generating questions to AI regarding folder/file-structure. 

$extensions = '.cs', '.csproj', '.sln', '.razor', '.json', '.config', '.wsdl', '.svcinfo', '.xsd', '.svc', '.svcmap', '.datasource'
$excluded = '\\(bin|obj|\.vs)(\\|$)'

Get-ChildItem -Path . -Recurse -Force |
  Where-Object {
    $_.FullName -notmatch $excluded -and
    (
      ($_.PSIsContainer -and -not (Get-ChildItem -Path $_.FullName -Force)) -or
      (-not $_.PSIsContainer -and $_.Extension -in $extensions)
    )
  } |
  Sort-Object FullName |
  Select-Object -ExpandProperty FullName |
  Set-Content .\folders-files-list.txt
Permalink

Powershell-script below can be used to set registry setting that enables "long paths". 
 (Make sure to start PowerShell with elevated admin privileges)

Useful when code repositories (in TFVC or GIT) might run in to issues, and Visual Studio might complain.
Restart the computer after the script has been run. 

New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
Permalink

One-liner to start a new elevated PowerShell-window with the same path as existing command-window (existing can be either Windows old terminal or PowerShell).

powershell -NoProfile -Command "Start-Process powershell -Verb RunAs -ArgumentList '-NoExit','-Command',('Set-Location -LiteralPath ' + [char]34 + (Get-Location).Path + [char]34)"

Created with help from ChatGpt :-)
 

-