この間書いた「無駄話」で「【Visual Studio探検記】の準備が整いました」と書き、現実にそのブログインスタンス(ブログクラスの実体-要すればネタ)を作っていますが、ネタ的にC++やC#のプログラムが要るので、先ずは先般Embarcaderoの32bitネイティブコンパイラーで作ったC++用の「各種ソートの比較」をベンチマークプログラム的に使おうかと考えました。

 

"Comparison_Sort.cpp"というプログラムなんですが、まだ覚えておられるでしょうか?

 

 

となると、

 

矢張りC#用にも欲しいですよね?と、いうことでこのプログラムをC#に移植(末尾参照)し、実行してみました。

 

解説:一番遅いBubbleソートはC++よりも遅いが、アルゴリズム的に速いHeap、Quick、Shellソートでは(テストプログラムのデータセットの違いを考えても)早くなっていることがわかります。なお、.NETは.Netはコンパイラーとインタープリターの両方の特性を組み合わせたような実行環境をとっており、「遅い」とか「速い」とかいろいろと言われますが、実際に計測すると面白いですね。

 

ウ~ン、.NET、速いですね。恐るべし。

アルゴリズムの勝利、恐るべし。

 

【Compare_Sort.cs】

解説:以下のプログラムは、C++用のComparison_Sort.cppのアルゴリズム、構成をなるべく忠実にC#に移したものですが、両言語の違いにより変更したところがあります。

///////////////////////

// C# Sort Comparison
///////////////////////

using System;
using System.Diagnostics;        //Stopwatchを使う為

namespace Comparison_Sort
{
    class comparison_sort
    {
        ///////////
        //定数定義
        ///////////

        const int MAX = 10000;        //取り敢えず10,000がお勧め
        ////////////////////
        // 共通テスト用配列
        ////////////////////

        int[] original = new int[MAX];
        double[,] results = new double[4, MAX];

        ///////////////
        //Mainメソッド
        ///////////////
        public static void Main()

        {
            comparison_sort cs = new comparison_sort();
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for(int i = 0; i < MAX; i++) {
                cs.comparison(i);
            }
            for(int i = 0; i < 4; i++) {
                cs.print_result(i);
            }
            sw.Stop();
            TimeSpan ts = sw.Elapsed;    //時間ts.Hours, 分ts.Minutes, 秒ts.Seconds, ミリ秒ts.Milliseconds
            string elapsed = String.Format("Total time consumed for the above processing is: {0:00.000000}", ts.Milliseconds);
            Console.WriteLine(elapsed);
            Console.WriteLine("Push CR key ..." + Environment.NewLine);
            Console.Read();        //コンソールを閉じない為
        }

        ///////////////
        // Comparison
        ///////////////

        void comparison(int n)
        {
            //乱数の初期化
            Random rand = new Random((int) DateTime.Now.Ticks & 0x0000FFFF);
            //テスト用の配列の作成
            //解説:C#では引数に配列を渡す場合、参照渡しになる-https://water2litter.net/rye/post/c_array_ref/
            int[] test_array = new int[MAX];    //テスト用ローカル変数
            for(int i = 0; i < MAX; i++)
            {
                test_array[i] =                 //originalを保存し、テストはこれで行う
                original[i] = rand.Next();        //0から32,767の整数で初期化する
            }
            //時間計測の準備
            Stopwatch sw = new Stopwatch();
            //ソート比較
            sw.Start();
            bubblesort(test_array);
            sw.Stop();
            TimeSpan ts = sw.Elapsed;    //時間ts.Hours, 分ts.Minutes, 秒ts.Seconds, ミリ秒ts.Milliseconds
            results[0, n] =  (double)ts.Milliseconds;

            for(int i = 0; i < MAX; i++)
                test_array[i] = original[i];
            sw.Reset();
            sw.Start();
            heapsort(test_array);
            sw.Stop();
            ts = sw.Elapsed;    //時間ts.Hours, 分ts.Minutes, 秒ts.Seconds, ミリ秒ts.Milliseconds
            results[1, n] =  (double)ts.Milliseconds;

            for(int i = 0; i < MAX; i++)
                test_array[i] = original[i];
            sw.Reset();
            sw.Start();
            quicksort(test_array, 0, MAX - 1);    //配列、開始添字、終了添字
            sw.Stop();
            ts = sw.Elapsed;    //時間ts.Hours, 分ts.Minutes, 秒ts.Seconds, ミリ秒ts.Milliseconds
            results[2, n] =  (double)ts.Milliseconds;

            for(int i = 0; i < MAX; i++)
                test_array[i] = original[i];
            sw.Reset();
            sw.Start();
            shellsort(test_array);
            sw.Stop();
            ts = sw.Elapsed;    //時間ts.Hours, 分ts.Minutes, 秒ts.Seconds, ミリ秒ts.Milliseconds
            results[3, n] =  (double)ts.Milliseconds;
        }

        ////////////////
        // Bubble Sort
        ////////////////
        /*
            n個の整数配列dataを総て順に比較、交換し、配列の最後から大きい順に並べる
            通称「馬鹿ソー
ト」
        */
        void bubblesort(int[] data)
        {
            int i, j, temp, n = data.Length;

            for(i = n - 1; i > 0; i--) {        //配列の末尾から先頭へ
                for(j = 0; j < i; j++) {        //配列の先頭から末尾へ
                    if(data[j] > data[j + 1]) {    //次の配列要素の方が小さければ交換する
                        temp = data[j];
                        data[j] = data[j + 1];
                        data[j + 1] = temp;
                    }
                }                                //その結果iに最大の要素が置かれる
            }
        }

        //////////////
        // Heap Sort
        //////////////
        /*
        ヒープソートは次のようなヒープ(二分木)の「親-子」関係を用いる
                Parent(0)
                  /\
          ChildL(1)  ChildR(2)

        この二分木を用いて配列を表現すると以下のようになる(数字は添字)
                   0
                 / \
                1     2
              / \ / \
             3    4 5    6
           / \
          7     8 ...
        */


        void exchange(int top, int[] data, int n)
        {
            int temp = data[top];                        //開始時の二分木の親の値をtempに退避
            //子のある二分木の左の子供を指定し、(交換があればやり直す為)末尾迄子孫を辿る
            for(int i = top * 2 + 1; i < n; top = i, i = top * 2 + 1) {
                if(i < n - 1 && data[i] < data[i + 1])    //右の子供が左の子供より大きければ
                    i++;                                //右の子供を指定する
                if(temp >= data[i])                        //開始時の親と大きい方の子供を比較
                    break;                                //親が大きければループを抜ける(topは変化しない)
                data[top] = data[i];                    //二分木の親に大きい子の値を代入する
            }                                            //大きい子(data[i])はループのi = topで
            data[top] = temp;                            //data[top]となり、退避した親の値を代入
        }

        void heapsort(int[] data)
        {
            int top, i, n = data.Length;
            for(top = n / 2 - 1; top >= 0; top--)        //最初に「子がある最後の二分木」から
                exchange(top, data, n);                    //「親が最大値を持つ」ように頂点まで継続する
            for(i = n - 1; i > 0; i--) {                //次に配列の最後と頂点(最大値)の値を交換し
                int temp;
                temp = data[i];
                data[i] = data[0];
                data[0] = temp;
                exchange(0, data, i);
            }                                            //配列の最後を切り離し、その前の要素から頂点まで継続する
        }

        //////////////
        // Quick Sort
        //////////////
        //検索範囲(startとend)で、基準値(key)を定め、それよりも多いものと少ないものを分割し、更にkeyの前後で同じ処理を再帰呼び出しする。

        void quicksort(int[] data, int start, int end)    //配列、開始添字、終了添字
        {
            if(start < end)                                //開始位置が終了位置以上で終了(最後の再帰呼び出し参照)
            {
                int left, right, key, kp;                //順に右進行添字、左進行添字、「分水嶺」値、その添字
                //右端乃至左端に到達し、breakで抜けるまでループする
                for(left = start, right = end, key = data[right];;) {
                    while(key >= data[left])
                    {
                        left++;                            //keyを超える値迄右に進む
                        if(left == right)                //配列添字が範囲を超えないよう追加
                            break;
                    }
                    if(left < right)                    //rightの位置迄は
                        data[right] = data[left];        //leftの値をrightの位置に書き込む
                    else                                //leftがright位置を過ぎたなら
                    {
                        kp = right;                        //keyの位置をrightの位置としてループを抜ける
                        break;
                    }
                    while(key <= data[right])
                    {
                        right--;                        //key未満の値迄右に進む
                        if(right == 0)                    //配列添字が範囲を超えないよう追加
                            break;
                    }
                    if(left < right)                    //leftの位置迄は
                        data[left] = data[right];        //rightの値をleftの位置に書き込む
                    else                                //rightがleft位置を過ぎたなら
                    {
                        kp = left;                        //keyの位置をleftの位置としてループを抜ける
                        break;
                    }
                }
                data[kp] = key;                            //keyポインターの位置にkeyの値を代入する
                quicksort(data, start, kp - 1);            //開始位置からkeyポインター迄で再帰呼び出しする
                quicksort(data, kp + 1, end);            //keyポインターから終了位置迄で再帰呼び出しする
            }
        }

        //////////////
        // Shell Sort
        //////////////
        //シェルソートは配列要素を一定の距離を置いたグループに分けて比較、交換を行いソートする方法

        void shellsort(int[] data)
        {
            int gap, i, j, temp, n = data.Length;        //gapは比較、交換する要素間の距離
            for(gap = n / 2; gap > 0; gap /= 2) {    //初期的な距離は配列サイズの1/2とする
                for(i = gap; i < n; i++) {            //距離は徐々に狭まってゆく
                    for(j = i - gap; j >= 0 && data[j] > data[j + gap]; j -= gap) {
                        //v[j]とv[j + gap]を交換する
                        temp = data[j];
                        data[j] = data[j + gap];
                        data[j + gap] = temp;
                    }
                }
            }
        }

        /////////////////
        // Print results
        /////////////////

        void print_result(int n)
        {
            double[] array = new double[MAX];    //n行の配列のコピー用
            string[] title = new string[4] {">>> Bubble Sort <<<", ">>> Heap Sort <<<", ">>> Quick Sort <<<", ">>> Shell Sort <<<"};
            double max = 0.0, min = (double)MAX, med = 0, ave = 0;
            for(int i = 0; i < MAX; i++)
            {
                if(results[n, i] > max)            //n番目のソートの結果の最大値を求める
                    max = results[n, i];    
                if(results[n, i] < min)            //n番目のソートの結果の最小値を求める
                    min = results[n, i];
                ave += results[n, i];            //n番目のソートの結果を合計する
                array[i] = results[n, i];        //n番目の配列をコピーする
            }
            Array.Sort(array);                    //コピー配列をソートする (
            med = array[(MAX % 2 != 0) ? MAX / 2 : MAX / 2 - 1];
            Console.WriteLine(title[n]);
            Console.WriteLine("最大値  :{0:00.000000}", max);
            Console.WriteLine("最小値  :{0:00.000000}", min);
            Console.WriteLine("平均値  :{0:00.000000}",  ave / MAX);
            Console.WriteLine("中央値  :{0:00.000000}", med);
            Console.WriteLine("総所要時間:{0:00.000000}", ave);
            Console.WriteLine();
        }
    }
}

以下はCopilotのアドバイスです。

.NETArray.Sort()メソッドは、状況に応じて**イントロソート (Introsort)**という複合アルゴリズムを使用しています。

具体的には、以下の3つのソートアルゴリズムを組み合わせて、効率的なソートを実現しています。

  • クイックソート (Quicksort): 一般的なケースで使用されます。平均的な時間計算量はO(n log n)と高速です。
  • 挿入ソート (Insertion Sort): 配列の要素数が非常に少ない場合(通常16要素以下)に使用されます。オーバーヘッドが少なく、小さな配列では効率的です。
  • ヒープソート (Heapsort): クイックソートの再帰が深くなりすぎた場合(最悪ケースに陥りそうな場合)に切り替わります。これにより、最悪ケースでの時間計算量がO(n^2)になるのを防ぎ、常にO(n log n)のパフォーマンスを保証します。

これにより、どのようなデータに対しても高いパフォーマンスと安定した時間計算量を実現しています。

なお、.NET Frameworkのバージョン4.5より前では、デフォルトのアルゴリズムは単純なクイックソートでした。 

 

こういう「遊び」って、面白くありません?

 

【Visual Studio探検記】の準備を着々と進めていますが)余りコンピューター系に偏っても面白みがなくなるので、久々の食い物話など...

 

私の場合、古希を過ぎていますが一日2(時々2++)合程度の飲酒(注1)を(入院したりしなければ)毎日欠かさずに続けていますが、(さすがに完全定年6年目になると)世の主婦|主夫の方のお悩みと同じ

 

今晩は何にするかなぁ~

 

と途方に暮れます。(注2

注1:70過ぎで2~3合/日はさすがに多い、と思われますが、私、生まれてからこの方健康診断で肝臓が引っ掛かったことがなく、高血圧もなく、糖尿もなく、唯一高尿酸血症、高脂血症、高コレステロールだけ薬を飲んでます。まぁ、薬を処方してもらうために定期的に通う内科医も「相変わらず毎日飲んでますか?」と聞くぐらいで「やめなさい」と言わない程度の健康をキープしております。何せ、お袋は102でまだ存命なので、「80歳をゴール」とする私は何か「身体に悪いこと」をしていないと不味いと考えてのことです。

注2:皆同じなんでしょうが、完全定年直後は自由感に浮かれて「あれもやりたい、これもやりたい」「あれも食いたい、これも食いたい(東海林さん、すみません、お借りします)」等と、次から次にアイデアが出て来たのですが...

 

私の場合、「摘みから入る」と「お酒から入る」の二つのアプローチがあり、今回は「あー、久々に赤ワインが飲みたい」という気持ちから「だったらトマトとチーズだよね?」、「だったらお肉かも?」という流れの発想で、

 

「鶏肉を外側カリッと焼きあげ」て、

「玉葱、人参でミネストローネ的に煮詰めて、そう後ブロッコリ」を入れたら、

出来上がり。これをスープ皿に入れてチーズの欠片を載せて電子レンジにかければとろけたチーズが点在する

 

赤ワインのための一品

 

になります。

 

ということで、こいつをチビチビ啄み乍ら赤ワインをチビチビ舐める、という酒飲みの至福の一時を愉しみました。

 

あ”~、幸せ!

 

ps. 単に出来上がった一品の撮影を忘れた為に"Making"にしたこと、バレました?

前回旧機の新たな使用方針についての検討、決定について書きましたが、今回は実行に移す際のドタバタについて書いてみます。

 

1.クリーンインストール

まず、クリーンインストールについては、すでに新機用にツールを作っていたので、やるべきことは「旧機のProduct Key(== Installed Key)を調べ、正常に動いているドライバーを保存しておく」ことでした。

これは難なく実行され、インストールする際の立ち上がりでは何ら問題も起こらず、スムースに進みました。

このマシンはチャネル情報が"OEM_DM"で、もともとInstalled Key(デジタル認証用のハードウェア仮体キー)とOEMキーが同じだったのですが、クリーンインストールするとやはりチャネルが"RETAIL"になりましたが、OEMキーはまだ存在していました。(Installed KeyはWIndowsのdigital entitlementを表し、チャネルは単に販路を表すだけなのでしょう。従ってWEBでMicrosoftがダウンロードさせる個体OSは皆RETAIL扱いになるものと理解しています。)

 

2.Wifiモデム不良

さて、「どんがら」のマシンをどう「Visual Studio専用機」として構成してゆくか等を考えながら、ブラウザーを開こうとすると「ネットワークが使えません」だの、「イーサネットにつながっていない」等のエラー表示が出ます。「オイオイ、Wifiがあるだろ?」とタスクバーを見るとアイコンが表示されていません。「あれっ」ということで「設定」-「ネットワークとインターネット」を見ると接続オプションにWifi自体が表示されていません。「それでは」ということで、Wifiドライバーを読み込ませてデバイスマネージャーを見ると、Wifiアダプター(RZ 608 Wifi)の存在は確認されたのですが、「このアダプターは機能していません」というエラーが出ます。どうもハードウェアトラブルのようです。(

:旧機が立ち上がる際にネットワーク接続の時点で渋くなり、時間がかかったこともこれで頷けます。

 

え"~

 

とは思いましたが、引退直前のこのマシン(mini PCはラップトップなどと同じく、部品交換修理となると、海外送付を含めやたら高額になり得ます)に修理などはありえず、

 

ん、そうだっ!

 

と「義手」をつけることにしました。「義手」とは旧機の前機で使っていたUSB Wifiアダプター(TP-Link Wireless Nano USB Adaptor)で、まず内臓アダプターを殺し、USBアダプターを差し込んでこれを選択するときちんと動作するようになりました。(PCの立ち上がりも良好です。)

問題は私の家のWifiは5Gなんですが、このアダプターは古い2Gで速度が遅いのですが、このマシンは基本スタンドアローンでインターネットを使用するのは技術的記事閲覧、Chat-GPT(または今度からCoPilotですか)交信、GitHubアクセスとこのブログ程度なので、ファイルの転送などがない限り、痛痒を感じないと思います。(追記:この原稿を書いているときに、一応調べましたら、5GのUSBアダプターがなーんと「送料無料で¥158」で売られていたので、さっそくゲットしました。いずれこれと交換しましょう。)

 

ということで、

 

【Visual Studio探検記】の準備が整いました。少しづつ「素人目線」でVisual Studioと格闘する様をお伝えしたいと思います。

 

前回のラストで書いたお話です。

 

旧機(CHUWI製RZBox、Ryzen 7マシン)には満足していたのですが、3年経ったあたりから立ち上がり時にずーっと考え込んでしまったり、まれに落ちることもあったために今回メイン機としてCore-i9マシンに切り替えたのですが、旧機も十分なスピードと使いやすさがあり、まだ処分するには惜しいと感じていました。

 

しかし、旧機と同じ環境、同じデータ(開発ソフトを含み別途HDとMicro SDでバックアップを取っています)で使い続けるのは、無駄のみならず、寧ろシンクロ維持管理負荷等マイナス面が大きいので「全く別用途で新規出直し」をすべきだと考えました

 

が、

 

この「全く別用途で新規出直し」というのが存外難しい問題です。

 

(1)UNIX機にするか?→UNIXはすべて初めてだし、ツールやソフトなどもそろえてゆくことを考えると古希過ぎには荷が重すぎない?

 ↓

(2)ゲーム機、ビデオ機→新機はCore-i9、Intel® Iris® Xe Graphics内臓で1TB SSDのストーレージがあるのに、旧機はRyzen 7+Radeonと500GB SSDなので、この用途では逆でしょう。

 ↓

(3)「何らかの専用機」にすべきでは?→だーかーらー、その「何らか」が難しいのよ、と自分に言い聞かせ、またOSをWindows 11のままにするには「立ち上がりの不安定」問題をどうするか考えなければなりません。

 

ここで思いついたのが、

 

・OSをWindows 11のままにするのですが、「立ち上がりの不安定」対策として新機と同じように一旦クリーンインストールしてはどうか?(AMDのRadeonは週に一回ぐらいドライバーの更新が来て、なんだか輻輳してきているみたいだし。)

 

・ついこの間の11月24日に新しい(私があまり気に入らない)Visual Studio 2026がリリースされたそうで、旧機をこのIDEの専用テスト機として使い、このブログのために(単にディスるのではなく、実際に体験して印象や評価をコメントする)新たな【Visual Studio探検記】を始めてはどうか?

 

という着想です。

 

悪くない(Not bad or even pretty gooooooood!)

 

ということで、その方針で進めようと思います。

 

ps. ところが早々にトラブルが待っていたんですよね。

 

前回メーカーサポートにOEMキーを依頼している途上の週末に、独自調査をもとにクリーンインストールを敢行して、見事成功したことを書きました。

 

クリーンインストール前と後の違いは、

 

(1) Windows 11の「設定」-「システム]-「バージョン情報」に現れる「デバイスID」と「プロダクトID」が変更された。

(2) コマンドプロンプロで"slmgr.vbs -dli"を実行した出力では、(marketing)Channel情報が"VOLUME_MAK"→"RETAIL"変更された。

(3) ハードに仮体したInstalled Keyは不変。(当然「設定」-「システム]-「ライセンス認証」アクティブ

 

 

です。

 

週が明けると直ぐにサポートからOEMキーが送られてきて、私も精いっぱいの感謝を伝えましたが、↑のとおり、RETAILチャネルでハード固有のInstalled Keyでライセンス認証されているので(敢えて「設定」-「システム]-「ライセンス認証」-「プロダクトキーを変更する」を実行する必要性が認められず)、このまま使用することに決めました。(OEMキーは何かのために大事に取っておきましょう。)

 

ここにも書きましたが、CHUWIのRyzen 7マシンからTrigKeyのCore-i9マシンへのデータや環境の設定移行も、データバックアップとMicrosoftのグローバルアカウントを使って難なく()完了し、現在従前と変わりない使用環境でスムースなmini PC生活を送っています。

:正確に言うと旧機で開発したIDとパスワードを暗号化して管理するソフトの移行で解読ができない、という問題が発生しましたが、これは私の勘違いからトラブル化(ボケ由来?)しただけで、すぐに復旧しました。

 

ということで、

 

一件落着

 

です。本シリーズの目的である

 

「中国製のmini PCってどーよ?」とか、「PCには余り詳しくないけど、日本製メーカーのものでなくて大丈夫?」という疑問や不安を持っておられる方の一助になる

 

という意味では、

 

(1)安くて、省スペースで、機能的にハイスペックな中国製mini PCは断然選択肢の一つ

(2)とはいえ、信用性については自己責任でメーカーや販路などの情報を十分にとって調査、分析することが必要

(3)(最近の「排外」「反中」環境があり)なんでも「中国はダメ」「中国は危ない」という反応は合理的ではない

 

といえるでしょう。私が2度mini PCを購入した経験から言えば

 

「あり」

 

だと思います。

 

ということで、本シリーズは完了なんですが、

 

では、(最近立ち上がりが不安定な)CHUWIのRyzen 7マシンをどーする?

 

という問題が残り、

 

いっそ、こいつもクリーンインストールして同じデータを消去し、全く別の用途で使おう!

 

ということで

 

そうしました!

 

(旧機と「全く別の用途」については追って【無駄話】で「旧機をどーする?」を書き、その用途について新しいシリーズを始めようかと思います。)

 

前回、新たに購入したmini PCの現物が来てクリーンインストールをする際に逆上し、製造元のサポートへ「OEMキーをください」と連絡をとったというところまで書きました。

 

特に十分に新しい「今年の夏に書かれたwebの記事(2025年7月)」で、ライセンスの販売チャネルとプロダクトキーの一部を表示する(Visual Basic Scriptで書かれた)コマンド、

 

"slmgr.vbs -dli"

 

は動くのですが、(旧機では動いた)"wmic"コマンド

 

"wmic path softwarelicensingservice get OA3xOriginalProductKey"

 

が使えず、PowerShellによるプロダクトキーの確認もできなかったことが最大の問題でした。(Windows 95からの「手動インストール世代」の私にとっては、「プロダクトキーがなければインストール不能という常識」が強かったので。)

 

しかし、Ianさんから「OK、分かった。また連絡するよ。」という連絡を週末受け取った後、(週末の時間があるので)自分でも少し調べてみよう」ということで各種キーと「デジタル認証」について調べてみました。

 

まず、「プロダクトキーが何か」を調べる前にその確認方法をチェックして、Microsoft Store(要すればMSのお墨付きソフト)に"ProductKeys"と"ShowKeyPlus"というフリーソフトがあることを調べ、両方ダウンロードして使ってみましたが、"ShowKeyPlus"の方が断然優れているのでこれを使うことにしました。

 

"ShowKeyPlus"を実行すると"OEM Key"に"OEM Key not present in firmware"と表示されます。()また、"Installed Key"の25桁の後にアスタリスクがあり、末尾の"Default Key - requires Degital License for activation"を引用しているので、(その時はまだ)「(VOLUME_MAKチャネルの)本製品にはOEM Keyがなく、有効化するにはデジタル認証が必要」と理解し、「矢張りOEMキーがなければだめじゃないか?」と誤解していました。

:以下の画像は(クリーンインストール前の画像をとっていなかったので)クリーンインストール後のものです。ただし、"OEM Key"の文言は全く同じでした。

 

 

一方、基本的な用語の意味の調査も行いました。例えば、「ライセンス認証」とは「プロダクト キーまたはデジタルエンタイトルメント(デジタルサービスやデータに対する「利用権」や「権利」)デバイスのハードウェア構成ペアにする技術的なプロセス」で「プロダクト キーまたはデジタルエンタイトルメントがハードウェア構成に対して有効であることを保証」します。(出典)要すれば、「特定のPC(ハードウェア構成)がWindowsというOS(デジタルサービスやデータ)を使うことができるためにはプロダクトキーが必要」ということです。

 

そんなこたぁ、わかっとるわい!

 

ところで「プロダクト キー」や「Installed Key」や「OEM Key」というものがあるようですが、これらはどうも、それぞれライセンスの種類や状態を表すようです。調べたところでは、


(1) プロダクトキー (Product Key):
Windows 11を正規にインストールして使用するための、
25桁の英数字コードです。
リテール版(パッケージ販売版-プロダクトキーがシールに記載)のプロダクトキーは、PC購入時のパッケージや、購入したオンラインストアなどから入手でき、別のPCへ移行して使用できます。メーカー製のPCに付属するプロダクトキーは、OEM版の可能性があります。

(2) インストール済みキー (Installed Key):

PCに最初からWindowsがインストールされている場合インストールされているライセンス認証済みのプロダクトキー、またはデジタルライセンスを指し、通常プロダクトキーの入力は不要です。(マザーボードに紐づいた「インストール済みキー」で自動的にライセンス認証が行われるためです。)

(3) OEMキー (OEM Key):

ハードウェアメーカーのPCにプレインストールされているWindowsに紐付けられたプロダクトキーで、通常マザーボードに紐づいているため、別のPCへ移行することはできず、PCの交換やマザーボードの交換を行うと、ライセンス認証が無効になる場合があります。 
 

フ~ン...

 

要すれば「最初っからWindows 11が入っているPCは、「Installed Key」キーであり、販売チャネルによる違い(OEM vs. VOLUME)があるにせよ、CPUやマザーボードというハードウェアに埋め込まれたプロダクトキーで認証が行われる(デジタルライセンス認証)ので、通常手動によるプロダクトキーの入力は不要」ということのようです。

 

この「デジタルライセンス認証」を確認する意味で、ご本家の関連サイトに行き、

 

デジタル ライセンスは、お使いのハードウェアに関連付けられ、Microsoft アカウントにリンクされているため、PC 上で探す必要はありません。 PC がインターネットに接続され、Microsoft アカウントにログインすれば準備は完了です。

 

お墨付きが得られました。

 

現実に現在のmini PC(「ハードウェア構成」)がWindows 11の「設定」-「システム」-「ライセンス認証」で「アクティブ」となっているので、すでにこのマシンのWindows 11 Proの利用権(プロダクトキー)ハードウェアに仮体(無体物が有体物の一部のようになっている状態)していると考えてよいようです。では、

 

本当にそうだか、いけるところまで行ってみよう!

 

ということで、(サポートからOEMキーが届く前ですが)クリーンインストールを実行してみました。

 

3.ドライバーの保存
まず、すでに作成していたWindows 11インストールメディア(メモリースティック)に"drivers"というフォールダーを作成し、管理者権限のコマンドプロンプトから"pnputil /export-driver * D:\drivers"を入力、実行し、きれいにエクスポートされました。

 

6.USBメモリで起動
電源を入れてDelを連打し、ブートメニューで接続したUSBメモリを指定して立ち上げます。

7.Windowsセットアップ
言語、時刻と通貨の形式、キーボード方式(Microsoft IME)等を設定し、OSエディションの選択画面で(私が購入したmini PCがWindows 11がProなので)「Windows 11 Pro」を選択し、インストールの種類を「カスタム:Windowsのみをインストールする (詳細設定)」にします。

8.パーティションの削除とストレージの初期化
不要なパーティションを一つずつ削除し、最終的に「ディスク0」が未割当領域、「ディスク1:パーティション1(USB)」を残して次に進みます。

9.Windows 11 Proのクリーンインストール
再起動時に再びブートメニューを呼び出し、USBメモリから起動しないようにPCのSSDストレージを指定して再起動し、完了を待ちます。

10.Windows 11の初期設定(OOBE)
「ネットワークに接続しましょう」画面でインターネットに接続し、私のMSグローバルアカントを使いました。(ログイン時のPINも作成します。)

11.デバイスマネージャーでの「不明なデバイス」の確認
「デバイスマネージャー」を起動し、十数個あった黄色のマーク「」がついたデバイスを一つづつ、「コンピューターを参照してドライバーを検索」でメモリースティックに保存したドライバーを指定して更新します。

12.ライセンスの再確認
基本的なWindowsのインストールを終了したので、コマンドプロンプトで"slmgr -dli"を実行すると、

 

 

「プロダクトキーの一部」はクリーンインストール前と同じままで、"VOLUME_MAK"チャネルが"RETAIL"チャネルになっています。「設定」-「システム」-「ライセンス認証」でも(手動入力無しでも)デジタルライセンスによって」認証されました。

 

 

成功!

13.Windows Update
利用可能な更新を全てインストールします。一旦終わっても再度チェックすると更新プログラムが出てくるので、何度か繰り返しましょう。

 

要すれば、webにある「中国製PCは安全か?」「中国製製品による情報漏洩」「中国製製品に対するセキュリティ対策」等々の記事により、

 

滅茶苦茶不安!

 

になったのですが、この記事(前のCHUWIも「B」のお墨付き)の内容を裏付けるようなサポート体制や製品品質であったということです。まぁ、

 

何事も疑ってかかり、安全策をとることは必要

 

ではあるのですが、

 

幽霊の正体見たり枯れ尾花

 

ということもある、という話でしょう。なお、この話はまだちょっとだけ続けます。

 

お約束通り、これからは前回書いた流れに沿って話を進めてゆきます。

 

まず、製品(TrigKey Key i13)が届く前に、

 

4.Windows 11インストールメディア(注)の作成
5."ei.cfg"ファイルの作成、保存(注意:購入したmini PCのWindows 11がProの場合)

前回書いた通り、Microsoftのダウンロードサイトで「MediaCreationTool.exe」を入手し、このプログラムを実行して「8GB以上のUSBメモリ」に展開して作成します。

 

を済ませたことは既に書きました。後は製品待ちですが、Amazonは製品の発送、輸送中、配送、到着とメールで細かく報告してはくれるのですが、「(いつの間にか)置き配」になっているのはどういうことでしょう?

 

とまれ、

 

クリスマスプレゼントのように「紙袋に入ったmini PCの製品

 

 

はいつの間にか入り口に置かれていました。(外装箱は結構素敵なデザインですね。)そしてこの箱を開けると、

 

 

 

とってもコンパクトな本体、電源コード(造りがしっかりしていて好感が持てます)、HDMIケーブル(これは親切!)と多言語で書かれUser(s) Manual(内容は極めて乏しかった!)が入っています。

 

早速電源、キーボード、マウス、ディスプレーにつないでセットアップを行い、Windows 11の「設定」-「システム」メニューで確認と基本動作テストを行います。

 

(1) まずシステムスペックは確かにアマゾンで書かれた通りの内容(Intel Core i9-13900HK、32GBメモリー、64bit Windows 11 Pro)でした。(解説:「システム」ー「バージョン情報」で「デバイスID」と「プロダクトID」を確認できますが、これらはキーではありません。また、これらのIDはクリーンインストールを行うと変更されます。

 

(2) 次に「設定」-「システム」-「ライセンス認証」メニューで確認すると、確かに「アクティブ」に緑のチェックが入っています。

 

(3) 次にコマンドプロンプトを使い、"slmgr -dli"コマンドでライセンスを確認すると、懸念された「VOLUME_MAK」チャネルのライセンスであることがわかります。(解説:しかし、「プロダクトキーの一部」に記載があることから、プロダクトキー==インストールキーは存在して、合法にインストールされていると考えられます。が、その時はあまりよくわかっていなませんでした。

 

 

この結果、このサイトで「ハズレ個体」と書かれているので「必ずOEMまたはRETAILのプロダクトキーを取得することが必要」と思い込んでしまいました。

 

(4) いずれにしても上のサイトの次の記事(「プロダクトキーの抽出と保存」)に従って、現在のプロダクトキーをとっておかなければならないと思い、書かれている通り、コマンドプロンプトから

 

"wmic path softwarelicensingservice get OA3xOriginalProductKey"

 

を実行すると、(これも旧PCではキチンと実行され、出力が出ていましたが...)

 

 

という予想外の事態が発生。慌てて調べてみると、ご本家から「もう使わんでくれ」とのお達しが出ていた由。

(旧機では動いていたのにぃー)何とかならんのか?」ということで、wmic.exeを復活させようとするのですが、そうするとすぐにOSがこれを無効化してしまい、全く使えないことが判明しました。「では、PowerShellで行こう!」と出直しますが、結局「管理者としてPowerShellを開き、" (Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xProductKey"と入力」しても、何も帰ってこない(== プロダクトキーがない???)という事態に逆上して、すぐにTrigKeyのサービスを調べ、上の顛末を画像付きで、「だんまり、だったらどうしよう...アセアセ」と不安に思いながら、メールで送ります。

 

そして、

 

案に相違して「2025年11月27日15:58」に送った英文の照会状に対して、「2025年11月27日17:04」にBettieさんから迅速で親切な返信

 

"Thank you for your letter.

We will apply for an OEM Key for you.

 

Please provide a picture of the bottom of your machine with the SN code and a record of your machine purchase.
Meanwhile, please check if your machine is an OEM Key in the following way.
Press Windows+R at the same time, input cmd , press enter.  Input the command slmgr.vbs -dli, press enter.  Send us the shown message. 

 

Have a beautiful day!"

 

が来て、必要な情報のやり取りが始まりました。この要請に対して画像を送ると、次はBonyさんから"purchase records that include the store where the purchase was made, the purchase time, and the order number"が必要、と連絡が来ました。さあ大変。アマゾンで海外から物品を購入したので、そのサイトの画像を送っても「購入記録」や「販売店」情報がわかりません。頭を抱えてアマゾンの当該購入履歴を確認すると「Invoice」を取得できるようじゃないですか!このPDFのInvoiceを取得すると、そこにオーダー日時、番号や深圳の販売店の情報が書かれており、何とか対応することができました。

 

その結果、

 

Ianさんから「OK、分かった。また連絡するよ。」という連絡を週末に受け、週明け(メール日付は2025年12月1日)に、Georgeさん(この時はTrigKeyのサポート)から別メールでOEMキーを送る、という連絡が入り、Georgeさん(この時は別メーカーのBeelinkのメールアドレス)からOEMキーをもらいました。確かに受け取ったという確認メールに関係したすべての担当の方に謝意を送ると、Ianさんから、

 

" Hi ,(名前)

 

Glad to help anytime !  have a nice day ~
Many thanks. "

 

という有難い返信をもらいました。

 

迅速で親切なサービスとフォローアップ。評価は大幅にアップ!となりました

 

が、

 

実はそれが無駄になってしまったのです。(次回に続く)

 

ps. プロダクトキーの確認については、wmicコマンドも、PowerShellでもできませんでしたが、実はもっと安全で確実な方法がありました。それも次回お話しします。(後で追加しました)

既に何度か途中経過()を書いてきましたが、(前回のCHUWI製 AMD Ryzen 7 + Radeonマシンに引き続き、)この度またまたmini PC(TrigKey製 Intel Core-i9マシン)を購入し、現在データ移行中です。

【無駄話】ブラックフライデー

  【無駄話】悪戦苦闘中...

  【無駄話】悪戦苦闘中...(2)

  【無駄話】悪戦苦闘終了...(3)

 

先ずは「百聞は一見に如かず("Seeing is believing")」。これ(↓)が現状です。

 

円形ターンテーブルに載っているのは(下から)CHUWI製旧PC、TrigKey製新PC、USBスイッチャー、カメラとなります。これらの状況を説明すると、

 

(1)今回はディスプレー(接続:アナログ、デジタル、Displayport)、キーボード・マウス(一対無線接続型)はそのまま使用し、PCだけ(取り敢えず、「落ち着く」までは交換ではなく)追加する形をとりました。

 

(2)その為、(最終的には交代させますが)旧PCがDisplayportのまま、新PCを(取り敢えず音無しで)HDMI(High-Definition Multimedia Interface)からデジタルポートへ二重接続()し、キーボードとマウスはUSB切替スイッチ(↑の写真のカメラの左側にあるデバイス)で共用です。

:好奇心に駆られて、新旧PCを同時にディスプレーに接続したら、Displyportが優先されて「二重表示」にはなりませんでした。残念。

 

(3)新PC(小さいですね。容量的には旧PCの半分ほどです。)は購入後、(泣く泣く)クリーンインストール、基本初期設定後、旧機のバックアップデータを使って現在整備中で、出来高95%というところです。完全にデータ移行し、今後のバックアップ方針を立てて、最終的に旧PCの今後を決めるつもりです。

 

さて、

 

以降本シリーズでは、「中国製のmini PCってどーよ?」とか、「PCには余り詳しくないけど、日本製メーカーのものでなくて大丈夫?」という疑問や不安を持っておられる方の一助になるような話をするつもりです。(今回のmini PC購入で、私も3年ブランクのハード知識を今更ながらアップデートすることになりましたので。)

 

先ず、

 

最初(【無駄話】ブラックフライデー)に書きましたように、「ポチッ」としてからメーカーを調べたり、安全対策を勉強したり、という後手を踏みましたので、webにあった「製品が届いたらすべきこと」を(一番腑に落ちた)2005年7月の記事(↓)に沿って、自分なりに整理してみました。今後はこれに沿って話を進めてまいりましょう。

 

【2025年最新版】中華ミニPCを安全に使うためにWindows 11 Proをクリーンインストールした」

(https://zenn.dev/km100/articles/7f13605224c44a)

事前に新しいPCに(Bluetoothは不可らしい)キーボード、マウスを接続してリリース状態で動く状態にする。

1.PCスペック確認
Windows メニュー→「設定」→(ダイアログメニュー)「システム」→(最下段)「バージョン情報」(解説:旧PCの「システム」→「ライセンス認証」は勿論「アクティブ」になっています。)

2.ライセンスとプロダクトキーの確認
【ライセンス】
(メニュー検索+"cmd"等で)コマンドプロンプトを呼び出す。
"slmgr -dli"を入力実行し、ダイアログの「プロダクトキーチャネル」に個人向けライセンスの「RETAIL」または「OEM」となっていること(即ち、事業者向けの「VOLUME_MAK」や「VOLUME_KMS」ではないこと)を確認する。(解説:旧PCでは「OEM」キーになっていました。)

【プロダクトキー】
同様にコマンドプロンプトから"wmic path softwarelicensingservice get OA3xOriginalProductKey"と入力実行し、プロダクトキーを確認する。

3.ドライバーの保存
管理者権限のコマンドプロンプト()から"pnputil /export-driver * (コピー先Path)"を入力実行する。

:メニュー検索+"cmd"とすると、右側に「コマンドプロンプト」と表示され、その下にある「管理者として実行する」を選択する。また、「コピー先Path」はなんでもよいのですが、私は次のインストールメディアを入れたメモリースティッに"drivers"というフォールダーを作ってそこに入れました。(解説:旧PCで試しましたが、きれいにエクスポートされました。)


4.Windows 11インストールメディアの作成
Microsoft公式 Windows 11ダウンロードページで、「Windows 11のインストールメディアを作成する」の「今すぐダウンロード」ボタンをおして「MediaCreationTool.exe」を入手し、このプログラムを実行して「8GB以上のUSBメモリ」にツールを作成する。(解説:これは旧PCで事前に作成しました。)

5."ei.cfg"ファイルの作成、保存(注意:購入したmini PCのWindows 11がProの場合)
インストール時にHome版が選択されるのを防ぎ、確実にPro版をインストールするため"ei.cfg"という設定ファイルを作成、Windows 11インストールUSBメモリ内の"Sources"フォルダに保存。(解説:これも旧PCで作成した↑のツールにエディターで作成したファイルを入れました。)
 

【ei.cfg】
[EditionID]
[Channel]
Retail
[VL]
0

6.USBメモリで起動
電源を入れてF2、Del、F7、F12、Escなどを連打し、BIOS/UEFI設定画面またはブートメニューを呼び出し、接続したUSBメモリ(「UEFI: [USBメモリ名]」)を指定する。

7.Windowsセットアップ
言語、時刻と通貨の形式、キーボード方式(Microsoft IME)等を設定し、OSエディションの選択画面で「Windows 11 Pro」を選択。(購入したmini PCのWindows 11がProの場合)インストールの種類は「カスタム:Windowsのみをインストールする (詳細設定)」を選択。

8.パーティションの削除とストレージの初期化
表示されている「ディスク0 」の全てのパーティションを一つずつ選択、削除し、最終的に「ディスク0」が未割当領域、「ディスク1:パーティション1(USB)」を残して次に進む。(ディスク1のUSBを削除しないように。)

9.Windows 11 Proのクリーンインストール
数回再起動()するので、PCの電源を切らずに完了を待つ。
:再起動時に再びブートメニューを呼び出し、USBメモリから起動しないようにPCのSSDストレージ優先に再変更する。

10.Windows 11の初期設定(OOBE)
web記事では、「ネットワークに接続しましょう」という画面でShift + F10 キーを押し、コマンドプロンプトを起動して"start ms-cxh:localonly"を実行し、ローカルアカントを作るようになっていますが、私はインターネットに接続し、MSのグローバルアカントを使いました。

11.デバイスマネージャーでの「不明なデバイス」の確認

Windowsキー+'x'で呼ぶメニューから「デバイスマネージャー」を起動し、黄色のマーク「」がついたデバイスを、右クリックメニューの「ドライバーの更新」、「コンピューターを参照してドライバーを検索」を選択して上記(3.ドライバーの保存)のドライバーを設定する。

12.ライセンスの再確認
コマンドプロンプトで"slmgr -dli"を実行して「RETAIL」チャネルになっていることを確認する。

13.Windows Update
「設定」→「システム」→「電源とバッテリー」の「画面とスリープ」で、「電源接続時にデバイスがスリープ状態になるまでの時間」を「なし」に設定し、「設定」→「Windows Update」から「更新プログラムのチェック」を行い、利用可能な更新を全てインストールする。

この間、つなぎで書いた【無駄話】悪戦苦闘中...(2)ですが、とうとうトラブルシューティングも終わり、新PCのセットアップを行えるようになりました。(因みにこの記事が新PCの寄稿第1号です。)

 

詳しくはシリーズ物でお伝えしますが、深圳に「OEMキーおくれ」と頼んで、戴きましたが、戴かなくともデジタル認証ができたので大丈夫だったということですが、

 

Product ID

Product Key

Installed Key

OEM Key

等々

似たような言葉が多数あって混乱しますね。これも含めてシリーズでお話しさせていただこうかと思います。

 

ps. 未だRZBOXマシンで使っていたソフトの移行が完全ではないので、新PCへ完全に移行してから新PCシリーズを開始したいと思います。

 

CHUWIのAMD Ryzenマシンの立ち上がりが不安定なので、IntelのCore-i9マシンを発作的にポチっとしたことを書きました。(【無駄話】ブラックフライデー

 

また、想定されたことですが、「機械は良いが、ソフトが不安」)ということで、実はリテール/OEMライセンスではないことを確認し、プロダクトキー(インストールする為のパスワード)が無いとしてメーカーのサポートへ連絡を取っています。(【無駄話】悪戦苦闘中...

:これは1990年代、米国に駐在していた際に、日本製品について米国人に言われたことです。それで思い出しましたが、第2次大戦後から高度成長期にかけての日本製品の評判は「安かろう、悪かろう」というのが定番で"Made in Japan"は「粗悪品」と同義であったこと等、今の若い人は分かりませんよね?その後、日本は企画、設計、製造、品質管理で20世紀に世界の頂点に立ったのが、既に「今は昔」。"Mama, co you remember."です。

 

私が連絡しているのは深圳の方で、(どうもTrigKeyだけではなく、アウトソースサービスの様でBeelink、Geekomなどもやってそうです)途中からファーストネームの"Bony"さんを開示してくれました。現在と連絡を取って必要な情報を渡し終えて(週末になったので)今週には解決できるのでは、と思っています。

 

そーしたら、

 

矢張り(Office365とかIntelのツールとかはいっていますが)一旦プリインストールのWindowsは捨てて、クリーンインストールしてみようかと思っています。

 

その後に今回の顛末をお話ししましょう。