Monday, July 6, 2009

Cách chạy Crystal Report trên Windows Vista/7

Giới thiệu

Khi tôi chạy chương trình để hiển thị các báo cáo sử dụng Crystal Report XI trên Windows Vista hoặc Windows 7 thì luôn nhận được thông báo lỗi:

Description:
  Stopped working

Problem signature:
  Problem Event Name:    APPCRASH
  Application Name:    CRXISample.exe
  Application Version:    1.0.0.0
  Application Timestamp:    4a517191
  Fault Module Name:    unknown
  Fault Module Version:    0.0.0.0
  Fault Module Timestamp:    00000000
  Exception Code:    c0000005
  Exception Offset:    04b978c8
  OS Version:    6.1.7100.2.0.0.256.1
  Locale ID:    1041

Mô tả lỗi

Lỗi này xuất hiện do tính năng DEP (Data Execution Prevention) trên Windows Vista/7 khi được kích hoạt (enabled) thì sẽ ngăn chặn (block) tất cả các chương trình  đang cố gắng chạy mà không nằm trong danh sách tin cậy (trusted list).

Khắc phục lỗi

Lỗi này có thể được khắc phục bằng cách vô hiệu hóa tính năng DEP, tuy nhiên khi tính năng này được khóa thì có thể dẫn đến một số nguy hại đối với máy tính của bạn. Do đó, ở đây tôi sẽ đưa ra cách vô hiệu hóa tính năng này và có thể kích hoạt tính năng này nếu cần thiết.

Hình sau minh họa khi kích hoạt DEP và khi vô hiệu hóa DEP, ngầm định là DEP được kích hoạt.

DEP_Enabled DEP_Disabled

Kích hoạt DEP (Enabled)

1. Mở màn hình Command Prompt: Nhấn tổ hợp phím Windows+R; nhấn cmd và Enter.

2. Đánh dòng lệnh bcdedit.exe /set {current} nx OptIn và nhấn Enter.

3. Bạn có thể nhận được thông điệp báo thành công.

4. Khởi động lại máy.

Vô hiệu hóa DEP (Disabled)

1. Mở màn hình Command Prompt: Nhấn tổ hợp phím Windows+R; nhấn cmd và Enter.

2. Đánh dòng lệnh bcdedit.exe /set {current} nx AlwaysOff và nhấn Enter.

3. Bạn có thể nhận được thông điệp báo thành công.

4. Khởi động lại máy.

Kết luận

Cách vô hiệu hóa DEP có thể giúp nhiều chương trình chạy tốt trên môi trường Windows Vista hoặc Windows 7, tuy nhiên nó cũng có thể đem đến rắc rối với virus. Do đó, bạn nên cẩn thận khi sử dụng cách này.

Về Crystal Report bạn sẽ gặp vấn đề này trên hầu hết các phiên bản khi chạy trên Windows Vista hoặc Windows 7, tuy nhiên hiện nay phiên bản Crystal Report 2008 V1 (SP1) đã được khắc phục lỗi này. Do đó, bạn nên dùng CR 2008 V1 nếu có thể.

Friday, May 22, 2009

How to publish a ClickOnce Application without Visual Studio

When i search a solution for the question “How to change .exe.config.deploy”, i cannot have a good answer. So, i try to create my solution and it is successful.

In this solution, you can deploy a ClickOnce Application to customer’s server, it execute with requests:

  • Modify config in app.config, example: Connection String, Web Reference URL,…
  • Change start location of a signed ClickOnce Application.
  • Change Version of product.
  • Publish application without VS and .NET Framework SDK.
1. Create necessary files for ClickOnce Server

        To publish the ClickOnce Application to a server, you must have necessary files includes: MyApp.application (my application sample is MyApp), index.html and setup.exe.

        Open the source code in Visual Studio and publish ClickOnce Application to local IIS . Next, open  publish folder (C:\Inetpub\wwwroot\MyApp) and copy only files MyApp.application, index.html and setup.exe to the deployment folder (MyAppClickOnce). This folder will be provided the customer who will publish application to his server.

  2. Copy the contents of the application to the deployment folder

       Copy the contents of the application from the build output folder (bin\Release) to folder’s name [ApplicationName_Version(a_b_c_d)] to the deployment folder (MyAppClickOnce\MyApp_1_0_0_0).

       Copy the publisher certificate that was generated by Visual Studio when you first published to the deployment folder.

       Open folder [Microsoft Visual Studio 8]\SDK\v2.0\Bin and copy file mageui.exe  to the deployment folder.

       Now, you can compress the deployment folder to your customer with install guide and he should be install a ClickOnce Application without Visual Studio and .NET Framework SDK 2.0.

3. Publish application
  • Open mageui.exe, on menu File –> New –> Application Manifest.
  • In the tab “app1.exe.manifest”, select “Name” from list in the left, input name of application into Name textbox  (MyApp) and Version textbox (1.0.0.0).
  • In the tab “app1.exe.manifest”, select “Files” from list in the left,
    • At “Application directory:”, select folder containing the application files (MyApp_1_0_0_0) .
    • Click check on checkbox “When populating add the .deploy extension to any files that does not have it”.
    • Click button “Populate”.
  • On menu of mageui, select File –> Save.
    • In the screen “Signing Options”, select option “Sign with certificate file”, click button […] to select publisher certificate. Click OK to next.
    • In the screen “Save As”, save with default file name to folder containing application files (MyApp_1_0_0_0).
  • On menu of mageui, select File –> Open.
  • Select file MyApp.application in the deployment folder.
  • In the tab “MyApp.application”, select “Name” from list in the left, change Version to 1.0.0.0
  • In the tab “MyApp.application”, select “Deployment Options”, modify “Start Location” to new path or url of the current server.
  • In the tab “MyApp.application”, select “Application Reference”, click button “Select Manifest…” to select file manifest that is created above.
  • On menu of mageui, select File –> Save.
  • In the screen “Signing Options”, select option “Sign with certificate file”, click button […] to select publisher certificate. Click OK to save.

Now, you can install ClickOnce Application from new location.

P.S: I am sorry about my English. :)

Wednesday, May 6, 2009

Test-Driven Development (TDD) trong .NET bằng ví dụ – Phần 3

Phần này sẽ cài đặt các Test 3 và Test 4 trong loại bài về Test-Driven Development trong .NET qua ví dụ. Các phần trước bao gồm:

Test-Driven Development (TDD) trong .NET bằng ví dụ

Test-Driven Development (TDD) trong .NET bằng ví dụ – Phần 2

Test 3: Push một đối tượng đơn, Pop đối tượng đó và xác nhận IsEmpty là true.

Trong Test case này, ta thêm một phương thức mới cho lớp Stack có nhiệm vụ lấy ra phần tử trên đỉnh của Stack. Nhưng trước tiên, ta cần tiến thành cài đặt unit test cho test case này, đoạn code như sau:

    [Test]
    public void Pop()
    {
        stack.Push("first element");
        stack.Pop();
        Assert.IsTrue(stack.IsEmpty,
            "Sau khi Push - Pop. IsEmpty phải bằng true.");
    }

Và tất nhiên, ta phải cài đặt một phương thức Pop trong lớp Stack.

    public void Pop()
    {
    }

Tuy nhiên, nếu bây giờ bạn tiến hành complite và chạy test, thì sẽ trả về kết quả fail. Do đó, ta bổ sung thêm m_IsEmpty = true để hoàn thành test case này.

    public void Pop()
    {
        m_IsEmpty = true;
    }

Kết quả là chúng ta đã hoàn thành unit test cho Test case 3. Tiếp theo, ta sẽ cài đặt test case 4.

Test 4: Push một đối tượng đơn, ghi nhớ đối tượng đó; Pop đối tượng, và xác nhận hai đối tượng này là giống nhau.

Trong unit test của test case này, chúng ta sẽ thực hiện so sánh nội dung của 2 phần tử, đó là phần từ đưa vào Stack với phần tử lấy ra từ Stack ngay sau khi đưa vào. Do đó, ta sẽ đặt tên là PushPopContentCheck:

    [Test]
    public void PushPopContentCheck()
    {
        int expected = 1234;
        stack.Push(expected);   
        int actual = (int) stack.Pop();
        Assert.AreEqual(expected, actual);
    }

Tiếp theo, ta cần phải thay đổi lại phương thức Pop của lớp Stack.

    public object Pop()
    {
        m_IsEmpty = true;
        return null;
    }

Sau khi build thành công và chạy test, thì kết quả test trả về sẽ error vì lúc này ta chưa trả về giá trị trên đỉnh của Stack. Do đó, để pass cho unit test này, chúng ta lưu lại giá trị nhận được từ Push và trả lại giá trị trong Pop. Đoạn code sau khi thay đổi sẽ như sau:

using System;

public class Stack
{
    private bool m_IsEmpty = true;
    private object m_Element;

    public bool IsEmpty
    {
        get {
            return m_IsEmpty;
        }
    }

    public void Push(object element)
    {
        m_IsEmpty = false;
        m_Element = element;
    }

    public object Pop()
    {
        m_IsEmpty = true;
        object top = m_Element;
        m_Element = null;
        return top;
    }
}

Lúc này, ta thấy phương thức IsEmpty chỉ cần kiểm tra xem phần tử đang được lưu có bằng null hay không. Do đó, ta sẽ thay đổi ở phương thức IsEmpty như sau:

using System;

public class Stack
{
    private object m_Element = null;

    public bool IsEmpty
    {
        get {
            return (m_Element == null);
        }
    }

    public void Push(object element)
    {
        m_Element = element;
    }

    public object Pop()
    {
        object top = m_Element;
        m_Element = null;
        return top;
    }
}

Lúc này đã tốt hơn với code của Stack vì ta thấy rằng lúc này chỉ cần cập nhập lại một biến thay vì hai như trước đây.  Đến lúc này, khi thực hiện đưa vào 1 phần tử thì nó vẫn nằm trên đỉnh của Stack vì lúc lấy ra ta lấy đúng phần tử đã đưa vào. Tuy nhiên, sẽ có vấn đề lúc đưa nhiều hơn 1 phần từ vào Stack, ta sẽ được thấy điều này qua các test case tiếp theo.