Further to Jeff Kosowsky's wonderful server side support for client VSS snapshots [1] and with the deprectation and removal of WMIC from new Windows 11 builds [2], I've gone ahead and updated the commands to use Powershell instead of WMIC.
I haven't found a way to use Jeff's scripts with rsyncd, only rsync over ssh - and the required changes look too complicated - so I've switched to rsync. I found all this out the hard way as I haven't needed to touch BackupPC for a number of years and only just got a new Windows desktop. So this has been tested in exactly this one scenario and "works for me" :) I also updated the "mount" section for my use case as I also saw another user on the list with the same issue [3] - where cygwin's "mount -m" doesn't show anything unless you have actually updated fstab. Most people don't so I think using the default output of "mount" is more reliable. [1] https://sourceforge.net/p/backuppc/mailman/message/37227904/ [2] https://techcommunity.microsoft.com/blog/windows-itpro-blog/wmi-command-line-wmic-utility-deprecation-next-steps/4039242 [3] https://sourceforge.net/p/backuppc/mailman/message/37228426/ # diff -Naru vss.pl_append vss.pl_append_new --- vss.pl_append 2025-07-11 10:55:31.000000000 +1000 +++ vss.pl_append_new 2025-07-11 10:53:57.000000000 +1000 @@ -67,11 +67,12 @@ #BASH_CREATESHADOW: Create single shadow for drive letter: $I my $bash_createshadow = <<'EOF'; #Create shadow copy and capture shadow id - { SHADOWID="$(wmic shadowcopy call create Volume=${I}:\\ | sed -ne 's|[ \t]*ShadowID = "\([^"]*\).*|\1|p')" ; } 2> >(tail +2) - #Note: redirection removes extra new line from stderr + SHADOWID=$(powershell -c "Invoke-CimMethod -ClassName Win32_ShadowCopy -MethodName Create -Arguments @{ Volume = \"${I}:\\\" } | Select-Object -ExpandProperty ShadowID") + SHADOWID=$(echo "$SHADOWID" | tr -d '\r\n') #Get shadow GLOBALROOT path from shadow id - SHADOWPATH="$(wmic shadowcopy | awk -v id=$SHADOWID 'id == $8 {print $3}')" + SHADOWPATH=$(powershell -c "Get-CimInstance -ClassName Win32_ShadowCopy | Where-Object { \$_.ID -eq \"$SHADOWID\" } | Select-Object -ExpandProperty DeviceObject") + SHADOWPATH=$(echo "$SHADOWPATH" | tr -d '\r\n') #Create reparse-point link in shadowdir (since GLOBALROOT paths not readable by cygwin or rsync) SHADOWLINK="$(cygpath -w ${shadowdir})$I-$hosttimestamp" @@ -85,7 +86,7 @@ my $bash_loopcreateshadow = <<'EOF'; [ -n "$shadows" ] && mkdir -p $shadowdir for I in $shadows; do - if ! [ -d "$(cygpath -u ${I}:)" ] || ! grep -qE "^${I^^}: \S+ ntfs " <(mount -m); then + if ! [ -d "$(cygpath -u ${I}:)" ] || ! grep -qE "^${I^^}: on \S+ type ntfs " <(mount); then echo "No such NTFS drive '${I}:' skipping corresponding shadow setup..." continue fi @@ -102,11 +103,13 @@ DRIVE=${SHADOWLINK##*\\}; DRIVE=${DRIVE%%-*}; DRIVE="${DRIVE^^}:" #Fsutil used to get the target reparse point which is the GLOBALROOT path of the shadow copy - #NOTE: '\r' is used to remove trailing '^M' in output of fsutil - SHADOWPATH=$(fsutil reparsepoint query $SHADOWLINK | sed -ne "s|^Print Name:[[:space:]]*\(.*\)\\\\\r|\1|p") + SHADOWPATH=$(fsutil reparsepoint query $SHADOWLINK | sed -ne "s|^Print Name:[[:space:]]*\(.*\)\$|\1|p") + SHADOWPATH=$(echo "$SHADOWPATH" | tr -d '\r\n' ) + SHADOWPATH=${SHADOWPATH%\\} #Get the shadow id based on the shadowpath - SHADOWID="$(wmic shadowcopy | awk -v path=${SHADOWPATH//\\/\\\\} 'path == $3 {print $8}')" + SHADOWID=$(powershell -c "Get-CimInstance -ClassName Win32_ShadowCopy | Where-Object { \$_.DeviceObject -eq \"$SHADOWPATH\" } | Select-Object -ExpandProperty ID") + SHADOWID=$(echo "$SHADOWID" | tr -d '\r\n') echo " Deleting shadow for '$DRIVE' PATH=$SHADOWPATH; ID=$SHADOWID; LINK=$SHADOWLINK" #Delete the shadow copy _______________________________________________ BackupPC-users mailing list BackupPC-users@lists.sourceforge.net List: https://lists.sourceforge.net/lists/listinfo/backuppc-users Wiki: https://github.com/backuppc/backuppc/wiki Project: https://backuppc.github.io/backuppc/