Asset Management Suite

 View Only

Automating Maintenance with the ASDK – Deleting Unmanaged Machines 

Apr 29, 2009 02:57 PM

The purpose of this document is to provide a walk through on how the ASDK can be used to automate NS cleanup and maintenance tasks. It assumes that you have a basic understanding of Visual Studio and .NET programming.

There are a number of things in my organization that we found ourselves doing manually to recoup licenses and make sure that the data in our notification and asset servers stays clean. What I plan on covering in this article is how with a little programming and the Altiris SDK, you can automate the cleanup of unmanaged machines and run it on a regular schedule.


Where to Begin

The first step in using any portion of the SDK is to install it on your Notification or Asset server so its methods will be available for use. The ASDK can be found here: http://altirisdl.com/eval/Altiris_ASDK_1_4.exe. The module that we will be using specifically for this example is:

ItemManagementService – This can be found in the Notification Server portion of the SDK. References to its methods can be found in the help file under Altiris ASDK > API Reference > Notification Server > Altiris.ASDK.NS > ItemManagementLib Class > Methods. – The method that we will be using is the DeleteItem Method.


Once the SDK is installed on your Notification and/or Asset Server, there are a couple of ways that we can begin. We can either use the compiled DLLs that Altiris provides, which works just fine, or we can create a proxy class, which is essentially uncompiled version of the DLL that is provided by Altiris. I prefer to use the proxy class just so all the code can be compiled into a single executable. If you choose to use the DLL, you will have to distribute the DLL with your exe for it to function. For this example, we will be creating and using the proxy class, but I will note along the way where you can use the DLL instead, if that is what you prefer.


Creating Your Proxy Classes

The first thing you will need for all of this is a copy of Visual Studio. You can use the free express edition if you like that is available through the Microsoft Site: http://www.microsoft.com/Express. I will be doing my development in C# in Visual Studio 2008. Once you have Visual Studio installed, open up the Visual Studio Command Prompt. If you are using 2008, it can be found here Start > Programs > Microsoft Visual Studio 2008 > Visual Studio Tools > Visual Studio 2008 Command Prompt. When the command prompt opens you will run the following command (make sure to replace "<your server>" with the name of the server that you just installed the SDK on):

wsdl /language:CS http://<your-server>/Altiris/ASDK.NS/ItemManagementService.asmx 

My command, for example, would look like this:

wsdl /language:CS http://its-altirisns/Altiris/ASDK.NS/ItemManagementService.asmx

If you are using 2008, the proxy classes are created and placed by default here: C:\Program Files\Microsoft Visual Studio 9.0\VC. If you browse to this location you will now see a new file titled ItemManagementService.cs. This will be used in your Visual Studio project.


Creating your Project

Now that we have our proxy classes created, launch Visual Studio and create a new project. This can be either a Console application or a Windows Forms application. For the purpose of this article, I will be using a Windows Forms application.

imagebrowser image

The first thing that we need to do is add a couple of references and some "using statements".
Replace the list of using statements at the top of your project with the following list:
using System;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Net;

Now add a new reference to System.Web.Services. This is done by going up to the menu at the top and clicking Project > Add Reference. Under the .NET tab, select System.Web.Services and click OK.

imagebrowser image

***NOTE***
If you are not using the proxy classes, but instead you are using the DLLs, you will also need to add a reference to the Altiris.ASDK.NS.COM.dll. This lives out on your Notification server here: Program Files\Altiris\Altiris ASDK\COM Assemblies\Altiris.ASDK.NS.COM.dll. You will also have to add the following using statement to the top of your code if you are using the DLL:
using Altiris.ASDK.NS.COM.ItemManagementProxy; 
Next, we will import the ItemManagementService class that we created earlier. To import the proxy class into your project, simply drag and drop it from where it currently lives in program files, into your solution explorer window and onto your project:

imagebrowser image

Next, lets add a button to our form so we have something we can click to test our code. Once everything is working properly, we can easily turn this into an application that runs from command line and take arguments for any variables that we need to fill where no button clicks are needed.

Next we will need to pull data from our Altiris SQL Database to determine which machines are unmanaged. This will require a new SQL connection. In the click event for your button, create your SQL connection. This can be done a number of ways, but for this demonstration, I have created my connection as follows (don't forget to replace my data source with the name of your SQL server):
//CREATE AND OPEN CONNECTION TO SQL DATABASE
var con = new SqlConnection(@"Trusted_Connection=true; Data Source=SQL03T; Initial Catalog=Altiris; Integrated Security=true");
con.Open();
Now we need to provide it with the SQL command that will be used to retrieve unmanaged machines. I will be taking the results from our query and storing them in a DataTable. The SQL query that we will use is:
SELECT DISTINCT i.[_ResourceGuid]
FROM [Inv_AeX_AC_Identification] i
INNER JOIN [vResourceEx] vr
ON vr.[Guid] = i.[_ResourceGuid]
WHERE vr.[IsManaged] = '0'
This pulls back just the resource guid for all machines that are unmanaged (where “IsManaged = 0”). So applying the SQL above and storing the results into a DataTable would look something like this:
//CREATE AND OPEN CONNECTION TO SQL DATABASE
var con = new SqlConnection(@"Trusted_Connection=true; Data Source=SQL03T; Initial Catalog=Altiris; Integrated Security=true");
con.Open();


//CREATE COMMAND AND DEFINE COMMAND TEXT (SQL QUERY THAT WILL BE RUN)
var cmd = con.CreateCommand();
cmd.CommandText = "SELECT DISTINCT i.[_ResourceGuid] " +
"FROM [Inv_AeX_AC_Identification] i " +
"INNER JOIN [vResourceEx] vr " +
"ON vr.[Guid] = i.[_ResourceGuid] " +
"WHERE vr.[IsManaged] = '0'";


//CREATE A DATA READER THAT WILL PULL BACK THE RESULTS
var dr = cmd.ExecuteReader();


//POPULATE A DATA TABLE WITH THE INFORMATION THE DATA READER PULLS BACK
var dt = new DataTable("Unmanaged Computers");
if (dr == null) return;
dt.Load(dr);
var dv = dt.DefaultView;


//CLOSE AND DISPOSE OF THE DATA READER AND CONNECTION
dr.Close();
dr.Dispose();
con.Close();
con.Dispose();
By stepping through your code in Debug mode, you should easily be able to see if your query was successful. If it was, you will see something like this stored in the contents of your DataTable:

imagebrowser image

Now we have the data, we just need to do something with it. This will be done using the proxy class that we created earlier. So the first step is to create a new ItemManagementService object. Along with this, there are a couple of properties that we need to set. First we need to set the URL property. By default, the URL will be exactly the same as the one that you used to create the class, so something like this: http://<your-server>/Altiris/ASDK.NS/ItemManagementService.asmx. If this is correct, you will not need to set the URL. If by chance, like me, you have more than one server you want to work with, instead of creating a different proxy class for each one, you can just repoint the URL property of the one you’ve created. I am going to repoint mine to my test server (I highly recommend running this in test prior to running it in production!). The other piece we need to take care of is defining what credentials will be used when running the deletion method. You can set specific credentials, or you can use the default credentials that the application is being run under, which is what I will be doing. Once the object is created, the URL is re-pointed, and the credentials are set, your code will look something like this:
//CREATE AND OPEN CONNECTION TO SQL DATABASE
var con = new SqlConnection(@"Trusted_Connection=true; Data Source=SQL03T; Initial Catalog=Altiris; Integrated Security=true");
con.Open();


//CREATE COMMAND AND DEFINE COMMAND TEXT (SQL QUERY THAT WILL BE RUN)
var cmd = con.CreateCommand();
cmd.CommandText = "SELECT DISTINCT i.[_ResourceGuid] " +
"FROM [Inv_AeX_AC_Identification] i " +
"INNER JOIN [vResourceEx] vr " +
"ON vr.[Guid] = i.[_ResourceGuid] " +
"WHERE vr.[IsManaged] = '0'";


//CREATE A DATA READER THAT WILL PULL BACK THE RESULTS
var dr = cmd.ExecuteReader();


//POPULATE A DATA TABLE WITH THE INFORMATION THE DATA READER PULLS BACK
var dt = new DataTable("Unmanaged Computers");
if (dr == null) return;
dt.Load(dr);
var dv = dt.DefaultView;


//CLOSE AND DISPOSE OF THE DATA READER AND CONNECTION
dr.Close();
dr.Dispose();
con.Close();
con.Dispose();


//CREATE A NEW ItemManagementService OBJECT AND SET PROPERTIES
var ims = new ItemManagementService
{
    Url = http://itsaltiristesta/Altiris/ASDK.NS/ItemManagementService.asmx,
    Credentials = CredentialCache.DefaultCredentials
};
Now all that is left is to step through your table of resource guids and feed each one to the DeleteItem method of your ItemManagementService object. This can be done through a simple foreach statement.

So stepping through the guids in your table would look like this:
//STEP THROUGH TABLE AND DELETE EACH RECORD
foreach(DataRow row in dv.Table.Rows)
{
    var guid = row[0].ToString();
    ims.DeleteItem(guid);
}
At this point, clicking your button should delete all unmanaged machines, but as I mentioned above, the goal is to automate the process so you don’t have to hire a button pusher just to keep your database clean. The best way I have found to automate the task our code performs is to either use a console application, or to move our code out of our click event and into our form’s load event. Then I would replace a couple of things with variables, like SQL server, and Notification Server for instance, so you could use the same compiled EXE with any server and database that you like. The other thing that you have to remember to do if you leave your code in a Windows form application is to make sure that your application exits when it is done with its work. By default, a form will just stay open until it is told to close, where as a console application will run through its code and quit when it is done.

For the sake of consistency, I will continue on with the form application that we have been using to this point. Below is what the code would look like if I were to convert the server names to variables that are passed in through command line. I have also hidden the form since it now needs no input from the user, and I put in a couple of exit events where they are needed. I have also moved my code to the form’s load event and out of the button’s click event.

Final code:
//HIDE THE FORM SINCE THERE IS NO NEED TO SEE IT ANYMORE
WindowState = FormWindowState.Minimized;
Visible = false;

//GET COMMAND LINE ARGUMENTS THAT ARE PASSED IN
var cmdLine = Environment.GetCommandLineArgs();

//EXIT PARAMETER COUNT IS INCORRECT.
if(cmdLine.Length != 3) Environment.Exit(2);

//SET THE VALUES OF THE SQL SERVER AND NS SERVER BASED ON COMMAND LINES
//COMMAND LINE 0 IS ALWAYS THE PATH TO THE EXE THAT IS RUNNNING
var sqlServer = cmdLine[1];
var ns = cmdLine[2];

//CREATE AND OPEN CONNECTION TO SQL DATABASE USING OUR VARIABLE AS A DATA SOURCE
var con = new SqlConnection(@"Trusted_Connection=true; Data Source="+ sqlServer +"; Initial Catalog=Altiris; Integrated Security=true");
con.Open();


//CREATE COMMAND AND DEFINE COMMAND TEXT (SQL QUERY THAT WILL BE RUN)
var cmd = con.CreateCommand();
cmd.CommandText = "SELECT DISTINCT i.[_ResourceGuid] " +
"FROM [Inv_AeX_AC_Identification] i " +
"INNER JOIN [vResourceEx] vr " +
"ON vr.[Guid] = i.[_ResourceGuid] " +
"WHERE vr.[IsManaged] = '0'";


//CREATE A DATA READER THAT WILL PULL BACK THE RESULTS
var dr = cmd.ExecuteReader();


//POPULATE A DATA TABLE WITH THE INFORMATION THE DATA READER PULLS BACK
var dt = new DataTable("Unmanaged Computers");

if (dr == null) Environment.Exit(1);//EXIT IF THE DATA READER COMES BACK AS NULL

dt.Load(dr);
var dv = dt.DefaultView;


//CLOSE AND DISPOSE OF THE DATA READER AND CONNECTION
dr.Close();
dr.Dispose();
con.Close();
con.Dispose();



//CREATE A NEW ItemManagementService OBJECT AND SET PROPERTIES USING OUR VARIABLE AS A NOTIFICATION SERVER
var ims = new ItemManagementService
{
    Url = "http://" + ns +"/Altiris/ASDK.NS/ItemManagementService.asmx",
    Credentials = CredentialCache.DefaultCredentials
};



//STEP THROUGH TABLE AND DELETE EACH RECORD
foreach (DataRow row in dv.Table.Rows)
{
    var guid = row[0].ToString();
    ims.DeleteItem(guid);
}



//EXIT AFTER UNMANAGED MACHINES ARE DELETED
Environment.Exit(0);

The task can now be run by passing the SQL server in as the first parameter and the Notification Server in as the second like this:

“RemoveUnmanagedMachines - Demo.exe" “SQL03T” “ITSALTIRISTESTA”

That is it for this article.
As you can see, we have just automated a task that can be quite time consuming with about 50 lines of code.
 

Statistics
0 Favorited
0 Views
0 Files
0 Shares
0 Downloads

Tags and Keywords

Related Entries and Links

No Related Resource entered.