Windows 탐색기(Explorer) 검색 방법

저기 보이는 저 입력란에 검색 조건을 넣어서 파일을 검색하는데 사용하는 몇가지 정리…

  1. 연산자
    • AND
      BS AND FILE => BS와 FILE을 모두 포함한
    • OR
      BS OR FILE => BS 또는 FILE을 포함한
    • NOT
      BS NOT FILE => BS는 포함하고 FILE 은 제외한
  2. 저기 보이는 입력란에 포커스를 주면 나타나는 검색 메뉴를 사용하기
  3. 최종 전문가 버전
    [Windows Property System] 를 사용해서 검색하기
    예로 저 입력란에 System.Kind: 을 입력하면 종류를 고르는 리스트가 나옵니다. 폴더를 고르면 ‘종류:=폴더’ 라는 글씨로 바뀌는데, 이걸 다시 ‘종류:<>폴더’ 가 되게 하면 폴더를 제외하고 검색이 됩니다.
    그 외에도 다양한 속성이 있는데 링크를 참고하세요

모니터 색상 교정

간만에 사진 좀 정리하고 있습니다.
포토 프린터로 출력한 결과물과 모니터의 색감이 너무 차이가 나서
색 교정을 해 보려고 했습니다.

여러 가지 방법이 있습니다.

  1. Windows 에 있는 디스플레이 색 교정
  2. 웹 이미지를 통해서
    [Photo Friday: Monitor Calibration Tool]
    [모니터 무결점 테스트 사이트]
    [The Lagom LCD monitor test pages]
  3. 어플리케이션을 이용해서
    [QuickGamma] <- 이게 상주하는 프로세스가 없는 걸로 알고 있습니다
    [Calibrize]

BS의 선택은? 1번 Windows 기본 디스플레이 색 교정

Windows 10 1809 문제

출시한 당일 회사 컴퓨터와 집 컴퓨터를 모두 1809 업데이트를 이미 했는데…

[윈도10 업데이트 긴급중단…파일 무차별 삭제 오류]
http://www.asiae.co.kr/news/view.htm?idxno=2018100713495940172

이런 기사를 만나게 되었습니다.

그리고 아래와 같이 MS 공식 홈페이지에서도 배포를 중단한 상태입니다.

이런… 이미 디스크 정리까지 해버렸는데!!!

추가로 이번 업데이트 후 이전과 다른 문제점 하나가 더 늘어났습니다.
바로 디스크 정리 대상에서 다운로드 폴더가 포함되어 있는 것입니다.

무심코 모든 걸 체크하고 돌렸는데 역시 다운로드 폴더가 깨끗해져 버렸습니다.

하지만 기사의 내용과 달리 BS의 경우에는 내 문서 폴더는 멀쩡하네요.
이제 다운로드 폴더를 다운로드용으로 쓰지 않아야 할 거 같습니다.

MS… 반성하세요.

HTML5 + CSS + JavaScript 로 멀티 플랫폼 Application 을 만들기

Desktop 용 Application 을 만든다면 [Electron]
예) Skype, Visual Studio Code, Atom, Slack, …

Mobile 용 App 을 만든다면 [Apache Cordova]
Cordova 로 직접 App 을 만드는 건 마치 Java 로 Andriod 앱을 만드는 것과 다름이 없을 거 같고…
Cordova 를 다시 특정 용도에 맞게 좀더 다듬은 것을 사용하지 않을까 생각되네요.
예) Adobe PhoneGap, Ionnic, InstaBug, …

최신 Windows 설치를 도와줄 드라이버 백업툴

BS가 최근 아내의 J-Tab 2 에 Windows 10 을 클린설치 하면서 엄청 고생을 했는데요.
이런 툴을 썼다면 훨씬 더 쉽게 했을 거 같습니다.

[DriverBackup!]
[Double Driver]

BS 는 DriverBackup! 이 더 간편한 것 같습니다.

사용에 대한 가상의 시나리오

  1. PC 가 조립식으로 만들어 진 것이 아닌 완제품이다.
  2. 제조사가 좀 떨어져서 최신 Windows 에 대한 지원을 해 주지 않는다.
    마치 J-Tab 2 처럼!!!
  3. 최신의 Windows 는 시도해 보고 싶다!!!
  4. 현재 사용하고 있는 Windows 의 각종 디바이스 드라이버들 중에 MS 가 제공하지 않는 Third party 드라이버를 백업한다.
  5. 개인 자료를 잘 백업하고 나서 새 버전의 Windows 를 설치한다.
  6. 드라이버가 자동으로 잡히면 감사감사
  7. 안잡히는 드라이버는 하드웨어 제조사를 통해 먼저 구해본다.
  8. 이런!!! 하드웨어 제조사도 완제품 제조사 꼴이구나!!! 싶으면 먼저 백업 받았던 드라이버를 가지고 시도한다.
  9. 다행히 모든 드라이버가 잘 잡히고 동작한다.
  10. 난 행복하다!!!

특정 확장자나 폴더 등에 Explorer Shell Context Menu 추가하기

특정 확장자를 가진 파일을 우클릭 했을 때에 Context 메뉴가 나타나도록 하려면
키: HKEY_CLASSES_ROOT/<확장자 또는 *>/shell/<기능을 표현하는 이름>
기본값: REG_SZ 타입으로 메뉴의 이름을 입력 (& 기호로 Keyboard shortcut 만들 수 있음)
Icon: REG_SZ 타입으로 아이콘 파일 경로 또는 실행 파일 경로 또는 실행 파일 경로 + 아이콘 인덱스
키: HKEY_CLASSES_ROOT/<확장자 또는 *>/shell/<기능을 표현하는 이름>/command
기본값: REG_SZ 타입으로 실행할 명령을 입력

키: HKEY_CLASSES_ROOT/*/shell/VSCode
기본값: Open w&amp;ith Code
Icon: C:\Users\bs\AppData\Local\Programs\Microsoft VS Code\Code.exe,0

키: HKEY_CLASSES_ROOT/*/shell/VSCode/command
기본값: "C:\Users\bs\AppData\Local\Programs\Microsoft VS Code\Code.exe" "%1"
키: HKEY_CLASSES_ROOT/Directory/shell/VSCode
기본값: Open with Code
Icon: C:\Users\bs\AppData\Local\Programs\Microsoft VS Code\Code.exe,0

키: HKEY_CLASSES_ROOT/Directory/shell/VSCode/command
기본값: "C:\Users\bs\AppData\Local\Programs\Microsoft VS Code\Code.exe" "%1"
키: HKEY_CLASSES_ROOT/Directory/Background/shell/OpenCMD
기본값: CMD 열기
Icon: cmd.exe

키: HKEY_CLASSES_ROOT/Directory/Background/shell/OpenCMD/command
기본값: cmd.exe /s /k pushd "%V"

AstroGrep – Windows 용 파일 내용 검색 프로그램 (grep, Find in Files 유사)

[AstroGrep]

grep 명령처럼 원하는 문자열을 가진 파일을 찾아주는 Windows 용 도구 입니다.
Visual Studio 의 Find in Files 를 생각하시면 됩니다.

오랫동안 Notepad++ 을 사용하다가 최근에 Visual Studio Code 를 기본 텍스트 편집기로 변경했습니다.

이유는…

Notepad++ 에서 검정 배경에 흰색 글자로 텍스트 파일을 작성 후에 프린트를 했더니…
검정 배경은 무시되고, 흰색 글자는 유효해서 새하얀 A4 용지가 그대로 프린터에서 출력되는 말도 안되는 상황을 겪어서…

그래도 그건 참을 수 있었으나, 회사에서 XML 편집 중에 Perforce 를 통해 Resolve 를 하고 돌아오면 파일 내용이 변경된 것을 인지하지 못하여 이전 버전의 파일 내용으로 덮어 씌우는 사태가 벌어졌습니다.

그래서 VSCode(Visual Studio Code)로 갈아 탔습니다.

Visual Studio Code 의 장점은 역시 공짜!!! 그리고 엄청난 Extension 들이 나오고 있고, 아무래도 계속 진행형이다보니 개선도 빨리 되고 하여…

그런데 이 놈은 역시 범용 Text Editor 가 아니기 때문에 이런 저런 설정이나 Extension 을 설치해야 하는 불편함은 있습니다.

그 중, 가장 불편한 점은 Find in Files 에서 파일명을 대소문자 구분을 한다는 것이죠!!!
실행하는 OS인 Windows 가 파일명의 대소문자를 구분하지 않는데, Visual Studio Code는 아무래도 Chrome 기반으로 만든 멀티 플랫폼 도구이다보니, Windows 를 제외한 나머지 OS(macOS, Linux 등)에서 대소문자를 구분하기 때문에 이렇게 되었나봅니다.

그래서 다시 찾은 것이 AstroGrep 입니다.

상당히 빠르게 검색이 되고 툴 설정을 잘 하면 VSCode 에서 File:Line:Column 형식으로 특정 위치에 캐럿이 위치하도록 열 수도 있고… 무료에 오픈소스에 좋은 거 같습니다.

macOS 모하비(Mojave) + 와컴 태블릿(Wacom Tablet) Intuos + Photoshop CC 201x

이런 조합에서 펜 압력이 먹지 않는다면

시스템 설정에서 아래와 같은 설정이 되어 있는지 확인하고
설정 후에 리붓 하고 나서 다시 한번 펜의 필압이 먹는지 확인해 보자

자료 출처: [Wacom]

Microsoft Windows 를 사용하면서는 이런 경우를 겪어본 것이 9x 시리즈에서 XP 넘어갈 때랑, XP 에서 다음 버전으로 넘어갈 때 딱 2번이었는데…

그나마도 Windows 는 상당수의 Application 은 잘 실행되고 아주 극히 일부 Application 만 문제가 되었다. 그런데 Photoshop 과 같은 굵직한 Application 이 정상 동작 하지 못하는 OS 업데이트라니… 정말 놀라울 따름이다.

리눅스 성능 측정을 위한 도구들

출처: [TecMint]

  1. top – Table Of Processes
    Windows의 작업관리자 비슷한 그것
  2. vmstat – Virtual Memory Statistics
    메모리, 스왑, IO, 시스템 인터럽트, CPU 상태 등을 확인하는 도구
  3. lsof – List Open Files
    열려 있는 파일을 확인하는 도구
  4. tcpdump – TCP Dump
    TCP 통신을 분석하는데 사용하는 도구
  5. netstat – Network Statistics
    네트워크 상태를 확인하는 도구
  6. htop
    top 의 ncurses 버전
  7. iotop – I/O Monitor
    top 비슷하게 생긴 I/O 모니터 도구
  8. iostat – I/O Statistics
    CPU와 디바이스 I/O 상태를 확인하는 도구
  9. IPTraf – IP Network Monitoring
    IP 기반의 네트워크 모니터링 도구, TCP, UDP, ICMP 등등 IP 기반의 프로토콜을 지원

그외 등등이 출처에 링크 건 곳에 있습니다.

HyperLogLog 에 대해 잠깐 테스트를 해 보았습니다.

BS가 근무하는 팀에서 이런 저런 스터디를 하는데 Redis 에 대해서 스터디 중입니다.
이번 스터디에 Redis 의 PFADD, PFCOUNT, PFMERGE 를 다루게 되어 조금 찾아 보았습니다.

참고자료 #1: [성태의 닷넷 이야기]
참고자료 #2: [Naver D2]
참고자료 #3: [Adnan.Korkmaz Blog]
참고자료 #4: [Microsoft CardinalityEstimation]
참고자료 #5: [Wikipedia]

위 자료에서 3, 4번의 소스와 라이브러리를 받아 간단하게 테스트 프로그램을 작성하였습니다.

using CardinalityEstimation;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace HyperLogLogTest {

    // from http://adnan-korkmaz.blogspot.com/2012/06/hyperloglog-c-implementation.html

    public class HyperLogLog {
        private readonly double mapSize, alpha_m, k;
        private readonly int kComplement;
        private readonly Dictionary<int, int> Lookup = new Dictionary<int, int>();
        private const double pow_2_32 = 4294967297;
        private readonly Func<object, uint> hashFunc;

        public HyperLogLog(double stdError, Func<object, uint> hashFunc) {
            this.hashFunc = hashFunc;

            mapSize = 1.04 / stdError;
            k = (long)Math.Ceiling(Log2(mapSize * mapSize));

            kComplement = 32 - (int)k;
            mapSize = (long)Math.Pow(2, k);

            alpha_m = mapSize == 16 ? 0.673
                  : mapSize == 32 ? 0.697
                  : mapSize == 64 ? 0.709
                  : 0.7213 / (1 + 1.079 / mapSize);
            for (int i = 0; i < mapSize; i++)
                Lookup[i] = 0;
        }

        private static double Log2(double x) {
            return Math.Log(x) / 0.69314718055994530941723212145818;//Ln2 
        }
        private static int GetRank(uint hash, int max) {
            int r = 1;
            uint one = 1;
            while ((hash & one) == 0 && r <= max) { ++r; hash >>= 1;
            }
            return r;
        }

        public int Count() {
            double c = 0, E;

            for (var i = 0; i < mapSize; i++)
                c += 1d / Math.Pow(2, Lookup[i]);

            E = alpha_m * mapSize * mapSize / c;

            // Make corrections & smoothen things. 
            if (E <= (5 / 2) * mapSize) {
                double V = 0;
                for (var i = 0; i < mapSize; i++) if (Lookup[i] == 0) V++; if (V > 0)
                    E = mapSize * Math.Log(mapSize / V);
            }
            else
                if (E > (1 / 30) * pow_2_32)
                E = -pow_2_32 * Math.Log(1 - E / pow_2_32);
            // Made corrections & smoothen things, or not. 

            return (int)E;
        }

        public void Add(object val) {
            uint hashCode = hashFunc(val);
            int j = (int)(hashCode >> kComplement);

            Lookup[j] = Math.Max(Lookup[j], GetRank(hashCode, kComplement));
        }
    }

    class Program {

        static MD5 md5 = MD5.Create();
        static readonly string outputFormat = "{0,-40}: {1,10}: {2,10}";

        static uint CustomHash(object val) {
            string text = val.ToString();
            uint hash = 0;

            for (int i = 0, l = text.Length; i < l; i++) {
                hash += text[i];
                hash += hash << 10; hash ^= hash >> 6;
            }
            hash += hash << 3; hash ^= hash >> 6;
            hash += hash << 16;

            return hash;
        }

        static uint DefaultHash(object val) {
            return (uint)val.GetHashCode();
        }

        static uint MD5Hash(object val) {
            var bt = md5.ComputeHash(Encoding.UTF8.GetBytes(val.ToString()));
            return BitConverter.ToUInt32(bt, 0) ^ BitConverter.ToUInt32(bt, 4) ^ BitConverter.ToUInt32(bt, 8) ^ BitConverter.ToUInt32(bt, 12);
        }

        static void HyperLogLogTest(Func<object, uint> hashFunc, string name, int testCount) {
            var hll = new HyperLogLog(0.01, hashFunc);
            for (var i = 0; i < testCount; i++)
                hll.Add(i);
            Console.WriteLine(outputFormat, name, testCount, hll.Count());
        }

        // from https://github.com/Microsoft/CardinalityEstimation
        static void MSHyperLogLogTestFnv1A(Func<object, uint> hashFunc, string name, int testCount) {
            var hllMS = new CardinalityEstimator(hashFunctionId: CardinalityEstimation.Hash.HashFunctionId.Fnv1A);
            for (var i = 0; i < testCount; i++)
                hllMS.Add(i);
            Console.WriteLine(outputFormat, name, testCount, hllMS.Count());
        }

        // from https://github.com/Microsoft/CardinalityEstimation
        static void MSHyperLogLogTestMurmur3(Func<object, uint> hashFunc, string name, int testCount) {
            var hllMS = new CardinalityEstimator(hashFunctionId: CardinalityEstimation.Hash.HashFunctionId.Murmur3);
            for (var i = 0; i < testCount; i++)
                hllMS.Add(i);
            Console.WriteLine(outputFormat, name, testCount, hllMS.Count());
        }

        static void Main(string[] args) {
            HyperLogLogTest(DefaultHash, "Adnan.Korkmaz: DefaultHash", 10);
            HyperLogLogTest(DefaultHash, "Adnan.Korkmaz: DefaultHash", 10000);
            HyperLogLogTest(MD5Hash, "Adnan.Korkmaz: MD5 + XOR", 10);
            HyperLogLogTest(MD5Hash, "Adnan.Korkmaz: MD5 + XOR", 10000);
            HyperLogLogTest(CustomHash, "Adnan.Korkmaz: Adnan.Korkmaz", 10);
            HyperLogLogTest(CustomHash, "Adnan.Korkmaz: Adnan.Korkmaz", 10000);
            MSHyperLogLogTestFnv1A(CustomHash, "CardinalityEstimation with Fnv1A", 10);
            MSHyperLogLogTestFnv1A(CustomHash, "CardinalityEstimation with Fnv1A", 10000);
            MSHyperLogLogTestMurmur3(CustomHash, "CardinalityEstimation with Murmur3", 10);
            MSHyperLogLogTestMurmur3(CustomHash, "CardinalityEstimation with Murmur3", 10000);
        }
    }
}

최대한 비슷한 결과를 얻기 위해 두 라이브러리 모두 레지스터 수량을 16K 개(pow(2, 14)) 로 하였습니다.
그리고 결과는 아래와 같이 나왔습니다.

Adnan.Korkmaz: DefaultHash              :         10:          1
Adnan.Korkmaz: DefaultHash              :      10000:          1
Adnan.Korkmaz: MD5 + XOR                :         10:         10
Adnan.Korkmaz: MD5 + XOR                :      10000:      10068
Adnan.Korkmaz: Adnan.Korkmaz            :         10:         10
Adnan.Korkmaz: Adnan.Korkmaz            :      10000:       9853
CardinalityEstimation with Fnv1A        :         10:         10
CardinalityEstimation with Fnv1A        :      10000:      11419
CardinalityEstimation with Murmur3      :         10:         10
CardinalityEstimation with Murmur3      :      10000:       9980

여기에서 확인되는 것은 동일한 알고리즘으로 구현된 것이라도 어떤 Hash 함수를 넣는가에 따라서 굉장히 다른 결과를 얻게 된다는 것입니다.
C#의 GetHashCode() 의 경우에는… 쩝…

Redis 의 PFADD, PFCOUNT 를 쓰면

var redis = require('redis');
var client = redis.createClient();

function test(n) {
  client.flushall();
  for (i = 0; i < n; i++)
    client.pfadd("hll", i);
  client.pfcount("hll", function(e, r) {
    console.log(n, r);
  });
}

test(10);
test(10000);

client.flushall();
client.quit();
10 10
10000 9999

이렇게 나오네요.

Windows 10 을 VHDX 에 설치

아직도 사라지지 않는 각종 보안 프로그램들의 악행들을 피하고자 BS는 PC에 Windows 10 을 2개 설치해서 사용 중입니다.

하나는 일반적인 설치로 절대 ActiveX 를 비롯하여 nProtect 와 같은 Windows 서비스 형태의 보안툴을 설치하지 않고

또 다른 하나는 VHDX(가상 하드)에 가볍게 설치해서 각종 은행 업무, 공공기관 업무에 사용하고 있습니다.

이전에 Hyper-V를 통해서 설치하다가 중간에 멈추고 bcdedit 로 해당 VHDX 를 연결해서 멀티 부팅을 설정하는 방법을 썼는데, 이보다 편리하게 할 수 있는 방법이 있습니다.

  1. Convert-WindowsImage.ps1 다운로드
    https://github.com/MikeFal/PowerShell 에서 위 파일을 받습니다.
  2. 관리자 권한의 PowerShell 을 열어서 받은 파일을 로드합니다.
    PS X:\Downloads&amp;gt; . .\Convert-WindowsImage.ps1
    
  3. 만약 권한 오류가 발생하면
    PS X:\Downloads&amp;gt; Set-ExecutionPolicy Bypass CurrentUser
    
  4. 도움말 일단 한 번 구경
    HELP Convert-WindowsImage
    
  5. 이런 식으로 변환 합니다. (예제는 40GB 짜리 동적 크기 가상하드에 설치하는 거)
    PS X:\Downloads> Convert-WindowsImage -SourcePath "Y:\install.wim" -WorkingDirectory "X:\somedir" -SizeBytes 40GB -VHDFormat VHDX -VHDType dynamic -Edition Professional -ExpandOnNativeBoot:$False
    

그런데 위에서 쓰는 install.wim 은 어디서 구하냐구요?

  1. MS 사이트를 통해서 Windows 10 ISO 를 받습니다.
    https://www.microsoft.com/ko-kr/software-download/windows10?SearchToggle=true
  2. ISO 파일을 Mount(탑재, 마운트)합니다.
    설명에서는 E 드라이브로 마운트 되었다고 가정하겠습니다.
  3. ISO 파일에서 가능한 에디션의 인덱스 번호를 확인합니다.
    DISM /Get-WimInfo /WimFile:"E:\sources\install.esd"
    
  4. 이제 추출합니다.
    Compress 옵션은 fast, max, none 중 하나로 넣으면 되는데 무난한 것이 fast로 생각됩니다.

    DISM /Export-Image /SourceImageFile:"E:\sources\install.esd" /SourceIndex:<IndexNumber> /DestinationImageFile:"X:\somedir\install.wim" /Compress:fast /CheckIntegrity
    

metadata-extractor – EXIF 정보를 읽을 수 있는 .NET Framework 용 라이브러리

EXIF 정보를 읽어야 할 일이 생겨서 찾다보니 이것!

metadata-extractor

EXIF란 Exchangeable Image File Format 의 약어로, JPEG, TIFF 등 이미지 파일에 각종 메타정보를 저장하는 포맷입니다.

쌩으로 .NET Framework 에 있는 기본 라이브러리로 읽을 수도 있겠지만… 엄청 고난의 길…

metadata-extractor 는 Java, C# 을 지원하기 때문에 웹 기반 + 사진 관련된 어플리케이션을 개발한다면 유용하게 사용할 수 있습니다.

물론 정말 하드코어하게

Image.PropertyItems 으로 이런 식으로 직접 만들 수 있습니다.

LiteDB – Embedded NoSQL for .NET

.NET Framework 환경에서

  • Embedded
  • NoSQL
  • Single file

로 하면 이것 말고 쓸 게 없네요.

http://www.litedb.org/

SQLite와 비교하면 파일의 용량이 거의 2배가 되긴 하지만요…

순수 C#으로 만들어져 모바일 환경에서도 쓸 수 있습니다.
모습은 음… MongoDB 를 보는 듯한…