35

프로그래밍을 하다보면

부팅할때 프로그램을 같이 시작해야 할 때가 있습니다

 

이럴때 가장 확실하고 간단한 방법은 레지스트리에 등록하는 겁니다

당연히 아무 레지스트리에나 등록한다고 되는 것은 아니고

부팅시 시작 프로그램을 등록하는 레지스트리 경로에 등록해줘야 하겠죠

 

이제 실제 구현 하면서 알아보도록 합시다 ㅇ_ㅇ

 

 

1. 먼저 Main Form(여기서는 AutoStartTestForm)에 버튼 두개를 등록하고 각각 Click이벤트를 만들어 줍니다

 

2. 아래와 같이 코드를 작성해 줍니다

namespace BlogTest
{
    public partial class AutoStartTestForm : Form
    {
        public AutoStartTestForm()
        {
            InitializeComponent();
        }


        private void BtnRegStart_Click(object sender, EventArgs e)
        {
            AddStartupProgram("AutoStartTestForm", Application.ExecutablePath);
        }

        private void BtnUnRegStart_Click(object sender, EventArgs e)
        {
            RemoveStartupProgram("AutoStartTestForm");
        }


        // 부팅시 시작 프로그램을 등록하는 레지스트리 경로
        private static readonly string _startupRegPath =
            @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";

        private Microsoft.Win32.RegistryKey GetRegKey(string regPath, bool writable)
        {
            return Microsoft.Win32.Registry.CurrentUser.OpenSubKey(regPath, writable);
        }

        // 부팅시 시작 프로그램 등록
        public void AddStartupProgram(string programName, string executablePath)
        {
            using (var regKey = GetRegKey(_startupRegPath, true))
            {
                try
                {
                    // 키가 이미 등록돼 있지 않을때만 등록
                    if (regKey.GetValue(programName) == null)
                        regKey.SetValue(programName, executablePath);

                    regKey.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

        // 등록된 프로그램 제거
        public void RemoveStartupProgram(string programName)
        {
            using (var regKey = GetRegKey(_startupRegPath, true))
            {
                try
                {
                    // 키가 이미 존재할때만 제거
                    if (regKey.GetValue(programName) != null)
                        regKey.DeleteValue(programName, false);

                    regKey.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }
}

 

3. 레지스트리에 등록 되는지 확인!

Before
After (AutoStartTestForm로 등록된걸 알 수 있다)

 

4. 컴퓨터 재시작해서 확인

 

코드 설명을 자세히 하려고 했습니다만...

코드도 짧고 메서드명도 직관적이라 간단한 주석만 달고 생략 했습니다

사실 레지스트리 경로만 알면 등록, 해제가 끝이거든요

 

혹시라도 질문 있으시면 댓글달아주세요~

윈폼을 이용해 프로그램을 만들었을때, 프로그램을 한개만 실행되도록 해야 할때가 있습니다

이런 경우 C#의 뮤텍스(mutex) 클래스를 이용해 프로그램의 중복 실행을 막을 수 있습니다

 

뮤텍스(mutex)는 상호 배제(mutual exclusion)의 약자로 프로세스나 스레드등이 동시에 접근해서는 안되는 공유영역을 뜻합니다

C#에서는 Mutex클래스를 제공해서 비교적 쉽게 구현할수 있죠

 

그럼 바로 구현해보도록 하겠습니다

 

먼저 중복실행을 방지할 프로젝트의 Program.cs를 엽니다

 

그 다음 Program.cs의 소스코드를 아래와 같이 바꿔줍니다

namespace TestFrm
{
    static class Program
    {
        /// <summary>
        /// 해당 애플리케이션의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            bool flagMutex;

            System.Threading.Mutex m_hMutex = new System.Threading.Mutex(true, "TestFrm", out flagMutex);
            if (flagMutex)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                // 실행할 Form 클래스
                Application.Run(new Form1());
                m_hMutex.ReleaseMutex();
            }
            else
            {
                // 여러개 실행시켰을때 띄울 메시지
                MessageBox.Show("프로그램이 이미 실행 중입니다", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

 

프로그램 중복 실행시 아래와 같이 나온다면 성공입니다

아시는분은 아시겠지만 지난달 알리익스프레스에서 대대적인 할인행사가 있었습니다

할인 쿠폰 이것저것 받아 놓긴 했지만 정작 살게 없어서 잊고 지내던 어느날...

 

스폰지밥 삼대장

이 사진을 발견하고 말았습니다

 

사실 원피스는 그다지 좋아하지 않는데, 스폰지밥을 좋아해서 급격하게 뽐이 오더군요

결국 알리에서 검색 노가다로 발견!

대륙에는 없는게 없다

아쉽게도 집게센고쿠와 황금뚱이는 없었지만

중요 삼인방은 다 있어서 구입 결정

쿠폰 이것저것 써서 3개, 66.38 달러에 주문완료

달러환율이 올라서 가슴 아프지만 어쩔수 없죠...

 

배송은 3월 31일 주문, 4월 18일 도착했습니다

코로나 때문에 배송 더 늦어질거라 예상했는데 빨리 도착해서 다행이었습니다

 

 

사실 사진에는 잘 안보이지만, 미세한 스크래치가 있고 도색 퀄도 그다지 좋지는 않습니다

의자 다리도 바닥에 완벽히 닿지는 않고 몇개가 뜨고요

 

그래도 가격도 생각보다 저렴하고 어차피 책장에 놓고 관상용으로만 둘 예정이라 크게 신경 쓰이지는 않습니다.

셀러 주소는 괜한 오해사기 싫어서 올리지는 않겠습니다

구입 원하시면 올린 사진에 있는 검색어 입력하면 셀러 여럿나오니 구입하시면 될듯합니다

아, 그리고 종이박스 퀄 안 좋으니 박스는 구입 안 하시는걸 추천드려요

 

'My Life > 취미' 카테고리의 다른 글

XBOX ONE 엘리트 패드 범퍼 버튼 수리기  (0) 2020.03.13

정식 발매하고 얼마 안 지났을때 국전 한우리에서 구매했던 엘리트 패드가 드디어 고장이 났습니다 .

증상은 RB 범퍼 버튼이 제대로 눌리지 않는것.

 

엘리트 패드의 고질적인 문제라 예전부터 알고는 있었지만 막상 닥치니까 당황스럽습니다.

그렇다고 이 비싼 패드를 겨우 부품 하나때문에 안쓸수도 없으니 DIY 수리를 결심!

 

정품부품 구하고 싶었지만 구하기도 쉽지않고, 비싸고, 무엇보다 또 고장날수 있으니

그냥 알리에서 대체부품(짭)을 구입해서 교체 하기로 했습니다.

 

준비물은 별드라이버(T8), 분리할때 사용할 기타픽 비슷하게 생긴 따개(?) <- 죄송합니다 정식명칭을 모르겠네요;

 

알리에서 구매한 제품

가운데 부품까지 포함돼 있는걸로 3개 구매했습니다.

한국까지 배송료 포함 8.89달러(약 11000원) 이 들었네요.

 

위에 말한 준비물까지 포함해서 파는 셀러도 있으니 필요에 따라 구매하시기 바랍니다.

저는 이미 다 있는거라 교체품만 구매했어요.

 

도착한 부품들

드디어 부품이 도착했습니다.

그런데 역시 짭이라 그런지 약간 스크래치도 있고, 무엇보다 색상이 약간 다릅니다.

뭐 이것도 감안하고 산거니 그러려니 넘어가도록 합시다.

 

분해전 썸스틱등 부품 제거

분해에 앞서 썸스틱, 방향키 덮개를 제거하도록 합니다.

 

배터리 커버 제거

이제 본격적으로 분해해 보도록 합시다.

먼저 배터리 커버를 벗깁니다.

그리고 사진에는 없지만 가운데 나사 위로 제품정보가 적힌 검은색 스티커가 있습니다.

그것도 제거해 주세요.

그러면 사진처럼 가운데에 별나사가 나오는데 별 드라이버를 이용해 제거해 주세요.

 

사이드 그립 제거

이제 양쪽의 사이드 그립을 제거해야 합니다.

기타픽(?)을 트리거 버튼 밑의 공간에 넣고 힘을 줘서 분리하도록 합시다.

놀랍게도 저 사이드 그립은 양면테이프;;로 고정돼 있어서 힘을 꽤나 줘야 빠집니다.

중간에 부러뜨려 먹을까봐 걱정했는데 의외로 튼튼하더라구요.

 

사이드 그립 분리한 모습

이제 사이드 그립을 분리하면 안에 별 나사로 고정된 부분이 보입니다.

위에 적었다시피 테이프는 제가 붙인게 아니라 원래 저렇게 생겨먹었어요.

10만원 넘게 쓴 고오오오오오급 패드가 저리 돼 있다니 꽤나 충격입니다.

 

어쨌든 사진의 빨간색 부분에 나사가 있으니 빼주세요.

각도 때문에 안 보이는데 실제로 보면 색이 확 튀어서 잘보여요.

 

커버 제거

나사를 모두 제거하면 패드 커버는 자연스럽게 빠집니다.

그리고 빨간색으로 표시한 부분을 위로 살짝 들여올려서 범퍼를 분리하세요.

 

위(원래 부품), 아래(교체품)

범퍼를 분리하고나서 비교한 모습입니다.

역시나 범퍼가 부러져 있습니다.

그나저나 정품은 흰색인데 가품은 검게 돼 있네요.

이제 교체품으로 분해의 역순으로 다시 조립하면 됩니다.

분해도 했으니, 어렵지 않게 하실수 있을겁니다.

 

교체 완료!

교체를 완료한 모습입니다.

역시 범퍼 색깔이 살짝 튀네요;

 

교체후 테스트겸 몬헌 4시간 돌렸는데, 클릭감은 정품과 크게 다르지 않습니다.

색상 빼고는 사용감이 정품과 크게 다르지 않습니다.

좀더 돌려봐야 겠지만 현재로서는 만족!

 

추가로 직접 교체하시고 싶으신 분은 유튜브에서 동영상 한번 보시고 참고하시는것도 좋을듯 합니다.

제가 참고했던 동영상 링크는 아래에 달아 놓을게요.

 

이글이 도움이 되셨다면 짧게나마 댓글 부탁드립니다 ^^

 

 

 

https://www.youtube.com/watch?v=MR6TuCnV0k8

'My Life > 취미' 카테고리의 다른 글

원피스×스폰지밥 삼대장 피규어 구입후기  (0) 2020.04.27

오래전 숫자가 포함된 문자 배열을 정렬 할때 1다음에 10이오는걸 보고 당황한 적이 있습니다.

 

 

Array.Sort를 했음에도 제대로 정렬되지 않는다

 

바로 위 그림처럼 말이죠.

Array.Sort메서드로 정렬을 했음에도 불구하고 1다음에 10이오고, 2다음에 20이 오는등 원하던대로 정렬 되지 않습니다.

 

 

이건 프로그램 입장에선 당연한 겁니다. 왜냐하면 '문자열'을 기준으로 비교하는 거니까요.

사람이야 저게 숫자니까 1다음에 2가 오는게 맞다고 생각하지만, 프로그램은 저걸 '문자'로 인식하고 정렬 합니다.

 

 

사실 기존 Array.Sort를 사용하면서 숫자 정렬 하는 방법이 있긴합니다.

그냥 숫자 앞에 0을 붙여줘서 01, 02 ··· 이런식으로 자리수를 맞춰주면 되죠.

하지만 이 방법은 파일이름을 일일이 바꿔줘야 하고

파일이 수백, 수천개가 되면 자리수를 맞추기위해 앞에 0을 계속 붙여줘야 하는 문제가 있습니다.

따라서 이 글에서는 다른 방식으로 해결해 보겠습니다.

 

 

이 문제를 해결하기 위해서는 ArraySort메서드를 좀더 살펴봐야 합니다.

Array.Sort 메서드는 IComparer 인터페이스를 구현한 클래스를 대상으로, IComparer의 구현대로 정렬을 시행합니다.

하지만 기존 String클래스의 IComparer로는 우리가 원하는대로 정렬할수 없습니다.

 

 

그렇다면 숫자를 고려하여 정렬 하기 위해서는 어떻게 해야 할까요?

사실 Array.Sort 메서드에는 직접 구현한 IComparer을 사용할수 있게 오버로드가 되어 있습니다.

그렇다면 숫자까지 고려한 IComparer을 직접 만들어서 정렬 하면 문제는 해결 됩니다.

 

 

다행히도 구글링을 통해 스택 오버플로에서 구현한 걸 찾았습니다. 스택 오버플로에 웬만한 건 다 있네요

해당 링크는 본문 하단에 첨부했으니 관심있으시면 방문해 보세요.

 

 

아래는 구글링한 소스를 바탕으로 구현한 StringAsNumericComparer 클래스입니다.

public class StringAsNumericComparer : IComparer<string>
{
    public StringAsNumericComparer()
    { }

    public int Compare(object x, object y)
    {
        if ((x is string) && (y is string))
        {
            return StringLogicalComparer.Compare((string)x, (string)y);
        }

        return -1;
    }

    public int Compare(string x, string y)
    {
        return StringLogicalComparer.Compare(x, y);
    }

    private class StringLogicalComparer
    {
        public static int Compare(string s1, string s2)
        {
            //get rid of special cases
            if ((s1 == null) && (s2 == null)) return 0;
            else if (s1 == null) return -1;
            else if (s2 == null) return 1;

            if ((s1.Equals(string.Empty) && (s2.Equals(string.Empty)))) return 0;
            else if (s1.Equals(string.Empty)) return -1;
            else if (s2.Equals(string.Empty)) return -1;

            //WE style, special case
            bool sp1 = Char.IsLetterOrDigit(s1, 0);
            bool sp2 = Char.IsLetterOrDigit(s2, 0);
            if (sp1 && !sp2) return 1;
            if (!sp1 && sp2) return -1;

            int i1 = 0, i2 = 0; //current index
            int r = 0; //temp result
            while (true)
            {
                bool c1 = Char.IsDigit(s1, i1);
                bool c2 = Char.IsDigit(s2, i2);
                if (!c1 && !c2)
                {
                    bool letter1 = Char.IsLetter(s1, i1);
                    bool letter2 = Char.IsLetter(s2, i2);
                    if ((letter1 && letter2) || (!letter1 && !letter2))
                    {
                        if (letter1 && letter2)
                        {
                            r = Char.ToLower(s1[i1]).CompareTo(Char.ToLower(s2[i2]));
                        }
                        else
                        {
                            r = s1[i1].CompareTo(s2[i2]);
                        }
                        if (r != 0) return r;
                    }
                    else if (!letter1 && letter2) return -1;
                    else if (letter1 && !letter2) return 1;
                }
                else if (c1 && c2)
                {
                    r = CompareNum(s1, ref i1, s2, ref i2);
                    if (r != 0) return r;
                }
                else if (c1)
                {
                    return -1;
                }
                else if (c2)
                {
                    return 1;
                }
                i1++;
                i2++;
                if ((i1 >= s1.Length) && (i2 >= s2.Length))
                {
                    return 0;
                }
                else if (i1 >= s1.Length)
                {
                    return -1;
                }
                else if (i2 >= s2.Length)
                {
                    return -1;
                }
            }
        }

        private static int CompareNum(string s1, ref int i1, string s2, ref int i2)
        {
            int nzStart1 = i1, nzStart2 = i2; // nz = non zero
            int end1 = i1, end2 = i2;

            ScanNumEnd(s1, i1, ref end1, ref nzStart1);
            ScanNumEnd(s2, i2, ref end2, ref nzStart2);
            int start1 = i1; i1 = end1 - 1;
            int start2 = i2; i2 = end2 - 1;

            int nzLength1 = end1 - nzStart1;
            int nzLength2 = end2 - nzStart2;

            if (nzLength1 < nzLength2) return -1;
            else if (nzLength1 > nzLength2) return 1;

            for (int j1 = nzStart1, j2 = nzStart2; j1 <= i1; j1++, j2++)
            {
                int r = s1[j1].CompareTo(s2[j2]);
                if (r != 0) return r;
            }
            // the nz parts are equal
            int length1 = end1 - start1;
            int length2 = end2 - start2;
            if (length1 == length2) return 0;
            if (length1 > length2) return -1;
            return 1;
        }

        private static void ScanNumEnd(string s, int start, ref int end, ref int nzStart)
        {
            nzStart = start;
            end = start;
            bool countZeros = true;
            while (Char.IsDigit(s, end))
            {
                if (countZeros && s[end].Equals('0'))
                {
                    nzStart++;
                }
                else countZeros = false;
                end++;
                if (end >= s.Length) break;
            }
        }
    }
}

 

이제 힘들게 구현했으니 사용해봐야겠죠?

사용할때는 Array.Sort(strArray new StringAsNumericComparer()); <- 이런식으로 사용하면 됩니다.

 

 

아래 코드는 실제 사용예 입니다.

static void Main(string[] args)
{
    string _dirPath = @"D:\Test";

    var dirInfo = new DirectoryInfo(_dirPath);
    var dirName = dirInfo.FullName;

    // 파일명 배열
    string[] fileArr = dirInfo.GetFiles().Select(o => o.Name).ToArray();

    Array.Sort(fileArr, new StringAsNumericComparer());
}

 

 

이제 결과를 살펴봅시다.

정렬 결과 확인

 

 

이제 우리가 원하던 대로 정렬 됐습니다

저같은 경우는 꽤나 쓸일이 많은지라, 따로 보관해 필요할때마다 쓰고있습니다.

이글이 도움이 됐으면 좋겠네요

 

 

 

 

 

https://stackoverflow.com/questions/23114201/sorting-issue-in-net

 

Sorting issue in .NET

I am using this linq query to sort a string column but the results I am getting does not seems to be in right order? Query: userList = users.OrderBy(u => u.FirstName) .Skip(off...

stackoverflow.com

 

+ Recent posts