<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【UWP】讓 UWP 自己和自己通信

      眾所周知,UWP 一般是運(yùn)行在沙盒里面的,當(dāng)我們需要訪問(wèn)沙盒外資源的時(shí)候,就需要通過(guò)沙盒外的代理服務(wù)器來(lái)獲取。一般情況下我們都是利用 WinRT API 通過(guò) Runtime Broker 來(lái)和沙盒外互通,遇到要自定義的情況則是手動(dòng)開(kāi)一個(gè) Win32 服務(wù)器來(lái)互通,但是有沒(méi)有可能我們可以直接拿 UWP 本體當(dāng)服務(wù)器呢?

      UWP 本體實(shí)際上就是一個(gè)普通的 Win32 EXE 程序,只是想要以 UWP 狀態(tài)運(yùn)行只能通過(guò)系統(tǒng)托管,但是如果我們不需要它以 UWP 狀態(tài)執(zhí)行的時(shí)候完全可以直接雙擊打開(kāi)它,這時(shí)候它就是一個(gè)很普通的散裝 Win32 程序了。

      利用這個(gè)特性,我們可以制作一種假裝雙擊打開(kāi)的方法,只需要在發(fā)現(xiàn)是 Win32 狀態(tài)下啟動(dòng)就去用 API 喚起 UWP 形態(tài)的自己就行了。

      private static unsafe bool IsPackagedApp
      {
          get
          {
              uint length = 0;
              PWSTR str = new();
              _ = PInvoke.GetCurrentPackageFullName(ref length, str);
      
              char* ptr = stackalloc char[(int)length];
              str = new(ptr);
              WIN32_ERROR result = PInvoke.GetCurrentPackageFullName(ref length, str);
              return result != WIN32_ERROR.APPMODEL_ERROR_NO_PACKAGE;
          }
      }
      
      private static void Main()
      {
          if (IsPackagedApp)
          {
              Application.Start(static p =>
              {
                  DispatcherQueueSynchronizationContext context = new(DispatcherQueue.GetForCurrentThread());
                  SynchronizationContext.SetSynchronizationContext(context);
                  _ = new App();
              });
          }
          else
          {
              StartCoreApplicationAsync().Wait();
          }
      }
      
      private static async Task StartCoreApplicationAsync()
      {
          PackageManager manager = new();
          string basePath = AppDomain.CurrentDomain.BaseDirectory;
          XmlDocument manifest = await XmlDocument.LoadFromFileAsync(await StorageFile.GetFileFromPathAsync(Path.Combine(basePath, "AppxManifest.xml")));
          IXmlNode identity = manifest.GetElementsByTagName("Identity")?[0];
          string name = identity.Attributes.FirstOrDefault(x => x.NodeName == "Name")?.InnerText;
          IXmlNode application = manifest.GetElementsByTagName("Application")?[0];
          string id = application.Attributes.FirstOrDefault(x => x.NodeName == "Id")?.InnerText;
          IEnumerable<Package> packages = manager.FindPackagesForUser(string.Empty).Where(x => x.Id.FamilyName.StartsWith(name));
          if (packages.FirstOrDefault() is Package package)
          {
              IReadOnlyList<AppListEntry> entries = await package.GetAppListEntriesAsync();
              if (entries?[0] is AppListEntry entry)
              {
                  _ = await entry.LaunchAsync();
              }
          }
      }

      既然我們可以讓自己?jiǎn)酒鹱约海敲醋约汉妥约和ㄐ乓膊皇鞘裁措y事了,我們只需要在 UWP 形態(tài)下喚起一個(gè) Win32 的自己,就可以自己利用自己濫權(quán)(bushi)了。

      既然知道了原理可行,那么我們就來(lái)嘗試把它造出來(lái),眾所周知,通信的方法有很多,比如 UWP 擴(kuò)展通信、TCP 通信、管道通信甚至是寫(xiě)文件通信,但是這些用起來(lái)都太復(fù)雜了,既然我們已經(jīng)用了 WinRT,那么我們直接用 WinRT 通信就是了。

      不過(guò)真正的 OOP/WinRT 通信的例子并不多,我到目前為止也沒(méi)有成功實(shí)現(xiàn),所以就先用 COM 通信湊數(shù)了。現(xiàn)在微軟到處都是 OOP/COM 通信,比如小組件和 Dev Home,自從微軟瘋狂用 OOP/COM 造插件之后這方面的示例已經(jīng)非常多了,這里就展示一下如何用 C# 實(shí)現(xiàn)基于 OOP/COM 的 WinRT 通信。

      既然是通信,肯定要有服務(wù)器和客戶(hù)端,這里這兩個(gè)都是自己,所以我們就只需要?jiǎng)?chuàng)建一個(gè) UWP 項(xiàng)目就行了。由于 C#/WinRT 并不能實(shí)現(xiàn) WinRT 類(lèi)與非 WinRT 類(lèi)混編,所以我們還需要?jiǎng)?chuàng)建一個(gè) C++/WinRT 項(xiàng)目來(lái)生成 winmd 清單,這個(gè) C++ 項(xiàng)目可以精簡(jiǎn)一下,只需要能編譯 IDL 文件就行了,當(dāng)然不修改也可以,只是看起來(lái)不太清爽罷了。

      由于 C++/WinRT 項(xiàng)目只負(fù)責(zé)生成清單,如果直接引用該項(xiàng)目會(huì)報(bào)找不到 dll 實(shí)現(xiàn),所以我們需要把 winmd 文件單獨(dú)拿出來(lái),在 vcxprj 中添加任務(wù):

      <Target Name="OutputWinMD" BeforeTargets="BuildCompile">
        <PropertyGroup>
          <PlatformName Condition="'$(Platform)' == 'Win32'">x86</PlatformName>
          <PlatformName Condition="'$(Platform)' == 'ARM64EC'">ARM64</PlatformName>
          <PlatformName Condition="'$(PlatformName)' == ''">$(Platform)</PlatformName>
        </PropertyGroup>
        <Copy SourceFiles="$(OutDir)\$(ProjectName).winmd" DestinationFolder="..\WinMD\$(PlatformName)\$(Configuration)\" />
        <Message Text="Copied output metadata file to '..\WinMD\$(PlatformName)\$(Configuration)\'." />
      </Target>

      這樣當(dāng)項(xiàng)目編譯完成后就會(huì)把 winmd 復(fù)制到..\WinMD\$(PlatformName)\$(Configuration)\里面,這個(gè)文件夾是什么可以根據(jù)情況修改,注意只復(fù)制 winmd 文件。

      接著我們?cè)?UWP 項(xiàng)目引用 winmd 文件 (SelfCOMServer.Metadata替換成實(shí)際值):

      <ItemGroup>
        <CsWinRTInputs Include="..\WinMD\$(Platform)\$(Configuration)\SelfCOMServer.Metadata.winmd" />
      </ItemGroup>
      
      <ItemGroup>
        <None Include="..\WinMD\$(Platform)\$(Configuration)\SelfCOMServer.Metadata.winmd" Visible="False">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
      </ItemGroup>

      接下來(lái)我們就可以開(kāi)始寫(xiě) COM 類(lèi)了,首先我們要實(shí)現(xiàn)一個(gè)負(fù)責(zé)服務(wù)器管理的類(lèi),這個(gè)類(lèi)用來(lái)管理服務(wù)器的聲明周期和遠(yuǎn)程類(lèi)的獲取方法。

      其中我們需要先實(shí)現(xiàn)一種讓服務(wù)器可以在客戶(hù)端關(guān)閉后自動(dòng)關(guān)閉的方法,讓客戶(hù)端通知是很不合理的,因?yàn)榭蛻?hù)端可能會(huì)突然暴斃,這樣就會(huì)導(dǎo)致服務(wù)器永遠(yuǎn)也不會(huì)釋放了,所以我們必須讓服務(wù)器去感知客戶(hù)端不再需要服務(wù)器了。在 C++,我們可以通過(guò)觀察引用計(jì)數(shù)的方法來(lái)知道遠(yuǎn)程類(lèi)是否被客戶(hù)端釋放了,但是在 C#,遠(yuǎn)程類(lèi)被客戶(hù)端釋放后并不會(huì)真的釋放,我暫時(shí)不清楚其中的原因,表現(xiàn)出來(lái)就是解構(gòu)方法并不會(huì)被執(zhí)行,所以我們就無(wú)法通過(guò)類(lèi)釋放來(lái)關(guān)閉服務(wù)器了。于是我們還有一種方法,當(dāng)通信斷開(kāi)后,我們執(zhí)行遠(yuǎn)程方法就會(huì)報(bào)錯(cuò),這樣我們就知道通信已經(jīng)斷開(kāi)了,于是我們可以讓客戶(hù)端給服務(wù)器發(fā)送一個(gè)保活委托,服務(wù)器每隔一段時(shí)間就去執(zhí)行一次,這樣通信斷開(kāi)后再執(zhí)行委托就會(huì)直接報(bào)錯(cuò)了。當(dāng)然我們還可以讓這個(gè)保活委托變成一個(gè)永遠(yuǎn)也不會(huì)結(jié)束的異步,讓 WinRT 自己去等待,這樣服務(wù)器在通信斷開(kāi)的一瞬間知道通信結(jié)束了,不過(guò)由于我們并不需要瞬間就反應(yīng),有時(shí)候我們還需要考慮應(yīng)用被關(guān)閉后馬上就又打開(kāi)的情況,所以我還是選擇自己開(kāi)個(gè)間隔比較長(zhǎng)的定時(shí)器自己喂狗了。

      實(shí)現(xiàn)很簡(jiǎn)單,開(kāi)個(gè)定時(shí)器喂狗就行了:

      /// <summary>
      /// Represents a monitor that checks if a remote object is alive.
      /// </summary>
      public sealed partial class RemoteMonitor : IDisposable
      {
          private bool disposed;
          private readonly Timer _timer;
          private readonly Action _dispose;
      
          /// <summary>
          /// Initializes a new instance of the <see cref="RemoteMonitor"/> class.
          /// </summary>
          /// <param name="handler">The handler to check if the remote object is alive.</param>
          /// <param name="dispose">The action to dispose the remote object.</param>
          /// <param name="period">The period to check if the remote object is alive.</param>
          public RemoteMonitor(IsAliveHandler handler, Action dispose, TimeSpan period)
          {
              _dispose = dispose;
              _timer = new(_ =>
              {
                  bool isAlive = false;
                  try
                  {
                      isAlive = handler.Invoke();
                  }
                  catch
                  {
                      isAlive = false;
                  }
                  finally
                  {
                      if (!isAlive)
                      {
                          Dispose();
                      }
                  }
              }, null, TimeSpan.Zero, period);
          }
      
          /// <summary>
          /// Finalizes the instance of the <see cref="RemoteMonitor"/> class.
          /// </summary>
          ~RemoteMonitor() => Dispose();
      
          /// <inheritdoc/>
          public void Dispose()
          {
              if (!disposed)
              {
                  disposed = true;
                  _timer.Dispose();
                  _dispose?.Invoke();
                  GC.SuppressFinalize(this);
              }
          }
      }

      同時(shí)在 IDL 定義IsAliveHandler委托:

      delegate Boolean IsAliveHandler();

      接下來(lái)我們就可以寫(xiě)服務(wù)器管理類(lèi)了,我們只需要讓它能正確釋放服務(wù)器就行了,分別寫(xiě) IDL 定義和 C# 實(shí)現(xiàn):

      interface ISetMonitor
      {
          void SetMonitor(IsAliveHandler handler, Windows.Foundation.TimeSpan period);
      }
      
      interface IRemoteThing requires ISetMonitor, Windows.Foundation.IClosable, Windows.Foundation.IStringable
      {
          // 其他遠(yuǎn)程操作
      }
      /// <summary>
      /// The manage class for remote object.
      /// </summary>
      public sealed partial class RemoteThing : IRemoteThing
      {
          private bool disposed;
          private RemoteMonitor _monitor;
      
          /// <summary>
          /// Initializes a new instance of the <see cref="RemoteThing"/> class.
          /// </summary>
          public RemoteThing() => Program.RefCount++;
      
          /// <summary>
          /// Finalizes the instance of the <see cref="RemoteThing"/> class.
          /// </summary>
          ~RemoteThing() => Dispose();
      
          /// <summary>
          /// Sets the monitor to check if the remote object is alive.
          /// </summary>
          /// <param name="handler">The handler to check if the remote object is alive.</param>
          /// <param name="period">The period to check if the remote object is alive.</param>
          public void SetMonitor(IsAliveHandler handler, TimeSpan period) => _monitor = new RemoteMonitor(handler, Dispose, period);
      
          #region 其他遠(yuǎn)程操作
      
          #endregion
      
          /// <inheritdoc/>
          public void Dispose()
          {
              if (!disposed)
              {
                  disposed = true;
                  _monitor?.Dispose();
                  GC.SuppressFinalize(this);
                  if (--Program.RefCount == 0)
                  {
                      _ = Program.CheckComRefAsync();
                  }
              }
          }
      
          /// <summary>
          /// 隨便寫(xiě)點(diǎn)什么作為測(cè)試。
          /// </summary>
          public override string ToString() =>
              new StringBuilder()
                  .AppendLine("Information")
                  .AppendLine($"Framework: {RuntimeInformation.FrameworkDescription}")
                  .AppendLine($"OSPlatform: {Environment.OSVersion}")
                  .Append($"OSArchitecture: {RuntimeInformation.OSArchitecture}")
                  .ToString();
      }

      有了服務(wù)器管理類(lèi),我們就可以把它注冊(cè)到 COM 服務(wù)器了。想要注冊(cè) COM 類(lèi),我們需要一個(gè)  Factory 工廠類(lèi)來(lái)讓 COM 服務(wù)器可以在通信時(shí)初始化 COM 類(lèi)。首先我們需要導(dǎo)入 COM 相關(guān) API,定義IClassFactory接口,其中Factory.CLSID_IRemoteThing為遠(yuǎn)程類(lèi)的CLSID

      public static partial class Factory
      {
          public static readonly Guid CLSID_IRemoteThing = new("01153FC5-2F29-4F60-93AD-EFFB97CC9E20");
          public static readonly Guid CLSID_IUnknown = new("00000000-0000-0000-C000-000000000046");
      
          [LibraryImport("api-ms-win-core-com-l1-1-0.dll")]
          internal static partial int CoRegisterClassObject(in Guid rclsid, IClassFactory pUnk, uint dwClsContext, int flags, out uint lpdwRegister);
      
          [LibraryImport("api-ms-win-core-com-l1-1-0.dll")]
          internal static partial int CoRevokeClassObject(uint dwRegister);
      }
      
      // https://docs.microsoft.com/windows/win32/api/unknwn/nn-unknwn-iclassfactory
      [GeneratedComInterface]
      [Guid("00000001-0000-0000-C000-000000000046")]
      public partial interface IClassFactory
      {
          void CreateInstance(nint pUnkOuter, in Guid riid, out nint ppvObject);
      
          void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock);
      }

      接下來(lái)我們可以制作一個(gè)抽象的工廠類(lèi),然后就可以直接繼承這個(gè)工廠類(lèi)來(lái)實(shí)現(xiàn)對(duì)應(yīng)類(lèi)的工廠類(lèi),不過(guò)由于 COM 源生成暫時(shí)不支持泛型,所以這個(gè)抽象的工廠類(lèi)不能加GeneratedComClass

      public abstract partial class Factory<T, TInterface> : IActivationFactory, IClassFactory where T : TInterface, new()
      {
          private const int E_NOINTERFACE = unchecked((int)0x80004002);
          private const int CLASS_E_NOAGGREGATION = unchecked((int)0x80040110);
      
          private readonly Guid _iid = typeof(TInterface).GUID;
      
          public nint ActivateInstance() => MarshalInspectable<TInterface>.FromManaged(new T());
      
          public void CreateInstance(nint pUnkOuter, in Guid riid, out nint ppvObject)
          {
              ppvObject = 0;
      
              if (pUnkOuter != 0)
              {
                  Marshal.ThrowExceptionForHR(CLASS_E_NOAGGREGATION);
              }
      
              if (riid == _iid || riid == Factory.CLSID_IUnknown)
              {
                  // Create the instance of the .NET object
                  ppvObject = MarshalInspectable<TInterface>.FromManaged(new T());
              }
              else
              {
                  // The object that ppvObject points to does not support the
                  // interface identified by riid.
                  Marshal.ThrowExceptionForHR(E_NOINTERFACE);
              }
          }
      
          public void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock)
          {
          }
      
          public abstract void RegisterClassObject();
          public abstract void RevokeClassObject();
      }

      然后我們繼承這個(gè)抽象的工廠類(lèi)來(lái)實(shí)現(xiàn)我們需要的工廠類(lèi):

      [GeneratedComClass]
      public partial class RemoteThingFactory : Factory<RemoteThing, IRemoteThing>
      {
          private uint cookie;
      
          public override void RegisterClassObject()
          {
              int hresult = Factory.CoRegisterClassObject(
                  Factory.CLSID_IRemoteThing,
                  this,
                  (uint)CLSCTX.CLSCTX_LOCAL_SERVER,
                  (int)REGCLS.REGCLS_MULTIPLEUSE,
                  out cookie);
              if (hresult < 0)
              {
                  Marshal.ThrowExceptionForHR(hresult);
              }
          }
      
          public override void RevokeClassObject()
          {
              int hresult = Factory.CoRevokeClassObject(cookie);
              if (hresult < 0)
              {
                  Marshal.ThrowExceptionForHR(hresult);
              }
          }
      }

      然后我們就可以在程序入口點(diǎn)注冊(cè)這個(gè) COM 類(lèi)了:

      public static class Program
      {
          private static ManualResetEventSlim comServerExitEvent;
      
          public static int RefCount { get; set; }
      
          private static void Main(string[] args)
          {
              if (args is ["-RegisterProcessAsComServer", ..])
              {
                  comServerExitEvent = new ManualResetEventSlim(false);
                  comServerExitEvent.Reset();
                  RemoteThingFactory factory = new();
                  factory.RegisterClassObject();
                  _ = CheckComRefAsync();
                  comServerExitEvent.Wait();
                  factory.RevokeClassObject();
              }
              else
              {
                  Application.Start(static p =>
                  {
                      DispatcherQueueSynchronizationContext context = new(DispatcherQueue.GetForCurrentThread());
                      SynchronizationContext.SetSynchronizationContext(context);
                      _ = new App();
                  });
              }
          }
      
          public static async Task CheckComRefAsync()
          {
              await Task.Delay(100);
              if (RefCount == 0)
              {
                  comServerExitEvent?.Set();
              }
          }
      }

      最后我們需要在清單聲明 COM 服務(wù)器,其中SelfCOMServer.exe為服務(wù)器所在的可執(zhí)行文件,Class ID 填遠(yuǎn)程類(lèi)的CLSID

      <Applications>
        <Application>
          ...
          <Extensions>
            <com:Extension Category="windows.comServer">
              <com:ComServer>
                <com:ExeServer
                  Executable="SelfCOMServer.exe"
                  Arguments="-RegisterProcessAsComServer"
                  DisplayName="COM Server"
                  LaunchAndActivationPermission="O:SYG:SYD:(A;;11;;;WD)(A;;11;;;RC)(A;;11;;;AC)(A;;11;;;AN)S:P(ML;;NX;;;S-1-16-0)">
                  <com:Class Id="01153FC5-2F29-4F60-93AD-EFFB97CC9E20" DisplayName="COM Server" />
                </com:ExeServer>
              </com:ComServer>
            </com:Extension>
          </Extensions>
        </Application>
      </Applications>

      現(xiàn)在我們已經(jīng)完成了服務(wù)端的制作,接下來(lái)我們就可以讓客戶(hù)端調(diào)用服務(wù)器遠(yuǎn)程類(lèi)了。

      Factory類(lèi)繼續(xù)添加獲取遠(yuǎn)程類(lèi)的相關(guān)內(nèi)容:

      public static partial class Factory
      {
          private static bool IsAlive() => true;
      
          public static IRemoteThing CreateRemoteThing() =>
              CreateInstance<IRemoteThing>(CLSID_IRemoteThing, CLSCTX.CLSCTX_ALL, TimeSpan.FromMinutes(1));
      
          internal static T CreateInstance<T>(Guid rclsid, CLSCTX dwClsContext = CLSCTX.CLSCTX_INPROC_SERVER)
          {
              int hresult = CoCreateInstance(rclsid, 0, (uint)dwClsContext, CLSID_IUnknown, out nint result);
              if (hresult < 0)
              {
                  Marshal.ThrowExceptionForHR(hresult);
              }
              return Marshaler<T>.FromAbi(result);
          }
      
          internal static T CreateInstance<T>(Guid rclsid, CLSCTX dwClsContext, TimeSpan period) where T : ISetMonitor
          {
              T results = CreateInstance<T>(rclsid, dwClsContext);
              results.SetMonitor(IsAlive, period);
              return results;
          }
      
          [LibraryImport("api-ms-win-core-com-l1-1-0.dll")]
          private static partial int CoCreateInstance(in Guid rclsid, nint pUnkOuter, uint dwClsContext, in Guid riid, out nint ppv);
      }

      現(xiàn)在我們只需要執(zhí)行IRemoteThing remote = Factory.CreateRemoteThing();就能獲取遠(yuǎn)程類(lèi)了。

      到這里我們已經(jīng)完成了 OOP COM 的全部流程,我們想要實(shí)現(xiàn)什么內(nèi)容就可以按照構(gòu)建服務(wù)器管理類(lèi)的方法來(lái)制作 COM 遠(yuǎn)程類(lèi),然后通過(guò)在服務(wù)器管理類(lèi)添加一個(gè)構(gòu)造方法來(lái)獲取這個(gè)遠(yuǎn)程類(lèi),這樣我們就不需要單獨(dú)分配 CLSID 和注冊(cè) COM 類(lèi)了。

      比如我們可以給Process套個(gè)殼:

      /// <inheritdoc cref="Process"/>
      public partial class RemoteProcess(Process inner) : IProcess
      {
          /// <inheritdoc cref="Process.ProcessName"/>
          public string ProcessName => inner.ProcessName;
      
          /// <inheritdoc cref="Process.StandardError"/>
          public ITextReader StandardError => new RemoteTextReader(inner.StandardError);
      
          /// <inheritdoc cref="Process.ProcessName"/>
          public ITextWriter StandardInput => new RemoteTextWriter(inner.StandardInput);
      
          /// <inheritdoc cref="Process.StandardOutput"/>
          public ITextReader StandardOutput => new RemoteTextReader(inner.StandardOutput);
      
          /// <inheritdoc cref="Process.StartInfo"/>
          public IProcessStartInfo StartInfo
          {
              get => new RemoteProcessStartInfo(inner.StartInfo);
              set => value.ToProcessStartInfo();
          }
      
          private readonly ConditionalWeakTable<CoDataReceivedEventHandler, DataReceivedEventHandler> errorDataReceived = [];
          /// <inheritdoc cref="Process.ErrorDataReceived"/>
          public event CoDataReceivedEventHandler ErrorDataReceived
          {
              add
              {
                  void wrapper(object sender, DataReceivedEventArgs e) => value(this, new CoDataReceivedEventArgs(e.Data));
                  DataReceivedEventHandler handler = wrapper;
                  inner.ErrorDataReceived += handler;
                  errorDataReceived.Add(value, handler);
              }
              remove
              {
                  if (errorDataReceived.TryGetValue(value, out DataReceivedEventHandler handler))
                  {
                      inner.ErrorDataReceived -= handler;
                      errorDataReceived.Remove(value);
                  }
              }
          }
      
          private readonly ConditionalWeakTable<CoDataReceivedEventHandler, DataReceivedEventHandler> outputDataReceived = [];
          /// <inheritdoc cref="Process.OutputDataReceived"/>
          public event CoDataReceivedEventHandler OutputDataReceived
          {
              add
              {
                  void wrapper(object sender, DataReceivedEventArgs e) => value(this, new CoDataReceivedEventArgs(e.Data));
                  DataReceivedEventHandler handler = wrapper;
                  inner.OutputDataReceived += handler;
                  outputDataReceived.Add(value, handler);
              }
              remove
              {
                  if (outputDataReceived.TryGetValue(value, out DataReceivedEventHandler handler))
                  {
                      inner.OutputDataReceived -= handler;
                      outputDataReceived.Remove(value);
                  }
              }
          }
      
          /// <inheritdoc cref="Process.BeginErrorReadLine"/>
          public void BeginErrorReadLine() => inner.BeginErrorReadLine();
      
          /// <inheritdoc cref="Process.BeginOutputReadLine"/>
          public void BeginOutputReadLine() => inner.BeginOutputReadLine();
      
          /// <inheritdoc cref="Process.CancelErrorRead"/>
          public void CancelErrorRead() => inner.CancelErrorRead();
      
          /// <inheritdoc cref="Process.CancelOutputRead"/>
          public void CancelOutputRead() => inner.CancelOutputRead();
      
          /// <inheritdoc cref="Component.Dispose"/>
          public void Dispose()
          {
              inner.Dispose();
              GC.SuppressFinalize(this);
          }
      
          /// <inheritdoc cref="Process.ToString"/>
          public override string ToString() => inner.ToString();
      }

      靜態(tài)部分可以弄一個(gè)假裝的靜態(tài)類(lèi):

      /// <inheritdoc cref="Process"/>
      public sealed partial class ProcessStatic : IProcessStatic
      {
          /// <inheritdoc cref="Process.GetProcesses()"/>
          public IProcess[] GetProcesses() => Process.GetProcesses().Select(x => new RemoteProcess(x)).ToArray();
      
          public IProcess Start(IProcessStartInfo startInfo) =>
              Process.Start(startInfo.ToProcessStartInfo()) is Process process
                  ? new RemoteProcess(process) : null;
      }

      然后我們?cè)诜?wù)器管理類(lèi)里增加構(gòu)造方法:

      public IProcessStatic CreateProcessStatic() => new ProcessStatic();

      這樣我們就可以在 UWP 里使用 Process 創(chuàng)建一個(gè) cmd 進(jìn)程了:

      IRemoteThing remote = Factory.CreateRemoteThing();
      process = remote.CreateProcessStatic().Start(new RemoteProcessStartInfo
      {
          FileName = "cmd",
          CreateNoWindow = true,
          RedirectStandardError = true,
          RedirectStandardInput = true,
          RedirectStandardOutput = true,
          UseShellExecute = false
      });
      AppTitle.Text = process.ProcessName;
      process.OutputDataReceived += OnOutputDataReceived;
      process.ErrorDataReceived += OnErrorDataReceived;
      process.BeginOutputReadLine();
      process.BeginErrorReadLine();

      具體實(shí)現(xiàn)可以查看:SelfCOMServer/SelfCOMServer/Common/RemoteProcess.cs at main · wherewhere/SelfCOMServer

      最后附上示例應(yīng)用:https://github.com/wherewhere/SelfCOMServer

      posted @ 2025-04-01 14:04  where-where  閱讀(190)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 丰满少妇被猛烈进出69影院| 亚洲av色图一区二区三区| 四虎影视国产精品永久在线| 精品国产污污免费网站| 国产精品人伦一区二区三| 午夜精品区| 国内不卡一区二区三区| 成人一区二区三区在线午夜 | 国产精品福利自产拍久久 | 亚洲精品自拍视频在线看 | 亚洲精品日本一区二区| 无套后入极品美女少妇| 在线观看国产成人av天堂| 波多野结衣一区二区免费视频| 日韩少妇人妻vs中文字幕 | 成年午夜免费韩国做受视频| 九九热精品在线观看| 苍井空一区二区波多野结衣av| 亚洲av成人精品免费看| 亚洲精品中文av在线| 亚洲AV成人片不卡无码| 日韩中文日韩中文字幕亚| 国产一码二码三码区别| 色综合视频一区二区三区| 波多野结衣乳喷高潮视频| 蜜臀91精品国产高清在线| 久久精品国产亚洲av麻豆长发| 亚洲午夜无码久久久久蜜臀av| 强奷乱码中文字幕| 久久99国产精一区二区三区!| 日韩精品国产中文字幕| 精品无码成人片一区二区98| 久99久热免费视频播放| 日本亚洲一区二区精品| 日韩人妻精品中文字幕| 日韩一区二区三区在线视频| 色伦专区97中文字幕| 国产成人精品无人区一区| 日韩一区精品视频一区二区| 中文无码乱人伦中文视频在线| 国产亚洲精品AA片在线爽|