diff options
Diffstat (limited to 'MediaBrowser.Common')
| -rw-r--r-- | MediaBrowser.Common/Extensions/BaseExtensions.cs | 19 | ||||
| -rw-r--r-- | MediaBrowser.Common/Kernel/BaseKernel.cs | 3 | ||||
| -rw-r--r-- | MediaBrowser.Common/Kernel/BaseManager.cs | 49 | ||||
| -rw-r--r-- | MediaBrowser.Common/Kernel/IApplicationHost.cs | 7 | ||||
| -rw-r--r-- | MediaBrowser.Common/Kernel/TcpManager.cs | 78 | ||||
| -rw-r--r-- | MediaBrowser.Common/MediaBrowser.Common.csproj | 10 | ||||
| -rw-r--r-- | MediaBrowser.Common/Net/HttpManager.cs | 33 | ||||
| -rw-r--r-- | MediaBrowser.Common/Net/INetworkManager.cs | 72 | ||||
| -rw-r--r-- | MediaBrowser.Common/Net/NetUtils.cs | 219 | ||||
| -rw-r--r-- | MediaBrowser.Common/Win32/NativeMethods.cs | 631 |
10 files changed, 165 insertions, 956 deletions
diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs index 6abe6d4e0..5342cff4b 100644 --- a/MediaBrowser.Common/Extensions/BaseExtensions.cs +++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Security.Cryptography; using System.Text; -using System.Threading.Tasks; namespace MediaBrowser.Common.Extensions { @@ -46,23 +44,6 @@ namespace MediaBrowser.Common.Extensions } /// <summary> - /// Provides a non-blocking method to start a process and wait asynchronously for it to exit - /// </summary> - /// <param name="process">The process.</param> - /// <returns>Task{System.Boolean}.</returns> - public static Task<bool> RunAsync(this Process process) - { - var tcs = new TaskCompletionSource<bool>(); - - process.EnableRaisingEvents = true; - process.Exited += (sender, args) => tcs.SetResult(true); - - process.Start(); - - return tcs.Task; - } - - /// <summary> /// Shuffles an IEnumerable /// </summary> /// <typeparam name="T"></typeparam> diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index 2b9550496..08e8c3e75 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Events; -using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.ScheduledTasks; @@ -396,7 +395,7 @@ namespace MediaBrowser.Common.Kernel await ReloadComposableParts().ConfigureAwait(false); DisposeTcpManager(); - TcpManager = new TcpManager(ApplicationHost, this, Logger); + TcpManager = new TcpManager(ApplicationHost, this, ApplicationHost.Resolve<INetworkManager>(), Logger); } /// <summary> diff --git a/MediaBrowser.Common/Kernel/BaseManager.cs b/MediaBrowser.Common/Kernel/BaseManager.cs deleted file mode 100644 index 3d830caef..000000000 --- a/MediaBrowser.Common/Kernel/BaseManager.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; - -namespace MediaBrowser.Common.Kernel -{ - /// <summary> - /// Class BaseManager - /// </summary> - /// <typeparam name="TKernelType">The type of the T kernel type.</typeparam> - public abstract class BaseManager<TKernelType> : IDisposable - where TKernelType : class, IKernel - { - /// <summary> - /// The _kernel - /// </summary> - protected readonly TKernelType Kernel; - - /// <summary> - /// Initializes a new instance of the <see cref="BaseManager" /> class. - /// </summary> - /// <param name="kernel">The kernel.</param> - /// <exception cref="System.ArgumentNullException">kernel</exception> - protected BaseManager(TKernelType kernel) - { - if (kernel == null) - { - throw new ArgumentNullException("kernel"); - } - - Kernel = kernel; - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - } - } -} diff --git a/MediaBrowser.Common/Kernel/IApplicationHost.cs b/MediaBrowser.Common/Kernel/IApplicationHost.cs index ae2e71667..dccb65b2a 100644 --- a/MediaBrowser.Common/Kernel/IApplicationHost.cs +++ b/MediaBrowser.Common/Kernel/IApplicationHost.cs @@ -59,6 +59,13 @@ namespace MediaBrowser.Common.Kernel void Register<T>(T obj) where T : class; /// <summary> + /// Registers the specified service type. + /// </summary> + /// <param name="serviceType">Type of the service.</param> + /// <param name="implementation">Type of the implementation.</param> + void Register(Type serviceType, Type implementation); + + /// <summary> /// Resolves this instance. /// </summary> /// <typeparam name="T"></typeparam> diff --git a/MediaBrowser.Common/Kernel/TcpManager.cs b/MediaBrowser.Common/Kernel/TcpManager.cs index 086815cbf..0b171c492 100644 --- a/MediaBrowser.Common/Kernel/TcpManager.cs +++ b/MediaBrowser.Common/Kernel/TcpManager.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Common.Kernel /// <summary> /// Manages the Http Server, Udp Server and WebSocket connections /// </summary> - public class TcpManager : BaseManager<IKernel> + public class TcpManager : IDisposable { /// <summary> /// This is the udp server used for server discovery by clients @@ -66,6 +66,11 @@ namespace MediaBrowser.Common.Kernel private readonly ILogger _logger; /// <summary> + /// The _network manager + /// </summary> + private readonly INetworkManager _networkManager; + + /// <summary> /// The _application host /// </summary> private readonly IApplicationHost _applicationHost; @@ -76,6 +81,11 @@ namespace MediaBrowser.Common.Kernel private bool? _supportsNativeWebSocket; /// <summary> + /// The _kernel + /// </summary> + private readonly IKernel _kernel; + + /// <summary> /// Gets a value indicating whether [supports web socket]. /// </summary> /// <value><c>true</c> if [supports web socket]; otherwise, <c>false</c>.</value> @@ -107,7 +117,7 @@ namespace MediaBrowser.Common.Kernel /// <value>The web socket port number.</value> public int WebSocketPortNumber { - get { return SupportsNativeWebSocket ? Kernel.Configuration.HttpServerPortNumber : Kernel.Configuration.LegacyWebSocketPortNumber; } + get { return SupportsNativeWebSocket ? _kernel.Configuration.HttpServerPortNumber : _kernel.Configuration.LegacyWebSocketPortNumber; } } /// <summary> @@ -115,12 +125,31 @@ namespace MediaBrowser.Common.Kernel /// </summary> /// <param name="applicationHost">The application host.</param> /// <param name="kernel">The kernel.</param> + /// <param name="networkManager">The network manager.</param> /// <param name="logger">The logger.</param> - public TcpManager(IApplicationHost applicationHost, IKernel kernel, ILogger logger) - : base(kernel) + public TcpManager(IApplicationHost applicationHost, IKernel kernel, INetworkManager networkManager, ILogger logger) { + if (applicationHost == null) + { + throw new ArgumentNullException("applicationHost"); + } + if (kernel == null) + { + throw new ArgumentNullException("kernel"); + } + if (networkManager == null) + { + throw new ArgumentNullException("networkManager"); + } + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + _logger = logger; + _kernel = kernel; _applicationHost = applicationHost; + _networkManager = networkManager; if (kernel.IsFirstRun) { @@ -142,14 +171,14 @@ namespace MediaBrowser.Common.Kernel private void ReloadExternalWebSocketServer() { // Avoid windows firewall prompts in the ui - if (Kernel.KernelContext != KernelContext.Server) + if (_kernel.KernelContext != KernelContext.Server) { return; } DisposeExternalWebSocketServer(); - ExternalWebSocketServer = new WebSocketServer(Kernel.Configuration.LegacyWebSocketPortNumber, IPAddress.Any) + ExternalWebSocketServer = new WebSocketServer(_kernel.Configuration.LegacyWebSocketPortNumber, IPAddress.Any) { OnConnected = OnAlchemyWebSocketClientConnected, TimeOut = TimeSpan.FromMinutes(60) @@ -178,7 +207,7 @@ namespace MediaBrowser.Common.Kernel public void ReloadHttpServer(bool registerServerOnFailure = true) { // Only reload if the port has changed, so that we don't disconnect any active users - if (HttpServer != null && HttpServer.UrlPrefix.Equals(Kernel.HttpServerUrlPrefix, StringComparison.OrdinalIgnoreCase)) + if (HttpServer != null && HttpServer.UrlPrefix.Equals(_kernel.HttpServerUrlPrefix, StringComparison.OrdinalIgnoreCase)) { return; } @@ -189,7 +218,7 @@ namespace MediaBrowser.Common.Kernel try { - HttpServer = new HttpServer(Kernel.HttpServerUrlPrefix, "Media Browser", _applicationHost, Kernel, _logger); + HttpServer = new HttpServer(_kernel.HttpServerUrlPrefix, "Media Browser", _applicationHost, _kernel, _logger); } catch (HttpListenerException ex) { @@ -229,7 +258,7 @@ namespace MediaBrowser.Common.Kernel /// <param name="result">The result.</param> private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result) { - var tasks = Kernel.WebSocketListeners.Select(i => Task.Run(async () => + var tasks = _kernel.WebSocketListeners.Select(i => Task.Run(async () => { try { @@ -256,7 +285,7 @@ namespace MediaBrowser.Common.Kernel } // Avoid windows firewall prompts in the ui - if (Kernel.KernelContext != KernelContext.Server) + if (_kernel.KernelContext != KernelContext.Server) { return; } @@ -266,7 +295,7 @@ namespace MediaBrowser.Common.Kernel try { // The port number can't be in configuration because we don't want it to ever change - UdpServer = new UdpServer(new IPEndPoint(IPAddress.Any, Kernel.UdpServerPortNumber)); + UdpServer = new UdpServer(new IPEndPoint(IPAddress.Any, _kernel.UdpServerPortNumber)); } catch (SocketException ex) { @@ -276,7 +305,7 @@ namespace MediaBrowser.Common.Kernel UdpListener = UdpServer.Subscribe(async res => { - var expectedMessage = String.Format("who is MediaBrowser{0}?", Kernel.KernelContext); + var expectedMessage = String.Format("who is MediaBrowser{0}?", _kernel.KernelContext); var expectedMessageBytes = Encoding.UTF8.GetBytes(expectedMessage); if (expectedMessageBytes.SequenceEqual(res.Buffer)) @@ -284,7 +313,7 @@ namespace MediaBrowser.Common.Kernel _logger.Info("Received UDP server request from " + res.RemoteEndPoint.ToString()); // Send a response back with our ip address and port - var response = String.Format("MediaBrowser{0}|{1}:{2}", Kernel.KernelContext, NetUtils.GetLocalIpAddress(), Kernel.UdpServerPortNumber); + var response = String.Format("MediaBrowser{0}|{1}:{2}", _kernel.KernelContext, _networkManager.GetLocalIpAddress(), _kernel.UdpServerPortNumber); await UdpServer.SendAsync(response, res.RemoteEndPoint); } @@ -422,7 +451,7 @@ namespace MediaBrowser.Common.Kernel private void RegisterServerWithAdministratorAccess() { // Create a temp file path to extract the bat file to - var tmpFile = Path.Combine(Kernel.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".bat"); + var tmpFile = Path.Combine(_kernel.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".bat"); // Extract the bat file using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.Common.Kernel.RegisterServer.bat")) @@ -437,10 +466,10 @@ namespace MediaBrowser.Common.Kernel { FileName = tmpFile, - Arguments = string.Format("{0} {1} {2} {3}", Kernel.Configuration.HttpServerPortNumber, - Kernel.HttpServerUrlPrefix, - Kernel.UdpServerPortNumber, - Kernel.Configuration.LegacyWebSocketPortNumber), + Arguments = string.Format("{0} {1} {2} {3}", _kernel.Configuration.HttpServerPortNumber, + _kernel.HttpServerUrlPrefix, + _kernel.UdpServerPortNumber, + _kernel.Configuration.LegacyWebSocketPortNumber), CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, @@ -455,18 +484,25 @@ namespace MediaBrowser.Common.Kernel } /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool dispose) + protected virtual void Dispose(bool dispose) { if (dispose) { DisposeUdpServer(); DisposeHttpServer(); } - - base.Dispose(dispose); } /// <summary> diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 6542ab81d..57b30eedc 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -45,7 +45,6 @@ <HintPath>..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll</HintPath> </Reference> <Reference Include="PresentationCore" /> - <Reference Include="PresentationFramework" /> <Reference Include="protobuf-net, Version=2.0.0.621, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\protobuf-net.2.0.0.621\lib\net40\protobuf-net.dll</HintPath> @@ -91,7 +90,6 @@ <Reference Include="System" /> <Reference Include="System.Configuration" /> <Reference Include="System.Core" /> - <Reference Include="System.Management" /> <Reference Include="System.Net" /> <Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http.WebRequest" /> @@ -107,12 +105,8 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\Rx-Linq.2.0.21114\lib\Net45\System.Reactive.Linq.dll</HintPath> </Reference> - <Reference Include="System.Runtime.Remoting" /> - <Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Web" /> - <Reference Include="System.Xml.Linq" /> <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> @@ -130,7 +124,6 @@ <Compile Include="IO\ProgressStream.cs" /> <Compile Include="IO\StreamDefaults.cs" /> <Compile Include="Kernel\BaseApplicationPaths.cs" /> - <Compile Include="Kernel\BaseManager.cs" /> <Compile Include="Kernel\BasePeriodicWebSocketListener.cs" /> <Compile Include="Kernel\IWebSocketListener.cs" /> <Compile Include="Kernel\IApplicationHost.cs" /> @@ -142,12 +135,12 @@ <Compile Include="Net\Handlers\IHttpServerHandler.cs" /> <Compile Include="Net\Handlers\StaticFileHandler.cs" /> <Compile Include="Net\HttpManager.cs" /> + <Compile Include="Net\INetworkManager.cs" /> <Compile Include="Net\IRestfulService.cs" /> <Compile Include="Net\IUdpServer.cs" /> <Compile Include="Net\IWebSocket.cs" /> <Compile Include="Net\MimeTypes.cs" /> <Compile Include="Net\NativeWebSocket.cs" /> - <Compile Include="Net\NetUtils.cs" /> <Compile Include="Net\UdpServer.cs" /> <Compile Include="Net\WebSocketConnection.cs" /> <Compile Include="Plugins\BaseUiPlugin.cs" /> @@ -184,7 +177,6 @@ <Compile Include="ScheduledTasks\IntervalTrigger.cs" /> <Compile Include="ScheduledTasks\IScheduledTask.cs" /> <Compile Include="ScheduledTasks\WeeklyTrigger.cs" /> - <Compile Include="Win32\NativeMethods.cs" /> </ItemGroup> <ItemGroup> <None Include="app.config" /> diff --git a/MediaBrowser.Common/Net/HttpManager.cs b/MediaBrowser.Common/Net/HttpManager.cs index 1deffba69..180843e0f 100644 --- a/MediaBrowser.Common/Net/HttpManager.cs +++ b/MediaBrowser.Common/Net/HttpManager.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Common.Net /// <summary> /// Class HttpManager /// </summary> - public class HttpManager : BaseManager<IKernel> + public class HttpManager : IDisposable { /// <summary> /// The _logger @@ -27,14 +27,28 @@ namespace MediaBrowser.Common.Net private readonly ILogger _logger; /// <summary> + /// The _kernel + /// </summary> + private readonly IKernel _kernel; + + /// <summary> /// Initializes a new instance of the <see cref="HttpManager" /> class. /// </summary> /// <param name="kernel">The kernel.</param> /// <param name="logger">The logger.</param> public HttpManager(IKernel kernel, ILogger logger) - : base(kernel) { + if (kernel == null) + { + throw new ArgumentNullException("kernel"); + } + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + _logger = logger; + _kernel = kernel; } /// <summary> @@ -196,7 +210,7 @@ namespace MediaBrowser.Common.Net cancellationToken.ThrowIfCancellationRequested(); - var tempFile = Path.Combine(Kernel.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".tmp"); + var tempFile = Path.Combine(_kernel.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".tmp"); var message = new HttpRequestMessage(HttpMethod.Get, url); @@ -403,10 +417,19 @@ namespace MediaBrowser.Common.Net } /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool dispose) + protected virtual void Dispose(bool dispose) { if (dispose) { @@ -417,8 +440,6 @@ namespace MediaBrowser.Common.Net _httpClients.Clear(); } - - base.Dispose(dispose); } /// <summary> diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs new file mode 100644 index 000000000..7f6bfe152 --- /dev/null +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using MediaBrowser.Model.Net; + +namespace MediaBrowser.Common.Net +{ + public interface INetworkManager + { + /// <summary> + /// Gets the machine's local ip address + /// </summary> + /// <returns>IPAddress.</returns> + string GetLocalIpAddress(); + + /// <summary> + /// Gets a random port number that is currently available + /// </summary> + /// <returns>System.Int32.</returns> + int GetRandomUnusedPort(); + + /// <summary> + /// Creates the netsh URL registration. + /// </summary> + void AuthorizeHttpListening(string url); + + /// <summary> + /// Adds the windows firewall rule. + /// </summary> + /// <param name="port">The port.</param> + /// <param name="protocol">The protocol.</param> + void AddSystemFirewallRule(int port, NetworkProtocol protocol); + + /// <summary> + /// Removes the windows firewall rule. + /// </summary> + /// <param name="port">The port.</param> + /// <param name="protocol">The protocol.</param> + void RemoveSystemFirewallRule(int port, NetworkProtocol protocol); + + /// <summary> + /// Returns MAC Address from first Network Card in Computer + /// </summary> + /// <returns>[string] MAC Address</returns> + string GetMacAddress(); + + /// <summary> + /// Gets available devices within the domain + /// </summary> + /// <returns>PC's in the Domain</returns> + IEnumerable<string> GetNetworkDevices(); + + /// <summary> + /// Gets the network shares. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>IEnumerable{NetworkShare}.</returns> + IEnumerable<NetworkShare> GetNetworkShares(string path); + } + /// <summary> + /// Enum NetworkProtocol + /// </summary> + public enum NetworkProtocol + { + /// <summary> + /// The TCP + /// </summary> + Tcp, + /// <summary> + /// The UDP + /// </summary> + Udp + } +}
\ No newline at end of file diff --git a/MediaBrowser.Common/Net/NetUtils.cs b/MediaBrowser.Common/Net/NetUtils.cs deleted file mode 100644 index eb50a879d..000000000 --- a/MediaBrowser.Common/Net/NetUtils.cs +++ /dev/null @@ -1,219 +0,0 @@ -using MediaBrowser.Common.Win32; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Management; -using System.Net; -using System.Net.Sockets; -using System.Runtime.InteropServices; - -namespace MediaBrowser.Common.Net -{ - /// <summary> - /// Class NetUtils - /// </summary> - public static class NetUtils - { - /// <summary> - /// Gets the machine's local ip address - /// </summary> - /// <returns>IPAddress.</returns> - public static IPAddress GetLocalIpAddress() - { - var host = Dns.GetHostEntry(Dns.GetHostName()); - - return host.AddressList.FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork); - } - - /// <summary> - /// Gets a random port number that is currently available - /// </summary> - /// <returns>System.Int32.</returns> - public static int GetRandomUnusedPort() - { - var listener = new TcpListener(IPAddress.Any, 0); - listener.Start(); - var port = ((IPEndPoint)listener.LocalEndpoint).Port; - listener.Stop(); - return port; - } - - /// <summary> - /// Creates the netsh URL registration. - /// </summary> - /// <param name="urlPrefix">The URL prefix.</param> - public static void CreateNetshUrlRegistration(string urlPrefix) - { - var startInfo = new ProcessStartInfo - { - FileName = "netsh", - Arguments = string.Format("http add urlacl url={0} user=\"NT AUTHORITY\\Authenticated Users\"", urlPrefix), - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - Verb = "runas", - ErrorDialog = false - }; - - using (var process = Process.Start(startInfo)) - { - process.WaitForExit(); - } - } - - /// <summary> - /// Adds the windows firewall rule. - /// </summary> - /// <param name="port">The port.</param> - /// <param name="protocol">The protocol.</param> - public static void AddWindowsFirewallRule(int port, NetworkProtocol protocol) - { - // First try to remove it so we don't end up creating duplicates - RemoveWindowsFirewallRule(port, protocol); - - var args = string.Format("advfirewall firewall add rule name=\"Port {0}\" dir=in action=allow protocol={1} localport={0}", port, protocol); - - RunNetsh(args); - } - - /// <summary> - /// Removes the windows firewall rule. - /// </summary> - /// <param name="port">The port.</param> - /// <param name="protocol">The protocol.</param> - public static void RemoveWindowsFirewallRule(int port, NetworkProtocol protocol) - { - var args = string.Format("advfirewall firewall delete rule name=\"Port {0}\" protocol={1} localport={0}", port, protocol); - - RunNetsh(args); - } - - /// <summary> - /// Runs the netsh. - /// </summary> - /// <param name="args">The args.</param> - private static void RunNetsh(string args) - { - var startInfo = new ProcessStartInfo - { - FileName = "netsh", - Arguments = args, - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - Verb = "runas", - ErrorDialog = false - }; - - using (var process = new Process { StartInfo = startInfo }) - { - process.Start(); - process.WaitForExit(); - } - } - - /// <summary> - /// Returns MAC Address from first Network Card in Computer - /// </summary> - /// <returns>[string] MAC Address</returns> - public static string GetMacAddress() - { - var mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); - var moc = mc.GetInstances(); - var macAddress = String.Empty; - foreach (ManagementObject mo in moc) - { - if (macAddress == String.Empty) // only return MAC Address from first card - { - try - { - if ((bool)mo["IPEnabled"]) macAddress = mo["MacAddress"].ToString(); - } - catch - { - mo.Dispose(); - return ""; - } - } - mo.Dispose(); - } - - return macAddress.Replace(":", ""); - } - - /// <summary> - /// Uses the DllImport : NetServerEnum with all its required parameters - /// (see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp - /// for full details or method signature) to retrieve a list of domain SV_TYPE_WORKSTATION - /// and SV_TYPE_SERVER PC's - /// </summary> - /// <returns>Arraylist that represents all the SV_TYPE_WORKSTATION and SV_TYPE_SERVER - /// PC's in the Domain</returns> - public static IEnumerable<string> GetNetworkComputers() - { - //local fields - const int MAX_PREFERRED_LENGTH = -1; - var SV_TYPE_WORKSTATION = 1; - var SV_TYPE_SERVER = 2; - var buffer = IntPtr.Zero; - var tmpBuffer = IntPtr.Zero; - var entriesRead = 0; - var totalEntries = 0; - var resHandle = 0; - var sizeofINFO = Marshal.SizeOf(typeof(_SERVER_INFO_100)); - - try - { - //call the DllImport : NetServerEnum with all its required parameters - //see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp - //for full details of method signature - var ret = NativeMethods.NetServerEnum(null, 100, ref buffer, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, SV_TYPE_WORKSTATION | SV_TYPE_SERVER, null, out resHandle); - - //if the returned with a NERR_Success (C++ term), =0 for C# - if (ret == 0) - { - //loop through all SV_TYPE_WORKSTATION and SV_TYPE_SERVER PC's - for (var i = 0; i < totalEntries; i++) - { - //get pointer to, Pointer to the buffer that received the data from - //the call to NetServerEnum. Must ensure to use correct size of - //STRUCTURE to ensure correct location in memory is pointed to - tmpBuffer = new IntPtr((int)buffer + (i * sizeofINFO)); - //Have now got a pointer to the list of SV_TYPE_WORKSTATION and - //SV_TYPE_SERVER PC's, which is unmanaged memory - //Needs to Marshal data from an unmanaged block of memory to a - //managed object, again using STRUCTURE to ensure the correct data - //is marshalled - var svrInfo = (_SERVER_INFO_100)Marshal.PtrToStructure(tmpBuffer, typeof(_SERVER_INFO_100)); - - //add the PC names to the ArrayList - if (!string.IsNullOrEmpty(svrInfo.sv100_name)) - { - yield return svrInfo.sv100_name; - } - } - } - } - finally - { - //The NetApiBufferFree function frees - //the memory that the NetApiBufferAllocate function allocates - NativeMethods.NetApiBufferFree(buffer); - } - } - } - - /// <summary> - /// Enum NetworkProtocol - /// </summary> - public enum NetworkProtocol - { - /// <summary> - /// The TCP - /// </summary> - Tcp, - /// <summary> - /// The UDP - /// </summary> - Udp - } -} diff --git a/MediaBrowser.Common/Win32/NativeMethods.cs b/MediaBrowser.Common/Win32/NativeMethods.cs deleted file mode 100644 index a0462fb46..000000000 --- a/MediaBrowser.Common/Win32/NativeMethods.cs +++ /dev/null @@ -1,631 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Security; -using System.Text; - -namespace MediaBrowser.Common.Win32 -{ - /// <summary> - /// Class NativeMethods - /// </summary> - [SuppressUnmanagedCodeSecurity] - public static class NativeMethods - { - //declare the Netapi32 : NetServerEnum method import - /// <summary> - /// Nets the server enum. - /// </summary> - /// <param name="ServerName">Name of the server.</param> - /// <param name="dwLevel">The dw level.</param> - /// <param name="pBuf">The p buf.</param> - /// <param name="dwPrefMaxLen">The dw pref max len.</param> - /// <param name="dwEntriesRead">The dw entries read.</param> - /// <param name="dwTotalEntries">The dw total entries.</param> - /// <param name="dwServerType">Type of the dw server.</param> - /// <param name="domain">The domain.</param> - /// <param name="dwResumeHandle">The dw resume handle.</param> - /// <returns>System.Int32.</returns> - [DllImport("Netapi32", CharSet = CharSet.Auto, SetLastError = true), - SuppressUnmanagedCodeSecurityAttribute] - - public static extern int NetServerEnum( - string ServerName, // must be null - int dwLevel, - ref IntPtr pBuf, - int dwPrefMaxLen, - out int dwEntriesRead, - out int dwTotalEntries, - int dwServerType, - string domain, // null for login domain - out int dwResumeHandle - ); - - //declare the Netapi32 : NetApiBufferFree method import - /// <summary> - /// Nets the API buffer free. - /// </summary> - /// <param name="pBuf">The p buf.</param> - /// <returns>System.Int32.</returns> - [DllImport("Netapi32", SetLastError = true), - SuppressUnmanagedCodeSecurityAttribute] - - public static extern int NetApiBufferFree( - IntPtr pBuf); - - /// <summary> - /// The MA x_ PATH - /// </summary> - public const int MAX_PATH = 260; - /// <summary> - /// The MA x_ ALTERNATE - /// </summary> - public const int MAX_ALTERNATE = 14; - /// <summary> - /// The INVALI d_ HANDL e_ VALUE - /// </summary> - public static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); - /// <summary> - /// The STG m_ READ - /// </summary> - public const uint STGM_READ = 0; - - /// <summary> - /// Finds the first file ex. - /// </summary> - /// <param name="lpFileName">Name of the lp file.</param> - /// <param name="fInfoLevelId">The f info level id.</param> - /// <param name="lpFindFileData">The lp find file data.</param> - /// <param name="fSearchOp">The f search op.</param> - /// <param name="lpSearchFilter">The lp search filter.</param> - /// <param name="dwAdditionalFlags">The dw additional flags.</param> - /// <returns>IntPtr.</returns> - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr FindFirstFileEx(string lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, out WIN32_FIND_DATA lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, IntPtr lpSearchFilter, int dwAdditionalFlags); - - /// <summary> - /// Finds the first file. - /// </summary> - /// <param name="fileName">Name of the file.</param> - /// <param name="lpFindFileData">The lp find file data.</param> - /// <returns>IntPtr.</returns> - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr FindFirstFile(string fileName, out WIN32_FIND_DATA lpFindFileData); - - /// <summary> - /// Finds the next file. - /// </summary> - /// <param name="hFindFile">The h find file.</param> - /// <param name="lpFindFileData">The lp find file data.</param> - /// <returns>IntPtr.</returns> - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData); - - /// <summary> - /// Finds the close. - /// </summary> - /// <param name="hFindFile">The h find file.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - [DllImport("kernel32")] - public static extern bool FindClose(IntPtr hFindFile); - } - - //create a _SERVER_INFO_100 STRUCTURE - /// <summary> - /// Struct _SERVER_INFO_100 - /// </summary> - [StructLayout(LayoutKind.Sequential)] - public struct _SERVER_INFO_100 - { - /// <summary> - /// The sv100_platform_id - /// </summary> - internal int sv100_platform_id; - /// <summary> - /// The sv100_name - /// </summary> - [MarshalAs(UnmanagedType.LPWStr)] - internal string sv100_name; - } - - /// <summary> - /// Class FindFirstFileExFlags - /// </summary> - public class FindFirstFileExFlags - { - /// <summary> - /// The NONE - /// </summary> - public const int NONE = 0; - - /// <summary> - /// Searches are case-sensitive.Searches are case-sensitive. - /// </summary> - public const int FIND_FIRST_EX_CASE_SENSITIVE = 1; - - /// <summary> - /// Uses a larger buffer for directory queries, which can increase performance of the find operation. - /// </summary> - public const int FIND_FIRST_EX_LARGE_FETCH = 2; - } - - /// <summary> - /// Enum FINDEX_INFO_LEVELS - /// </summary> - public enum FINDEX_INFO_LEVELS - { - /// <summary> - /// The FindFirstFileEx function retrieves a standard set of attribute information. The data is returned in a WIN32_FIND_DATA structure. - /// </summary> - FindExInfoStandard = 0, - - /// <summary> - /// The FindFirstFileEx function does not query the short file name, improving overall enumeration speed. The data is returned in a WIN32_FIND_DATA structure, and the cAlternateFileName member is always a NULL string. - /// </summary> - FindExInfoBasic = 1 - } - - /// <summary> - /// Enum FINDEX_SEARCH_OPS - /// </summary> - public enum FINDEX_SEARCH_OPS - { - /// <summary> - /// The search for a file that matches a specified file name. - /// The lpSearchFilter parameter of FindFirstFileEx must be NULL when this search operation is used. - /// </summary> - FindExSearchNameMatch = 0, - - /// <summary> - /// The find ex search limit to directories - /// </summary> - FindExSearchLimitToDirectories = 1, - - /// <summary> - /// This filtering type is not available. - /// </summary> - FindExSearchLimitToDevices = 2 - } - - /// <summary> - /// Struct FILETIME - /// </summary> - [StructLayout(LayoutKind.Sequential)] - public struct FILETIME - { - /// <summary> - /// The dw low date time - /// </summary> - public uint dwLowDateTime; - /// <summary> - /// The dw high date time - /// </summary> - public uint dwHighDateTime; - } - - - /// <summary> - /// Struct WIN32_FIND_DATA - /// </summary> - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct WIN32_FIND_DATA - { - /// <summary> - /// The dw file attributes - /// </summary> - public FileAttributes dwFileAttributes; - /// <summary> - /// The ft creation time - /// </summary> - public FILETIME ftCreationTime; - /// <summary> - /// The ft last access time - /// </summary> - public FILETIME ftLastAccessTime; - /// <summary> - /// The ft last write time - /// </summary> - public FILETIME ftLastWriteTime; - /// <summary> - /// The n file size high - /// </summary> - public int nFileSizeHigh; - /// <summary> - /// The n file size low - /// </summary> - public int nFileSizeLow; - /// <summary> - /// The dw reserved0 - /// </summary> - public int dwReserved0; - /// <summary> - /// The dw reserved1 - /// </summary> - public int dwReserved1; - - /// <summary> - /// The c file name - /// </summary> - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NativeMethods.MAX_PATH)] - public string cFileName; - - /// <summary> - /// This will always be null when FINDEX_INFO_LEVELS = basic - /// </summary> - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NativeMethods.MAX_ALTERNATE)] - public string cAlternate; - - /// <summary> - /// Gets a value indicating whether this instance is hidden. - /// </summary> - /// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value> - public bool IsHidden - { - get - { - return dwFileAttributes.HasFlag(FileAttributes.Hidden); - } - } - - /// <summary> - /// Gets a value indicating whether this instance is system file. - /// </summary> - /// <value><c>true</c> if this instance is system file; otherwise, <c>false</c>.</value> - public bool IsSystemFile - { - get - { - return dwFileAttributes.HasFlag(FileAttributes.System); - } - } - - /// <summary> - /// Gets a value indicating whether this instance is directory. - /// </summary> - /// <value><c>true</c> if this instance is directory; otherwise, <c>false</c>.</value> - public bool IsDirectory - { - get - { - return dwFileAttributes.HasFlag(FileAttributes.Directory); - } - } - - /// <summary> - /// Gets the creation time UTC. - /// </summary> - /// <value>The creation time UTC.</value> - public DateTime CreationTimeUtc - { - get - { - return ParseFileTime(ftCreationTime); - } - } - - /// <summary> - /// Gets the last access time UTC. - /// </summary> - /// <value>The last access time UTC.</value> - public DateTime LastAccessTimeUtc - { - get - { - return ParseFileTime(ftLastAccessTime); - } - } - - /// <summary> - /// Gets the last write time UTC. - /// </summary> - /// <value>The last write time UTC.</value> - public DateTime LastWriteTimeUtc - { - get - { - return ParseFileTime(ftLastWriteTime); - } - } - - /// <summary> - /// Parses the file time. - /// </summary> - /// <param name="filetime">The filetime.</param> - /// <returns>DateTime.</returns> - private DateTime ParseFileTime(FILETIME filetime) - { - long highBits = filetime.dwHighDateTime; - highBits = highBits << 32; - - var val = highBits + (long) filetime.dwLowDateTime; - - if (val < 0L) - { - return DateTime.MinValue; - } - - if (val > 2650467743999999999L) - { - return DateTime.MaxValue; - } - - return DateTime.FromFileTimeUtc(val); - } - - /// <summary> - /// Gets or sets the path. - /// </summary> - /// <value>The path.</value> - public string Path { get; set; } - - /// <summary> - /// Returns a <see cref="System.String" /> that represents this instance. - /// </summary> - /// <returns>A <see cref="System.String" /> that represents this instance.</returns> - public override string ToString() - { - return Path ?? string.Empty; - } - } - - /// <summary> - /// Enum SLGP_FLAGS - /// </summary> - [Flags] - public enum SLGP_FLAGS - { - /// <summary> - /// Retrieves the standard short (8.3 format) file name - /// </summary> - SLGP_SHORTPATH = 0x1, - /// <summary> - /// Retrieves the Universal Naming Convention (UNC) path name of the file - /// </summary> - SLGP_UNCPRIORITY = 0x2, - /// <summary> - /// Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded - /// </summary> - SLGP_RAWPATH = 0x4 - } - /// <summary> - /// Enum SLR_FLAGS - /// </summary> - [Flags] - public enum SLR_FLAGS - { - /// <summary> - /// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set, - /// the high-order word of fFlags can be set to a time-out value that specifies the - /// maximum amount of time to be spent resolving the link. The function returns if the - /// link cannot be resolved within the time-out duration. If the high-order word is set - /// to zero, the time-out duration will be set to the default value of 3,000 milliseconds - /// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out - /// duration, in milliseconds. - /// </summary> - SLR_NO_UI = 0x1, - /// <summary> - /// Obsolete and no longer used - /// </summary> - SLR_ANY_MATCH = 0x2, - /// <summary> - /// If the link object has changed, update its path and list of identifiers. - /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine - /// whether or not the link object has changed. - /// </summary> - SLR_UPDATE = 0x4, - /// <summary> - /// Do not update the link information - /// </summary> - SLR_NOUPDATE = 0x8, - /// <summary> - /// Do not execute the search heuristics - /// </summary> - SLR_NOSEARCH = 0x10, - /// <summary> - /// Do not use distributed link tracking - /// </summary> - SLR_NOTRACK = 0x20, - /// <summary> - /// Disable distributed link tracking. By default, distributed link tracking tracks - /// removable media across multiple devices based on the volume name. It also uses the - /// Universal Naming Convention (UNC) path to track remote file systems whose drive letter - /// has changed. Setting SLR_NOLINKINFO disables both types of tracking. - /// </summary> - SLR_NOLINKINFO = 0x40, - /// <summary> - /// Call the Microsoft Windows Installer - /// </summary> - SLR_INVOKE_MSI = 0x80 - } - - - /// <summary> - /// The IShellLink interface allows Shell links to be created, modified, and resolved - /// </summary> - [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")] - public interface IShellLinkW - { - /// <summary> - /// Retrieves the path and file name of a Shell link object - /// </summary> - /// <param name="pszFile">The PSZ file.</param> - /// <param name="cchMaxPath">The CCH max path.</param> - /// <param name="pfd">The PFD.</param> - /// <param name="fFlags">The f flags.</param> - void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATA pfd, SLGP_FLAGS fFlags); - /// <summary> - /// Retrieves the list of item identifiers for a Shell link object - /// </summary> - /// <param name="ppidl">The ppidl.</param> - void GetIDList(out IntPtr ppidl); - /// <summary> - /// Sets the pointer to an item identifier list (PIDL) for a Shell link object. - /// </summary> - /// <param name="pidl">The pidl.</param> - void SetIDList(IntPtr pidl); - /// <summary> - /// Retrieves the description string for a Shell link object - /// </summary> - /// <param name="pszName">Name of the PSZ.</param> - /// <param name="cchMaxName">Name of the CCH max.</param> - void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); - /// <summary> - /// Sets the description for a Shell link object. The description can be any application-defined string - /// </summary> - /// <param name="pszName">Name of the PSZ.</param> - void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - /// <summary> - /// Retrieves the name of the working directory for a Shell link object - /// </summary> - /// <param name="pszDir">The PSZ dir.</param> - /// <param name="cchMaxPath">The CCH max path.</param> - void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); - /// <summary> - /// Sets the name of the working directory for a Shell link object - /// </summary> - /// <param name="pszDir">The PSZ dir.</param> - void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - /// <summary> - /// Retrieves the command-line arguments associated with a Shell link object - /// </summary> - /// <param name="pszArgs">The PSZ args.</param> - /// <param name="cchMaxPath">The CCH max path.</param> - void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); - /// <summary> - /// Sets the command-line arguments for a Shell link object - /// </summary> - /// <param name="pszArgs">The PSZ args.</param> - void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - /// <summary> - /// Retrieves the hot key for a Shell link object - /// </summary> - /// <param name="pwHotkey">The pw hotkey.</param> - void GetHotkey(out short pwHotkey); - /// <summary> - /// Sets a hot key for a Shell link object - /// </summary> - /// <param name="wHotkey">The w hotkey.</param> - void SetHotkey(short wHotkey); - /// <summary> - /// Retrieves the show command for a Shell link object - /// </summary> - /// <param name="piShowCmd">The pi show CMD.</param> - void GetShowCmd(out int piShowCmd); - /// <summary> - /// Sets the show command for a Shell link object. The show command sets the initial show state of the window. - /// </summary> - /// <param name="iShowCmd">The i show CMD.</param> - void SetShowCmd(int iShowCmd); - /// <summary> - /// Retrieves the location (path and index) of the icon for a Shell link object - /// </summary> - /// <param name="pszIconPath">The PSZ icon path.</param> - /// <param name="cchIconPath">The CCH icon path.</param> - /// <param name="piIcon">The pi icon.</param> - void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - /// <summary> - /// Sets the location (path and index) of the icon for a Shell link object - /// </summary> - /// <param name="pszIconPath">The PSZ icon path.</param> - /// <param name="iIcon">The i icon.</param> - void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - /// <summary> - /// Sets the relative path to the Shell link object - /// </summary> - /// <param name="pszPathRel">The PSZ path rel.</param> - /// <param name="dwReserved">The dw reserved.</param> - void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); - /// <summary> - /// Attempts to find the target of a Shell link, even if it has been moved or renamed - /// </summary> - /// <param name="hwnd">The HWND.</param> - /// <param name="fFlags">The f flags.</param> - void Resolve(IntPtr hwnd, SLR_FLAGS fFlags); - /// <summary> - /// Sets the path and file name of a Shell link object - /// </summary> - /// <param name="pszFile">The PSZ file.</param> - void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - - } - - /// <summary> - /// Interface IPersist - /// </summary> - [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), - InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IPersist - { - /// <summary> - /// Gets the class ID. - /// </summary> - /// <param name="pClassID">The p class ID.</param> - [PreserveSig] - void GetClassID(out Guid pClassID); - } - - - /// <summary> - /// Interface IPersistFile - /// </summary> - [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), - InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IPersistFile : IPersist - { - /// <summary> - /// Gets the class ID. - /// </summary> - /// <param name="pClassID">The p class ID.</param> - new void GetClassID(out Guid pClassID); - /// <summary> - /// Determines whether this instance is dirty. - /// </summary> - [PreserveSig] - int IsDirty(); - - /// <summary> - /// Loads the specified PSZ file name. - /// </summary> - /// <param name="pszFileName">Name of the PSZ file.</param> - /// <param name="dwMode">The dw mode.</param> - [PreserveSig] - void Load([In, MarshalAs(UnmanagedType.LPWStr)] - string pszFileName, uint dwMode); - - /// <summary> - /// Saves the specified PSZ file name. - /// </summary> - /// <param name="pszFileName">Name of the PSZ file.</param> - /// <param name="remember">if set to <c>true</c> [remember].</param> - [PreserveSig] - void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, - [In, MarshalAs(UnmanagedType.Bool)] bool remember); - - /// <summary> - /// Saves the completed. - /// </summary> - /// <param name="pszFileName">Name of the PSZ file.</param> - [PreserveSig] - void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName); - - /// <summary> - /// Gets the cur file. - /// </summary> - /// <param name="ppszFileName">Name of the PPSZ file.</param> - [PreserveSig] - void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName); - } - - // CLSID_ShellLink from ShlGuid.h - /// <summary> - /// Class ShellLink - /// </summary> - [ - ComImport, - Guid("00021401-0000-0000-C000-000000000046") - ] - public class ShellLink - { - } -} |
