Juniper Pulse Disconnecting Users – Shared Install

email me

Problem

Multiple users report intermittent disconnects with the Pulse Secure Desktop client. There is no specific interval when this issue will occur as it will depend if the multiple user are attempting to login to the computer with the same machine guid.


Cause

This issue will occur when Pulse Secure Desktop client is preinstalled on a base image which is used to deploy to multiple machines. If this is true, the local machine ID stored in the connection store file may be the same on multiple machine.

When a Pulse Secure Desktop client connects to the PCS device, some session data is sent including the local machine identifier in the connection store file. The Pulse Connect Secure device identifies each user sessions by the local machine identifier and expects this value to be unique. If multiple connections are sending the same machine identifier, the PCS device will terminate the oldest session for security reasons.

Screenshot of Connstore.dat and Registry (click to zoom)


Solution

If you already have users that have the Pulse client installed, I recommend doing two things.

#1 Delete this reg key
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Juniper Networks\Device Id

#2 Use Orca to modify the Pulse.msi and change SHAREDINSTALL from 0 to 1. Reinstall this modified client using a simple script or your desktop management software.

Orca – Property Table – Property SHAREDINSTALL

A reboot will most likely be required to reload all the Juniper services.

 

Notes

The Junos Pulse connection store file is located
C:\ProgramData\Pulse Secure\ConnectionStore\connstore.dat

The reg key is located
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Juniper Networks\Device Id]

Also see: Deploying Pulse Client

 

Bookshelf 7.1.2

email me

The Bookshelf Application


When trying to package…


Locate the MSI in the %TEMP%, once you launch the EXE

setup.msi /qn /norestart

Or, just use the EXE

setup.exe /v”/qn”

You will run into a snag with the application eula; not the setup eula, but the actual application eula. The settings are stored in the user profile.

Even if you run the setup silently, this happens upon app launch:

App Eula (you don’t want to see this)

This setting, along with several others, are stored in the BookShelf Prefs file.

BookShelf Prefs

I captured the Bookmark Prefs from a reference machine and added it to a compiled package. I used this script I created a while back to actually copy the file to each user profile:

on error resume next

Set objShell = CreateObject("Wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")

Const HKEY_LOCAL_MACHINE = &H80000002
Const OverwriteExisting = TRUE
Const POPUP_TITLE = "User To SID Conversion"
'SETS CURRENT DIRECTORY TO VARIABLE
strCurrentDirectory = objShell.CurrentDirectory
strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objRegistry=GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
strKeyPath = "SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\ProfileList"
objRegistry.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubkeys
For Each objSubkey In arrSubkeys
on error resume next
strValueName = "ProfileImagePath"
strSubPath = strKeyPath & "\" & objSubkey
objRegistry.GetExpandedStringValue HKEY_LOCAL_MACHINE,strSubPath,strValueName,strValue

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objAccount = objWMIService.Get("Win32_SID.SID='" & objSubkey & "'")
strUser = objAccount.AccountName
'strDomain = objAccount.ReferencedDomainName'returns referenced domain

'DISPLAY PROFILE NAME & SID
objSubkey = trim(objSubkey)'trims whitespace
strUser = trim(strUser)'trims whitespace
'msgbox "objSubkey: " & objSubkey'returns SID
'msgbox strUser'returns username

'LOGIC TO DETERMINE IF REGISTRY ACCOUNT IS TO BE LOADED
if strUser = "SYSTEM" then strUser=""
if strUser = "LOCAL SERVICE" then strUser=""
if strUser = "NETWORK SERVICE" then strUser=""
'if strUser = "ADMINISTRATOR" then strUser=""
if strUser <> "" then
on error resume next
Wscript.Sleep 1000

target = "C:\Users\" & strUser & "\Documents\My Books\VitalSource Bookshelf\User Data\"

'Copy file
If (objFSO.FileExists(strCurrentDirectory & "\Bookshelf Prefs")) Then
objShell.Run "%comspec% /c copy /y " & chr(34) & strCurrentDirectory & "\Bookshelf Prefs" & chr(34) & " " & chr(34) & target & chr(34),0,true
end if

end if

Next

VBScript – Determine Domain and Do Something

email me

This can be used to determine a domain, in a multi-domain enterprise. If a specific domain, do something.

Option Explicit

Dim objWMISvc, ColItems, objItem, strComputerDomain

Set objWMISvc = GetObject( "winmgmts:\\.\root\cimv2" )
Set colItems = objWMISvc.ExecQuery( "Select * from Win32_ComputerSystem", ,48 )
For Each objItem in colItems
	strComputerDomain = objItem.Domain
		If objItem.PartOfDomain Then
			'DOMAIN 1
			if strComputerDomain = "DOMAIN1.com" then
				'do something here
				msgbox "Domain 1"
			'DOMAIN 2
			elseif strComputerDomain = "DOMAIN2.com" then
				'do something here
				msgbox "Domain 2"
			'EVERYONE ELSE
			else
				'do something here
				msgbox "Everyone Else"
			end if
		end if
next

'CLEAR SESSION
Set objWMISvc = Nothing
Set colItems = Nothing
objItem = ""
strComputerDomain = ""

VBScript – Is User a Member of Group

email me

Option Explicit

Dim arrMemberNames(), initialSize, i, strHolder, objADGroup
Dim strMemberName, strADUser, objADUser, strBool, objNetwork, strComputerUser
Dim strGroupMember
initialSize = 0
strBool = "FALSE"

Set objNetwork = CreateObject("Wscript.Network")

 
'SET AD GROUP
 Set objADGroup = GetObject("LDAP://CN=TheGroupName,DC=DomainName,DC=com")

'SET USER
strComputerUser = objNetwork.UserName
strComputerUser = LCase(strComputerUser)


'DETERMINE WHETHER COMPUTER USER IS IN GROUP 
For Each strADUser in objADGroup.Member
	Set objADUser = GetObject("LDAP://" & strADUser)	
	strGroupMember = LCase(objADUser.sAMAccountName)
	if strComputerUser = strGroupMember then
		strBool = "TRUE"
	end if	
	ReDim Preserve arrMemberNames(initialSize)
	arrMemberNames(initialSize) = objADUser.CN	
	initialSize = initialSize + 1
Next

If strBool = "TRUE" then msgbox "User was found in group!"


'CLEAR SESSION
initialSize = ""
i = ""
strHolder = ""
objADGroup = ""
strMemberName = ""
strADUser = ""
objADUser = ""
strBool = ""

'EXIT
WScript.Quit(0)

PowerShell/VBScript – Return Members from AD Group

email me

VBScript Method

Option Explicit

Dim arrMemberNames(), initialSize, i, j, strHolder, objADGroup
Dim strMemberName, strADUser, objADUser
initialSize = 0
 
Set objADGroup = GetObject("LDAP://CN=TheGroupName,OU=TheOU,DC=YourDomain,DC=com")
 
For Each strADUser in objADGroup.Member
Set objADUser = GetObject("LDAP://" & strADUser)
'msgbox strADUser
ReDim Preserve arrMemberNames(initialSize)
arrMemberNames(initialSize) = objADUser.CN
initialSize = initialSize + 1
Next
 
For i = (UBound(arrMemberNames) - 1) to 0 Step -1
For j= 0 to i
If UCase(arrMemberNames(j)) > UCase(arrMemberNames(j+1)) Then
strHolder = arrMemberNames(j+1)
arrMemberNames(j+1) = arrMemberNames(j)
arrMemberNames(j) = strHolder
End If
Next
Next
 
For Each strMemberName in arrMemberNames
Wscript.Echo strMemberName
Next

initialSize = ""
i = ""
j = ""
strHolder = ""
objADGroup = ""
strMemberName = ""
strADUser = ""
objADUser = ""

 

PowerShell Method

Import-Module ActiveDirectory
Get-AdGroupMember -identity "GroupNameHere" | select-object "samaccountname"

 

Import-Module ActiveDirectory

PowerShell – Return Product Key and/or Save to Text File

email me

Function Get-ProductKey
{   Clear-Host
	$HKLM = 2147483650
	$ComputerName = $env:COMPUTERNAME
	$MSRegPath = "Software\Microsoft\Windows NT\CurrentVersion"
	$DigitalID = "DigitalProductId"
	$wmi = [WMIClass]"\\$ComputerName\root\default:stdRegProv"
	#Return MS Reg Value - used in translation
	$WMIObject = $wmi.GetBinaryValue($HKLM,$MSRegPath,$DigitalID)
	[Array]$DigitalValue = $WMIObject.uValue 
	#If value is returned
	If($DigitalValue)
	{		
		#Perform translation 
		$TranslatedResult = ConvertTokey $DigitalValue
		$OperatingSystem = (Get-WmiObject "Win32_OperatingSystem"  | select Caption).Caption
		If($OperatingSystem -match "Microsoft Windows 8" -or $OperatingSystem -match "Microsoft Windows 10")
		{
			if($TranslatedResult)
			{
				
				[string]$ProductKey ="$TranslatedResult"
				$ProductKey 
				#Save Windows info to a file 
				$UserChoice = UserOption
				If( $UserChoice -eq 0 )
				{	
					$TextFilePath = "C:\Users\"+$env:USERNAME+"\Desktop"
					New-Item -Path $TextFilePath -Name "ProductKey.txt" -Value $ProductKey -ItemType File -Force | Out-Null 
                    
				}                			
			}
			
		}	
		
	}
	

}
#User Option 
Function UserOption
{
    $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes",""
    $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No",""
    $UserChoices = [System.Management.Automation.Host.ChoiceDescription[]]($yes,$no)
    $MsgCaption = "Confirm"
    $Msg = "  Save product key to ProductKey.txt on Desktop?"
    $TranslatedResult = $Host.UI.PromptForChoice($MsgCaption,$Msg,$UserChoices,0)
    $TranslatedResult
}
#Perform translation 
Function ConvertToKey($Key)
{
	$Keyoffset = 52 
	$isWin8 = [int]($Key[66]/6) -band 1
	$HF7 = 0xF7
	$Key[66] = ($Key[66] -band $HF7) -bOr (($isWin8 -band 2) * 4)
	$i = 24
	[String]$Chars = "BCDFGHJKMPQRTVWXY2346789"	
	do
	{
		$Cur = 0 
		$X = 14
		Do
		{
			$Cur = $Cur * 256    
			$Cur = $Key[$X + $Keyoffset] + $Cur
			$Key[$X + $Keyoffset] = [math]::Floor([double]($Cur/24))
			$Cur = $Cur % 24
			$X = $X - 1 
		}while($X -ge 0)
		$i = $i- 1
		$KeyOutput = $Chars.SubString($Cur,1) + $KeyOutput
		$last = $Cur
	}while($i -ge 0)
	
	$Keypart1 = $KeyOutput.SubString(1,$last)
	$Keypart2 = $KeyOutput.Substring(1,$KeyOutput.length-1)
	if($last -eq 0 )
	{
		$KeyOutput = "N" + $Keypart2
	}
	else
	{
		$KeyOutput = $Keypart2.Insert($Keypart2.IndexOf($Keypart1)+$Keypart1.length,"N")
	}
	$a = $KeyOutput.Substring(0,5)
	$b = $KeyOutput.substring(5,5)
	$c = $KeyOutput.substring(10,5)
	$d = $KeyOutput.substring(15,5)
	$e = $KeyOutput.substring(20,5)
	$keyproduct = $a + "-" + $b + "-"+ $c + "-"+ $d + "-"+ $e
	$keyproduct 
	
  
}
Get-ProductKey

Batch – Resetting Windows Update Agent

email me

This script is to be used to repair the Windows Update Agent. Note, you must run it as admin or deploy in the System Account.

@echo off
title Reset Windows Update Agent
cls
color 0a

echo Stopping Windows Update services…
ping -n 4 127.0.0.1>nul
net stop wuauserv
net stop bits
net stop appidsvc
net stop cryptsvc
net stop ccmexec
echo Success!
echo.
ping -n 4 127.0.0.1>nul

echo Checking services…
ping -n 4 127.0.0.1>nul
sc query wuauserv | findstr /I /C:”STOPPED”
if %errorlevel% NEQ 0 goto END

sc query bits | findstr /I /C:”STOPPED”
if %errorlevel% NEQ 0 goto END

sc query appidsvc | findstr /I /C:”STOPPED”
if %errorlevel% NEQ 0 sc query appidsvc | findstr /I /C:”OpenService FAILED 1060?
if %errorlevel% NEQ 0 goto END

sc query cryptsvc | findstr /I /C:”STOPPED”
if %errorlevel% NEQ 0 goto END

sc query ccmexec | findstr /I /C:”STOPPED”
if %errorlevel% NEQ 0 sc query ccmexec | findstr /I /C:”OpenService FAILED 1060?
if %errorlevel% NEQ 0 goto END
echo Success!
echo.
ping -n 4 127.0.0.1>nul

echo Deleting AU cache folder and log file…
ping -n 4 127.0.0.1>nul
del /f /q “%ALLUSERSPROFILE%\Application Data\Microsoft\Network\Downloader\qmgr*.dat”
del /f /s /q %SystemRoot%\SoftwareDistribution\*.*
del /f /s /q %SystemRoot%\system32\catroot2\*.*
del /f /q %SystemRoot%\WindowsUpdate.log
Data\Microsoft\Network\Downloader\qmgr*.dat”
echo Success!
echo.
ping -n 4 127.0.0.1>nul

echo Re-registering DLL files…
ping -n 4 127.0.0.1>nul
cd /d %WinDir%\system32
regsvr32.exe /s atl.dll
regsvr32.exe /s urlmon.dll
regsvr32.exe /s mshtml.dll
regsvr32.exe /s shdocvw.dll
regsvr32.exe /s browseui.dll
regsvr32.exe /s jscript.dll
regsvr32.exe /s vbscript.dll
regsvr32.exe /s scrrun.dll
regsvr32.exe /s msxml.dll
regsvr32.exe /s msxml3.dll
regsvr32.exe /s msxml6.dll
regsvr32.exe /s actxprxy.dll
regsvr32.exe /s softpub.dll
regsvr32.exe /s wintrust.dll
regsvr32.exe /s dssenh.dll
regsvr32.exe /s rsaenh.dll
regsvr32.exe /s gpkcsp.dll
regsvr32.exe /s sccbase.dll
regsvr32.exe /s slbcsp.dll
regsvr32.exe /s cryptdlg.dll
regsvr32.exe /s oleaut32.dll
regsvr32.exe /s ole32.dll
regsvr32.exe /s shell32.dll
regsvr32.exe /s initpki.dll
regsvr32.exe /s wuapi.dll
regsvr32.exe /s wuaueng.dll
regsvr32.exe /s wuaueng1.dll
regsvr32.exe /s wucltui.dll
regsvr32.exe /s wups.dll
regsvr32.exe /s wups2.dll
regsvr32.exe /s wuweb.dll
regsvr32.exe /s qmgr.dll
regsvr32.exe /s qmgrprxy.dll
regsvr32.exe /s wucltux.dll
regsvr32.exe /s muweb.dll
regsvr32.exe /s wuwebv.dll
echo Success!
echo.
ping -n 4 127.0.0.1>nul

echo Removing WSUS Client ID…
ping -n 4 127.0.0.1>nul
REG DELETE “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate” /v AccountDomainSid /f
REG DELETE “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate” /v PingID /f
REG DELETE “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate” /v SusClientId /f
echo Success!
echo.
ping -n 4 127.0.0.1>nul

echo Resetting Winsock and WinHTTP Proxy…
ping -n 4 127.0.0.1>nul
netsh winsock reset
proxycfg.exe -d
netsh winhttp reset proxy
echo Success!
echo.
ping -n 4 127.0.0.1>nul

echo Starting services…
ping -n 4 127.0.0.1>nul
net start ccmexec
net start cryptsvc
net start appidsvc
net start bits
net start wuauserv
echo Success!
echo.
ping -n 4 127.0.0.1>nul

echo Deleting all BITS jobs…
ping -n 4 127.0.0.1>nul
bitsadmin.exe /reset /allusers
echo Success!
echo.
ping -n 4 127.0.0.1>nul

echo Forcing AU discovery…
ping -n 4 127.0.0.1>nul
wuauclt /resetauthorization /detectnow
echo Success!
echo.
ping -n 4 127.0.0.1>nul

:END
echo Windows Update Agent has been reset!
pause
exit /b 0

PowerShell – Return Product Key

email me

This is how you return the product key for your computer using PowerShell

$Computer = $Env:Computername

$TranslationMapping="BCDFGHJKMPQRTVWXY2346789"


$MSRegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Computer)

$value = $MSRegKey.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue('DigitalProductId4')[0x34..0x42]

$ProductKeyOutput = "" 

for ($i = 24; $i -ge 0; $i--) { 
    $r = 0 
    for ($j = 14; $j -ge 0; $j--) { 
        $r = ($r * 256) -bxor $value[$j] 
        $value[$j] = [math]::Floor([double]($r/24)) 
        $r = $r % 24 
        } 

    $ProductKeyOutput = $TranslationMapping[$r] + $ProductKeyOutput 

    if (($i % 5) -eq 0 -and $i -ne 0) { 
        $ProductKeyOutput = "-" + $ProductKeyOutput 
        } 
}


clear-host
write-host ""
"Product Key: " + $ProductKeyOutput
write-host ""