-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathModule.cs
More file actions
137 lines (121 loc) · 4.07 KB
/
Module.cs
File metadata and controls
137 lines (121 loc) · 4.07 KB
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
// <copyright file="Module.cs" company="Microsoft Corporation">
// Copyright (C) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt in the project root for license information.
// </copyright>
namespace Microsoft.VisualStudio.Setup
{
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
/// <summary>
/// A native module.
/// </summary>
internal class Module : IDisposable
{
private readonly SafeModuleHandle handle;
private string path = null;
private Module(SafeModuleHandle handle)
{
this.handle = handle;
}
/// <summary>
/// Finalizes an instance of the <see cref="Module"/> class.
/// </summary>
~Module()
{
Dispose(false);
}
/// <summary>
/// Gets a value indicating whether the object is already disposed.
/// </summary>
public bool IsDisposed { get; private set; }
/// <summary>
/// Gets the path to the <see cref="Module"/>.
/// </summary>
public string Path
{
get
{
if (path == null)
{
var sb = new StringBuilder(NativeMethods.MAX_PATH);
var length = NativeMethods.GetModuleFileName(handle, sb, sb.Capacity);
if (length > 0)
{
path = sb.ToString();
}
}
return path;
}
}
/// <summary>
/// Gets the <see cref="Version"/> of the module.
/// </summary>
public Version Version
{
get
{
var path = Path;
if (!string.IsNullOrEmpty(path))
{
var info = FileVersionInfo.GetVersionInfo(path);
return new Version(info.FileMajorPart, info.FileMinorPart, info.FileBuildPart, info.FilePrivatePart);
}
return null;
}
}
/// <summary>
/// Gets a <see cref="Module"/> for a runtime-callable wrapper.
/// </summary>
/// <param name="object">An <see cref="object"/> that represents the COM object.</param>
/// <param name="module">The <see cref="Module"/> if the <paramref name="object"/> is a COM object.</param>
/// <returns>True if we could get the <see cref="Module"/> for a runtime-callable wrapper for the given COM object; otherwise, false.</returns>
public static bool TryFromComObject(object @object, out Module module)
{
if (@object != null)
{
var unk = Marshal.GetIUnknownForObject(@object);
if (unk != IntPtr.Zero)
{
try
{
var addr = Marshal.ReadIntPtr(unk);
if (NativeMethods.GetModuleHandleEx(GetModuleHandleExFlags.FromAddress, addr, out var handle))
{
module = new Module(handle);
return true;
}
}
finally
{
Marshal.Release(unk);
}
}
}
module = null;
return false;
}
/// <inheritdoc/>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes the object.
/// </summary>
/// <param name="disposing">True if the object is being disposed; otherwise, false if the object is being finalized.</param>
protected virtual void Dispose(bool disposing)
{
if (!IsDisposed)
{
if (!handle.IsInvalid)
{
handle.Dispose();
}
IsDisposed = true;
}
}
}
}