Add and remove VMware NFS datastores via PowerCLI

Been experimenting with these recently, and they have to be added to or removed from each host individually, which is tedious via the GUI.

Easy via PowerShell/PowerCLI though.

Add:

$hosts = Get-VMHost -Location "RCM"
foreach($VMHost in $hosts){
    Write-Host $VMHost.Name
    New-Datastore -VMHost $VMHost -Name "VM Archive" -Nfs -NfsHost nfs01.rcmtech.co.uk -Path "/vmarchive"
}

Remove:

$hosts = Get-VMHost -Location "RCM"
foreach($VMHost in $hosts){
    Write-Host $VMHost.Name
    Remove-Datastore -VMHost $VMHost -Datastore "VM Archive" -confirm:$false
}
Posted in PowerShell, vSphere | Tagged , , , , , , , , | Leave a comment

MsMpSvc terminates on Windows Server 2003 with defininition version 1.171.1.0

Have had various servers this morning with the Microsoft System Center Endpoint Protection Client service msmpsvc.exe terminating frequently. The service control manager restarts it but it dies again fairly quickly.

So far all the servers are running Windows Server 2003 32-bit.

The version of SCEP I have running is 4.5.216.0, although I tried uninstalling and reinstalling, which reverted it back to 4.3.220.0 and that has the same problem.

The virus and spyware definitions were updated from version 1.169.2706.0 to 1.171.1.0 overnight. It seems as though it is the definition change which is causing the problems.

Have posted this to TechNet Forums.

The following event is posted into the System event log:

Event Type: Error
Event Source: Service Control Manager
Event Category: None
Event ID: 7034
User:  N/A
Description:
The Microsoft Antimalware Service service terminated unexpectedly.  It has done this 3 time(s).

There is nothing posted to the Application event log unless you have some kind of debugger installed, e.g. on some servers with SQL Server 2005 management tools installed I’m seeing:

Event Type: Error
Event Source: VsJITDebugger
Event Category: None
Event ID: 4096
User:  NT AUTHORITY\SYSTEM
Description:
An unhandled win32 exception occurred in MsMpEng.exe [4400]. Just-In-Time
debugging this exception failed with the following error: Debugger could
not be started because no user is logged on.
Check the documentation index for 'Just-in-time debugging, errors' for more
information.
Data:
0000: 02 00 5c 80               ..\€

Workaround

A possible temporary workaround seems to be to uninstall SCEP and revert to the older Forefront Client Security. Have just installed client version 1.5.1996.0 which has given me engine version 1.1.10501.0 and that has so far not died with definition version 1.171.1.0.

Workaround #2

From the TechNet forum thread linked to above: Set the following registry DWORD value to 1:

HKLM\Software\Microsoft\Microsoft Antimalware\Real-Time Protection\DisableBehaviorMonitoring

Note that you’ll have to give Administrators full control to the Real-Time Protection key first, unless you change the value via something that runs as the local System account. You should probably change the permissions back to Read for Administrators afterwards.

Also note that the word Behavior is spelt in American, without the “u”!

Or go into the GUI, Settings tab, Real-time protection and untick the box titled Enable behaviour monitoring.

Update

Seems as though this can also affect Windows XP.

Update #2 (updated!)

New definitions have been released, version 1.171.46.0 and higher, but as yet these have not fixed the problem. I initially thought they had as the service ran for nearly an hour without failing, but fail it did. Apparently (see link in first update above) there will be a new engine released later today to resolve the problem.

Update #3

Definitions 1.171.64.0 or higher are apparently the ones to go for and do fix the problem, though I’ve not been able to confirm this personally yet. I’ll know by tomorrow morning.

Posted in Applications, Windows | Tagged , , , , , , , , , , | 9 Comments

2919355 Windows Update not showing in WSUS

I have been keen to get hold of this update early to check it out before some of our other users get hold of it so have been checking Windows Update directly rather than going via our WSUS server. The update is now available via Windows Update but is not being picked up by my WSUS servers.

Currently this behaviour is by design, due to KB2919355 breaking connectivity with SSL (HTTPS) secured WSUS servers. The 2919355 update has been held back from WSUS whilst a new update to fix this problem can be prepared and released, otherwise you’d potentially get 2919355  and then nothing else from WSUS, ever.

I’m not using SSL for my WSUS servers so this wouldn’t affect me, but at least I now know why the update isn’t showing.

Info from:

Quoting from the latter:

There is a known issue which causes some PCs updated with the Windows 8.1 Update (KB 2919355) to stop scanning against Windows Server Update Services 3.0 Service Pack 2 (WSUS 3.0 SP2 or WSUS 3.2) servers which are configured to use SSL and have not enabled TLS 1.2.

Microsoft plans to issue an update as soon as possible that will correct the issue and restore the proper behavior for Windows 8.1 Update KB 2919355 scanning against all supported WSUS configurations. Until that time, we are temporarily suspending the distribution of the Windows 8.1 Update KB 2919355 to WSUS servers.

UPDATE 2014/04/15

There is now a KB article KB2959977 about this issue, though no fix yet (and I also fixed the link to the blog post above that I’m quoting from).

Posted in Windows | Tagged , , , , , , , , | Leave a comment

PowerShell: Finding user sessions on RDSH servers

If you’ve been working with Citrix Metaframe/Presentation Server/XenApp and/or Microsoft Terminal Server/Terminal Services/Remote Desktop Session Host for a while you’ll probably be familiar with the command line utility quser (or query user). It returns a tabular output showing details of users currently logged on:

 USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
 a-user                ica-tcp#15          1  Active          7  08/04/2014 07:19
 an-other              ica-tcp#16          2  Active          .  08/04/2014 08:26
 all-rest              ica-tcp#19          3  Active          .  08/04/2014 08:36
 no-play               ica-tcp#20          5  Active          .  08/04/2014 08:37
 b-usy                 ica-tcp#18          4  Active          .  08/04/2014 08:30

You can get the same information from a remote server by appending /server:<servername> onto the end of the command.

If no users are logged on to the server being queried then the command returns (via StdErr):

No User exists for *

This is a very useful command.Very untouched by Microsoft for approaching the last 15 years…

Which is a shame because the output format leaves a little to be desired. For example if there are some disconnected sessions the table format goes a bit awry:

 USERNAME           SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
 a-user                                 2  Disc        none   07/04/2014 09:58
 an-other           ica-tcp#69          1  Active          .  08/04/2014 08:15

Looks ok on screen but try and parse that empty SESSIONAME column from a scripting point of view, nasty.

So you can use this command to retrieve information, but for anything other than a basic test of “is somebody logged on or not” for scripting purposes it’s not ideal.

Oh, and there’s basically no (built in) PowerShell equivalent. You might be able to use Get-RDUserSession, or not, depending on whether your server is part of a Remote Desktop Deployment.

So, I tried using WMI to get a count of user sessions:

$OSVersion = (Get-WmiObject -Class Win32_OperatingSystem -ComputerName $NewVMName).Version
if($OSVersion -eq "5.2.3790"){
    # Server 2003
    $ActiveSessions = (Get-WmiObject -Class Win32_PerfRawData_TermService_TerminalServices -ComputerName $NewVMName).ActiveSessions
    $InactiveSessions = ((Get-WmiObject -Class Win32_PerfRawData_TermService_TerminalServices -ComputerName $NewVMName).InactiveSessions - 1) # subtract one for "Console" session
} else {
    $ActiveSessions = (Get-WmiObject -Class Win32_PerfRawData_LocalSessionManager_TerminalServices -ComputerName $NewVMName).ActiveSessions
    $InactiveSessions = ((Get-WmiObject -Class Win32_PerfRawData_LocalSessionManager_TerminalServices -ComputerName $NewVMName).InactiveSessions - 2) # subtract two for "Service" and "Console" sessions
}

Which as you can see, is a little fiddly due to the classes being different between 2003 and newer OSs, and that the console and service sessions are included. It also doesn’t tell you if there is a user logged on to the (local) console, as there is always a console session present. Not ideal if you’re wanting to ensure there are no people logged on to a server prior to rebooting/rebuilding it.

So in the end I’ve gone back to old faithful, quser:

$Server = "SomeServerName"
$ErrorActionPreference = "Continue"
$QUResult = quser /server:$Server 2>&1
$ErrorActionPreference = "Stop"
if($QUResult -notmatch "no user exists for"){
    Write-Host "Sessions found" -ForegroundColor Red
    $QUResult
}

Note that I’m setting $ErrorActionPreference to “Continue” because I tend to set it to “Stop” at the top of my scripts (not shown in the chunk above) and because quser returns the “No User exists for *” text via StdErr, the script will stop with an error if there are no users logged on. That’s also the reason for the 2>&1 on the end of the quser command line – re send the StdErr output to the same place as StdOut, to ensure they both end up in the $QUResult variable irrespective of whether users are logged on or not.

Posted in PowerShell, Remote Desktop, Scripting | Tagged , , , , , , , , , | Leave a comment

Missing row when using ExecuteReader to fill a DataTable

I’ve been using the following PowerShell code to retrieve the contents of an SQL Server table and store it in a DataTable for fast local processing:

$BuildDBConnection = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList "Server=RCMSQL01;Database=TSBuild;Integrated Security=SSPI"
$BuildDBConnection.Open()
# Get Main table
$SQLCommand = $BuildDBConnection.CreateCommand()
$SQLCommand.CommandText = ("SELECT * FROM Main")
$SQLReader = $SQLCommand.ExecuteReader()
if($SQLReader.Read()){
    $MainTable = New-Object System.Data.DataTable
    $MainTable.Load($SQLReader)
    $SQLReader.Close()
}
$MainTable | ft -AutoSize

It looked like it had been working fine. However, today I noticed that some data was missing. Specifically the first row of data as seen if you view the SQL table via a Select query (e.g. via SQL Server Management Studio).

I eventually tracked this down to being caused by the if statement, and thus probably the the $SQLReader.Read() is retrieving the first row of the table, and then the $DataTable.Load() is getting everything else.

I have two fixes so far:

1) Don’t use the if statement, just try and load the $SQLReader object straight into the DataTable.

2) Use a SQLDataAdapter instead:

$BuildDBConnection = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList "Server=RCMSQL01;Database=TSBuild;Integrated Security=SSPI"
$BuildDBConnection.Open()
# Get Main table
$SQLCommand = $BuildDBConnection.CreateCommand()
$SQLCommand.CommandText = ("SELECT * FROM Main")
$SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter $SQLCommand
$MainTable = New-Object System.Data.DataTable
$SQLAdapter.Fill($MainTable)
$MainTable | ft -AutoSize
Posted in PowerShell, Scripting | Tagged , , , , , , , , | Leave a comment

PowerShell: There are null values and then there are SQL null values

I was reading some data out of a SQL Server table, and wanted to do an operation if one of the string values returned, MAC, was either blank or null. I was using the following code:

$NewServerName = "SomeServerName"
$DBServerName = "RCMSQL01"
$SQLConnection = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList "Server=$DBServerName;Database=Build;Integrated Security=SSPI"
$SQLConnection.Open()
$SQLCommand = $SQLConnection.CreateCommand()
$SQLCommand.CommandText = "SELECT Host,OU,MAC FROM [Build].[dbo].[Main] WHERE ServerName like '$NewServerName'"
$SQLReader = $SQLCommand.ExecuteReader()
if($SQLReader.Read()){
    $HyperVHost = $SQLReader["Host"]
    $OU = $SQLReader["OU"]
    $MAC = $SQLReader["MAC"]
    $SQLReader.Close()
} else {
    Write-Host "VM record missing in Build DB"
}

Due to the nature of the SQL database, the values in the $MAC column might be any of null (the SQL Server default), blank (i.e. some text had been added but removed), or “some actual text”.

If the MAC column was showing as Null, the following code did not work as expected:

if($MAC -eq $null){
    Write-Host "MAC is null"
}

It seems as though this is because the value being returned is actually of the type System.DBNull rather than being an actual PowerShell null value ($null). You can see this by piping the variable into Get-Member.

There are several ways to work with this:

1) Test the $MAC variable against the “special” DBNull variable

if($MAC -eq [System.DBNull]::Value)
    Write-Host "MAC is null"
}

2) Ensure that the variable is created as a string, then test for it being blank rather than null. At the top of the script:

[string]$MAC = ""

Then to test, once the value has been retrieved from SQL Server:

if($MAC -eq ""){
    Write-Host "MAC is blank (might actually be Null in SQL Server)"
}

3) Convert the variable into a string, then test for it being blank

$MACString = $MAC.ToString()
if($MACString -eq ""){
    Write-Host "MAC is blank (might actually be Null in SQL Server)"
}
Posted in PowerShell, Scripting | Tagged , , , , , , , | Leave a comment

No HTML5 video in IE11 on RDSH 2012 R2

Have had a thread open on TechNet forums about this for a while.

Essentially, I use System Center Virtual Machine Manager (SCVMM) to build VMs that are then made into Remote Desktop Session Host Servers by a combination of PowerShell and VBScript.

Some of these publish RemoteApp applications, others publish full desktops. Thanks to the much improved method that RDP 8 uses to stream and transcode video the multimedia performance is pretty good. Except that HTML5 video wasn’t working in Internet Explorer 11. If you could convince websites that IE wasn’t up to HTML5 video then the site would sometimes drop back to trying the Flash player (e.g. add youtube.com to the Compatibility View list).

I discovered that the key to this problem was the state of Internet Explorer Enhanced Security Configuration (IE ESC). If the setting was turned off for users, the HTML5 video played back fine, but turn it on for users (as is the default) and HTML5 video doesn’t work, even if you’re logged on as an administrator.

You can see and alter the state of the IE ESC via Server Manager – Local Server. Changing it programmatically proved to be more difficult and the only method I’ve found that worked was to turn it off via the unattended settings when VMM is customising the new VM. The VM at this point is just a regular server, the RDSH role is added later in the build process.

I was already having to turn IE ESC off for admins as otherwise the PowerShell build script that runs after autologon of the build user would not run.

Sample code as follows:

Template = Get-SCVMTemplate -Name $TempTemplateName
$Unattend = $Template.UnattendSettings
# Unattend sections: 0 = windowsPE, 1 = offlineServicing, 2 = generalize, 3 = specialize, 4 = auditsystem, 5 = auditsystem, 6 = oobesystem
$Unattend.Add("3/Microsoft-Windows-IE-ESC/IEHardenAdmin","false")
$Unattend.Add("3/Microsoft-Windows-IE-ESC/IEHardenUser","false")
Set-SCVMTemplate -VMTemplate $Template -UnattendSettings $Unattend | Out-Null

Turns off IE ESC for both users and admins.

Posted in PowerShell, Remote Desktop, VMM 2012 R2, Windows | Tagged , , , , , , , , , , , , | Leave a comment