SpywareBlaster Database Update – January 28, 2015

15 Internet Explorer
0 Restricted Sites
0 Firefox

17153 items in database


Windows 10 – Feedback

I have always believed that Microsoft Windows should be all things to all people and until Windows 8, that is how it was. Some features had been lost over the years, but new ones had also been added, and the general feel of Windows was still there.

Windows 8 really crushed everything that Windows has previously delivered. It was colourful but awkward, especially for those of us who still work with plain screens, a mouse and a keyboard.

Windows 10, while sharing some features with Windows 8, has changed the picture and some of Windows 8’s more annoying habits have gone. The ‘Windows apps are being smartened up to better compete with regular Windows 7 style programs, and not before time.

In some of the feedback I have seen for Windows 10, there are calls to dump the older stuff like Control Panel and put everything into ‘Settings’, but I vehemently disagree. The more features, ways of working and customizations, the better.

Desktops and notebooks are not going away anytime soon, and if we have to work on computers, we want something usable and familiar. Windows 10 as it stands presently is usable and does have some more familiar parts to it, the Start menu and the ability to have groups of apps/programs in the menu, the controls to minimize and close individual windows, spit screen views etc.

Microsoft needs to keep working with stuff like Windows Essentials too. Windows 7 users are not going to give up without a fight, and the Windows 8 apps are still a long way from reliability, failing to update, install and generally work like a useful program should.

Windows 10 is still a little scary because at the end of the day all you have initially are the dreaded apps, albeit with more functionality than they had originally. Don’t be scared to do what you did with Windows 7. That operating system came supplied with virtually nothing, but it only took a few minutes to fill it with some useful stuff. You can do the same for Windows 10..


Leadership – Each Day makes a difference

John Maxwell shares excellent advice for managers and business leaders in this month’s blog entries:



If I could come to your house and spend just one day with you, I would be able to tell whether or not you will be successful. You could pick the day. If I got up with you in the morning and went through the day with you, watching you for 24 hours, I could tell in what direction your life is headed.

Here is why: I believe that the secret of your success is determined by your daily agenda. If you make a few key decisions and then manage them well in your daily agenda, you will succeed. You will never change your life until you change something you do daily. You see, success, doesn’t just suddenly occur one day in someone’s life. For that matter, neither does failure. Each is a process. Every day of your life is merely preparation for the next. What you become is the result of what you do today. In other words… You are preparing for something.

Microsoft Security Updates – JANUARY 2015

Critical Security updates to Microsoft Windows and other products became available on Patch Tuesday and users should promptly update for the best levels of protection against new threats



How to Add ‘Take Ownership’ to Context Menu in Windows 10

This tutorial will show you how to add Take Ownership to the context menu of all files, folders, and drives for all users in Windows 10.

This will allow you to be able to instantly take ownership of a file, folder (and all contents), or drive (and all contents) by changing the owner to the current user and grant the Administrators group full access permission.

Read more…

When a website doesn’t work

Why I hate the CNN redesign, quantified | The Robservatory:

Glad to know that I’m not the only one that feels that CNN’s redo has jumped the shark.  Now granted I’m guessing that on mobile devices the transformation makes more sense and is less jarring, but on a desktop, man is the new format PAINFUL as every photo is larger than a page and just takes too much scrolling.

Of interest is how many devices are now the majority of our computing experience these days.


Entity Framework Pitfalls: Command Interceptors and Identity Keys

The IDbCommandInterceptor (sorry, no official documentation) interface was introduced in Entity Framework 6 as part of the new interception and logging API, and allows the interception of the SQL and its parameters that are sent to the database as the result of DbContext CRUD operations.

It offers two methods for each of the basic ADO.NET operations, those defined in DbCommand, one called before the operation is executed, and the other called afterwards:

  • ExecuteNonQuery (UPDATEs, INSERTs, DELETEs) –> NonQueryExecuting, NonQueryExecuted;
  • ExecuteScalar (SELECTs returning a single value) –> ScalarExecuting, ScalarExecuted;
  • ExecuteReader (SELECTs returning rows) –> ReaderExecuting, ReaderExecuted.

As usual, the methods ending with “ing” are executed before and those ending with “ed” are executed afterwards, always synchronously.

One might naively assume that INSERTs would always trigger a NonQueryExecuting/NonQueryExecuted call, and indeed it is so, unless we have an IDENTITY primary key, in which case, Entity Framework will instead call ReaderExecuting/ReaderExecuted. It’s easy to understand why: when we use an IDENTITY, we need to retrieve the generated value immediately after the INSERT, hence Entity Framework will generate code like:

   1: INSERT INTO [dbo].[SomeTable] (...)

   2: VALUES (...)

   3: SELECT [Id]

   4: FROM [dbo].[SomeTable]


The INSERT and SELECT are combined in the same command, which justifies the choice of ReaderExecuting/ReaderExecuted. Because in Entity Framework we always use IDENTITY – don’t we? –, it’s ReaderExecuting/ReaderExecuted that you should be implementing if you want to change the INSERT SQL or its parameters.

Spybot Search & Destroy Weekly Update – January 28, 2015


++ Ad.GoHD + Ad.Jpdesk ++ Ad.OmigaPlus + Ad.Strictor + VuuPC + Firseria + InstallMonetizer ++ Irismedia.hosts
+ Somoto.BetterInstaller
+ iCrossRider
Total: 2603189 fingerprints in 814055 rules for 7399 products.


8. Treffen der Forefront User Group Nord (FUGN) in Köln

Karsten und Marc laden ein zum achten Treffen der Forefront User Group Nord am Freitag, 20. Februar 2015 in Köln.

Weitere Infos etc. findet ihr in ihrem Blog:

8. Treffen der Microsoft User Group Nord (MUGN)

Viele Grüße

Dieter Rauscher
MVP Enterprise Security

Instantly disable, enable, Java, JavaScript, Flash in Firefox with QuickJava

If your Firefox browser is running slow due to various add-ons installed, then here comes QuickJava to the rescue. QuickJava allows users to enable and disable Java, JavaScript, Cookies, Stylesheets, Image Animations, Flash, Silverlight, Images and Proxy from the toolbar. This is great for increasing security or decreasing bandwidth.

Usually, if we want to disable Adobe Flash, then one has to navigate to the Add-ons page and wait for the Adobe Flash player to load. Once you see all the add-ons loaded completely, then switch to plugins and look for Adobe Flash Player, and click on the enable or disable option to turn that plugin on/off.


Microsoft Security Advisory Notification Issued: January 27, 2015

Security Advisories Updated or Released Today

* Microsoft Security Advisory (2755801)
– Title: Update for Vulnerabilities in Adobe Flash Player in
Internet Explorer
– Revision Note: V36.0 (January 27, 2015): Added the 3035034
update to the Current Update section.

WMI errors

Most PowerShell users will have done something like this:

£> Get-WmiObject -ClassName Win32_ComputerSystem
Domain              : WORKGROUP
Manufacturer        : Microsoft Corporation
Model               : Surface Pro 2
Name                : RSSURFACEPRO2
PrimaryOwnerName    :
TotalPhysicalMemory : 8506093568


Or you can use a computername to access a remote system

£> $computer = $env:COMPUTERNAME
£> Get-WmiObject -ClassName Win32_ComputerSystem -ComputerName $computer

Domain              : WORKGROUP
Manufacturer        : Microsoft Corporation
Model               : Surface Pro 2
Name                : RSSURFACEPRO2
PrimaryOwnerName    :
TotalPhysicalMemory : 8506093568


But if you try to access a remote machine that doesn’t exist

£> $computer = ‘WillNotBeFound’
£> Get-WmiObject -ClassName Win32_ComputerSystem -ComputerName $computer
Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:1 char:1
+ Get-WmiObject -ClassName Win32_ComputerSystem -ComputerName $computer
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand


You’ve heard of try – catch  so you do something like this

$computer = ‘WillNotBeFound’

try {
  Get-WmiObject -ClassName Win32_ComputerSystem -ComputerName $computer -ErrorAction Stop
catch {
  Write-Warning "An error occurred"


OR your catch may do something to record the error.

$computer = ‘WillNotBeFound’

try {
  Get-WmiObject -ClassName Win32_ComputerSystem -ComputerName $computer -ErrorAction Stop
catch {
  Write-Warning "An error occurred for machine: $computer"


If you make the warning message specific

$computer = ‘WillNotBeFound’

try {
  Get-WmiObject -ClassName Win32_ComputerSystem -ComputerName $computer -ErrorAction Stop
catch {
  Write-Warning "The RPC server is unavailable for machine: $computer"


What happens if you have a different error. Lets say you copy the code and change the class. You test the code

$computer = $env:COMPUTERNAME

try {
  Get-WmiObject -ClassName Win32_LogicalDsik -ComputerName $computer -ErrorAction Stop
catch {
  Write-Warning "The RPC server is unavailable for machine: $computer"


And get a message

WARNING: The RPC server is unavailable for machine: RSSURFACEPRO2


What you should see is

Get-WmiObject : Invalid class "Win32_LogicalDsik"
At line:1 char:1
+ Get-WmiObject -ClassName Win32_LogicalDsik -ComputerName $computer
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidType: (:) [Get-WmiObject], ManagementException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand


Because the class is mistyped.


You could try and create a number of catch statements – one for each error type.  Good luck with that. Its a lot of work.  A better approach, in my mind is to extract the error information you need

$computer = $env:COMPUTERNAME

try {
  Get-WmiObject -ClassName Win32_LogicalDsik -ComputerName $computer -ErrorAction Stop
catch {
$errordata = @"
  Computer = $computer
  Exception = $($error[0].Exception)
  ErrorId = $($error[0].FullyQualifiedErrorId)
  Write-Warning $errordata


If you look in the PowerShell automatic variable $error – you’ll find its a collection of error messages.  $error[0] contains the last error.  So now you get

£> $computer = $env:COMPUTERNAME

try {
  Get-WmiObject -ClassName Win32_LogicalDsik -ComputerName $computer -ErrorAction Stop
catch {
$errordata = @"
  Computer = $computer
  Exception = $($error[0].Exception)
  ErrorId = $($error[0].FullyQualifiedErrorId)
  Write-Warning $errordata

  Exception = System.Management.ManagementException: Invalid class "Win32_LogicalDsik"
  ErrorId = GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand


For a set of computers

$computers = $env:COMPUTERNAME, ‘WillNotBefound’

foreach ($computer in $computers){
try {
  Get-WmiObject -ClassName Win32_computersystem -ComputerName $computer -ErrorAction Stop
catch {
$errordata = @"
  Computer = $computer
  Exception = $($error[0].Exception)
  ErrorId = $($error[0].FullyQualifiedErrorId)
  Write-Warning $errordata


You get the data where you can contact the machine – otherwise a warning message that the server is unavailable.  Rather than outputting a warning message create an object from the error data and save to a CSV file

Part 7: Updated to Swift & Xcode 6: Unleash Your Inner App Developer – The Big Picture

Step-by-step instructions for creating an iOS App with Swift and Xcode 6.


All the best!
Kevin McNeish
Author: iOS App Development for Non-Programmers book series
Twitter: @kjmcneish

SQL Server Auditing

Probably the best mechanism for auditing changes to tables in SQL Server is Change Data Capture, which I already covered here. Unfortunately, it only works with the Enterprise editions of SQL Server, something that not everyone has access to.

I once had to implement a similar solution that should work on any edition of SQL Server, which is what I am going to talk about. Its only requirement was that for any changes made to target tables, their old values would be stored in a shared history table, with the indication of the timestamp and user who made the change.

Let’s imagine we have some table, anything will do:

   1: CREATE TABLE dbo.audit_target

   2: (


   4:     a NVARCHAR(50),

   5:     b INT

   6: )

As you can see, it’s just a regular table with a single-column primary key and a couple of other columns, any number and type will do, doesn’t really matter.

Now let’s create a table for holding the change history:

   1: CREATE TABLE dbo.history

   2: (


   4:     [table_name] NVARCHAR(30) NOT NULL,

   5:     table_id INT NOT NULL,

   6:     [changes] NVARCHAR(MAX),


   8:     [user] NVARCHAR(30) NOT NULL

   9: )

The table_name column shall hold the name of the table whose changes we are tracking, table_id, the id of the updated row, changes will get a XML containing all the old values, timestamp the date and time the change occurred, and user, the person who made the change (more on this later).

OK, next we need a stored procedure to populate the changes table:

   1: CREATE PROCEDURE dbo.generic_audit_procedure

   2: (

   3:     @procid INT,

   4:     @xml XML

   5: )

   6: AS

   7: BEGIN

   8:     SET NOCOUNT ON


  10:     -- check if there are changes, in which case, xml will not be empty

  11:     IF ((@xml IS NULL) OR (CAST(@xml AS NVARCHAR(MAX)) = N''))

  12:     BEGIN

  13:         RETURN 0

  14:     END


  16:     -- get the current table id for the current process (trigger)

  17:     DECLARE @tablename NVARCHAR(30)


  19:     SELECT @tablename = OBJECT_NAME(t.id)

  20:     FROM sys.sysobjects p

  21:     INNER JOIN sys.sysobjects t

  22:     ON p.parent_obj = t.id 

  23:     WHERE p.id = @procid


  25:     IF ((@tablename IS NULL) OR (@tablename = N''))

  26:     BEGIN

  27:         RAISERROR(N'Could not get table name', 16, 16)

  28:         ROLLBACK TRAN

  29:         RETURN

  30:     END


  32:     -- get the primary key column for the current table

  33:     DECLARE @idname NVARCHAR(30)


  35:     SELECT @idname = name 

  36:     FROM sys.syscolumns

  37:     WHERE id = OBJECT_ID(@tablename)

  38:     AND colstat = 1


  40:     IF ((@idname IS NULL) OR (@idname = ''))

  41:     BEGIN

  42:         RAISERROR(N'Could not get id column for the current table', 16, 16)

  43:         ROLLBACK TRAN

  44:         RETURN

  45:     END


  47:     -- get the current user from the context

  48:     DECLARE @username NVARCHAR(30)


  50:     SELECT @username = CONVERT(NVARCHAR(30), CONTEXT_INFO())


  52:     IF ((@username IS NULL) OR (@username = ''))

  53:     BEGIN

  54:         RAISERROR(N'Could not get current username', 16, 16)

  55:         ROLLBACK TRAN

  56:         RETURN

  57:     END


  59:     DECLARE @tmp TABLE([key] NVARCHAR(MAX), [value] XML)


  61:     INSERT INTO @tmp SELECT q.[key], q.[value]

  62:     FROM

  63:     (

  64:         SELECT T.N.value(N'(*[local-name(.)=sql:variable("@idname")])[1]', N'INT') AS [key], T.N.query(N'*') AS [value]

  65:         FROM @xml.nodes('/row') AS T(N)    

  66:     ) q



  69:     SET @ROWS = 0


  71:     -- loop all modified records

  72:     WHILE (1 = 1)

  73:     BEGIN

  74:         DECLARE @id NVARCHAR(MAX)

  75:         DECLARE @value XML


  77:         -- pick the first record

  78:         SELECT TOP 1 @id = [key], @value = [value]

  79:         FROM @tmp


  81:         IF (@@ROWCOUNT = 0)

  82:         BEGIN

  83:             BREAK

  84:         END


  86:         -- insert into the shared table

  87:         INSERT INTO dbo.history (table_name, table_id, [user], [changes])

  88:         VALUES (@tablename, @id, @username, CAST(@value AS NVARCHAR(MAX)))


  90:         -- increment the updated rows

  91:         SET @ROWS = @ROWS + @@ROWCOUNT


  93:         -- remove the processed record

  94:         DELETE FROM @tmp

  95:         WHERE [key] = @id

  96:     END


  98:     RETURN @ROWS

  99: END

The generic_audit_procedure will get the current table from the current process id, as passed in the @@procid parameter, the current user from CONTEXT_INFO (again, more on this later), the changes from the @xml parameter and will insert everything into the history table.

And the final part, a trigger to “glue” together the changes made to a table to the stored procedure:

   1: CREATE TRIGGER dbo.generic_audit_trigger

   2: ON dbo.test -- replace this with other target tables' names


   4: AS

   5: BEGIN

   6:     SET NOCOUNT ON


   8:     -- get all changes

   9:     -- this needs to be done on the trigger

  10:     DECLARE @xml XML

  11:     SET @xml = (SELECT * FROM inserted FOR XML PATH('row'))


  13:     -- call the generic stored procedure

  14:     EXEC dbo.generic_audit_procedure @@PROCID, @xml

  15: END

This trigger will run after changes are accepted (AFTER UPDATE) and will cast all changes (the INSERTED pseudo-table) as XML, and then invoke the generic_audit_procedure stored procedure with it as an argument, together with the current process id (@@PROCID). Of course, you need to call this for every table that you wish to audit.

The only thing left is, we need to provide a way for SQL Server to know the name of the current user. We do that by manually executing the following query (actually, it was an automated process that was executed by the data access library):

   1: DECLARE @username VARBINARY(128) = CAST(N'rjperes' AS VARBINARY(128))

   2: SET CONTEXT_INFO @username

So, whenever a change is made to a table, it will appear as this:


You can see that the changes column will contain an XML node with all the old values that were changed by the update made to the target table.

In a nutshell:

  1. We add a trigger that calls a stored procedure upon change to a number of target tables;
  2. Save the application user in CONTEXT_INFO;
  3. Modify the data in a table;
  4. Get the old values in an auditing table;

There are some limitations with this implementation:

  • Only single-column primary key target tables are supported;
  • All of the “old” values are recorded, not just those that changed;
  • It only keeps the “old” values, not the new ones, although this is by design and easy to change;
  • Binary columns could use a better treatment;
  • Doesn’t keep track of deleted or inserted records;
  • Doesn’t track schema changes (add/drop/modify columns, etc);
  • It is necessary to set CONTEXT_INFO explicitly with the application user that we want to record;
  • Although I didn’t implement it, it would be easy to add a version column to the history table, to keep track of how many changes were made to each target table.

However, it suited perfectly what I needed, maybe it will work for you too! Winking smile

Einstellung der Website www.msisafaq.de

Nach der gestern verkündeten Einstellung der Forefront User Group ist heute der Zeitpunkt gekommen, auch die Website www.msisafaq.de einzustellen. Fällt mir nach 13 Jahren nicht leicht. Jedoch ist es ein notwendiger und aus meiner Sicht logischer Schritt:

  • Das Kernprodukt, um das sich die Website dreht, wurde abgekündigt.
  • Ich habe schon lange keinen neuen Artikel mehr veröffentlicht.
  • Die Seite wäre quasi kernsanierungsbedürftig – eigentlich hoffnungslos.

Ich werde die Seite aber nicht vom Netz nehmen, sondern als Referenz verfügbar lassen. Die aktuellen Besucherzahlen zeigen, dass es noch immer ein Interesse dafür gibt. Und letztendlich sind ja noch viele Installationen vorhanden. Solange ich es finanziell realisieren kann wird die Seite also online bleiben. Keine Panik.

Eine andere Website für die Community ist in Planung. Wird dann sicherlich jedoch auf einer anderen Plattform laufen und mehr Möglichkeiten bieten. Dauert aber noch ein bisschen… Thema noch streng geheim :)

Ein ganz großer Dank gilt Christian Gröbner, der die ganzen Jahre immer wieder Beiträge beigesteuert hat sowie immer ein Ohr für mich hatte, wenn ich mal wieder Hilfe oder Ideen brauchte.

Viele Grüße

Dieter Rauscher
MVP Enterprise Security

Letztmaliges Treffen der Forefront User Group am 05.03.2015

"Nichts in der Geschichte des Lebens ist beständiger als der Wandel."

Charles Darwin (Englischer Naturforscher)

Am 27. November 2003 fand das erste Treffen der (damals noch) ISA Server User Group in Unterschleißheim bei München statt. Seither fanden knapp 40 weitere Treffen im Raum München statt. Vielen Dank allen Teilnehmern und Referenten!

Microsoft hat ja im September 2012 das Forefront TMG abgekündigt. Bedingt dadurch als auch durch meine berufliche und örtliche Veränderung haben Christian und ich nun vereinbart, dass wir die Forefront User Group in München einstellen. Im vergangenen Jahr ist es uns schon nicht gelungen, ein weiteres Treffen zu organisieren.

Deswegen möchten wir ein letztes Treffen für Donnerstag, 05. März 2015 im Raum München organisieren, quasi um uns von euch zu verabschieden. Wir planen für diesen Abend keine Vorträge ein sondern möchten uns in einem Restaurant treffen und einen gemütlichen Abend verbringen – dabei kann man sich ja auch über das ein oder andere unterhalten :)

Einladungen dazu gehen in den nächsten Stunden wie gewohnt über Xing raus. Alternativ Anmeldung und Details direkt bei mir. Wir würden uns freuen, wenn ihr dabei seid!

Marc und Karsten planen für die Forefront User Group Nord (FUGN) ebenfalls Veränderungen, die werden sie aber selber ankündigen.

Ich arbeite an der Planung neuer Communityprojekte und werde zu gegebener Zeit dazu berichten – meine zeitliche Auslastung erlaubt mir derzeit keine großen Sprünge.

Viele Grüße
Christian und Dieter

Dieter Rauscher
MVP Enterprise Security

How to Turn On or Off Automatically Connect to Wi-Fi Hotspots in Windows 10

If your Windows 10 PC has a Wi-Fi adapter, then Wi-Fi Sense can allow you to automatically connect to Wi-Fi hotspots when in range and not able to connect to one of your usual wireless network profiles.

This tutorial will show you how to turn on or off allowing your Windows 10 PC to automatically connect to Wi-Fi hotspots when in range.

Read more…

Unravelling lists of distinguished names

There are a number of AD properties such as MemberOf and directrports that consist of a collection of distinguisednames.  Sometimes you need the  name  of the object rather than the distinguished name:

function getname {
param (

$name = Get-ADObject $dn | select -ExpandProperty Name

return $name

Get-ADUser -Filter * -SearchBase "OU=Testing,DC=Manticore,DC=org" -Properties MemberOf |
foreach {
$name = $psitem.Name

foreach ($member in $psitem.MemberOf) {
   $props = [ordered]@{
     User = $name
     Group = getname -dn $member

   New-Object -Property $props -TypeName PSObject



In this example I’m looking at the MemberOf property.  Pull back the set of users and foreach look at each member in the MemberOf list. I pass that to a function that returns the name – I can reuse the function in other scripts.


Don’t make the mistake of looking at group membership in this way though. You can get the names of group members much more simply

Get-ADGroupMember -Identity tg1 | select name

Filtering on if an AD property exists

There are times when you want to filter the results based on whether a user has an AD property set.  You could do this:

Get-ADUser -Filter * -Properties Title | Where Title  | select Name, Title


However, that involves pulling back all of the users and then filtering. Not very efficient especially across the network in a big domain.

A better solution would be to use an LDAP filter

Get-ADUser -LDAPFilter "(Title=*)" -Properties Title  | select Name, Title


Get-ADUser does the checking to see if the user has a title set so only those objects with that property are retrieved. If you want to see the value of the property you need to include it by using the –Properties parameter.

Mozilla Firefox Updated to 35.0.1 – January 26, 2015

Firefox Notes
Version 35.0.1, first offered to Release channel users on January 26, 2015

Check out “What’s New” and “Known Issues” for this version of Firefox


Recent Comments