Bluebeam acting slow in my softdrive machine

Modified on Sun, 24 Aug at 2:18 PM

Issue: Bluebeam is unresponsive and slow when I use is from my softdrive virtual machine.


Solutions: 


The solution is to disable camera access in bluebeam. There are two main ways to disable camera access inside a Softdrive virtual machine:

  1. Disable the camera specifically for Bluebeam Revu (via a registry script).

  2. Disable the camera entirely for the Softdrive machine (using Windows privacy settings).

 




1) Disable Camera for Bluebeam Revu Only (via Registry Script) 

This method blocks Bluebeam Revu from accessing the camera, while leaving camera functionality available for other applications like Teams or Zoom. This script will do the following: 

  • On machines without Bluebeam, the script runs safely and does nothing permanent (no junk keys created).

  • On machines with Bluebeam already installed or launched, the keys exist and the script applies Value="Deny".

  • On machines where Bluebeam is installed later, Windows will create the NonPackaged entry at first camera use, and your Intune remediation will catch it (if deployed as a proactive remediation) and flip it to Deny.



Notes:

  • Scope: current user, all loaded users, all profiles on disk, and Default (new users).

  • Layouts handled: both ...\Bluebeam Revu\21\Revu and ...\Bluebeam Revu 21\Revu, plus any other Revu.exe found under the Bluebeam vendor folder.

  • Keys set: for each match, creates/updates both nested and flat # NonPackaged keys with Value = "Deny" and a zeroed LastUsedTimeStop.

  • Creates Logging in this path: %PROGRAMDATA%\BluebeamCamBlock\log_*.txt.


Steps to Create and Run the Script

  1. Open Notepad

    • On your Softdrive desktop, click Start → Notepad.

  2. Paste the script below into Notepad:

<# Bluebeam Revu camera = Deny for ALL users (auto-detect both layouts + logging) #>

$ErrorActionPreference = 'Continue'

# --- Logging ---

$LogDir  = Join-Path $env:ProgramData 'BluebeamCamBlock'

$LogFile = Join-Path $LogDir ("log_{0:yyyyMMdd_HHmmss}.txt" -f (Get-Date))

New-Item -ItemType Directory -Path $LogDir -Force | Out-Null

function Write-Log($m){ $l="[${(Get-Date -f 'yyyy-MM-dd HH:mm:ss')}] $m"; Add-Content $LogFile $l; Write-Host $l }

Write-Log "=== Start Bluebeam Camera Block (all users) ==="

Write-Log "ProgramData: $env:ProgramData"

Write-Log "Log: $LogFile"

# --- Ensure HKU: exists (PS7-safe) ---

if (-not (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) {

  try { New-PSDrive -Name HKU -PSProvider Registry -Root 'Registry::HKEY_USERS' -ErrorAction Stop | Out-Null; Write-Log "Mounted HKU: PSDrive." } catch { Write-Log "Could not mount HKU:. Using Registry:: paths only." }

}

# --- Find Revu.exe candidates (handles both layouts & future versions) ---

function Get-RevuExeTargets {

  $candidates = [System.Collections.Generic.List[string]]::new()

  $common = @(

    'C:\Program Files\Bluebeam Software\Bluebeam Revu\21\Revu\Revu.exe',   # layout A

    'C:\Program Files\Bluebeam Software\Bluebeam Revu 21\Revu\Revu.exe'    # layout B

  )

  foreach ($p in $common) { if (Test-Path $p) { $candidates.Add($p) } }

  # also search under vendor root for any other versions

  $vendor = 'C:\Program Files\Bluebeam Software'

  if (Test-Path $vendor) {

    try {

      $found = Get-ChildItem -Path $vendor -Filter 'Revu.exe' -Recurse -Depth 5 -ErrorAction SilentlyContinue |

               Where-Object { $_.FullName -match '\\Bluebeam Revu(  ?\d+)?\\Revu\\Revu\.exe$' } |

               Select-Object -ExpandProperty FullName -Unique

      foreach ($f in $found) {

        if (-not ($candidates.Contains($f))) { $candidates.Add($f) }

      }

    } catch {}

  }

  # If still nothing, pre-seed using the first layout so the key exists in advance

  if ($candidates.Count -eq 0) {

    $candidates.Add('C:\Program Files\Bluebeam Software\Bluebeam Revu\21\Revu\Revu.exe')

  }

  return $candidates.ToArray()

}

$ExeTargets = Get-RevuExeTargets

$ExeTargets | ForEach-Object { Write-Log "Target EXE: $_" }

# --- Helpers ---

function New-RegKeyDeep {

  param([string]$BaseKey,[string]$RelativePath)

  $cur = $BaseKey

  foreach ($part in $RelativePath -split '\\') {

    $cur = Join-Path $cur $part

    if (-not (Test-Path -LiteralPath $cur)) { New-Item -Path $cur -Force | Out-Null }

  }

  return $cur

}

function Ensure-Deny-Leaf {

  param(

    [Parameter(Mandatory)] [string] $HiveRootReg, # e.g., 'Registry::HKEY_CURRENT_USER' or 'Registry::HKEY_USERS\SID'

    [Parameter(Mandatory)] [string[]] $ExePaths

  )

  $base = Join-Path $HiveRootReg 'Software\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\webcam\NonPackaged'

  if (-not (Test-Path -LiteralPath $base)) { New-Item -Path $base -Force | Out-Null }

  # Flip any existing Bluebeam/Revu keys (nested or flat)

  Get-ChildItem -Path $base -Recurse -ErrorAction SilentlyContinue |

    Where-Object { $_.PSChildName -match '(?i)bluebeam|revu|revu\.exe' } |

    ForEach-Object {

      try {

        New-ItemProperty -LiteralPath $_.PSPath -Name 'Value' -Value 'Deny' -Force | Out-Null

        $z = New-Object byte[] 16

        New-ItemProperty -LiteralPath $_.PSPath -Name 'LastUsedTimeStop' -PropertyType Binary -Value $z -Force | Out-Null

        Write-Log "Set Deny on existing: $($_.PSPath)"

      } catch { Write-Log "ERROR existing: $($_.PSPath) :: $($_.Exception.Message)" }

    }

  # Pre-seed for each target path

  foreach ($ExePath in $ExePaths) {

    # NESTED: ...\NonPackaged\C:\Program Files\...\Revu.exe

    try {

      $nestedLeaf = New-RegKeyDeep -BaseKey $base -RelativePath $ExePath

      New-ItemProperty -LiteralPath $nestedLeaf -Name 'Value' -Value 'Deny' -Force | Out-Null

      $z = New-Object byte[] 16

      New-ItemProperty -LiteralPath $nestedLeaf -Name 'LastUsedTimeStop' -PropertyType Binary -Value $z -Force | Out-Null

      Write-Log "Pre-seeded (nested): $nestedLeaf"

    } catch { Write-Log "ERROR nested: $ExePath :: $($_.Exception.Message)" }

    # FLAT: ...\NonPackaged\C:#Program Files#...\#Revu.exe

    try {

      $flatName = ($ExePath -replace '\\','#')

      $flatLeaf = Join-Path $base $flatName

      if (-not (Test-Path -LiteralPath $flatLeaf)) { New-Item -Path $base -Name $flatName -ItemType Key -Force | Out-Null }

      New-ItemProperty -LiteralPath $flatLeaf -Name 'Value' -Value 'Deny' -Force | Out-Null

      $z = New-Object byte[] 16

      New-ItemProperty -LiteralPath $flatLeaf -Name 'LastUsedTimeStop' -PropertyType Binary -Value $z -Force | Out-Null

      Write-Log "Pre-seeded (flat):   $flatLeaf"

    } catch { Write-Log "ERROR flat: $flatName :: $($_.Exception.Message)" }

  }

}

# --- Apply to CURRENT HKCU ---

Write-Log "Applying to current HKCU..."

Ensure-Deny-Leaf -HiveRootReg 'Registry::HKEY_CURRENT_USER' -ExePaths $ExeTargets

# --- Apply to all LOADED user hives ---

$loaded = @()

try {

  $loaded = Get-ChildItem 'Registry::HKEY_USERS' | Where-Object {

    $_.Name -match '\\S-1-5-21-' -and ($_.Name -notmatch '_Classes$')

  } | Select-Object -ExpandProperty PSChildName

} catch {}

foreach ($sid in $loaded) {

  $hiveRoot = "Registry::HKEY_USERS\$sid"

  Write-Log "Applying to loaded hive: $hiveRoot"

  Ensure-Deny-Leaf -HiveRootReg $hiveRoot -ExePaths $ExeTargets

}

# --- Apply to every PROFILE on disk (offline) ---

$profiles = Get-ChildItem 'C:\Users' -Force | Where-Object {

  $_.PSIsContainer -and $_.Name -notin @('All Users','Default','Default User','Public')

}

foreach ($p in $profiles) {

  $nt = Join-Path $p.FullName 'NTUSER.DAT'

  if (Test-Path $nt) {

    $alias = "TempHive_$($p.Name)"

    Write-Log "Loading profile hive: $($p.FullName) -> HKU\$alias"

    & reg.exe load "HKU\$alias" "$nt" | Out-Null

    try { Ensure-Deny-Leaf -HiveRootReg "Registry::HKEY_USERS\$alias" -ExePaths $ExeTargets }

    catch { Write-Log "ERROR applying to HKU\$alias :: $($_.Exception.Message)" }

    finally { & reg.exe unload "HKU\$alias" | Out-Null; Write-Log "Unloaded HKU\$alias" }

  } else {

    Write-Log "Skipping (no NTUSER.DAT): $($p.FullName)"

  }

}

# --- Default profile (new users) ---

$defaultNT = 'C:\Users\Default\NTUSER.DAT'

if (Test-Path $defaultNT) {

  Write-Log "Loading Default user hive..."

  & reg.exe load HKU\DefaultUser "$defaultNT" | Out-Nul

    c. Save the script

  • Click File → Save As.

  • Set File name = BluebeamCamBlock.ps1.

  • Set Save as type = All Files (*.*).

  • Save it to your Desktop.

   d. Run the script

  • Open PowerShell as Administrator:

    • Click Start → type PowerShell, right-click → Run as administrator.

  • Run the script with:

    powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$env:USERPROFILE\Desktop\BluebeamCamBlock.ps1"

        

    e. Verify the change

  • Open Registry Editor (regedit.exe).

  • Navigate to:

    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\webcam\NonPackaged
  • You should see a key for ...Revu.exe with Value = Deny.

  • In Bluebeam, the camera tool will no longer function.




2: Disable camera access in Softdrive.


Step 1: Open Privacy Settings

  1. Press Windows Key + I to open Settings.
  2. Click on Privacy (Windows 10) or Privacy & security (Windows 11).
  3. On the left panel (or scroll down), click Camera under App permissions.

Step 2: Modify App Permissions

  • Scroll further down to “Allow desktop apps to access your camera”.
  • Turn OFF the toggle.



Contact your IT team to determine the best option for your situation.