顯示具有 c# 標籤的文章。 顯示所有文章
顯示具有 c# 標籤的文章。 顯示所有文章

2014年2月2日 星期日

c# Get Email Address from Active Directory (using Username) in Asp.net

Sometimes it’s handy to grab either a username or email address (why not both?) from active directory. Below are the steps I believe you’ll need to get going quickly. In my example, I’m using VS2012 and .net 4.5.
1. Set your app to use windows authentication, you’ll need to set these to debug in VS:
Your web.config:
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <authentication mode="Windows" />
    <identity impersonate="true" />

    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
  </system.webServer>
</configuration>
Your project settings:
vs_winauth
2. Now in your application, add a reference to System.DirectoryServices:
dirservices
3. And in your code file:
using System.DirectoryServices;
4. A little function to search through active directory:
 private string uEmail(string uid)
        {
            DirectorySearcher dirSearcher = new DirectorySearcher();
            DirectoryEntry entry = new DirectoryEntry(dirSearcher.SearchRoot.Path);
            dirSearcher.Filter = "(&(objectClass=user)(objectcategory=person)(mail=" + uid + "*))";

            SearchResult srEmail = dirSearcher.FindOne();

            string propName = "mail";
            ResultPropertyValueCollection valColl = srEmail.Properties[propName];
            try
            {
                return valColl[0].ToString();
            }
            catch
            {
                return "";
            }

        }
5. And finally, how you can use:
string uName = "";
uName = uEmail(HttpContext.Current.User.Identity.Name.Replace(@"yourdomain\", ""));
Hope you enjoy! You can also use this method to retrieve other AD details (groups, full name, etc.).

C# class to validate User credentials on Active Directory (LDAP)

One to validate a user's credential, and the other to retrieve all users from the AD. Part one is self explanatory. Part two was important for me because I do roles management (and no I dont use Membership Providers - its either too little or too much)

Here's the full implementation. 

1. if (!String.IsNullOrEmpty(string errorMessage =ADConnector.AuthenticateUserPassword("LDAP://secure.company.com", "tech1", "tech1234")))
{
//blah blah blah
)
2. SearchResultCollection resColl =ADConnector.DumpAllUsers("LDAP://secure.comapy.com", "admin", "admin1234");

foreach (SearchResult res in resColl)
{
//If account is not disabled
if (!Convert.ToBoolean(Convert.ToInt32(res.Properties["userAccountControl"][0], System.Globalization.CultureInfo.InvariantCulture) &ADConnector.UF_DISABLED))
{
//blah blah blah
}
}
}

---------------------------------------------------------------------------------ADConnector.cs------------------------------------------------------------------------------------------------

namespace Utilities.Login.SSO
{
/// <summary>
/// <remarks>Developed by: Praveen Rangarajan
/// <CR1 date="10/12/2008">Included the functionality to retrieve all accounts from the AD</CR1>
/// <CR2 date="2/4/2009">Functionality to return "Locked-out", "Password expired", and "Account disabled" error message</CR2>
/// </remarks>
/// </summary>
public partial class ADConnector
{
public const int UF_DISABLED = 0x0002;
public const int UF_LOCKED = 0x0010;
public const int UF_EXPIRED = 0x800000;


/// <summary>
/// Authenticate the login credentials of the user on the AD.
/// </summary>
/// <param name="ldap">Url to the LDAP server alongwith the default DC settings. Example "LDAP://contoso.com, DC=contoso, DC=com"</param>
/// <param name="userName">Domain account of the user. Just the account name is sufficient</param>
/// <param name="password">User password</param>
/// <returns>
/// null If valid.
/// Non-empty string with the error message, if invalid.
/// </returns>
public static string AuthenticateUserPassword(string ldap, string userName,string password, string adminName, string adminPassword)
{
try
{
DirectoryEntry deSystem = new DirectoryEntry(ldap, userName, password);
DirectorySearcher s = new DirectorySearcher(deSystem, "SAMAccountName="+ userName,
new string[] { "userAccountControl" }
, SearchScope.Subtree);
SearchResult res;
if ((res = s.FindOne()) == null)
return "Username and/or Password incorrect";
if (Convert.ToBoolean(Convert.ToInt32(res.Properties["userAccountControl"][0]) & UF_DISABLED))
return "Account has been disabled. Please contact administrator for more details";
return null;
}
catch
{
//User validation returned exception. Now check for Password expired or Account locked out.
// Use the admin account (any account has LDAP query rights) to check for the above condition.

DirectoryEntry deSystem = new DirectoryEntry(ldap, adminName, adminPassword);
DirectorySearcher s = new DirectorySearcher(deSystem, "SAMAccountName="+ userName,
new string[] { "userAccountControl", "msDS-User-Account-Control-Computed" }
, SearchScope.Subtree);
SearchResult res;
if ((res = s.FindOne()) == null)
return "User not identified in AD";
if (Convert.ToBoolean(Convert.ToInt32(res.Properties["userAccountControl"][0]) & UF_DISABLED))
return "Account has been disabled. Please contact administrator for more details";
if (res.Properties.Contains("msDS-User-Account-Control-Computed") &&
Convert.ToBoolean(Convert.ToInt32(res.Properties["msDS-User-Account-Control-Computed"][0]) & UF_LOCKED))
return "Account locked-out. Please contact administrator for more details";
if (Convert.ToBoolean(Convert.ToInt32(res.Properties["userAccountControl"][0]) & UF_EXPIRED))
return "Password has expired. Please change your password before attempting to login again.";

return "Username and/or Password incorrect";
}
}

/// <summary>
/// Internal function to convert Large integer into its highpart and lowpart equivalents.
/// </summary>
/// <param name="largeInteger">Large integer object</param>
/// <returns></returns>
private static long LongFromLargeIntegerObject(object largeInteger)
{
System.Type type = largeInteger.GetType();
int highPart = (int)type.InvokeMember("HighPart", BindingFlags.GetProperty,null, largeInteger, null);
int lowPart = (int)type.InvokeMember("LowPart", BindingFlags.GetProperty, null, largeInteger, null);
return (long)highPart << style="color: #0000ff">uint)lowPart;
}

/// <summary>
/// Returns a collection of all users on the AD, for the given CN.
/// </summary>
/// <param name="ldap">Fully qualified LDAP url, alongwith the CN and OU.</param>
/// <param name="connectUser">Domain account having privileges to query to the LDAP.</param>
/// <param name="connectPassword">Password for the domain account.</param>
/// <returns>SearchResultCollection</returns>
public static SearchResultCollection DumpAllUsers(string ldap, stringconnectUser, string connectPassword)
{
DirectoryEntry deSystem = new DirectoryEntry(ldap, connectUser, connectPassword);
DirectorySearcher s = new DirectorySearcher(deSystem,"SAMAccountName=*",
new string[] { "cn", "mail", "samAccountName", "userAccountControl" }
, SearchScope.Subtree);

return s.FindAll();
}
}
}

2014年1月20日 星期一

How To Call a Parameterized Stored Procedure by Using ADO.NET and Visual Basic .NET

There are several ways to use ADO.NET to call a stored procedure and to get back return values and return parameters, including:
Use a DataSet object to gather the returned rows and to work with these rows in addition to the return values and the return parameters.
Use a DataReader object to gather the returned rows, to move through these rows, and to gather return values and return parameters.
Use the ExecuteScalar method to return the value from the first column of the results' first row with the return values and the return parameters. This is most useful with aggregate functions.
Use the ExecuteNonQuery method to return only the return parameters and the return values. Any returned rows are discarded. This is most useful for executing action queries.
This article demonstrates the last three methods and uses both the SqlCommand and the OleDbCommand objects. Make sure that you copy only the code for the managed provider that you are using. If you are not sure which managed provider you should use, visit the following Microsoft Developer Network Web site:
.NET Data Providers
http://msdn.microsoft.com/en-us/library/a6cd7c08.aspx In each of the samples in this article, the parameters are added to the Parameters collection of the Command object. When you use the SqlCommand object, you do not have add the parameters in any particular order, but the parameters must have the correct name. When you use the OleDbCommand object, you must add the parameters in the correct order, and you cannot use the parameters by name.

Use DataReader to Return Rows and Parameters

You can use the DataReader object to return a read-only, forward-only stream of data. The information that the DataReader contains can come from a stored procedure. This example uses the DataReader object to run a stored procedure that has an input and an output parameter and then moves through the returned records to view the return parameters.
Create the following stored procedure on the server that is running Microsoft SQL Server:
Create Procedure TestProcedure
  (
     @au_idIN varchar (11),
     @numTitlesOUT Integer OUTPUT
  )
As

select A.au_fname, A.au_lname, T.title
from authors as A join titleauthor as TA on
A.au_id=TA.au_id
join titles as T
on T.title_id=TA.title_id
where A.au_id=@au_idIN
set @numTitlesOUT = @@Rowcount
return (5)

Use the Imports statement on the System and the System.Data namespaces so that you do not have to qualify declarations in those namespaces later in your code. You must use the Imports statement prior to any other declarations. Make sure to copy only the code for the provider that you have chosen.SQL Client
Imports System.Data.SqlClient
OLE DB Data Provider
Imports System.Data.OleDb
Add the following code to the Form_Load event:SQL Client
Dim PubsConn As SqlConnection = New SqlConnection & _
    ("Data Source=server;integrated security=sspi;" & _
    "initial Catalog=pubs;")

Dim testCMD As SqlCommand = New SqlCommand & _
    ("TestProcedure", PubsConn)

testCMD.CommandType = CommandType.StoredProcedure

Dim RetValue As SqlParameter = testCMD.Parameters.Add & _
    ("RetValue", SqlDbType.Int)
RetValue.Direction = ParameterDirection.ReturnValue
Dim auIDIN As SqlParameter = testCMD.Parameters.Add & _
    ("@au_idIN", SqlDbType.VarChar, 11)
auIDIN.Direction = ParameterDirection.Input
Dim NumTitles As SqlParameter = testCMD.Parameters.Add & _
    ("@numtitlesout", SqlDbType.Int)
NumTitles.Direction = ParameterDirection.Output

auIDIN.Value = "213-46-8915"
PubsConn.Open()

Dim myReader As SqlDataReader = testCMD.ExecuteReader()
Console.WriteLine("Book Titles for this Author:")
Do While myReader.Read
    Console.WriteLine("{0}", myReader.GetString(2))
Loop
myReader.Close()
       
Console.WriteLine("Return Value: " & (RetValue.Value))
Console.WriteLine("Number of Records: " & (NumTitles.Value))

OLE DB Data Provider
Dim PubsConn As OleDbConnection = New OleDbConnection & _
    ("Provider=sqloledb;Data Source=server;" & _
    "integrated security=sspi;initial Catalog=pubs;")

Dim testCMD As OleDbCommand = New OleDbCommand & _
    ("TestProcedure", PubsConn)

testCMD.CommandType = CommandType.StoredProcedure

Dim RetValue As OleDbParameter = testCMD.Parameters.Add & _
    ("RetValue", OleDbType.Integer)
RetValue.Direction = ParameterDirection.ReturnValue
Dim auIDIN As OleDbParameter = testCMD.Parameters.Add & _
    ("@au_idIN", OleDbType.VarChar, 11)
auIDIN.Direction = ParameterDirection.Input
Dim NumTitles As OleDbParameter = testCMD.Parameters.Add & _
    ("@numtitlesout", OleDbType.Integer)
NumTitles.Direction = ParameterDirection.Output

auIDIN.Value = "213-46-8915"
PubsConn.Open()

Dim myReader As OleDbDataReader = testCMD.ExecuteReader()
Console.WriteLine("Book Titles for this Author:")
Do While myReader.Read
    Console.WriteLine("{0}", myReader.GetString(2))
Loop
myReader.Close()

Console.WriteLine("Return Value: " & (RetValue.Value))
Console.WriteLine("Number of Records: " & (NumTitles.Value))

Modify the connection string for the Connection object to point to the server that is running SQL Server.
Run the code. Notice that the DataReader retrieves the records and then returns the parameter values. You can use the Read method of the DataReader object to move through the returned records.

The Output window displays the titles of two books, the return value of 5, and the output parameter, which contains the number of records (2). Notice that you must close the DataReader in the code to see the parameter values. Additionally, note that you do not have to move through all of the records to see the return parameters if the DataReader is closed.
Use the ExecuteScalar Method of the Command Object

You can use the ExecuteScalar method of the Command object to retrieve parameter values. Additionally, ExecuteScalar returns the first column of the first row of the stored procedure. This is most useful for aggregate functions as in the following example.
Create the following stored procedure on the server that is running SQL Server:
Create Procedure TestProcedure2
 (
   @au_idIN varchar (11)
  )
As
/* set nocount on */
select count (T.title)
from authors as A join titleauthor as TA on
A.au_id=TA.au_id
join titles as T
on T.title_id=TA.title_id
where A.au_id=@au_idIN
Return(5)

Use the Imports statement on the System and the System.Data namespaces so that you do not have to qualify declarations in those namespaces later in your code. You must use the Imports statement prior to any other declarations. Make sure that you copy only the code for the provider that you have chosen.SQL Client
Imports System.Data.SqlClient
OLE DB Data Provider
Imports System.Data.OleDb
Add the following code to the Form_Load event:SQL Client
Dim PubsConn As SqlConnection = New SqlConnection & _
    ("Data Source=server;integrated security=sspi;" & _
    "initial Catalog=pubs;")

Dim testCMD As SqlCommand = New SqlCommand & _
    ("TestProcedure2", PubsConn)

testCMD.CommandType = CommandType.StoredProcedure

Dim RetValue As SqlParameter = testCMD.Parameters.Add & _
    ("RetValue", SqlDbType.Int)
RetValue.Direction = ParameterDirection.ReturnValue
Dim auIDIN As SqlParameter = testCMD.Parameters.Add & _
    ("@au_idIN", SqlDbType.VarChar, 11)
auIDIN.Direction = ParameterDirection.Input

auIDIN.Value = "213-46-8915"
PubsConn.Open()

Dim intCount As Integer = testCMD.ExecuteScalar
Console.WriteLine(intCount)
Console.WriteLine("Return Value: " & (RetValue.Value))

OLE DB Data Provider
Dim PubsConn As OleDbConnection = New OleDbConnection & _
    ("Provider=SQLOLEDB;Data Source=server;" & _
    "integrated Security=sspi;initial catalog=pubs;")

Dim testCMD As OleDbCommand = New OleDbCommand & _
    ("TestProcedure2", PubsConn)

testCMD.CommandType = CommandType.StoredProcedure

Dim RetVal As OleDbParameter = testCMD.Parameters.Add & _
    ("RetVal", OleDbType.Integer)
RetVal.Direction = ParameterDirection.ReturnValue
Dim IdIn As OleDbParameter = testCMD.Parameters.Add & _
    ("@au_idIN", OleDbType.VarChar, 11)
IdIn.Direction = ParameterDirection.Input

IdIn.Value = "213-46-8915"
       
PubsConn.Open()

Dim intCount As Integer = testCMD.ExecuteScalar

Console.WriteLine("Number of Rows: " & intCount)
Console.WriteLine(RetVal.Value)

Modify the connection string for the Connection object to point to the server that is running SQL Server.
Run the code. Notice that the ExecuteScalar method of the Command object returns the parameters. ExecuteScalar also returns the value of column 1, row 1 of the returned rowset. Thus, the value of intCount is the result of the count function from the stored procedure.
Use the ExecuteNonQuery Method of the Command Object

This sample uses the ExecuteNonQuery method to run the query and to return the parameter values. ExecuteNonQuery also returns the number of records that are affected after the query runs. However, ExecuteNonQuery does not return any rows or columns from the stored procedure.

The ExecuteNonQuery method is most useful when you use INSERT, UPDATE, or DELETE statements if you only have to know how many rows are changed. In a stored procedure in which you are using only a SELECT statement, you receive -1 because no rows are affected by the query.
Create the following stored procedure on the server that is running SQL Server:
Create Procedure TestProcedure3
  (
@au_idIN varchar (11),
@au_fnam varchar (30)
  )

As
/* set nocount on */
Update authors set au_fname = @au_fnam
where au_id = @au_idin
return (5)

Use the Imports statement on the System and the System.Data namespaces so that you do not have to qualify declarations in those namespaces later in your code. You must use the Imports statement prior to any other declarations. Make sure that you copy only the code for the provider that you have chosen.SQL Client
Imports System.Data.SqlClient
OLE DB Data Provider
Imports System.Data.OleDb
Add the following code to the Form_Load event:SQL Client
Dim PubsConn As SqlConnection = New SqlConnection & _
    ("Data Source=server;integrated security=sspi;" & _
    "initial Catalog=pubs;")

Dim testCMD As SqlCommand = New SqlCommand & _
    ("TestProcedure3", PubsConn)

testCMD.CommandType = CommandType.StoredProcedure

Dim RetValue As SqlParameter = testCMD.Parameters.Add & _
    ("RetValue", SqlDbType.Int)
RetValue.Direction = ParameterDirection.ReturnValue
Dim auIDIN As SqlParameter = testCMD.Parameters.Add & _
    ("@au_idIN", SqlDbType.VarChar, 11)
auIDIN.Direction = ParameterDirection.Input
Dim auFname As SqlParameter = testCMD.Parameters.Add & _
    ("@au_fnam", SqlDbType.VarChar, 30)
auFname.Direction = ParameterDirection.Input

auIDIN.Value = "213-46-8915"
auFname.Value = "Marjorie"
PubsConn.Open()

Dim rvRows As Integer = testCMD.ExecuteNonQuery
Console.WriteLine(rvRows)
Console.WriteLine(RetValue.Value)

OLE DB Data Provider
Dim PubsConn As OleDbConnection = New OleDbConnection & _
    ("Provider=SQLOLEDB;Data Source=server;" & _
    "integrated Security=sspi;initial catalog=pubs;")

Dim testCMD As OleDbCommand = New OleDbCommand & _
    ("TestProcedure3", PubsConn)

testCMD.CommandType = CommandType.StoredProcedure

Dim RetVal As OleDbParameter = testCMD.Parameters.Add & _
    ("RetVal", OleDbType.Integer)
RetVal.Direction = ParameterDirection.ReturnValue
Dim IdIn As OleDbParameter = testCMD.Parameters.Add & _
    ("@au_idIN", OleDbType.VarChar, 11)
IdIn.Direction = ParameterDirection.Input
Dim FnameIn As OleDbParameter = testCMD.Parameters.Add & _
    ("@au_fname", OleDbType.VarChar, 30)
FnameIn.Direction = ParameterDirection.Input

IdIn.Value = "213-46-8915"
FnameIn.Value = "Marjorie"

PubsConn.Open()

Dim intRowAffected As Integer = testCMD.ExecuteNonQuery

Console.WriteLine("Number of Rows affected: " & intRowAffected)
Console.WriteLine(RetVal.Value)

Modify the connection string for the Connection object to point to the server that is running SQL Server.
Run the code. The Output window displays the number of affected rows (intRowAffect) and the value of the return parameter.

2012年10月31日 星期三

Playing youtube in full screen in WebBrowser control


I try to play youtube video. This is what I have tried:
this.webBrowser1.Source = new Uri("http://youtube.googleapis.com/v/L8bE5-g8VC0");
This one displays YouTube player with all player controls. However full screen button doesn't work. I click on it, but player doesn't go full screen. Button becomes just disabled.
I have also tried this one:
this.webBrowser1.Source = new Uri("http://www.youtube.com/embed/L8bE5-g8VC0");
This also display YouTube player with all player controls. Full screen button is working properly. However when I go again to this video or another one (by setting Source property), player buttons disappear. To see player buttons again, I need to delete temporary internet files for IE. I could delete temp files every time before playing video, but this is not solution for me.
I'm running Windows 7 64bit and using WPF 4.0. What I want is to display YouTube player in my WebBrowser and have full screen button working properly. Anyone have some idea?



Solution, which worked for me - building a small HTML page with embedded video player:
public static class WebBrowserExtensions
{
    private static string GetYouTubeVideoPlayerHTML(string videoCode)
    {
        var sb = new StringBuilder();

        const string YOUTUBE_URL = @"http://www.youtube.com/v/";

        sb.Append("<html>");
        sb.Append("    <head>");
        sb.Append("        <meta name=\"viewport\" content=\"width=device-width; height=device-height;\">");
        sb.Append("    </head>");
        sb.Append("    <body marginheight=\"0\" marginwidth=\"0\" leftmargin=\"0\" topmargin=\"0\" style=\"overflow-y: hidden\">");
        sb.Append("        <object width=\"100%\" height=\"100%\">");
        sb.Append("            <param name=\"movie\" value=\"" + YOUTUBE_URL + videoCode + "?version=3&amp;rel=0\" />");
        sb.Append("            <param name=\"allowFullScreen\" value=\"true\" />");
        sb.Append("            <param name=\"allowscriptaccess\" value=\"always\" />");
        sb.Append("            <embed src=\"" + YOUTUBE_URL + videoCode + "?version=3&amp;rel=0\" type=\"application/x-shockwave-flash\"");
        sb.Append("                   width=\"100%\" height=\"100%\" allowscriptaccess=\"always\" allowfullscreen=\"true\" />");
        sb.Append("        </object>");
        sb.Append("    </body>");
        sb.Append("</html>");

        return sb.ToString();
    }

    public static void ShowYouTubeVideo(this WebBrowser webBrowser, string videoCode)
    {
        if(webBrowser == null) throw new ArgumentNullException("webBrowser");

        webBrowser.NavigateToString(GetYouTubeVideoPlayerHTML(videoCode));
    }
}
Usage:
this.webBrowser1.ShowYouTubeVideo("L8bE5-g8VC0");

2012年10月21日 星期日

Protect .NET code from reverse engineering?


Obfuscation is one way, but it can't protect from breaking the piracy protection security of the application. How to make sure that the application is not tampered with, and how to make sure that the registration mechanism can't be reverse engineered. Also it is possible to make to convert C# app in native code, Xenocode is too costly.
C# provides lot of features, and is the ideal language for my code, so writing in C++ again the whole codebase is out of question.
Secure certificates can be easily removed from the signed assemblies in .NET

You can't.
There are steps you can take to make it a little more difficult but ultimately any executable on the local machine is crackable. Eventually that code has to be converted into native machine code and every application that is runnable is vulnerable.
What you want to do is just make it difficult enough to crack to make it not worth peoples trouble.
Some suggestions I have for you to help protect your app:
  • Obfuscate your code. Dotfuscator has a free edition and comes with Visual Studio.
  • Use public/private key or asymmetric encryption to generate your product licenses. This ensures that only you can generate your license codes. Even if your app is cracked you can be sure that they won't be releasing a key generator for your application because it is impossible to reverse the key generating algorithm.
  • Use a 3rd party packer to pack your .NET executable into an encrypted w32 wrapper application.Themida is one of the better ones. This stops people from reflecting your application in .NET Reflector and makes it a pain to unpack for reversing.
  • Write your own custom packer. If the 3rd party packers are too expensive, consider writing your own. Sometimes custom packers can be very effective because there aren't well published methods on how to unpack them. This tutorial gives a ton of good information on writing your own win32 packer.
Ultimately though, if people want your application cracked they will. Look at all the commercial software out there that has a vast amount of resources to protect their applications and yet they are cracked before the applications are even released to the public.
A skilled reverse engineer can fire up IDA-Pro and slice through your application like butter no matter what you do. A packed application can be unpacked and obfuscation only prevents it from making it a walk in the park. All your hard work with your complex license code can be undone with a single byte patch.
You just need to accept that there is a very real chance people are going to pirate your software. There are some people who are never going to pay for your application no matter what and these are the people you don't need to worry about.
There are however, many businesses out there who would never risk a lawsuit and happily buy software licenses and many computer users who either don't want to risk it, find it wrong or are not tech savvy enough to pirate. These are your true customers and you should focus your efforts on providing them with a good user experience and ignore the people cracking your software.
I've had my application pirated before and I took it as a personal affront. Here I was, a small-time developer, pouring my heart and soul into an application and these people had the gall to pirate from me?! They were taking money directly from my pocket!
I immediately added in a bunch of draconian DRM code and attempted to sabotage any person using an illegitimate or cracked copy. I should of been working on making my application better instead of trying to stop the inevitable. Not only that, but I was hurting my true customers will all these extra protections I was putting in.
After a long battle I realized I was fighting the tides and all this time wasted was for naught. I took out all the phone-home code except for the barebones license functions and never looked back.

How to protect C# DLL from Reverse engineering


Solution 1

Hi,

you can use an obfuscator to protect your code. Here is one product:

http://www.red-gate.cm/products/smartassembly/index.htm 

Solution 4

Use an obfuscator like Crypto Obfuscator . An obfuscator converts your code and symbols into senseless data while retaining the logic.

Solution 5

Using an obfuscator tool is the only way. Be aware that obfuscating doesn't make it "impossible", but it can make it significantly more difficult to do in a timely manner. One tool not to bother with is the one that comes with Visual Studio. It doesn't do *nearly* enough.

Solution 6

You can try ILProtector . It protects .NET code using code virtualization. In this case level of code protection increases manyfold compared to obfuscation.

2012年10月13日 星期六

.NET的保護方式

目前就我所知
.NET的保護方式有幾種
1.混淆
2.核級加密
3.硬體保護

混淆簡單的說就是把程式用無意義的字串來取代
像是GetValue()=>AAA()
或是會加入一些不會影響結果的程式讓返組譯變得困難
像是For(int i=0;i<100;i++);
使用混淆保護的程式仍是可以使用反組譯工具看到混淆後的MSIL
且很容易被有心人反推回去的
像微軟自帶的Dotfuscator Community Edition好像已經有現成反推回去的程式在網路上流佈

若採用核級加密來保護
使用反組譯工具試圖去看MSIL時
會顯示不是CLR程式
無法看到反組譯過後的程式碼
有比混淆稍微安全些的感覺
類似的軟體有MaxToCode

硬體保護方面
像是有聖天狗、Aladdin等硬體加密鎖
Visual Studio 本身有一個 Dotfuscator Community Edition 可以用:
http://msdn.microsoft.com/zh-tw/library/ms227240.aspx

2012年10月2日 星期二

C# 使用 System.Data.SQLite

http://note.jhpeng.com/2010/12/c-%E4%BD%BF%E7%94%A8-systemdatasqlite.html

System.Data.SQLite
http://sqlite.phxsoftware.com/
檔案下載後, 解壓縮, 從中取得 System.Data.SQLite.dll
以下範例來自:http://www.javaeye.com/topic/114055
using
using System.Data.SQLite;
Connection和Command:
private SQLiteConnection conn;
private SQLiteCommand cmd;
連接db:
conn = new SQLiteConnection("Data Source=c:\\test.db");
conn.Open();
INSERT/UPDATE:
cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO user(email,name) VALUES ('email','name')";
cmd.ExecuteNonQuery();

cmd.CommandText = "UPDATE userSET name = 'Codelicious' WHERE ID = 1";
cmd.ExecuteNonQuery();
SELECT:
cmd.CommandText = "SELECT ID, name FROM user";
SQLiteDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine("ID: " + reader.GetInt16(0));
Console.WriteLine("name: " + reader.GetString(1));
}
} 

C# webbrowser对网页内容的缩放

http://social.msdn.microsoft.com/Forums/zh-CN/visualcshartzhchs/thread/23ce7cff-cda4-4fd4-87ce-98dd376e88ab
使用Visual C#2008自带的Webbrowser控件,怎么实现对网页中显示的内容的缩放呢
There appears to be a solution at IE Zoom that involves overriding AttachInterfaces and DetachInterfaces in the WebBrowser to get a IWebBrowser2 interface,
and  then calling ExecWB with OLECMDID_OPTICAL_ZOOM.
WinForm的WebBrowser缺少一个非常强大的方法ExecWB方法,用它可以做一些WebBrowser控件不能完成的功能,可以参看这个帖子:
http://stackoverflow.com/questions/738232/zoom-in-on-a-web-page-using-webbrowser-net-control
範例下載
https://skydrive.live.com/?cid=63c0c5f1723a3dc0&id=63C0C5F1723A3DC0%21172&sc=documents

2012年9月19日 星期三

安装Visual Studio 2010,Windows Driver Kits 7


Visual Studio 2010 With Windows Driver Kits 7 驱动环境配置 For XP/Vista/7

[ 驱动开发 ]  
348
0
+1
0


1.
安装Visual Studio 2010,Windows Driver Kits 7
2.新建VC控制台项目(选择为空项目)
3.新建项目配置“Driver”----
Build - Configuration Manager…      - Active Solution configuration
- <New...> Name="Driver"
           - Copy Setting from=Debug|Release [这里选择Debug]
View – Property Manager                - Driver | Win32 右键
                      - Add New Project Property Sheet
                      - Name="Driver" [可能是所有工程通用属性 - Can Try]
新生成的"Driver" - 右键 - Properties:
Genernal
Target Extension   = .sys
VC++ Directories
Include Directorie = D:\WINDDK\7600.16385.1\inc\ddk;D:\WINDDK\7600.16385.1\inc\api;D:\WINDDK\7600.16385.1\inc\crt;
Library Directories= D:\WINDDK\7600.16385.1\lib\wxp\i386;
C/C++
Genernal - Debug Information Format                         = Program Database (/Zi)                             /* 可选 [C7 compatible (/Z7)] */
    
Code Generation - Basic Runtime Checks                        = Default
     
Advanced - Calling Convention                                     = __stdcall (/Gz)
     
Preprocessor - Preprocessor Definitions                     = _X86_;DBG              
 [后面可以不要]=1;WIN32=100;WINVER=0x501;DBG=1;
 原因:提示—— 1>D:\WINDDK\7600.16385.1\inc\ddk\wdm.h(14197): fatal error C1189: #error :  "No target architecture defined"
#if !(defined(_X86_) || defined(_AMD64_) || defined(_IA64_))
#error "No target architecture defined"
#endif
     
Genernal - Treat Warnings As Errors        =Yes(/WX)        (警告信息变成错误信息:最大程序保障代码可靠性 /* 可选 */)
     
Code Generation - Enable Minimal Rebuild=No(/Gm-)若上面设置 [C7 compatible (/Z7)] 则必选
Compile As                        =[有时无需设置]Compile as C Code (/TC) [选中代码中不需加extern "C",不选则需加]
Linker
Genernal - Enable Incremental Linking                         = No (/INCREMENTAL:NO)
System - Subsystem                                         = Console (/SUBSYSTEM:CONSOLE)
Advanced - EntryPoint                                         = DriverEntry
Input - Additional Dependencies                                 = ntoskrnl.lib;wdm.lib;wdmsec.lib;wmilib.lib;ndis.lib;Hal.lib;MSVCRT.LIB;LIBCMT.LIB;

[C#][ASP.NET]如何使用Client Script呼叫Server Function


前幾天剛好有相關需求,自己打算使用ajax PageMethods來實現,這裡記錄備忘一下。
.aspx
image
TextBox:輸入使用者名稱
Label:顯示歡迎訊息
ScriptManager請設定EnablePageMethods="true"(asp.net ajax和ScriptManager是很親密的..XD)
 
Client Script(使用PageMethods呼叫Server Function時都要指定接收結果的JavaScript function)
               <script type="text/javascript">
             
           function CallServer(srcid,destid) {
             //取得來源控制項 Value
           var value = $("#" + srcid).val(); 
            //呼叫Server Function   
            PageMethods.Wellcome(value, OnSuccess, OnFailure, destid);
         }
            
          function OnSuccess(result, destid) {
             //成功時,目地控制項顯示所接收結果
               $("#" + destid).text(result);
             }
           
           function OnFailure(error, destid) {
             if (error != null) {
          alert(error.get_message()); 
               }    
               } 
         </script>


image
.aspx.cs
          [WebMethod]
                public static string Wellcome(string name)
              {
          if( string.IsNullOrEmpty( name ) )
            return string.Empty;
         else
             return "歡迎 " + name +" 參觀";
         }        


 記得要宣告成public static並加上[WebMethod]修飾詞。

           protected void Page_Load( object sender, EventArgs e )
            {
           if( !IsPostBack )
               {
           //當textbpx失去焦點時執行client script(callserver function)
              TextBox1.Attributes.Add( "onblur", "CallServer('" + TextBox1.ClientID + "','" + Label1.ClientID + "')" );            
               }
          }   


註冊client function到TextBox1的onblur事件上。

結果:
image
輸入姓名。

image
textbox失去焦點時,顯示歡迎訊息。