.NETプログラミング研究 第37号 †
.NET質問箱 †
「.NET質問箱」では、「どぼん!のプログラミング掲示板」に書き込まれた.NETプログラミングに関する投稿を基に、さらに考察を加え、Q&A形式にまとめて紹介します。
拡張子に関連付けられた実行ファイルのパスを取得するには? †
【質問】
あるファイルの拡張子に関連付けられている実行ファイルのフルパスを取得するには、どのようにすればよいでしょうか?
【回答】
まず、Win32 APIのFindExecutable関数を使う方法が考えられます。
この場合、次のようなコードで実行ファイルのパスを取得できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| | Class MainClass
<System.Runtime.InteropServices.DllImport("shell32.dll")> _
Public Shared Function FindExecutable(ByVal lpFile As String, _
ByVal lpDirectory As String, _
ByVal lpResult As System.Text.StringBuilder) As Integer
End Function
Public Shared Sub Main()
Dim fileName As String = "C:\test.txt"
Dim exePath As New System.Text.StringBuilder(255)
If FindExecutable(fileName, Nothing, exePath) > 32 Then
Console.WriteLine(exePath.ToString())
Else
Console.WriteLine("失敗しました。")
End If
End Sub
End Class
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| | class MainClass
{
[System.Runtime.InteropServices.DllImport("shell32.dll")]
public static extern int FindExecutable(
string lpFile, string lpDirectory,
System.Text.StringBuilder lpResult);
public static void Main()
{
string fileName = "C:\\test.txt";
System.Text.StringBuilder exePath =
new System.Text.StringBuilder(255);
if (FindExecutable(fileName, null, exePath) > 32)
{
Console.WriteLine(exePath.ToString());
}
else
{
Console.WriteLine("失敗しました。");
}
}
}
|
しかし残念ながらFindExecutableには、関連付けられた実行ファイルのパスにスペース文字が含まれる時、はじめのスペースがnull文字で置き換えられてしまうというバグがあります。このために、例えば実行ファイルのパスが、
C:\Program Files\Microsoft Office\WINWORD.EXE
であった場合、FindExecutableは、
C:\Program
という文字列を返したかのようになってしまいます。
FindExecutableのようなWin32 APIを使用しなくても、拡張子の関連付けに関する情報はレジストリに保存されていますので、レジストリを調べれば拡張子に関連付けられた実行ファイルのパスは分かります。
拡張子の関連付けに関する情報は、レジストリのHKEY_CLASS_ROOTにあります。具体的には、"HKEY_CLASS_ROOT\(拡張子)"というキーにその拡張子に関連付けられているファイルタイプ名が格納されており、"HKEY_CLASS_ROOT\(ファイルタイプ名)\shell\(openなどのアクション名)\command"というキーに実行ファイルのパス(コマンドライン引数を含む)が格納されています。
レジストリを調べて拡張子に関連付けられた実行ファイルのパスを取得するコードの例を示します。ここでは実行ファイルのパスだけでなく、コマンドライン引数が付いたまま返しています(つまり、「アクションを実行するアプリケーション」で指定されている文字列をそのまま返します)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| | Public Shared Function FindAssociatedExecutableFile( _
ByVal fileName As String, ByVal extra As String) As String
Dim extName As String = System.IO.Path.GetExtension(fileName)
Dim regKey As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(extName)
If regKey Is Nothing Then
Throw New Exception("見つかりませんでした。")
End If
Dim fileType As String = CStr(regKey.GetValue(""))
regKey.Close()
Dim regKey2 As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.ClassesRoot.OpenSubKey( _
String.Format("{0}\shell\{1}\command", fileType, extra))
If regKey2 Is Nothing Then
Throw New Exception("見つかりませんでした。")
End If
Dim command As String = CStr(regKey2.GetValue(""))
regKey2.Close()
Return command
End Function
Public Shared Function FindAssociatedExecutableFile( _
ByVal fileName As String) As String
Return FindAssociatedExecutableFile(fileName, "open")
End Function
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| | public static string FindAssociatedExecutableFile(
string fileName, string extra)
{
string extName = System.IO.Path.GetExtension(fileName);
Microsoft.Win32.RegistryKey regKey =
Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(extName);
if (regKey == null)
throw new Exception("見つかりませんでした。");
string fileType = (string) regKey.GetValue("");
regKey.Close();
Microsoft.Win32.RegistryKey regKey2 =
Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(
string.Format(@"{0}\shell\{1}\command", fileType, extra));
if (regKey2 == null)
throw new Exception("見つかりませんでした。");
string command = (string) regKey2.GetValue("");
regKey2.Close();
return command;
}
public static string FindAssociatedExecutableFile(
string fileName)
{
return FindAssociatedExecutableFile(fileName, "open");
}
|
拡張子に関連付けられている実行可能ファイルパスを取得するためのAPIには、AssocQueryString関数もあります。これを使用するには、Internet Explorer 5以上が必要となります。詳しくは次のリンク先をご覧ください。
○この記事の基になった掲示板のスレッド
ピクチャボックスに表示されている画像をドラッグ&ドロップする †
【質問】
ピクチャボックスに表示されている画像をワードパッドやWordなどのアプリケーションにドラッグ&ドロップしてデータを渡したいのですが、どのようにすればよいでしょうか?
【回答】
ドラッグ&ドロップの操作を開始するには、コントロールのDoDragDropメソッドを使いますが、ワードパッドやWordにドラッグ&ドロップでデータを渡す場合は、DoDragDropメソッドのドラッグするデータに画像のImageオブジェクトやBitmapオブジェクトをそのまま指定するだけで大丈夫のようです。なお、ドラッグ&ドロップの基本的な方法については、「ドラッグ&ドロップを行う」をご覧ください。
例えば、ピクチャボックス"PictureBox1"のImageプロパティに設定されている画像をドラッグするためのコードは、次のようになります。(ここではPictureBox1のMouseDownイベントハンドラPictureBox1_MouseDownでドラッグを開始しています。)
1
2
3
4
5
6
| | Private Sub PictureBox1_MouseDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles PictureBox1.MouseDown
PictureBox1.DoDragDrop(PictureBox1.Image, DragDropEffects.All)
End Sub
|
1
2
3
4
5
6
| | private void PictureBox1_MouseDown(
object sender, System.Windows.Forms.MouseEventArgs e)
{
PictureBox1.DoDragDrop(PictureBox1.Image, DragDropEffects.All);
}
|
さらに、画像をアプリケーションにドロップしたときに、画像のイメージに加えさらに画像ファイルのデータを渡すための方法がニュースグループの次のスレッドに投稿されています。
この方法によると、まずピクチャボックスに表示されている画像がファイルに保存されていない時はこれをファイルに保存してから、DataObjectオブジェクトのSetDataにより画像ファイルのパスとイメージを格納し、DoDragDropメソッドによりドラッグを行うというものです。
次にこの方法を使った例を示します。前と同様にピクチャボックス"PictureBox1"のImageプロパティに設定されている画像をドラッグするものとし、この画像はすでに"C:\temp.bmp"というファイルに保存されているものとします。画像が保存されていない場合は、あらかじめSaveメソッドにより保存するようにしてください。
1
2
3
4
5
6
7
8
9
10
11
12
| | Private Sub PictureBox1_MouseDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles PictureBox1.MouseDown
Dim fileNames As String() = {"c:\temp.bmp"}
Dim dataObj As New DataObject(DataFormats.FileDrop, fileNames)
dataObj.SetData(DataFormats.Bitmap, Image.FromFile(fileNames(0)))
PictureBox1.DoDragDrop(dataObj, DragDropEffects.All)
End Sub
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| | private void PictureBox1_MouseDown(
object sender, System.Windows.Forms.MouseEventArgs e)
{
string[] fileNames = {"c:\\temp.bmp"};
DataObject dataObj =
new DataObject(DataFormats.FileDrop, fileNames);
dataObj.SetData(
DataFormats.Bitmap, Image.FromFile(fileNames[0]));
PictureBox1.DoDragDrop(dataObj,DragDropEffects.All);
}
|
この方法でドラッグ&ドロップした場合、ドロップ先がエクスプローラである場合はもちろん、ワードパッドなど多くのアプリケーションへのドロップでも単にファイルのドロップとして扱われてしまうようです。
○この記事の基になった掲示板のスレッド
DataGridにLinkLabelを表示するには? †
【質問】
System.Windows.Forms.DataGridコントロールにLinkLabelを表示して、ハイパーリンクがはられているようにしたいのですが、どのようにすればよいでしょうか?
【回答】
DataGridColumnStyleクラスから派生した新しいクラスを作成することにより実現させる方法が適当だと思いますが、問題はどのようにLinkLabelを表示するかという点でしょう。
一番簡単で分かりやすいのは、DataGridColumnStyleクラスのEditメソッドでLinkLabelコントロールを表示するという方法です。ピラルクさんが掲示板に投稿していただいた方法や、ニュースグループ「microsoft.public.dotnet.framework.windowsforms」に投稿されたTravis Merkelさんの方法がこれです。DOBON.NET .NET Tipsで紹介している「DataGridでComboBoxを使う」のComboBoxをLinkLabelにそのまま代えたという感じです。
この方法はEditメソッドでLinkLabelを表示しているため、セルがアクティブになってからLinkLabelが表示され、はじめからLinkLabelが表示されるわけではありません。
この方法を使った簡単なサンプルを下に示します(かなりの手抜きです)。ここでは、LinkLabelをクリックすると、セルに表示されている文字列をProcess.Startメソッドに渡して呼び出しています。なお、DataGridColumnStyleクラスの使用法に関しては、「DataGridの列の幅を変更する」をご覧ください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
| | Imports System
Imports System.Data
Imports System.Drawing
Imports System.Windows.Forms
Namespace Dobon.Samples.Forms
Public Class DataGridLinkLabelColumn
Inherits DataGridTextBoxColumn
Private _linkLabel As LinkLabel
Public ReadOnly Property LinkLabel() As LinkLabel
Get
Return _linkLabel
End Get
End Property
Public Sub New()
_linkLabel = New LinkLabel
AddHandler _linkLabel.Click, AddressOf _linkLabel_Click
End Sub
Protected Overloads Overrides Sub Edit( _
ByVal source As System.Windows.Forms.CurrencyManager, _
ByVal rowNum As Integer, _
ByVal bounds As System.Drawing.Rectangle, _
ByVal [readOnly] As Boolean, _
ByVal instantText As String, _
ByVal cellIsVisible As Boolean)
MyBase.Edit(source, rowNum, bounds, [readOnly], _
instantText, cellIsVisible)
TextBox.Visible = False
_linkLabel.Parent = TextBox.Parent
_linkLabel.Bounds = bounds
_linkLabel.Text = TextBox.Text
_linkLabel.Visible = True
_linkLabel.BringToFront()
_linkLabel.Focus()
End Sub
Private Sub _linkLabel_Click( _
ByVal sender As Object, ByVal e As EventArgs)
Dim link As LinkLabel = CType(sender, LinkLabel)
System.Diagnostics.Process.Start(link.Text)
End Sub
End Class
End Namespace
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
| | using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
namespace Dobon.Samples.Forms
{
public class DataGridLinkLabelColumn : DataGridTextBoxColumn
{
private LinkLabel _linkLabel;
public LinkLabel LinkLabel
{
get {return _linkLabel;}
}
public DataGridLinkLabelColumn()
{
_linkLabel = new LinkLabel();
_linkLabel.Click += new EventHandler(_linkLabel_Click);
}
protected override void Edit(
CurrencyManager source,
int rowNum,
Rectangle bounds,
bool readOnly,
string instantText,
bool cellIsVisible)
{
base.Edit(source, rowNum, bounds, readOnly,
instantText, cellIsVisible);
TextBox.Visible = false;
_linkLabel.Parent = TextBox.Parent;
_linkLabel.Bounds = bounds;
_linkLabel.Text = TextBox.Text;
_linkLabel.Visible = true;
_linkLabel.BringToFront();
_linkLabel.Focus();
}
private void _linkLabel_Click(object sender, EventArgs e)
{
LinkLabel link = (LinkLabel) sender;
System.Diagnostics.Process.Start(link.Text);
}
}
}
|
アクティブなセルだけでなく、すべての行にLinkLabelを表示するには、Paintメソッドで何らかの処理を行う必要があります。具体的には、必要な数だけLinkLabelコントロールを作成するか、あたかもLinkLabelコントロールのように文字列を描画するかということになるでしょう。
必要な数だけLinkLabelコントロールを作成する例が、ニュースグループ「microsoft.public.dotnet.framework.windowsforms.controls」に投稿されています。
この方法は、LinkLabelコントロールを行ごとにHashtableに保存しておき、Paintメソッドで必要に応じて配置するというものです。行ごとにLinkLabelコントロールを作成しているため、行が多くなると、かなりメモリを消費するでしょう。
それが嫌であれば、PaintメソッドでLinkLabelのような文字列を描画すればよいということになります。ここで問題なのは、どうやってクリックされたことを知るかということです。そのためには、例えばDataGridのMouseUpイベントでHitTestInfoメソッドを使ってセル上でマウスボタンが押されたか判断するという方法があります。LinkLabelの動作とはかなり違いますが、仕方のないところでしょう。
以下にPaintメソッドで文字列を描画するDataGridColumnStyleの簡単な例を示します。ここでは、DataGridのMouseMoveイベントでマウスがセル上にあるか調べ、そうであればマウスカーソルをハンドカーソルに変更しています。また、DataGridのMouseUpイベントでクリックされたことにしています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
| | Namespace Dobon.Samples.Forms
Public Class DataGridLinkLabelColumn2
Inherits DataGridTextBoxColumn
Private _margin As New Point(1, 2)
Private _visitedLinks As System.Collections.ArrayList
Private _dataGrid As DataGrid
Public Sub New()
_visitedLinks = New System.Collections.ArrayList
End Sub
Protected Overloads Overrides Sub Edit( _
ByVal [source] As CurrencyManager, _
ByVal rowNum As Integer, _
ByVal bounds As Rectangle, _
ByVal [readOnly] As Boolean, _
ByVal instantText As String, _
ByVal cellIsVisible As Boolean)
End Sub
Protected Overloads Overrides Sub Paint( _
ByVal g As Graphics, _
ByVal bounds As Rectangle, _
ByVal [source] As CurrencyManager, _
ByVal rowNum As Integer, _
ByVal backBrush As Brush, _
ByVal foreBrush As Brush, _
ByVal alignToRight As Boolean)
Dim [text] As String = _
GetColumnValueAtRow([source], rowNum).ToString()
Dim sf As New StringFormat
Select Case Me.Alignment
Case HorizontalAlignment.Left
sf.Alignment = StringAlignment.Near
Case HorizontalAlignment.Center
sf.Alignment = StringAlignment.Center
Case HorizontalAlignment.Right
sf.Alignment = StringAlignment.Far
End Select
If alignToRight Then
sf.FormatFlags = _
sf.FormatFlags Or _
StringFormatFlags.DirectionRightToLeft
End If
g.FillRectangle(backBrush, bounds)
Dim textBrush As Brush
If _visitedLinks.Contains([text]) Then
textBrush = Brushes.Purple
Else
textBrush = Brushes.Blue
End If Dim textFont As New Font( _
DataGridTableStyle.DataGrid.Font.FontFamily, _
DataGridTableStyle.DataGrid.Font.Size, _
DataGridTableStyle.DataGrid.Font.Style _
Or FontStyle.Underline)
Dim rectf As New RectangleF( _
bounds.X, bounds.Y, bounds.Width, bounds.Height)
rectf.Inflate(-_margin.X, -_margin.Y)
g.DrawString([text], textFont, textBrush, rectf, sf)
sf.Dispose()
textFont.Dispose()
End Sub
Protected Overrides Sub SetDataGridInColumn( _
ByVal value As DataGrid)
MyBase.SetDataGridInColumn(value)
AddHandler value.MouseMove, AddressOf DataGrid_MouseMove
AddHandler value.MouseUp, AddressOf DataGrid_MouseUp
_dataGrid = value
End Sub
Protected Overloads Overrides Sub Dispose( _
ByVal disposing As Boolean)
MyBase.Dispose(disposing)
RemoveHandler _dataGrid.MouseMove, _
AddressOf DataGrid_MouseMove
RemoveHandler _dataGrid.MouseUp, _
AddressOf DataGrid_MouseUp
End Sub
Private Sub DataGrid_MouseMove( _
ByVal sender As Object, ByVal e As MouseEventArgs)
Dim hti As DataGrid.HitTestInfo = _
DataGridTableStyle.DataGrid.HitTest(e.X, e.Y)
If hti.Type = DataGrid.HitTestType.Cell And _
hti.Column = _
DataGridTableStyle.GridColumnStyles.IndexOf(Me) Then
DataGridTableStyle.DataGrid.Parent.Cursor = _
Cursors.Hand
Else
DataGridTableStyle.DataGrid.Parent.Cursor = _
Cursors.Default
End If
End Sub
Private Sub DataGrid_MouseUp( _
ByVal sender As Object, ByVal e As MouseEventArgs)
Dim grid As DataGrid = DataGridTableStyle.DataGrid
Dim info As DataGrid.HitTestInfo = grid.HitTest(e.X, e.Y)
If info.Type = DataGrid.HitTestType.Cell And info.Column = _
DataGridTableStyle.GridColumnStyles.IndexOf(Me) Then
Dim cm As CurrencyManager = _
CType(grid.BindingContext( _
grid.DataSource, grid.DataMember), CurrencyManager)
Dim str As String = _
GetColumnValueAtRow(cm, info.Row).ToString()
System.Diagnostics.Process.Start(str)
_visitedLinks.Add(str)
End If
End Sub
End Class
End Namespace
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
| | namespace Dobon.Samples.Forms
{
public class DataGridLinkLabelColumn2 : DataGridTextBoxColumn
{
Point _margin = new Point(1, 2);
private System.Collections.ArrayList _visitedLinks;
DataGrid _dataGrid;
public DataGridLinkLabelColumn2()
{
_visitedLinks = new System.Collections.ArrayList();
}
protected override void Edit(
CurrencyManager source,
int rowNum,
Rectangle bounds,
bool readOnly,
string instantText,
bool cellIsVisible)
{
}
protected override void Paint(Graphics g,
Rectangle bounds,
CurrencyManager source,
int rowNum,
Brush backBrush,
Brush foreBrush,
bool alignToRight)
{
string text =
GetColumnValueAtRow(source, rowNum).ToString();
StringFormat sf = new StringFormat();
switch (this.Alignment)
{
case HorizontalAlignment.Left:
sf.Alignment = StringAlignment.Near;
break;
case HorizontalAlignment.Center:
sf.Alignment = StringAlignment.Center;
break;
case HorizontalAlignment.Right:
sf.Alignment = StringAlignment.Far;
break;
}
if (alignToRight)
sf.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
g.FillRectangle(backBrush, bounds);
Brush textBrush;
if (_visitedLinks.Contains(text))
textBrush = Brushes.Purple;
else
textBrush = Brushes.Blue;
Font textFont =
new Font(DataGridTableStyle.DataGrid.Font.FontFamily,
DataGridTableStyle.DataGrid.Font.Size,
DataGridTableStyle.DataGrid.Font.Style
| FontStyle.Underline);
RectangleF rectf = new RectangleF(
bounds.X, bounds.Y, bounds.Width, bounds.Height);
rectf.Inflate(-_margin.X, -_margin.Y);
g.DrawString(text, textFont,
textBrush, rectf, sf);
sf.Dispose();
textFont.Dispose();
}
protected override void SetDataGridInColumn(DataGrid value)
{
base.SetDataGridInColumn(value);
value.MouseMove +=
new MouseEventHandler(DataGrid_MouseMove);
value.MouseUp +=
new MouseEventHandler(DataGrid_MouseUp);
_dataGrid = value;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_dataGrid.MouseMove -=
new MouseEventHandler(DataGrid_MouseMove);
_dataGrid.MouseUp -=
new MouseEventHandler(DataGrid_MouseUp);
}
private void DataGrid_MouseMove(
object sender, MouseEventArgs e)
{
DataGrid.HitTestInfo hti =
DataGridTableStyle.DataGrid.HitTest(e.X, e.Y);
if (hti.Type == DataGrid.HitTestType.Cell &&
hti.Column ==
DataGridTableStyle.GridColumnStyles.IndexOf(this))
DataGridTableStyle.DataGrid.Parent.Cursor =
Cursors.Hand;
else
DataGridTableStyle.DataGrid.Parent.Cursor =
Cursors.Default;
}
private void DataGrid_MouseUp(object sender, MouseEventArgs e)
{
DataGrid grid = DataGridTableStyle.DataGrid;
DataGrid.HitTestInfo info = grid.HitTest(e.X, e.Y);
if (info.Type == DataGrid.HitTestType.Cell
&& info.Column ==
DataGridTableStyle.GridColumnStyles.IndexOf(this))
{
CurrencyManager cm =
(CurrencyManager) grid.BindingContext[
grid.DataSource, grid.DataMember];
string str = GetColumnValueAtRow(cm, info.Row).ToString();
System.Diagnostics.Process.Start(str);
_visitedLinks.Add(str);
}
}
}
}
|
これらの方法に不満があるならば、市販品を使うのがよいでしょう。LinkLabelを表示できるフリーのライブラリはほとんど見かけませんが、「Extended DataGrid」というものがあります。
○この記事の基になった掲示板のスレッド
コンピュータ雑学 †
ここでは、話すと人に嫌われるなまぬるいコンピュータに関する雑学
を紹介します。
Windows NTの「NT」の意味は? †
Microsoft Windows NTの「NT」の意味に関して、Microsoftは公式にはなんら言及をしていないようですが、Microsoftのいくつかの発行物では、「New Technology」の略で「NT」と説明されているようです。
しかし広く信じられている説には、別のものがあります。それは、「Windows NTの父」と呼ばれるDave CutlerがMicrosoftに来る前にDEC社で開発したOS、VMSのそれぞれのアルファベットを次の文字に進めた「WNT」から由来しているというものです。しかし、Windows NTははじめ「NT OS/2」と呼ばれていたことを考慮すると、この説はただの冗談であるように思われます。
さらには、Windows & .NET Magazine Networkの「WinInfo Daily UPDATE, January 24, 2003」によると、Windows NTの開発者の一人であるMark Lucovskyが「NT」の意味について、開発にi860のエミュレータである「N10」を使っていたため、「N-Ten」で動くことから「NT」と名づけたと明かしています。
一体どれが真実でどれがただの噂話(あるいは冗談)なのか、本当のところは誰にも分からないのかもしれませんね。
コメント †