# C# Guide:  Making DLL's



## char[] rager (Feb 14, 2011)

*Steps to making a dynamic-link library (dll) in Visual Studio:*

Make sure your project configuration is in "Release" and not "Debug"
It is a good idea to have your platform target set to "Any CPU"
When you make a new project, instead of "Windows Form Application" or "Empty Project," choose "Class Library" instead
Whatever name you give it will be the name of your namespace, so name it something you will remember
Proceed to make a class like your normally would if you were making a class to be used in a main
When you are done with your code, press F6 to build it
It is important to remember that you can not "run" this code, becuase it is a library, not a program
In the program that you plan on calling the DLL you just made from, in the solution explorer, right-click on the name of your project
Click on "Add Reference"
Click the "Browse" tab
Find your DLL. It will be in whatever folder you stored the DLL in. In that folder, double click the "bin", then "release" then click once on your DLL
Click on "OK" at the bottom of the "Add Reference, Browse Tab" dialog
Now, you are ready to call that DLL from whatever program you wish

I will include code from a calculator that I am making in Visual Studio. This calculator is not finished yet, and is designed around the user not having to press many buttons with the mouse.

This code is not commented a lot, because it is designed for people who already have some working knowledge of C Sharp (C#).

*Code In My NumberSystemsConversion.dll:*

```
using System;

namespace NumberSystemsConversion
{
    public class NumberSystem
    {
        public string BinaryToDecimal(string binaryInput)
        {
            int length;
            double answer = 0.0;

            length = binaryInput.Length - 1;

            foreach (char letter in binaryInput)
            {
                answer += Math.Pow(2.0, length) * char.GetNumericValue(letter);

                length--;
            }

            return Convert.ToString(answer);
        }

        public string DecimalToBinary(string decimalInput)
        {
            int temporaryHolder, integer = int.Parse(decimalInput);
            double temporaryDouble;
            string binarySequence = "";

            while (integer >= 1)
            {
                temporaryHolder = integer / 2;

                temporaryDouble = Convert.ToDouble(integer / 2.0);

                if (temporaryDouble - Math.Floor(temporaryDouble) > 0.0)
                {
                    binarySequence += "1";
                }

                else
                {
                    binarySequence += "0";
                }

                integer = temporaryHolder;
            }

            char[] reverseBinarySequence = binarySequence.ToCharArray();

            Array.Reverse(reverseBinarySequence);

            return new string(reverseBinarySequence);
        }

        public string HexToBinary(string hexInput)
        {
            string newHexString = "";

            foreach (char letter in hexInput)
            {
                switch (letter)
                {
                    case '0':
                        newHexString += "0000";
                        break;

                    case '1':
                        newHexString += "0001";
                        break;

                    case '2':
                        newHexString += "0010";
                        break;

                    case '3':
                        newHexString += "0011";
                        break;

                    case '4':
                        newHexString += "0100";
                        break;

                    case '5':
                        newHexString += "0101";
                        break;

                    case '6':
                        newHexString += "0110";
                        break;

                    case '7':
                        newHexString += "0110";
                        break;

                    case '8':
                        newHexString += "1000";
                        break;

                    case '9':
                        newHexString += "1001";
                        break;

                    case 'A':
                        newHexString += "1010";
                        break;

                    case 'B':
                        newHexString += "1011";
                        break;

                    case 'C':
                        newHexString += "1100";
                        break;

                    case 'D':
                        newHexString += "1101";
                        break;

                    case 'E':
                        newHexString += "1110";
                        break;

                    case 'F':
                        newHexString += "1111";
                        break;
                }
            }

            return newHexString;
        }

        public string HexToDecimal(string hexInput)
        {
            string hexToBinary = HexToBinary(hexInput.ToUpper());

            string hexToDecimal = Convert.ToString(BinaryToDecimal(hexToBinary));

            return Convert.ToString(hexToDecimal);
        }

        public string DecimalToHex(string decimalInput)
        {
            int temporaryHolder, integer = int.Parse(decimalInput);
            double temporaryDouble;
            string temporaryRemainder, binarySequence = "";

            while (integer >= 1)
            {
                temporaryHolder = integer / 16;

                temporaryDouble = Convert.ToDouble(integer / 16.0);

                temporaryRemainder = Convert.ToString(temporaryDouble - Math.Floor(temporaryDouble));

                switch (temporaryRemainder)
                {
                    case "0":
                        binarySequence += "0";
                        break;
                    
                    case "0.0625":
                        binarySequence += "1";
                        break;

                    case "0.125":
                        binarySequence += "2";
                        break;

                    case "0.1875":
                        binarySequence += "3";
                        break;

                    case "0.25":
                        binarySequence += "4";
                        break;

                    case "0.3125":
                        binarySequence += "5";
                        break;

                    case "0.375":
                        binarySequence += "6";
                        break;

                    case "0.4375":
                        binarySequence += "7";
                        break;

                    case "0.5":
                        binarySequence += "8";
                        break;

                    case "0.5625":
                        binarySequence += "9";
                        break;

                    case "0.625":
                        binarySequence += "A";
                        break;

                    case "0.6875":
                        binarySequence += "B";
                        break;

                    case "0.75":
                        binarySequence += "C";
                        break;

                    case "0.8125":
                        binarySequence += "D";
                        break;

                    case "0.875":
                        binarySequence += "E";
                        break;

                    case "0.9375":
                        binarySequence += "F";
                        break;
                }

                integer = temporaryHolder;
            }

            char[] reverseBinarySequence = binarySequence.ToCharArray();

            Array.Reverse(reverseBinarySequence);

            return new string(reverseBinarySequence);
        }

        public string BinaryToHex(string binaryInput)
        {
            string decimalString = BinaryToDecimal(binaryInput);

            return DecimalToHex(decimalString);
        }

        public string OctalToDecimal(string binaryInput)
        {
            int length;
            double answer = 0.0;

            length = binaryInput.Length - 1;

            foreach (char letter in binaryInput)
            {
                answer += Math.Pow(8.0, length) * char.GetNumericValue(letter);

                length--;
            }

            return Convert.ToString(answer);
        }

        public string DecimalToOctal(string decimalInput)
        {
            int temporaryHolder, integer = int.Parse(decimalInput);
            double temporaryDouble;
            string temporaryRemainder, binarySequence = "";

            while (integer >= 1)
            {
                temporaryHolder = integer / 8;

                temporaryDouble = Convert.ToDouble(integer / 8.0);

                temporaryRemainder = Convert.ToString(temporaryDouble - Math.Floor(temporaryDouble));

                switch (temporaryRemainder)
                {
                    case "0":
                        binarySequence += "0";
                        break;
                    
                    case "0.125":
                        binarySequence += "1";
                        break;

                    case "0.25":
                        binarySequence += "2";
                        break;

                    case "0.375":
                        binarySequence += "3";
                        break;

                    case "0.5":
                        binarySequence += "4";
                        break;

                    case "0.625":
                        binarySequence += "5";
                        break;

                    case "0.75":
                        binarySequence += "6";
                        break;

                    case "0.875":
                        binarySequence += "7";
                        break;
                }

                integer = temporaryHolder;
            }

            char[] reverseBinarySequence = binarySequence.ToCharArray();

            Array.Reverse(reverseBinarySequence);

            return new string(reverseBinarySequence);
        }

        public string BinaryToOctal(string binaryInput)
        {
            string decimalEquivalent = BinaryToDecimal(binaryInput);

            return DecimalToOctal(decimalEquivalent);
        }

        public string HexToOctal(string hexInput)
        {
            string decimalEquivalent = HexToDecimal(hexInput);

            return DecimalToOctal(decimalEquivalent);
        }

        public string OctalToBinary(string octalInput)
        {
            string decimalEquivalent = OctalToDecimal(octalInput);

            return DecimalToBinary(decimalEquivalent);
        }

        public string OctalToHex(string octalInput)
        {
            string decimalEquivalent = OctalToDecimal(octalInput);

            return DecimalToHex(decimalEquivalent);
        }

        public string OnesComplement(string input)
        {
            string new_string = "";
            
            foreach (char letter in input)
            {
                switch(letter)
                {
                    case '0':
                        new_string += "1";
                        break;

                    case '1':
                        new_string += "0";
                        break;
                }
            }

            return new_string;
        }

        public string TwosComplement(string input)
        {
            int index;
            string corrected = "", non_corrected = "";

            index = input.LastIndexOf('1');

            for (int counter = index; counter <= input.Length - 1; counter++)
            {
                non_corrected += input[counter];
            }

            for (int counter = 0; counter < index; counter++)
            {
                switch (input[counter])
                {
                    case '0':
                        corrected += "1";
                        break;

                    case '1':
                        corrected += "0";
                        break;
                }
            }

            return corrected + non_corrected;
        }
    }
}
```

*Code in my ArithmeticOperations.dll:*

```
using System;

namespace ArithmeticOperations
{
    public class Operation
    {
        public string Add(string firstValue, string secondValue)
        {
            return Convert.ToString(double.Parse(firstValue) + double.Parse(secondValue));
        }

        public string Subtract(string firstValue, string secondValue)
        {
            return Convert.ToString(double.Parse(firstValue) - double.Parse(secondValue));
        }

        public string Multiply(string firstValue, string secondValue)
        {
            return Convert.ToString(double.Parse(firstValue) * double.Parse(secondValue));
        }

        public string Divide(string firstValue, string secondValue)
        {
            return Convert.ToString(double.Parse(firstValue) / double.Parse(secondValue));
        }

        public string MakeNegative(string firstValue)
        {
            return Convert.ToString(double.Parse(firstValue) * -1.0);
        }

        public string SquareRoot(string firstValue)
        {
            return Convert.ToString(Math.Sqrt(double.Parse(firstValue)));
        }

        public string Power(string baseNumber, string exponent)
        {
            return Convert.ToString(Math.Pow(double.Parse(baseNumber), double.Parse(exponent)));
        }

        public string Factorial(string firstValue)
        {
            if (decimal.Parse(firstValue) > 27) return "Result too large to handle";
            if (decimal.Parse(firstValue) == 0) return Convert.ToString(1);
            else return Convert.ToString(decimal.Parse(firstValue) * decimal.Parse(Factorial(Convert.ToString(decimal.Parse(firstValue) - 1))));
        }
    }
}
```

*Code in my Calculator project code/main:*

```
using ArithmeticOperations; // namespace in my arithmetic dll
using NumberSystemsConversion; // namespace in my number systems dll
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Calculator
{
    public partial class Form1 : Form
    {
        Operation operation = new Operation(); // make an object from the operation class
        NumberSystem convert = new NumberSystem(); // make an object from the numbersystem class

        bool addPressed, subtractPressed, multiplyPressed, dividePressed;
        int index; 
        long binary_one, binary_two, binary_answer;

        public Form1()
        {
            InitializeComponent();
        }

        // Make a function to contain code that is used a lot
        // throughout this program, this function is unnecessary in using
        // a dll
        private void NumberSystemsConversionProcess()
        {
            try
            {   
                // these show how powerful a dll can be, i just call the methods
                // contained in my dll like i would call a class
                if (radioButtonBinToDec.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.BinaryToDecimal(textBoxNumberTop.Text);
                }

                if (radioButtonBinToHex.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.BinaryToHex(textBoxNumberTop.Text);
                }

                if (radioButtonBinToOct.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.BinaryToOctal(textBoxNumberTop.Text);
                }

                if (radioButtonDecToBin.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.DecimalToBinary(textBoxNumberTop.Text);
                }

                if (radioButtonDecToHex.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.DecimalToHex(textBoxNumberTop.Text);
                }

                if (radioButtonDecToOct.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.DecimalToOctal(textBoxNumberTop.Text);
                }

                if (radioButtonHexToBin.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.HexToBinary(textBoxNumberTop.Text);
                }

                if (radioButtonHexToDec.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.HexToDecimal(textBoxNumberTop.Text);
                }

                if (radioButtonHexToOct.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.HexToOctal(textBoxNumberTop.Text);
                }

                if (radioButtonOctToBin.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.OctalToBinary(textBoxNumberTop.Text);
                }

                if (radioButtonOctToDec.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.OctalToDecimal(textBoxNumberTop.Text);
                }

                if (radioButtonOctToHex.Checked)
                {
                    textBoxNumberAnswerTop.Text = convert.OctalToHex(textBoxNumberTop.Text);
                }
            }

            catch (FormatException)
            {
                MessageBox.Show("Incorrect Format");
            }
        }

        private void buttonPerformOperation_Click(object sender, EventArgs e)
        {
            try
            {
                if (addPressed)
                {
                    index = textBoxFirst.Text.IndexOf('+');
                    textBoxFirst.Text = textBoxFirst.Text.Substring(0, index);

                    // using a dll method/function here
                    textBoxThird.Text = operation.Add(textBoxFirst.Text, textBoxSecond.Text);
                }

                if (subtractPressed)
                {
                    index = textBoxFirst.Text.IndexOf('-');
                    textBoxFirst.Text = textBoxFirst.Text.Substring(0, index);

                    // using a dll method/function here
                    textBoxThird.Text = operation.Subtract(textBoxFirst.Text, textBoxSecond.Text);
                }

                if (multiplyPressed)
                {
                    index = textBoxFirst.Text.IndexOf('*');
                    textBoxFirst.Text = textBoxFirst.Text.Substring(0, index);

                    // using a dll method/function here
                    textBoxThird.Text = operation.Multiply(textBoxFirst.Text, textBoxSecond.Text);
                }

                if (dividePressed)
                {
                    index = textBoxFirst.Text.IndexOf('/');
                    textBoxFirst.Text = textBoxFirst.Text.Substring(0, index);

                    // using a dll method/function here
                    textBoxThird.Text = operation.Divide(textBoxFirst.Text, textBoxSecond.Text);
                }

                textBoxFirst.Focus();
                textBoxFirst.SelectAll();
            }

            catch (ArgumentOutOfRangeException)
            {
                textBoxThird.Text = "Incorrect Format";
            }

            catch (FormatException)
            {
                textBoxThird.Text = "Incorrect Format";
            }
        }

        private void buttonAdd_Click(object sender, EventArgs e)
        {   
            textBoxSecond.Focus();
            textBoxSecond.SelectAll();
            
            addPressed = true;
            subtractPressed = false;
            multiplyPressed = false;
            dividePressed = false;
        }

        private void buttonSubtract_Click(object sender, EventArgs e)
        {
            textBoxSecond.Focus();
            textBoxSecond.SelectAll();

            addPressed = false;
            subtractPressed = true;
            multiplyPressed = false;
            dividePressed = false;
        }

        private void buttonMultiply_Click(object sender, EventArgs e)
        {
            textBoxSecond.Focus();
            textBoxSecond.SelectAll();

            addPressed = false;
            subtractPressed = false;
            multiplyPressed = true;
            dividePressed = false;
        }

        private void buttonDivide_Click(object sender, EventArgs e)
        {
            textBoxSecond.Focus();
            textBoxSecond.SelectAll();

            addPressed = false;
            subtractPressed = false;
            multiplyPressed = false;
            dividePressed = true;
        }

        private void buttonFactorial_Click(object sender, EventArgs e)
        {
            try
            {
                // using a dll method/function here
                textBoxFirst.Text = operation.Factorial(textBoxFirst.Text);
                
                textBoxFirst.Focus();
                textBoxFirst.SelectAll();
            }

            catch (FormatException)
            {
                textBoxThird.Text = "Incorrect Format";
            }
        }

        private void buttonSquareRoot_Click(object sender, EventArgs e)
        {
            try
            {
                // using a dll method/function here
                textBoxFirst.Text = operation.SquareRoot(textBoxFirst.Text);

                textBoxFirst.Focus();
                textBoxFirst.SelectAll();
            }

            catch (FormatException)
            {
                textBoxThird.Text = "Incorrect Format";
            }
        }

        private void buttonPower_Click(object sender, EventArgs e)
        {
            try
            {
                // using a dll method/function here
                textBoxThird.Text = operation.Power(textBoxFirst.Text, textBoxSecond.Text);
            }

            catch (FormatException)
            {
                textBoxThird.Text = "Incorrect Format";
            }
        }

        private void textBoxFirst_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '+')
            {
                buttonAdd.PerformClick();
            }
            
            if (e.KeyChar == '-')
            {
                buttonSubtract.PerformClick();
            }
            
            if (e.KeyChar == '*')
            {
                buttonMultiply.PerformClick();
            }

            if (e.KeyChar == '/')
            {
                buttonDivide.PerformClick();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            radioButtonBinToDec.Checked = true;
            textBoxNumberTop.Text = "0";
        }

        private void tabPage1_Enter(object sender, EventArgs e)
        {
            AcceptButton = buttonPerformOperation;
        }

        private void tabPage2_Enter(object sender, EventArgs e)
        {
            AcceptButton = buttonNumberPerformOperation;
        }

        private void textBoxNumberTop_TextChanged(object sender, EventArgs e)
        {
            // everytime the text changes, i call the function that i made at the top
            // otherwise, i would have to copy all of that code into this "textchanged" event
            NumberSystemsConversionProcess();
        }

        private void buttonNumberPerformOperation_Click(object sender, EventArgs e)
        {
            // everytime the text changes, i call the function that i made at the top
            // otherwise, i would have to copy all of that code into this "textchanged" event
            NumberSystemsConversionProcess();
        }

        private void buttonNumberAdd_Click(object sender, EventArgs e)
        {
            // using a dll method/function here
            // extra "code" is here because I do not have any method in my numbersystems
            // dll that add, subtracts, multiplies, or divides binary numbers,
            // this should show you what starts to happen
            // if you don't put code into a dll, you get more code taking space
            // in your main
            binary_one = int.Parse(convert.BinaryToDecimal(textBoxNumberTop.Text));
            binary_two = int.Parse(convert.BinaryToDecimal(textBoxNumberBottom.Text));

            binary_answer = binary_one + binary_two;
        
            textBoxNumberAnswerTop.Text = convert.DecimalToBinary(Convert.ToString(binary_answer));
        }

        private void buttonNumberSubtract_Click(object sender, EventArgs e)
        {
            binary_one = int.Parse(convert.BinaryToDecimal(textBoxNumberTop.Text));
            binary_two = int.Parse(convert.BinaryToDecimal(textBoxNumberBottom.Text));

            binary_answer = Math.Abs(binary_one - binary_two);

            if ((binary_one - binary_two) < 0)
            {
                textBoxNumberAnswerTop.Text = "Negative " + convert.DecimalToBinary(Convert.ToString(binary_answer));
            }
            else
            {
                textBoxNumberAnswerTop.Text = convert.DecimalToBinary(Convert.ToString(binary_answer));
            }
        }

        private void buttonNumberMultiply_Click(object sender, EventArgs e)
        {
            binary_one = int.Parse(convert.BinaryToDecimal(textBoxNumberTop.Text));
            binary_two = int.Parse(convert.BinaryToDecimal(textBoxNumberBottom.Text));

            binary_answer = binary_one * binary_two;

            textBoxNumberAnswerTop.Text = convert.DecimalToBinary(Convert.ToString(binary_answer));
        }

        private void buttonNumberDivide_Click(object sender, EventArgs e)
        {
            binary_one = int.Parse(convert.BinaryToDecimal(textBoxNumberTop.Text));
            binary_two = int.Parse(convert.BinaryToDecimal(textBoxNumberBottom.Text));

            binary_answer = binary_one / binary_two;

            textBoxNumberAnswerTop.Text = convert.DecimalToBinary(Convert.ToString(binary_answer));
        }

        private void buttonOnesComplement_Click(object sender, EventArgs e)
        {
            // using a dll method/function here
            textBoxNumberAnswerTop.Text = convert.OnesComplement(textBoxNumberTop.Text);
        }

        private void buttonTwosComplement_Click(object sender, EventArgs e)
        {
            // using a dll method/function here
            textBoxNumberAnswerTop.Text = convert.TwosComplement(textBoxNumberTop.Text);
        }
    }
}
```

EDIT:  Complete now


----------



## W1zzard (Feb 14, 2011)

are those exports decorated somehow or can i loadlibrary/getprocaddress import them from a non-.net language?


----------



## char[] rager (Feb 14, 2011)

You got me w1zzard. I thought that making dlls was simple, guess not...

To be honest, I don't know what you are asking. I think you are asking if these dlls can be ran from a non .net language. The answer is probably not as some of my methods include foreach loops, which I believe is only .net.

I am only teaching myself this stuff because, my school is getting us into win32 api programming.


----------



## W1zzard (Feb 14, 2011)

send me the release build of one of those dlls to w1zzard@techpowerup.com


----------



## char[] rager (Feb 14, 2011)

I am on my phone now since I am in a classroom that we are not using computers right now.

I will send it to you later on today. Do you have a preference as to which one?


----------



## W1zzard (Feb 14, 2011)

nah makes no difference, just want to take a look at the exports


----------



## char[] rager (Feb 14, 2011)

I just sent one to you.


----------



## W1zzard (Feb 14, 2011)

thanks. the dll doesnt seem to have any exports in a classical dll sense.
there's probably some magic that needs to added to export functions to non .net apps


----------



## FordGT90Concept (Feb 14, 2011)

I think you have to make it COM Visible for non-.NET to load a .NET library.

Once you have your DLL, expand the Properties portion of the project in the Solution Explorer.  Open AssemblyInfo.cs under there.  Change [assembly: ComVisible(false)] to [assembly: ComVisible(true)].  It should work then.


----------



## ctrain (Feb 15, 2011)

W1zzard said:


> thanks. the dll doesnt seem to have any exports in a classical dll sense.
> there's probably some magic that needs to added to export functions to non .net apps



nope, you can't just load .net dll's like a native one... i think i remember being able to start .net within your native program and going from there. haven't wrote anything .net in 500 years so..

edit: i found it, it deals with dll injection but still relevant-ish.
http://www.codingthewheel.com/archives/how-to-inject-a-managed-assembly-dll


----------



## Kreij (Feb 15, 2011)

FXCop will fuss if you make the whole assembly COM visible. Not best practices.
Of course FXCop fusses about a whole lot of stuff that my or may not be relevant depending upon what you are doing with your assemblies.


----------

