Author Archives: Rudolf - Page 7

2013 – the year after the end of the world

So we’ve survived the end of the world (Mayan calendar joke) and we’re stuck with ourselves… so to speak.

Some things to remember 2012 by (that I took interest in)

  • The Olympic games in London
  • People that passed away that I had respect for: Neil Armstrong, Ernest Borgnine, Patrick Moore, Whitney Houston
  • Riaan Cruywagen retired!
  • The end of the world… that didn’t happen!

What can we look forward to in this new year? Lets see

  • Windows 8/RT will be a spectacular… failure
  • Androids will take over (as long as they’re not paranoid)
  • Prices will go up… but at least the rain will come down (if any)
  • More politics and violence going nowhere
  • More strikes… over crap issues
  • I ran out of ideas.

On a personal front, my family will grow by one soon. That will probably keep us busy for the rest of the year. Also, I really hope to get going writing my books (Sci-Fi related)

Creating a Multi-instance self registering service

This is one of those things I’ve been wanting to do for a long time for my Event Scavenger pet project. Basically the requirement is this:

“Being able to have one executable (.exe) file that can be used multiple times for different service instances.”

It turns out it is not too hard to achieve this using C# and .Net 4.0 (might even work with older frameworks but haven’t tried it). It is an extension of my already improved self registering Windows Service extensions which make it possible to simply run the Service exe with a ‘-install’ command line parameter. With the latest additions a ‘named’ instance can also be specified. This means, in the Service Manager of Windows you can see the Service executable plus a command line parameter that makes it unique. It allows you to stop/start/manage it separately as an entity. This is exactly the same as how Microsoft BizTalk Server implements ‘Host Instances’.

Now lets get dirty with some code samples. The first code snippet shows (an example) part of main program.cs that handles the command like parameters.

string collectorName = "Default";		

if (args.Length > 0)
{                
  if (args[0].ToUpper() == "-INSTALL")
  {
              string serviceParameters = "";
    if (args.Length > 1)
    {
      collectorName = args[1];
                  serviceName = "Event Reaper - " + collectorName;
      displayName = "Event Reaper - " + collectorName;
                  serviceParameters = "\"-Collector:" + collectorName + "\"";
    }
    if (args.Length > 2)
      displayName = args[2];
    if (args.Length > 3)
      description = args[3];

    HenIT.Services.ServiceRegister.InstallService(
      System.Reflection.Assembly.GetExecutingAssembly().Location,
      serviceName,
      displayName,
      description,
                  serviceParameters);
    return;
  }
  else if (args[0].ToUpper() == "-UNINSTALL")
  {
    if (args.Length > 1)
    {
      collectorName = args[1];
                  serviceName = "Event Reaper - " + collectorName;
    }
    HenIT.Services.ServiceRegister.UnInstallService(
       System.Reflection.Assembly.GetExecutingAssembly().Location,
                 serviceName);
    return;
  }
  collectorName = HenIT.CommandLineUtils.GetCommand(args, "", "-Collector:");
}
if (collectorName.Length == 0)
  collectorName = Properties.Settings.Default.CollectorName;

ServiceBase[] servicesToRun;
servicesToRun = new ServiceBase[] 
{ 
  new EventReaperService() { CollectorName = collectorName }
};
ServiceBase.Run(servicesToRun);

All this section does is to check for the “-INSTALL” or “-UNINSTALL” parameters and then call the helper class that does the registration/unregistration. The Display name of the service instance is always prefixed with “Event Reaper – ” to grouped all instances visually together in Service manager.

InstallService

The ServiceRegister class only has two methods. InstallService is the first one and handles all the bits to gather login details, set properties and then register the service.

public static bool InstallService(string serviceExePath,
        string serviceName,
        string displayName,
        string description,
        string serviceParameters)
{
    bool success = false;
    try
    {
        string workingPath = System.IO.Path.GetDirectoryName(serviceExePath);
        string logPath = System.IO.Path.Combine(workingPath, "Install.log");
        ServiceStartMode startmode = ServiceStartMode.Automatic;
        ServiceAccount account = ServiceAccount.LocalService;
        string username = "";
        string password = "";
        bool delayedStart = true;

        InstallerForm installerForm = new InstallerForm();
        installerForm.StartType = ServiceStartMode.Automatic;
        installerForm.AccountType = ServiceAccount.User;
        installerForm.BringToFront();
        installerForm.TopMost = true;
        if (installerForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            startmode = installerForm.StartType;
            account = installerForm.AccountType;
            delayedStart = installerForm.DelayedStart;
            if (installerForm.AccountType == ServiceAccount.User)
            {
                username = installerForm.UserName;
                password = installerForm.Password;
            }


            Hashtable savedState = new Hashtable();
            ProjectInstallerForHelper myProjectInstaller = new ProjectInstallerForHelper(delayedStart);
            InstallContext myInstallContext = new InstallContext(logPath, new string[] { });
            myProjectInstaller.Context = myInstallContext;
            myProjectInstaller.ServiceName = serviceName;
            myProjectInstaller.DisplayName = displayName;
            myProjectInstaller.Description = description;
            myProjectInstaller.StartType = startmode;
            myProjectInstaller.Account = account;
            if (account == ServiceAccount.User)
            {
                myProjectInstaller.ServiceUsername = username;
                myProjectInstaller.ServicePassword = password;
            }
            myProjectInstaller.Context.Parameters["AssemblyPath"] = serviceExePath + " " + serviceParameters;

            myProjectInstaller.Install(savedState);
            success = true;
        }
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message, "Install service", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
    }
    return success;
}

The class InstallerForm is simply a plain Windows Form to capture service properties like the username/password etc. I’m not showing its code here now. AssemblyPath is the actual property that Service manager use to launch the executable plus its parameters.

ProjectInstallerForHelper is an utility class that simply inherits from System.Configuration.Install.Installer. It looks like this:

internal class ProjectInstallerForHelper : System.Configuration.Install.Installer
{
    private ServiceProcessInstaller processInstaller;
    private System.ServiceProcess.ServiceInstaller serviceInstaller;

    public ProjectInstallerForHelper(bool delayedAutoStart = true)
    {
        processInstaller = new ServiceProcessInstaller();
        serviceInstaller = new System.ServiceProcess.ServiceInstaller();
        serviceInstaller.DelayedAutoStart = delayedAutoStart;

        Installers.AddRange(new Installer[] {
                processInstaller,
                serviceInstaller});
    }

    #region Added properties
    public string ServiceName
    {
        get { return serviceInstaller.ServiceName; }
        set { serviceInstaller.ServiceName = value; }
    }
    public string DisplayName
    {
        get { return serviceInstaller.DisplayName; }
        set { serviceInstaller.DisplayName = value; }
    }
    public string Description
    {
        get { return serviceInstaller.Description; }
        set { serviceInstaller.Description = value; }
    }
    public ServiceStartMode StartType
    {
        get { return serviceInstaller.StartType; }
        set { serviceInstaller.StartType = value; }
    }
    public ServiceAccount Account
    {
        get { return processInstaller.Account; }
        set { processInstaller.Account = value; }
    }
    public string ServiceUsername
    {
        get { return processInstaller.Username; }
        set { processInstaller.Username = value; }
    }
    public string ServicePassword
    {
        get { return processInstaller.Password; }
        set { processInstaller.Password = value; }
    }
    #endregion
}

UnInstallService

This is essentially just the reverse of InstallService.

public static bool UnInstallService(string serviceExePath, string serviceName)
{
    bool success = false;
    try
    {
        ServiceController sc = new ServiceController(serviceName);
        if (sc == null)
        {
            System.Windows.Forms.MessageBox.Show("Service not installed or accessible!", "Stopping service", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
            return true;
        }
        if (sc.Status == ServiceControllerStatus.Running || sc.Status == ServiceControllerStatus.Paused)
        {
            sc.Stop();
        }
    }
    catch (Exception ex)
    {
        if (!ex.Message.Contains("was not found on computer"))
        {
            System.Windows.Forms.MessageBox.Show(ex.Message, "Stopping service", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
        }
        else
            return true;
    }
    try
    {
        string workingPath = System.IO.Path.GetDirectoryName(serviceExePath);
        string logPath = System.IO.Path.Combine(workingPath, "Install.log");

        ServiceInstaller myServiceInstaller = new ServiceInstaller();
        InstallContext Context = new InstallContext(logPath, null);
        myServiceInstaller.Context = Context;
        myServiceInstaller.ServiceName = serviceName;
        myServiceInstaller.Uninstall(null);
        success = true;
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message, "Uninstall service", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
    }
    return success;
}

Summary

And this is basically the whole thing that allows you to create a Windows Service in C# that can handle multiple instances. There are a few things to keep in mind like the fact that all instances share the same config file unless you make a physical copy of the exe and config file to another directory and register it from there. Using this you can multiple services using different config all running side by side not affecting each other (hopefully hehe)

CreateSqlDBHelper – Tool to create and set up database from scripts

I’ve done it again. re-invented the wheel… uhm, no. But I did create a tool to create and set up a new sql server database from scripts that can be launched from the command line. This could be useful if you must automate the process of setting up a test database each time you need to run a new set of tests.

It works like this (coomand line options)

Usage: CreateSqlDBHelper.exe <server> <database> <data files path> <-d> <script1.sql [script2.sql …]>
Where
-d : drop database first

This allows you to specify a sql server/instance name, database name, path where the database files will be located plus any number of sql script files that needs to be run to set up a new database. Typically you’ll start by running scripts that will create tables, views, sprocs and also initial data rows etc. Optionally the tool can first ‘drop’ the existing database (but for now that requires a manual press ‘Y’ step). It makes use of the .Net 4.0 client framework plus SQL server SMO libraries – which come with SQL server…

You can find a copy of the tool here.

SQLScripter

I’ve been wanting to creating something like this for myself for a while. A simple tool to quickly create a backup copy of a SQL Server database ‘structure’ (or schema if you will). It is really a simple command line tool that simply takes a few parameters like server\instance name, database, output directory and a prefix name for the output files.

It creates separate files for Tables, Views and Stored procedures (which includes UDFs)

Example usage:

SQLScripter.exe <-s:server> <-d:database> [-od:outputDirectory] [-p:prefixFileName]

Grab it here (plain exe in a zip file). It make use of the .Net 4.0 client framework.

Event Scavenger 5

A quick heads up about a new version of my Event Scavenger tool/system that is coming. There are a whole lot of changes that build up on the existing functionality as far as the gathering service(s) and Administration are concerned. The Viewer part has (so far) being left unchanged so that a previous version Viewer tool can still access the new version database and Vice Versa.

Why things have changed?

The reasons for the update is simple to cater for some limitations I experienced myself with the tool/system. These include the following:

– Newly added Event Logs required a service restart so the gathering service (Event Scavenger service) could become aware of them.

– The original (Event Scavenger) service kept ‘open’ threads for each machine/log that needed to be ‘polled’. Most of the time each thread was left in a ‘sleeping’ state doing no work at all and just taking up resources.

– Only one instance of the collecting (Event Scavenger) service could run on a single machine – thus limiting it to only one database it can store logs into, one service that could be managed etc.

– Logs polled/imported into another database were set up ‘sort of’ separately from actual (machine)logs already in the current database. This made them (sort of) hard to managed.

– Setting up permissions for users was mostly a manual process.

Changes

To solve these issues the following changes have been made:

– The gathering service now spawn threads only for enabled machine/logs each time it ‘runs’ based on a master frequency. This is set to 60 seconds by default (but as always can be changed and now managed from the Admin tool itself). This solves both the 1st and 2nd points mentioned. A side effect is that the performance counters for each Machine/Log now have disappeared (may be a bad thing…). This also means the whole concept of Thread recycling have gone the way of the Dodo…

– The service is now ‘Multi instance’ aware so that multiple copies of the same service (each with its own physical copy of the exe and config file) can run separately ‘servicing’ different Event Logs/databases etc on the same machine. Each instance can thus operate totally independent doing totally its own thing. Multi-machine instances are still possible as before. To set up  a new ‘instance’ you simple make a copy of the service exe & config file (plus editing) and then use the “-install ‘<serviceName>’ ‘<displayName>’ ‘<Description>’ ” parameters on the service exe. The result is a separate entry in Service Manager which you can start/stop on its own.

– A Machine/Log entry now has another (sorta) state other than just be enabled/disabled. The 3rd ‘state’ is the option to have it being imported from another EventScavenger database. Using the Admin tool now makes it a lot easier to manage this.

– The Admin tool now has a simplistic view/editor to manage users in the database.

– The Admin tool also now provides a way to ‘manage’ the collectors (services). A simplistic way to stop/start/pause/continue services is built right into the tool.

– To set up the database is now a bit easier. I included a new (command-line) tool that simply runs the various sql scripts for you. Some editing of the scripts might still be required if you don’t like the default settings). You can always still do it manually.

[Update]

– Something new, the admin tool now has a simplistic way to manage ‘Reaper’ services so you can start/stop/pause services, manage a view of what physical services service what Collector name etc. At the moment the actual registration of a service is still a manual process but the admin tool shows you a help screen with instructions on how to set it up (or even unregister it).

New name

Because the ‘main’ service for collecting Event Logs changed I decided to give it a new name as well – Event Reaper (being a fan of the Mass Effect games must be obvious by now… 😉 ).  The name ‘Event Scavenger’ is now just a global name for the whole project/tool set. With the new multi instance support this means you can have multiple reapers (on the same box).

Source code

So far I’ve kept the changed source code ‘offline’ as it is now a totally new ‘branch’ of the original source code. The global version number has now being changed to 5 (and in fact – the default database name has now being changed to EventScavenger5) as it is not compatible with the previous version (with the exception of the viewer tool that works on both versions – for now…). Thus, previous version collector services and the Admin tool will not work anymore with the new database version – per design.

Release

I’m still in testing so no actual ‘Release’ has been made yet. I’ll post an update here when here is something that others can start playing with.

Update: A preview (Beta) can be found here. It is (should be) fully functional with all the above mentioned features already working.

Alpha Centauri – Infographics

This is really cool. On Space.com there is a whole page with a bunch of facts about the Alpha Centauri system, including the newly found planet Alpha Centauri Bb. Most of the stuff I knew about (since these are the kind of things I’m interested in) but seeing things ‘graphically’ really makes it more cool!!

Alpha Centauri Infographic

Alpha Centauri Infographic – Linked from Space.com.

Creating custom BizTalk Event View

This is not exactly ‘new’ technology but someone might find it useful. In recent Windows versions Microsoft enhanced the way the Event log work and function plus the way you can access it. The default Event Viewer inside Windows support creating ‘Views’ with which you can filter events based on your needs. If you know your XML syntax you can create some nice views for yourself. I created one for filtering all BizTalk related events that can simply be imported and then used as is. The XML looks like this:

<ViewerConfig>
<QueryConfig>
<QueryParams>
  <UserQuery /> 
  </QueryParams>
<QueryNode>
  <Name>BizTalk Server</Name> 
<QueryList>
<Query Id="0" Path="Application">
  <Select Path="Application">*[System[Provider[@Name='BizTalk Server']]]</Select> 
  <Select Path="Application">*[System[Provider[@Name='BizTalk Server Deployment']]]</Select> 
  <Select Path="Application">*[System[Provider[@Name='ENTSSO']]]</Select> 
  </Query>
  </QueryList>
  </QueryNode>
  </QueryConfig>
<ResultsConfig>
<Columns>
  <Column Name="Level" Type="System.String" Path="Event/System/Level" Visible="">120</Column> 
  <Column Name="Keywords" Type="System.String" Path="Event/System/Keywords">70</Column> 
  <Column Name="Date and Time" Type="System.DateTime" Path="Event/System/TimeCreated/@SystemTime" Visible="">170</Column> 
  <Column Name="Source" Type="System.String" Path="Event/System/Provider/@Name" Visible="">99</Column> 
  <Column Name="Event ID" Type="System.UInt32" Path="Event/System/EventID" Visible="">80</Column> 
  <Column Name="Task Category" Type="System.String" Path="Event/System/Task" Visible="">80</Column> 
  <Column Name="User" Type="System.String" Path="Event/System/Security/@UserID">50</Column> 
  <Column Name="Operational Code" Type="System.String" Path="Event/System/Opcode">110</Column> 
  <Column Name="Log" Type="System.String" Path="Event/System/Channel">80</Column> 
  <Column Name="Computer" Type="System.String" Path="Event/System/Computer">170</Column> 
  <Column Name="Process ID" Type="System.UInt32" Path="Event/System/Execution/@ProcessID">70</Column> 
  <Column Name="Thread ID" Type="System.UInt32" Path="Event/System/Execution/@ThreadID">70</Column> 
  <Column Name="Processor ID" Type="System.UInt32" Path="Event/System/Execution/@ProcessorID">90</Column> 
  <Column Name="Session ID" Type="System.UInt32" Path="Event/System/Execution/@SessionID">70</Column> 
  <Column Name="Kernel Time" Type="System.UInt32" Path="Event/System/Execution/@KernelTime">80</Column> 
  <Column Name="User Time" Type="System.UInt32" Path="Event/System/Execution/@UserTime">70</Column> 
  <Column Name="Processor Time" Type="System.UInt32" Path="Event/System/Execution/@ProcessorTime">100</Column> 
  <Column Name="Correlation Id" Type="System.Guid" Path="Event/System/Correlation/@ActivityID">85</Column> 
  <Column Name="Relative Correlation Id" Type="System.Guid" Path="Event/System/Correlation/@RelatedActivityID">140</Column> 
  <Column Name="Event Source Name" Type="System.String" Path="Event/System/Provider/@EventSourceName">140</Column> 
  </Columns>
  </ResultsConfig>
  </ViewerConfig>

To use simply copy/past into an XML file and use the ‘Import Custom View…’ context menu option in the standard Event Log Viewer of Windows.

Of course, if you want a proper Event View solution over a whole group of servers use my Event Scavenger tool 😉

BizTalk and MSDTC

This is a quick post to summarize my frustrations about the process of setting up and configuring a BizTalk (2010) environment  on a multiple server environment.

If you encounter any/all of the following errors while doing the initial configuration:

  • Exception of type System.EnterpriseServices.TransactionProxyException was thrown
  • [WARN] AdminLib GetBTSMessage: hrErr=80070002; Msg=The system cannot find the file specified.;
  • [WARN] AdminLib GetBTSMessage: hrErr=c0c02560; Msg=Failed to read “KeepDbDebugKey” from the registry.

then start troubleshooting by looking at the following things:

  1. Check that MSDtc is installed, running and configured properly – especially the security settings. This apply to BOTH the SQL Server and all BizTalk servers! See the following screenshot:
    BizTalk MSDtc Security settings

    BizTalk MSDtc Security settings

    The Type of communication can be changed to Mutual or Incoming Caller but it HAS to be the same on all the machines (SQL and BizTalk servers)

  2. Check that MSDtc has been allowed access through the firewall – again on ALL machines including the SQL server!

    BizTalk/SQL MSDtc Firewall access

    BizTalk/SQL MSDtc Firewall access

  3. Check that the SQL Server Browser service is running on the SQL server machine.

I really hope that Microsoft will one day fix this issue where the Configuration Wizard does not check these things BEFORE you start trying to apply settings. It is really frustrating that you have to ‘stumble’ across this every time you set up a new environment – Yes you should check these things beforehand I know…

MSMQ Monitor

I have this really old tool I create (literally) 10 years ago do help with some MSMQ related development stuff at the time. Since then I have hardly touched it (source code) but it still seems to work to this day – even on Windows 7. It was intended to help me/developers to ‘see’ what is going on inside some test queues while we were in the process of working with a system that we developed that uses the technology.

The ‘Tool’ is really simple yet really powerful to do just what it was intended – to monitor MSMQ queues and let you manipulate messages inside the queues. It can view/create/delete/resubmit and do all kind of crazy things with MSMQ messages. It even has a simple MSMQ stress tool built right in!

Some screenshots

MSMQ Monitor Main window

Queue options

MSMQ Monitor Queue options

Stress Tester

MSMQ Monitor Stress Tester

Of course, this tool is provided ‘as is’. I simply thought of sharing it if someone else might find it useful. The source code was/is written in plain old vb.net.

Grab it from here

Mass Effect 3 Patch 4

It has been a while since there were any updates to the game (other than the DLC’s). High time some bugs get fixed. The full list of bugs fixed are available here.

The list was a bit random so I though I’ll group it a bit better (if possible)

Fixes

Single player

– Fixed Shepard’s shadow from not appearing after entering and exiting an Atlas
– Fixed a rare crash in the final mission level involving the firing of the Cain at the Hades Cannon.
– Fixed an issue with Ken/Gabby and Tali/Garrus ambient dialogues not triggering in Normandy engineering

Power evolution changes

– Sabotage power evolution 6 increased tech damage bonus no longer stacks
– Incinerate power evolution 5 now gives a damage bonus to frozen and chilled enemies
– N7 Shadow Sword Mastery power evolution 5 and 6 now apply to Shadow Strike damage

Character ability fixes

– Krogan Vanguard Rage bonuses now work properly
– Asari Justicar passive power evolution 3 power damage and force bonus now works properly
– Fixed Asari Justicar from not being able to activate Biotic Sphere within range of large enemies
– Fixed Flamer power of Vorcha from being activated simultaneously with the Reegar Carbine
– Fixed Atlas rocket applying damage over time on N7 Paladins using the Omni-Shield

Weapons

– Fixed weapons with natural piercing from having their damage reduced with piercing mods equipped
– Particle Rifle no longer replenishes ammo from ammo boxes and supply pylons
– Fixed SMG Ultralight Materials Mod not having impact on power recharge speed
– Fixed Armor Piercing Ammo not applying penetration bonus to secondary weapon
– Krysae no longer ignores enemy shield gates
– Fixed various weapon sound-replications for clients
– Fixed an issue with ammo boxes causing players to be unable to fire weapons after attempting to refill grenades
– Fixed an issue with the Krysae Sniper rifle not functioning properly on squad members (Firefight pack)
– Fixed seeking projectile powers occasionally failing to impact targets even though it appeared to impact

Enemies and NPC

– Fixed pathing for Banshees so they don’t get stuck in a teleport routine
– Fixed dropping Retrieve Objects that could potentially fall under the level
– Fixed an issue with enemies approaching a downed player to execute, but showing mercy and leaving
– Fixed an issue that caused the Retrieve Objective wave to not recognize the recovery of the object when it enters the retrieve zone
– Fixed Decoy that was blocking the use of ladders to NPCs and squadmates
– Fixed an issue with the Banshee being able to sync-kill players farther than she should be able to
– Fixed issue where enemies in Stasis surviving a biotic detonation would become un-synchronized for clients
– Fixed an issue that caused the Retrieve Objective wave to not recognize the recovery of the object when it enters the retrieve zone
– Fixed issue in which enemies surviving a detonated Stasis blast became invulnerable

Multiplayer maps

– Fixed an issue with Firebase Jade giving partial extractions when all players are already inside the extraction zone
– Fixed automatic revive at a specific spot in Firebase White
– Fixed a crash on Firebase Rio caused by heavy melee

Lobby, menu etc.

– Fixed an issue with Private Lobbies not staying private after the match has begun
– Fixed an issue in which purchasing multiplayer card pack purchases would not complete
– Fixed icons of powers disappearing from the Character Screen
– Fixed an issue with talent points remaining after a character promotion

Disconnects, unplayable maps

– Fixed quitting/disconnecting while holding Retrieve Object that could cause the Retrieve Object to disappear
– Fixed users logging off or disconnecting during gameplay from not being able to return online until rebooting the game
– Fixed an issue when using Biotic Charge before death that caused the match to be unplayable afterwards

Other

– Fixed tutorial tip that didn’t properly display an unbound command
– Fixed an issue in multiplayer where if a character has DLC weapons equipped, and the DLC associated to the weapons is deleted, the weapon loadout screen displayed no weapons
– Fixed the Encumbrance Bar from not updating correctly for the Earth DLC weapon mods
– Fixed player death camera beginning before a sync kill is complete
– Fixed Leviathan DLC Weapon Mods not carrying over to New Game +
– Fixed the health bar position of Tactical Scan on Swarmers
– Fixed bleedout effect that was disappearing when another player used an Ops Survival Pack

Exploits Fixed

– Fixed an exploit that allowed players to be invincible and invisible to enemies
– Fixed an exploit where players were able to use rockets from other weapons

PS3 Only

– Fixed an issue on PS3 where after accepting an invite, a player could get stuck in a multiplayer screen by entering the store from the promo screen and then exiting without purchase
– Fixed a crash when pressing PS button during the game’s boot sequence

PC Only

– Fixed the hint popup to update mouse left click and right click bindings
– Fixed an issue that made Origin users display their game as joinable when their game is full
– Fixed a crash on Firebase Rio caused by heavy melee

Xbox Only

– Fixed a rare crash (black screen) on Xbox 360: Upon booting up the game and attempting to reach the title screen, players will now be able to get to title screen to recover their save games. Progress to locked achievements will be reset. Achievements already unlocked will remain unaffected.

New stuff

– Players can no longer grab Geth Pyros over cover (Nooooooo !)
– Attempting to equip similar weapon mods will now present a ‘Slot Occupied’ message
– Disruptor Rounds consumable (all ranks) damage multiplier against shields and barriers increased from 100% to 400%
– All Batarian and Krogan kits will now stagger less than other kits
– Ops Survival Packs now grant a one second damage immunity when consumed
– Singularity power re-designed (see link for details)
– Melee creatures will now completely ignore pets (drones, decoys, etc.) rather than just having a chance to ignore them
– Krysae no longer ignores enemy shield gatesKrysae no longer ignores enemy shield gates
– Concussive Shot changes (see link for details)
– Marksman will instantly reload weapon ammunition when activated
– Can now headshot Banshees, Geth Primes, and Brutes for an extra 40% weapon damage.
– Can now shoot the Atlas’ exhaust port on his back for an extra 40% weapon damage.
– Successfully extracting from a match gives 10% bonus credits. This reward does not depend on your squad members – you must extract personally to get the reward.