桌面共享
2
.gitignore
vendored
@@ -6,4 +6,4 @@ node_modules
|
||||
/public/*
|
||||
/cmonitor.volume/x64/*
|
||||
/cmonitor.killer/x64/*
|
||||
/x64/*
|
||||
/x64/*
|
||||
@@ -70,7 +70,7 @@
|
||||
- [x] 发送命令,执行cmd命令,等等
|
||||
###### 互动
|
||||
- [x] 互动答题 **winform**
|
||||
- [x] 屏幕共享,以某一设备为主机,向其它设备共享屏幕,用于演示 **sharpDX** **第一次成功连接服务端后自动恢复**
|
||||
- [x] 屏幕共享,以某一设备为主机,向其它设备共享屏幕,用于演示 **RDPSession+RDPViewer** **第一次成功连接服务端后自动恢复**
|
||||
###### 壁纸
|
||||
- [x] 壁纸程序,为所有设备设置统一壁纸,以程序的方式 **winform** **第一次成功连接服务端后自动恢复**
|
||||
- [x] 键盘按键,显示键盘按键(当前键盘按键由壁纸程序提供) **win api**
|
||||
@@ -97,7 +97,7 @@
|
||||
1. **【--server】** 服务器ip **192.168.1.18**
|
||||
2. **【--service】** 服务端口 **1802**
|
||||
3. **【--share-key】** 自定数据共享 **cmonitor/share**
|
||||
4. **【--share-len】** 数量 **10**,默认10项位置,0保留,1键盘、2壁纸、3锁屏,4 SendSAS
|
||||
4. **【--share-len】** 数量 **100**,默认100项位置,0保留,1键盘、2壁纸、3锁屏,4 SendSAS, 5 抢答问题, 6 抢答答案, 7 屏幕共享, 8 剪贴板
|
||||
4. **【--share-item-len】** 每项数据长度 **1024**,attr(1)+version(8)+klen(4)+key(klen)+vlen(4)+value(vallen)
|
||||
|
||||
###### 服务端
|
||||
|
||||
60
cmonitor.clipboard.win/MainForm.Designer.cs
generated
Normal file
@@ -0,0 +1,60 @@
|
||||
namespace cmonitor.clipboard.win
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||
textBox1 = new TextBox();
|
||||
SuspendLayout();
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
textBox1.Location = new Point(12, 12);
|
||||
textBox1.Multiline = true;
|
||||
textBox1.Name = "textBox1";
|
||||
textBox1.Size = new Size(261, 287);
|
||||
textBox1.TabIndex = 0;
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 17F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(285, 450);
|
||||
Controls.Add(textBox1);
|
||||
Icon = (Icon)resources.GetObject("$this.Icon");
|
||||
Name = "MainForm";
|
||||
Text = "剪贴板";
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private TextBox textBox1;
|
||||
}
|
||||
}
|
||||
138
cmonitor.clipboard.win/MainForm.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace cmonitor.clipboard.win
|
||||
{
|
||||
public partial class MainForm : Form
|
||||
{
|
||||
protected override CreateParams CreateParams
|
||||
{
|
||||
get
|
||||
{
|
||||
const int WS_EX_APPWINDOW = 0x40000;
|
||||
const int WS_EX_TOOLWINDOW = 0x80;
|
||||
CreateParams cp = base.CreateParams;
|
||||
cp.ExStyle &= (~WS_EX_APPWINDOW);
|
||||
cp.ExStyle |= WS_EX_TOOLWINDOW;
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr nextClipboardViewer;
|
||||
const int WM_DRAWCLIPBOARD = 0x0308;
|
||||
const uint CF_TEXT = 1;
|
||||
const uint CF_HDROP = 15;
|
||||
public MainForm()
|
||||
{
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
|
||||
InitializeComponent();
|
||||
nextClipboardViewer = SetClipboardViewer(this.Handle);
|
||||
}
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
base.WndProc(ref m);
|
||||
|
||||
if (m.Msg == WM_DRAWCLIPBOARD)
|
||||
{
|
||||
OnClipboardChanged();
|
||||
}
|
||||
}
|
||||
private void OnClipboardChanged()
|
||||
{
|
||||
if (OpenClipboard(IntPtr.Zero))
|
||||
{
|
||||
uint format = 0;
|
||||
while ((format = EnumClipboardFormats(format)) != 0)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CF_TEXT:
|
||||
HandleTextData();
|
||||
break;
|
||||
case CF_HDROP:
|
||||
HandleFileListData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
}
|
||||
private void HandleTextData()
|
||||
{
|
||||
IntPtr clipboardData = GetClipboardData(CF_TEXT);
|
||||
if (clipboardData != IntPtr.Zero)
|
||||
{
|
||||
string text = Marshal.PtrToStringAnsi(clipboardData);
|
||||
this.Invoke(() =>
|
||||
{
|
||||
textBox1.Text = text;
|
||||
});
|
||||
}
|
||||
}
|
||||
private void HandleFileListData()
|
||||
{
|
||||
IntPtr clipboardData = GetClipboardData(CF_HDROP);
|
||||
if (clipboardData != IntPtr.Zero)
|
||||
{
|
||||
IntPtr fileDropHandle = Marshal.ReadIntPtr(clipboardData);
|
||||
uint fileCount = DragQueryFile(fileDropHandle, 0xFFFFFFFF, null, 0);
|
||||
|
||||
List<string> fileList = new List<string>();
|
||||
for (uint i = 0; i < fileCount; i++)
|
||||
{
|
||||
uint bufferSize = DragQueryFile(fileDropHandle, i, null, 0) + 1;
|
||||
char[] fileName = new char[bufferSize];
|
||||
|
||||
DragQueryFile(fileDropHandle, i, fileName, bufferSize);
|
||||
string filePath = new string(fileName);
|
||||
|
||||
fileList.Add(filePath);
|
||||
}
|
||||
|
||||
DragFinish(fileDropHandle);
|
||||
|
||||
this.Invoke(() =>
|
||||
{
|
||||
textBox1.Text = string.Join("\r\n", fileList);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern IntPtr GetClipboardData(uint uFormat);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern bool IsClipboardFormatAvailable(uint format);
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern uint EnumClipboardFormats(uint format);
|
||||
[DllImport("shell32.dll")]
|
||||
static extern uint DragQueryFile(IntPtr hDrop, uint iFile, char[] lpszFile, uint cch);
|
||||
|
||||
[DllImport("shell32.dll")]
|
||||
static extern void DragFinish(IntPtr hDrop);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern bool OpenClipboard(IntPtr hWndNewOwner);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern bool CloseClipboard();
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern IntPtr GlobalLock(IntPtr hMem);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern bool GlobalUnlock(IntPtr hMem);
|
||||
|
||||
}
|
||||
}
|
||||
17
cmonitor.clipboard.win/Program.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace cmonitor.clipboard.win
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
// To customize application configuration such as set high DPI settings or default font,
|
||||
// see https://aka.ms/applicationconfiguration.
|
||||
ApplicationConfiguration.Initialize();
|
||||
Application.Run(new MainForm());
|
||||
}
|
||||
}
|
||||
}
|
||||
17
cmonitor.clipboard.win/cmonitor.clipboard.win.csproj
Normal file
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFrameworks>net7.0-windows;net8.0-windows</TargetFrameworks>
|
||||
<Nullable>disable</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="favicon.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
72
cmonitor.install.win/MainForm.Designer.cs
generated
@@ -43,14 +43,6 @@
|
||||
shareLen = new TextBox();
|
||||
label6 = new Label();
|
||||
shareKey = new TextBox();
|
||||
label7 = new Label();
|
||||
wallpaperIndex = new TextBox();
|
||||
label8 = new Label();
|
||||
keyboardIndex = new TextBox();
|
||||
label9 = new Label();
|
||||
llockIndex = new TextBox();
|
||||
label10 = new Label();
|
||||
sasIndex = new TextBox();
|
||||
label11 = new Label();
|
||||
machineName = new TextBox();
|
||||
label12 = new Label();
|
||||
@@ -60,7 +52,6 @@
|
||||
label14 = new Label();
|
||||
screenScale = new TextBox();
|
||||
installBtn = new Button();
|
||||
label15 = new Label();
|
||||
runBtn = new Button();
|
||||
checkStateBtn = new Button();
|
||||
label16 = new Label();
|
||||
@@ -139,46 +130,6 @@
|
||||
resources.ApplyResources(shareKey, "shareKey");
|
||||
shareKey.Name = "shareKey";
|
||||
//
|
||||
// label7
|
||||
//
|
||||
resources.ApplyResources(label7, "label7");
|
||||
label7.Name = "label7";
|
||||
//
|
||||
// wallpaperIndex
|
||||
//
|
||||
resources.ApplyResources(wallpaperIndex, "wallpaperIndex");
|
||||
wallpaperIndex.Name = "wallpaperIndex";
|
||||
//
|
||||
// label8
|
||||
//
|
||||
resources.ApplyResources(label8, "label8");
|
||||
label8.Name = "label8";
|
||||
//
|
||||
// keyboardIndex
|
||||
//
|
||||
resources.ApplyResources(keyboardIndex, "keyboardIndex");
|
||||
keyboardIndex.Name = "keyboardIndex";
|
||||
//
|
||||
// label9
|
||||
//
|
||||
resources.ApplyResources(label9, "label9");
|
||||
label9.Name = "label9";
|
||||
//
|
||||
// llockIndex
|
||||
//
|
||||
resources.ApplyResources(llockIndex, "llockIndex");
|
||||
llockIndex.Name = "llockIndex";
|
||||
//
|
||||
// label10
|
||||
//
|
||||
resources.ApplyResources(label10, "label10");
|
||||
label10.Name = "label10";
|
||||
//
|
||||
// sasIndex
|
||||
//
|
||||
resources.ApplyResources(sasIndex, "sasIndex");
|
||||
sasIndex.Name = "sasIndex";
|
||||
//
|
||||
// label11
|
||||
//
|
||||
resources.ApplyResources(label11, "label11");
|
||||
@@ -226,11 +177,6 @@
|
||||
installBtn.UseVisualStyleBackColor = true;
|
||||
installBtn.Click += OnInstallClick;
|
||||
//
|
||||
// label15
|
||||
//
|
||||
resources.ApplyResources(label15, "label15");
|
||||
label15.Name = "label15";
|
||||
//
|
||||
// runBtn
|
||||
//
|
||||
resources.ApplyResources(runBtn, "runBtn");
|
||||
@@ -263,7 +209,6 @@
|
||||
Controls.Add(shareItemLen);
|
||||
Controls.Add(checkStateBtn);
|
||||
Controls.Add(runBtn);
|
||||
Controls.Add(label15);
|
||||
Controls.Add(installBtn);
|
||||
Controls.Add(label14);
|
||||
Controls.Add(screenScale);
|
||||
@@ -273,14 +218,6 @@
|
||||
Controls.Add(reportDelay);
|
||||
Controls.Add(label11);
|
||||
Controls.Add(machineName);
|
||||
Controls.Add(label10);
|
||||
Controls.Add(sasIndex);
|
||||
Controls.Add(label9);
|
||||
Controls.Add(llockIndex);
|
||||
Controls.Add(label7);
|
||||
Controls.Add(wallpaperIndex);
|
||||
Controls.Add(label8);
|
||||
Controls.Add(keyboardIndex);
|
||||
Controls.Add(label5);
|
||||
Controls.Add(shareLen);
|
||||
Controls.Add(label6);
|
||||
@@ -315,14 +252,6 @@
|
||||
private System.Windows.Forms.TextBox shareLen;
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.TextBox shareKey;
|
||||
private System.Windows.Forms.Label label7;
|
||||
private System.Windows.Forms.TextBox wallpaperIndex;
|
||||
private System.Windows.Forms.Label label8;
|
||||
private System.Windows.Forms.TextBox keyboardIndex;
|
||||
private System.Windows.Forms.Label label9;
|
||||
private System.Windows.Forms.TextBox llockIndex;
|
||||
private System.Windows.Forms.Label label10;
|
||||
private System.Windows.Forms.TextBox sasIndex;
|
||||
private System.Windows.Forms.Label label11;
|
||||
private System.Windows.Forms.TextBox machineName;
|
||||
private System.Windows.Forms.Label label12;
|
||||
@@ -332,7 +261,6 @@
|
||||
private System.Windows.Forms.Label label14;
|
||||
private System.Windows.Forms.TextBox screenScale;
|
||||
private System.Windows.Forms.Button installBtn;
|
||||
private System.Windows.Forms.Label label15;
|
||||
private System.Windows.Forms.Button runBtn;
|
||||
private System.Windows.Forms.Button checkStateBtn;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using Microsoft.Win32;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace cmonitor.install.win
|
||||
{
|
||||
@@ -18,11 +18,6 @@ namespace cmonitor.install.win
|
||||
|
||||
private void OnLoad(object sender, EventArgs e)
|
||||
{
|
||||
keyboardIndex.ReadOnly = true;
|
||||
wallpaperIndex.ReadOnly = true;
|
||||
llockIndex.ReadOnly = true;
|
||||
sasIndex.ReadOnly = true;
|
||||
|
||||
LoadConfig();
|
||||
SaveConfig();
|
||||
|
||||
@@ -33,61 +28,50 @@ namespace cmonitor.install.win
|
||||
private void SaveConfig()
|
||||
{
|
||||
RegistryKey key = CheckRegistryKey();
|
||||
key.SetValue("modeClient", modeClient.Checked ? "1" : "0");
|
||||
key.SetValue("modeServer", modeServer.Checked ? "1" : "0");
|
||||
|
||||
key.SetValue("machineName", machineName.Text);
|
||||
|
||||
key.SetValue("serverIP", serverIP.Text);
|
||||
key.SetValue("serverPort", serverPort.Text);
|
||||
key.SetValue("apiPort", apiPort.Text);
|
||||
key.SetValue("webPort", webPort.Text);
|
||||
|
||||
key.SetValue("reportDelay", reportDelay.Text);
|
||||
key.SetValue("screenDelay", screenDelay.Text);
|
||||
key.SetValue("screenScale", screenScale.Text);
|
||||
|
||||
key.SetValue("shareKey", shareKey.Text);
|
||||
key.SetValue("shareLen", shareLen.Text);
|
||||
key.SetValue("shareItemLen", shareItemLen.Text);
|
||||
|
||||
key.SetValue("keyboardIndex", keyboardIndex.Text);
|
||||
key.SetValue("wallpaperIndex", wallpaperIndex.Text);
|
||||
key.SetValue("llockIndex", llockIndex.Text);
|
||||
key.SetValue("sasIndex", sasIndex.Text);
|
||||
|
||||
key.SetValue("installParams", new ConfigInfo
|
||||
{
|
||||
Client = modeClient.Checked,
|
||||
Server = modeServer.Checked,
|
||||
MachineName = machineName.Text,
|
||||
ServerEndpoint = new IPEndPoint(IPAddress.Parse(serverIP.Text), int.Parse(serverPort.Text)).ToString(),
|
||||
ApiPort = int.Parse(apiPort.Text),
|
||||
WebPort = int.Parse(webPort.Text),
|
||||
ReportDelay = int.Parse(reportDelay.Text),
|
||||
ScreenDelay = int.Parse(screenDelay.Text),
|
||||
ScreenScale = double.Parse(screenScale.Text),
|
||||
ShareKey = shareKey.Text,
|
||||
ShareLen = int.Parse(shareLen.Text),
|
||||
ShareSize = int.Parse(shareItemLen.Text),
|
||||
}.ToJson());
|
||||
|
||||
}
|
||||
private void LoadConfig()
|
||||
{
|
||||
RegistryKey key = CheckRegistryKey();
|
||||
|
||||
string hostname = Dns.GetHostName();
|
||||
|
||||
modeClient.Checked = key.GetValue("modeClient", "0").ToString() == "1";
|
||||
modeServer.Checked = key.GetValue("modeServer", "0").ToString() == "1";
|
||||
ConfigInfo config = key.GetValue("installParams", "{}").ToString().DeJson<ConfigInfo>();
|
||||
|
||||
machineName.Text = key.GetValue("machineName", hostname).ToString();
|
||||
modeClient.Checked = config.Client;
|
||||
modeServer.Checked = config.Server;
|
||||
|
||||
serverIP.Text = key.GetValue("serverIP", "127.0.0.1").ToString();
|
||||
serverPort.Text = key.GetValue("serverPort", "1802").ToString();
|
||||
apiPort.Text = key.GetValue("apiPort", "1801").ToString();
|
||||
webPort.Text = key.GetValue("webPort", "1800").ToString();
|
||||
machineName.Text = config.MachineName;
|
||||
|
||||
reportDelay.Text = key.GetValue("reportDelay", "30").ToString();
|
||||
screenDelay.Text = key.GetValue("screenDelay", "200").ToString();
|
||||
screenScale.Text = key.GetValue("screenScale", "0.2").ToString();
|
||||
IPEndPoint ep = IPEndPoint.Parse(config.ServerEndpoint);
|
||||
serverIP.Text = ep.Address.ToString();
|
||||
serverPort.Text = ep.Port.ToString();
|
||||
apiPort.Text = config.ApiPort.ToString();
|
||||
webPort.Text = config.WebPort.ToString();
|
||||
|
||||
shareKey.Text = key.GetValue("shareKey", "cmonitor/share").ToString();
|
||||
shareLen.Text = key.GetValue("shareLen", "10").ToString();
|
||||
shareItemLen.Text = key.GetValue("shareItemLen", "1024").ToString();
|
||||
reportDelay.Text = config.ReportDelay.ToString();
|
||||
screenDelay.Text = config.ScreenDelay.ToString();
|
||||
screenScale.Text = config.ScreenScale.ToString();
|
||||
|
||||
shareKey.Text = config.ShareKey;
|
||||
shareLen.Text = config.ShareLen.ToString();
|
||||
shareItemLen.Text = config.ShareSize.ToString();
|
||||
|
||||
keyboardIndex.Text = "1";
|
||||
wallpaperIndex.Text = "2";
|
||||
llockIndex.Text = "3";
|
||||
sasIndex.Text = "4";
|
||||
}
|
||||
|
||||
private RegistryKey CheckRegistryKey()
|
||||
{
|
||||
Registry.SetValue("HKEY_CURRENT_USER\\SOFTWARE\\cmonitor", "test", 1);
|
||||
@@ -129,7 +113,7 @@ namespace cmonitor.install.win
|
||||
string dir = Path.GetDirectoryName(filename);
|
||||
string sasPath = Path.Combine(dir, exeName);
|
||||
|
||||
string sasIndexStr = sasIndex.Text;
|
||||
string sasIndexStr = "4";
|
||||
|
||||
string shareKeyStr = shareKey.Text;
|
||||
string shareLenStr = shareLen.Text;
|
||||
@@ -255,26 +239,7 @@ namespace cmonitor.install.win
|
||||
MessageBox.Show("共享每项数据长度必填");
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(keyboardIndex.Text))
|
||||
{
|
||||
MessageBox.Show("键盘键下标必填");
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(wallpaperIndex.Text))
|
||||
{
|
||||
MessageBox.Show("壁纸键下标必填");
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(llockIndex.Text))
|
||||
{
|
||||
MessageBox.Show("锁屏键下标必填");
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(sasIndex.Text))
|
||||
{
|
||||
MessageBox.Show("sas键下标必填");
|
||||
return false;
|
||||
}
|
||||
|
||||
installParams.Add($"--share-key {shareKey.Text}");
|
||||
installParams.Add($"--share-len {shareLen.Text}");
|
||||
installParams.Add($"--share-item-len {shareItemLen.Text}");
|
||||
@@ -392,5 +357,22 @@ namespace cmonitor.install.win
|
||||
CheckInstall();
|
||||
CheckRunning();
|
||||
}
|
||||
|
||||
public sealed class ConfigInfo
|
||||
{
|
||||
public bool Client { get; set; }
|
||||
public bool Server { get; set; }
|
||||
public string MachineName { get; set; } = Dns.GetHostName();
|
||||
public string ServerEndpoint { get; set; } = new IPEndPoint(IPAddress.Loopback, 1802).ToString();
|
||||
public int ApiPort { get; set; } = 1801;
|
||||
public int WebPort { get; set; } = 1800;
|
||||
public int ReportDelay { get; set; } = 30;
|
||||
public int ScreenDelay { get; set; } = 200;
|
||||
public double ScreenScale { get; set; } = 0.2;
|
||||
public string ShareKey { get; set; } = "cmonitor/share";
|
||||
public int ShareLen { get; set; } = 100;
|
||||
public int ShareSize { get; set; } = 1024;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,10 +117,19 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="label15.Text" xml:space="preserve">
|
||||
<value>每项1024长度,0项保留不可用</value>
|
||||
</data>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="installBtn.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>193, 290</value>
|
||||
</data>
|
||||
<data name="runBtn.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>106, 290</value>
|
||||
</data>
|
||||
<data name="checkStateBtn.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>323, 296</value>
|
||||
</data>
|
||||
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>418, 334</value>
|
||||
</data>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAEAAAAAAAEAIABdQAAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAEAAAABAAgGAAAAXHKoZgAAQCRJ
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace cmonitor.libs
|
||||
{
|
||||
//1 attr + 8 version + 4 klen + key + 4 vlen + val
|
||||
internal interface IShareMemory
|
||||
{
|
||||
public bool Init();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -71,7 +72,7 @@ namespace cmonitor.libs
|
||||
{
|
||||
try
|
||||
{
|
||||
if (OperatingSystem.IsWindows() && accessorGlobal == null)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && accessorGlobal == null)
|
||||
{
|
||||
gloablBytes = new byte[bytes.Length];
|
||||
accessorGlobal = ShareMemoryFactory.Create($"Global\\{key}", length, itemSize);
|
||||
@@ -462,11 +463,13 @@ namespace cmonitor.libs
|
||||
IncrementVersion(accessor, index);
|
||||
}
|
||||
|
||||
private DateTime startTime = new DateTime(1970, 1, 1);
|
||||
private void IncrementVersion(IShareMemory accessor, int index)
|
||||
{
|
||||
if (accessor == null || index >= length) return;
|
||||
long version = accessor.ReadInt64(index * itemSize + shareMemoryVersionIndex);
|
||||
accessor.WriteInt64(index * itemSize + shareMemoryVersionIndex, version + 1);
|
||||
|
||||
long version = (long)(DateTime.UtcNow.Subtract(startTime)).TotalMilliseconds;
|
||||
accessor.WriteInt64(index * itemSize + shareMemoryVersionIndex, version);
|
||||
}
|
||||
private long ReadVersion(IShareMemory accessor, int index)
|
||||
{
|
||||
@@ -548,9 +551,36 @@ namespace cmonitor.libs
|
||||
Closed = 0b0000_0010,
|
||||
Running = 0b0000_0100,
|
||||
HiddenForList = 0b0000_1000,
|
||||
Error = 0b0001_0000,
|
||||
All = 0b1111_1111
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ShareItem
|
||||
{
|
||||
public byte Attr;
|
||||
|
||||
public ulong Version;
|
||||
|
||||
public ulong Time;
|
||||
|
||||
public byte KeyLength;
|
||||
|
||||
/// <summary>
|
||||
/// 255长度
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
|
||||
public byte[] Key;
|
||||
|
||||
public byte ValLength;
|
||||
|
||||
/// <summary>
|
||||
/// 9966长度
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9966)]
|
||||
public byte[] Value;
|
||||
}
|
||||
|
||||
public sealed class ShareItemAttributeChanged
|
||||
{
|
||||
public Action<ShareMemoryAttribute> Action { get; set; }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace cmonitor.libs
|
||||
{
|
||||
@@ -6,15 +7,15 @@ namespace cmonitor.libs
|
||||
{
|
||||
public static IShareMemory Create(string key, int length, int itemSize)
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return new ShareMemoryWindows(key, length, itemSize);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux())
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
return new ShareMemoryLinux(key, length, itemSize);
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
return new ShareMemoryMacOS(key, length, itemSize);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.IO;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Runtime.InteropServices;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace cmonitor.libs
|
||||
{
|
||||
@@ -25,7 +24,7 @@ namespace cmonitor.libs
|
||||
{
|
||||
try
|
||||
{
|
||||
if (accessorLocal == null && OperatingSystem.IsWindows())
|
||||
if (accessorLocal == null && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
mmfLocal = MemoryMappedFile.CreateOrOpen($"{key}", length * itemSize, MemoryMappedFileAccess.ReadWriteExecute, MemoryMappedFileOptions.None, HandleInheritability.None);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||
<TargetFrameworks>net7;net8</TargetFrameworks>
|
||||
<PublishAot>false</PublishAot>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
using common.libs;
|
||||
using Microsoft.Win32;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace cmonitor.llock.win
|
||||
{
|
||||
internal class Hook : IDisposable
|
||||
{
|
||||
private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
|
||||
private static int hHook = 0;
|
||||
private const int WH_KEYBOARD_LL = 13;
|
||||
HookProc KeyBoardHookProcedure;
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private class KeyBoardHookStruct
|
||||
{
|
||||
public int vkCode;
|
||||
public int scanCode;
|
||||
public int flags;
|
||||
public int time;
|
||||
public int dwExtraInfo;
|
||||
}
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool UnhookWindowsHookEx(int idHook);
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr GetModuleHandle(string name);
|
||||
|
||||
public void Start()
|
||||
{
|
||||
// 安装键盘钩子
|
||||
if (hHook == 0)
|
||||
{
|
||||
KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);
|
||||
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardHookProcedure, GetModuleHandle(null), 0);
|
||||
//如果设置钩子失败.
|
||||
if (hHook == 0)
|
||||
Close();
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (string user in Registry.Users.GetSubKeyNames())
|
||||
{
|
||||
RegistryKey key = Registry.Users.OpenSubKey(user, true).OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true);
|
||||
if (key == null)
|
||||
key = Registry.Users.OpenSubKey(user, true).CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System");
|
||||
|
||||
RegistryKey key1 = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true);
|
||||
if (key1 == null)
|
||||
key1 = Registry.LocalMachine.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System");
|
||||
|
||||
//任务管理器
|
||||
key.SetValue("DisableTaskMgr", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("DisableTaskMgr", 1, RegistryValueKind.DWord);
|
||||
//锁定
|
||||
key.SetValue("DisableLockWorkstation", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("DisableLockWorkstation", 1, RegistryValueKind.DWord);
|
||||
//切换用户
|
||||
key.SetValue("HideFastUserSwitching", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("HideFastUserSwitching", 1, RegistryValueKind.DWord);
|
||||
//修改密码
|
||||
key.SetValue("DisableChangePassword", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("DisableChangePassword", 1, RegistryValueKind.DWord);
|
||||
//关机
|
||||
key.SetValue("ShutdownWithoutLogon", 0, RegistryValueKind.DWord);
|
||||
key1.SetValue("ShutdownWithoutLogon", 0, RegistryValueKind.DWord);
|
||||
//注销
|
||||
key.SetValue("StartMenuLogOff", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("StartMenuLogOff", 1, RegistryValueKind.DWord);
|
||||
|
||||
|
||||
|
||||
key.Close();
|
||||
key1.Close();
|
||||
|
||||
//注销
|
||||
RegistryKey zxKey = Registry.Users.OpenSubKey(user, true).OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer", true);
|
||||
if (zxKey == null)
|
||||
zxKey = Registry.Users.OpenSubKey(user, true).CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer");
|
||||
zxKey.SetValue("NoLogOff", 1, RegistryValueKind.DWord);
|
||||
zxKey.SetValue("NoClose", 1, RegistryValueKind.DWord);
|
||||
zxKey.SetValue("StartMenuLogOff", 1, RegistryValueKind.DWord);
|
||||
zxKey.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
Task.Run(() =>
|
||||
{
|
||||
CommandHelper.Windows(string.Empty, new string[] { "gpupdate /force" });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Close()
|
||||
{
|
||||
if (hHook != 0)
|
||||
{
|
||||
UnhookWindowsHookEx(hHook);
|
||||
hHook = 0;
|
||||
}
|
||||
try
|
||||
{
|
||||
foreach (string user in Registry.Users.GetSubKeyNames())
|
||||
{
|
||||
RegistryKey key = Registry.Users.OpenSubKey(user, true).OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true);
|
||||
RegistryKey key1 = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true);
|
||||
if (key != null)
|
||||
{
|
||||
key.DeleteValue("DisableTaskMgr", false);
|
||||
key1.DeleteValue("DisableTaskMgr", false);
|
||||
key.DeleteValue("DisableLockWorkstation", false);
|
||||
key1.DeleteValue("DisableLockWorkstation", false);
|
||||
key.DeleteValue("HideFastUserSwitching", false);
|
||||
key1.DeleteValue("HideFastUserSwitching", false);
|
||||
key.DeleteValue("DisableChangePassword", false);
|
||||
key1.DeleteValue("DisableChangePassword", false);
|
||||
key.DeleteValue("ShutdownWithoutLogon", false);
|
||||
key1.DeleteValue("ShutdownWithoutLogon", false);
|
||||
key.DeleteValue("StartMenuLogoff", false);
|
||||
key1.DeleteValue("StartMenuLogoff", false);
|
||||
|
||||
|
||||
key.Close();
|
||||
key1.Close();
|
||||
}
|
||||
|
||||
RegistryKey zxKey = Registry.Users.OpenSubKey(user, true).OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer", true);
|
||||
if (zxKey != null)
|
||||
{
|
||||
zxKey.DeleteValue("NoLogOff", false);
|
||||
zxKey.DeleteValue("NoClose", false);
|
||||
zxKey.DeleteValue("StartMenuLogoff", false);
|
||||
zxKey.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
CommandHelper.Windows(string.Empty, new string[] { "gpupdate /force" }, false);
|
||||
}
|
||||
private int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)
|
||||
{
|
||||
if (nCode >= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return CallNextHookEx(hHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
#region IDisposable 成员
|
||||
public void Dispose()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private struct tagMSG
|
||||
{
|
||||
public int hwnd;
|
||||
public uint message;
|
||||
public int wParam;
|
||||
public long lParam;
|
||||
public uint time;
|
||||
public int pt;
|
||||
}
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int GetMessage(ref tagMSG lpMsg, int a, int hwnd, int wMsgFilterMax);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using cmonitor.libs;
|
||||
using common.libs;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
@@ -24,7 +25,7 @@ namespace cmonitor.llock.win
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MainForm(string shareMkey, int shareMLength, int shareItemMLength, int shareIndex)
|
||||
{
|
||||
this.shareIndex = shareIndex;
|
||||
@@ -61,7 +62,7 @@ namespace cmonitor.llock.win
|
||||
|
||||
private void OnLoad(object sender, EventArgs e)
|
||||
{
|
||||
hook.Start();
|
||||
hook.Start((code) => { return true; });
|
||||
#if RELEASE
|
||||
this.WindowState = FormWindowState.Maximized;
|
||||
#endif
|
||||
@@ -119,7 +120,6 @@ namespace cmonitor.llock.win
|
||||
private void CloseClear()
|
||||
{
|
||||
shareMemory.RemoveAttribute(shareIndex, ShareMemoryAttribute.Running);
|
||||
shareMemory.Update(this.shareIndex, keyBytes, BitConverter.GetBytes((long)0));
|
||||
|
||||
cancellationTokenSource.Cancel();
|
||||
hook.Close();
|
||||
@@ -132,14 +132,13 @@ namespace cmonitor.llock.win
|
||||
}
|
||||
|
||||
private DateTime startTime = new DateTime(1970, 1, 1);
|
||||
private byte[] keyBytes = Encoding.UTF8.GetBytes("LLock");
|
||||
private long lastTime = 0;
|
||||
private void WriteLLock()
|
||||
{
|
||||
long time = (long)(DateTime.UtcNow.Subtract(startTime)).TotalMilliseconds;
|
||||
if (time - lastTime >= 800)
|
||||
{
|
||||
shareMemory.Update(this.shareIndex, keyBytes, BitConverter.GetBytes(time));
|
||||
shareMemory.IncrementVersion(shareIndex);
|
||||
lastTime = time;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
|
||||
namespace cmonitor.llock.win
|
||||
{
|
||||
internal static class Program
|
||||
@@ -13,15 +18,16 @@ namespace cmonitor.llock.win
|
||||
{
|
||||
Environment.Exit(1);
|
||||
}
|
||||
//ProcessProtection.ProtectProcess();
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += (a, b) =>
|
||||
{
|
||||
};
|
||||
|
||||
string shareMkey = arg[0];
|
||||
int shareMLength = int.Parse(arg[1]);
|
||||
int shareItemMLength = int.Parse(arg[2]);
|
||||
int shareIndex = int.Parse(arg[3]);
|
||||
string shareMkey = "cmonitor/share";
|
||||
int shareMLength = 100;
|
||||
int shareItemMLength = 10240;
|
||||
int shareIndex = 3;
|
||||
|
||||
if (arg.Length > 0)
|
||||
{
|
||||
@@ -36,4 +42,82 @@ namespace cmonitor.llock.win
|
||||
Application.Run(new MainForm(shareMkey, shareMLength, shareItemMLength, shareIndex));
|
||||
}
|
||||
}
|
||||
|
||||
class ProcessProtection
|
||||
{
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern int NtSetInformationProcess(IntPtr hProcess, int processInformationClass, ref int processInformation, int processInformationLength);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
private static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
|
||||
|
||||
[DllImport("ntdll.dll")]
|
||||
private static extern uint NtRaiseHardError(
|
||||
uint ErrorStatus,
|
||||
uint NumberOfParameters,
|
||||
uint UnicodeStringParameterMask,
|
||||
IntPtr Parameters,
|
||||
uint ValidResponseOption,
|
||||
out uint Response
|
||||
);
|
||||
|
||||
private static bool IsDebugMode = false;
|
||||
|
||||
public static void ProtectProcess()
|
||||
{
|
||||
int isCritical = 1;
|
||||
int BreakOnTermination = 0x1D;
|
||||
if (!IsDebugMode)
|
||||
{
|
||||
Process.EnterDebugMode();
|
||||
IsDebugMode = true;
|
||||
}
|
||||
NtSetInformationProcess(Process.GetCurrentProcess().Handle, BreakOnTermination, ref isCritical, sizeof(int));
|
||||
}
|
||||
|
||||
public static void ProtectProcess(Process target)
|
||||
{
|
||||
int isCritical = 1;
|
||||
int BreakOnTermination = 0x1D;
|
||||
if (!IsDebugMode)
|
||||
{
|
||||
Process.EnterDebugMode();
|
||||
IsDebugMode = true;
|
||||
}
|
||||
NtSetInformationProcess(target.Handle, BreakOnTermination, ref isCritical, sizeof(int));
|
||||
}
|
||||
|
||||
public static void UnprotectProcess()
|
||||
{
|
||||
int isCritical = 0;
|
||||
int BreakOnTermination = 0x1D;
|
||||
if (!IsDebugMode)
|
||||
{
|
||||
Process.EnterDebugMode();
|
||||
IsDebugMode = true;
|
||||
}
|
||||
NtSetInformationProcess(Process.GetCurrentProcess().Handle, BreakOnTermination, ref isCritical, sizeof(int));
|
||||
}
|
||||
|
||||
public static void UnprotectProcess(Process target)
|
||||
{
|
||||
int isCritical = 0;
|
||||
int BreakOnTermination = 0x1D;
|
||||
if (!IsDebugMode)
|
||||
{
|
||||
Process.EnterDebugMode();
|
||||
IsDebugMode = true;
|
||||
}
|
||||
NtSetInformationProcess(target.Handle, BreakOnTermination, ref isCritical, sizeof(int));
|
||||
}
|
||||
|
||||
public static void BSOD()
|
||||
{
|
||||
bool b;
|
||||
uint response;
|
||||
uint STATUS_ASSERTION_FAILURE = 0xC0000420;
|
||||
RtlAdjustPrivilege(19, true, false, out b);
|
||||
NtRaiseHardError(STATUS_ASSERTION_FAILURE, 0, 0, IntPtr.Zero, 6, out response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
using common.libs;
|
||||
using Microsoft.Win32;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace cmonitor.share.win
|
||||
{
|
||||
internal class Hook : IDisposable
|
||||
{
|
||||
private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
|
||||
private static int hHook = 0;
|
||||
private const int WH_KEYBOARD_LL = 13;
|
||||
HookProc KeyBoardHookProcedure;
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private class KeyBoardHookStruct
|
||||
{
|
||||
public int vkCode;
|
||||
public int scanCode;
|
||||
public int flags;
|
||||
public int time;
|
||||
public int dwExtraInfo;
|
||||
}
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool UnhookWindowsHookEx(int idHook);
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr GetModuleHandle(string name);
|
||||
|
||||
public void Start()
|
||||
{
|
||||
// 安装键盘钩子
|
||||
if (hHook == 0)
|
||||
{
|
||||
KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);
|
||||
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardHookProcedure, GetModuleHandle(null), 0);
|
||||
//如果设置钩子失败.
|
||||
if (hHook == 0)
|
||||
Close();
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (string user in Registry.Users.GetSubKeyNames())
|
||||
{
|
||||
RegistryKey key = Registry.Users.OpenSubKey(user, true).OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true);
|
||||
if (key == null)
|
||||
key = Registry.Users.OpenSubKey(user, true).CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System");
|
||||
|
||||
RegistryKey key1 = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true);
|
||||
if (key1 == null)
|
||||
key1 = Registry.LocalMachine.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System");
|
||||
|
||||
//任务管理器
|
||||
key.SetValue("DisableTaskMgr", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("DisableTaskMgr", 1, RegistryValueKind.DWord);
|
||||
//锁定
|
||||
key.SetValue("DisableLockWorkstation", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("DisableLockWorkstation", 1, RegistryValueKind.DWord);
|
||||
//切换用户
|
||||
key.SetValue("HideFastUserSwitching", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("HideFastUserSwitching", 1, RegistryValueKind.DWord);
|
||||
//修改密码
|
||||
key.SetValue("DisableChangePassword", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("DisableChangePassword", 1, RegistryValueKind.DWord);
|
||||
//关机
|
||||
key.SetValue("ShutdownWithoutLogon", 0, RegistryValueKind.DWord);
|
||||
key1.SetValue("ShutdownWithoutLogon", 0, RegistryValueKind.DWord);
|
||||
//注销
|
||||
key.SetValue("StartMenuLogOff", 1, RegistryValueKind.DWord);
|
||||
key1.SetValue("StartMenuLogOff", 1, RegistryValueKind.DWord);
|
||||
|
||||
|
||||
|
||||
key.Close();
|
||||
key1.Close();
|
||||
|
||||
//注销
|
||||
RegistryKey zxKey = Registry.Users.OpenSubKey(user, true).OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer", true);
|
||||
if (zxKey == null)
|
||||
zxKey = Registry.Users.OpenSubKey(user, true).CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer");
|
||||
zxKey.SetValue("NoLogOff", 1, RegistryValueKind.DWord);
|
||||
zxKey.SetValue("NoClose", 1, RegistryValueKind.DWord);
|
||||
zxKey.SetValue("StartMenuLogOff", 1, RegistryValueKind.DWord);
|
||||
zxKey.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
Task.Run(() =>
|
||||
{
|
||||
CommandHelper.Windows(string.Empty, new string[] { "gpupdate /force" });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Close()
|
||||
{
|
||||
if (hHook != 0)
|
||||
{
|
||||
UnhookWindowsHookEx(hHook);
|
||||
hHook = 0;
|
||||
}
|
||||
try
|
||||
{
|
||||
foreach (string user in Registry.Users.GetSubKeyNames())
|
||||
{
|
||||
RegistryKey key = Registry.Users.OpenSubKey(user, true).OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true);
|
||||
RegistryKey key1 = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System", true);
|
||||
if (key != null)
|
||||
{
|
||||
key.DeleteValue("DisableTaskMgr", false);
|
||||
key1.DeleteValue("DisableTaskMgr", false);
|
||||
key.DeleteValue("DisableLockWorkstation", false);
|
||||
key1.DeleteValue("DisableLockWorkstation", false);
|
||||
key.DeleteValue("HideFastUserSwitching", false);
|
||||
key1.DeleteValue("HideFastUserSwitching", false);
|
||||
key.DeleteValue("DisableChangePassword", false);
|
||||
key1.DeleteValue("DisableChangePassword", false);
|
||||
key.DeleteValue("ShutdownWithoutLogon", false);
|
||||
key1.DeleteValue("ShutdownWithoutLogon", false);
|
||||
key.DeleteValue("StartMenuLogoff", false);
|
||||
key1.DeleteValue("StartMenuLogoff", false);
|
||||
|
||||
|
||||
key.Close();
|
||||
key1.Close();
|
||||
}
|
||||
|
||||
RegistryKey zxKey = Registry.Users.OpenSubKey(user, true).OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer", true);
|
||||
if (zxKey != null)
|
||||
{
|
||||
zxKey.DeleteValue("NoLogOff", false);
|
||||
zxKey.DeleteValue("NoClose", false);
|
||||
zxKey.DeleteValue("StartMenuLogoff", false);
|
||||
zxKey.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
CommandHelper.Windows(string.Empty, new string[] { "gpupdate /force" }, false);
|
||||
}
|
||||
private int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)
|
||||
{
|
||||
if (nCode >= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return CallNextHookEx(hHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
#region IDisposable 成员
|
||||
public void Dispose()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private struct tagMSG
|
||||
{
|
||||
public int hwnd;
|
||||
public uint message;
|
||||
public int wParam;
|
||||
public long lParam;
|
||||
public uint time;
|
||||
public int pt;
|
||||
}
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int GetMessage(ref tagMSG lpMsg, int a, int hwnd, int wMsgFilterMax);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
using cmonitor.libs;
|
||||
using RDPCOMAPILib;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace cmonitor.share.win
|
||||
{
|
||||
public partial class MainForm : Form
|
||||
{
|
||||
protected override CreateParams CreateParams
|
||||
{
|
||||
get
|
||||
{
|
||||
const int WS_EX_APPWINDOW = 0x40000;
|
||||
const int WS_EX_TOOLWINDOW = 0x80;
|
||||
CreateParams cp = base.CreateParams;
|
||||
cp.ExStyle &= (~WS_EX_APPWINDOW);
|
||||
cp.ExStyle |= WS_EX_TOOLWINDOW;
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Hook hook = new Hook();
|
||||
private readonly ShareMemory shareMemory;
|
||||
private readonly byte[] bytes;
|
||||
private long version = 0;
|
||||
public MainForm(string key, int size)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
bytes = new byte[size];
|
||||
shareMemory = new ShareMemory(key, 1, size);
|
||||
shareMemory.InitLocal();
|
||||
}
|
||||
|
||||
private void OnLoad(object sender, EventArgs e)
|
||||
{
|
||||
#if RELEASE
|
||||
this.FormBorderStyle = FormBorderStyle.None;
|
||||
this.ShowInTaskbar = false;
|
||||
this.WindowState = FormWindowState.Maximized;
|
||||
#endif
|
||||
TopMost = true;
|
||||
CheckRunning();
|
||||
}
|
||||
|
||||
private void CheckRunning()
|
||||
{
|
||||
hook.Start();
|
||||
shareMemory.AddAttribute(0, ShareMemoryAttribute.Running);
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (shareMemory.ReadAttributeEqual(0, ShareMemoryAttribute.Closed))
|
||||
{
|
||||
shareMemory.RemoveAttribute(0, ShareMemoryAttribute.Running);
|
||||
hook.Close();
|
||||
Application.ExitThread();
|
||||
Application.Exit();
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void OpenShareDesktop()
|
||||
{
|
||||
RDPSession session = new RDPSession();
|
||||
session.OnAttendeeConnected += Session_OnAttendeeConnected;
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>湲<EFBFBD><E6B9B2>
|
||||
session.Open();
|
||||
|
||||
IRDPSRAPIInvitation invitation = session.Invitations.CreateInvitation("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ", "<22>ҵĹ<D2B5><C4B9><EFBFBD><EFBFBD>Ự", "123", 1024);
|
||||
string invitationString = invitation.ConnectionString;
|
||||
|
||||
Console.WriteLine("<22>뽫<EFBFBD><EBBDAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>ṩ<EFBFBD><E1B9A9>Զ<EFBFBD>̿ͻ<CCBF><CDBB>ˣ<EFBFBD>");
|
||||
Console.WriteLine(invitationString);
|
||||
|
||||
// <20>ȴ<EFBFBD><C8B4>رմ<D8B1><D5B4><EFBFBD>
|
||||
Console.WriteLine("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD>...");
|
||||
Console.ReadKey();
|
||||
|
||||
session.Close();
|
||||
}
|
||||
private void Session_OnAttendeeConnected(object pAttendee)
|
||||
{
|
||||
IRDPSRAPIAttendee attendee = (IRDPSRAPIAttendee)pAttendee;
|
||||
// <20><><EFBFBD>ÿͻ<C3BF><CDBB>˷<EFBFBD><CBB7><EFBFBD>Ȩ<EFBFBD><C8A8>Ϊ ViewOnly
|
||||
attendee.ControlLevel = CTRL_LEVEL.CTRL_LEVEL_VIEW;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
cmonitor.sln
@@ -23,10 +23,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.message.win", "cmo
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.snatch.win", "cmonitor.snatch.win\cmonitor.snatch.win.csproj", "{5267B401-6818-407C-8323-E6C8A3CC01D6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.share.win", "cmonitor.share.win\cmonitor.share.win.csproj", "{AB10024E-9307-4231-872E-3564A57BA035}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.viewer.server.win", "cmonitor.viewer.server.win\cmonitor.viewer.server.win.csproj", "{AB10024E-9307-4231-872E-3564A57BA035}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmonitor.killer", "cmonitor.killer\cmonitor.killer.vcxproj", "{E19B86AC-AC42-417A-8536-C2FFF1FB7FDC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.clipboard.win", "cmonitor.clipboard.win\cmonitor.clipboard.win.csproj", "{2A23EA37-3EAC-4B60-8576-84607ADB0256}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -181,6 +183,18 @@ Global
|
||||
{E19B86AC-AC42-417A-8536-C2FFF1FB7FDC}.Release|x64.Build.0 = Release|x64
|
||||
{E19B86AC-AC42-417A-8536-C2FFF1FB7FDC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E19B86AC-AC42-417A-8536-C2FFF1FB7FDC}.Release|x86.Build.0 = Release|Win32
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2A23EA37-3EAC-4B60-8576-84607ADB0256}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
61
cmonitor.viewer.client.win/.build/default.Manifest.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly
|
||||
xmlns="urn:schemas-microsoft-com:asm.v1"
|
||||
manifestVersion="1.0">
|
||||
<assemblyIdentity
|
||||
processorArchitecture="x86"
|
||||
version="5.1.0.0"
|
||||
type="win32"
|
||||
name="cmonitor.share.screen.client.win.exe"/>
|
||||
<description>cmonitor.share.screen.client.win</description>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
processorArchitecture="x86"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!--Windows Vista -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||
<!--Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
<!--Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<!-- Windows 10, Windows 11 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<!--
|
||||
可任选以下配置之一指定一个进程权限:
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
requireAdministrator 为管理员权限,
|
||||
highestAvailable 为可以获取到的最高权限,
|
||||
asInvoker 为默认值,即调用进程当前权限,一般不需要显式指定,指定后会禁用虚拟化。
|
||||
|
||||
虚拟化指Vista以后系统禁止写 Program File目录,启用虚拟化则重定向到%localappdata%\VirtualStore目录,
|
||||
而注册表 HKEY_LOCAL_MACHINE\Software 则重定向到HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\Software
|
||||
-->
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
|
||||
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
2
cmonitor.viewer.client.win/.build/default.init.aardio
Normal file
@@ -0,0 +1,2 @@
|
||||
//发布前触发
|
||||
import ide;
|
||||
6
cmonitor.viewer.client.win/.build/default.main.aardio
Normal file
@@ -0,0 +1,6 @@
|
||||
//此触发器在生成EXE以后执行
|
||||
import ide;
|
||||
import fsys;
|
||||
|
||||
//获取生成的EXE文件路径
|
||||
var publishFile = ide.getPublishPath();
|
||||
6
cmonitor.viewer.client.win/default.aproj
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project ver="10" name="cmonitor.viewer.client.win" libEmbed="true" icon="D:\desktop\cmonitor\cmonitor\favicon.ico" ui="win" output="cmonitor.viewer.client.win.exe" CompanyName="snltty" FileDescription="cmonitor.viewer.client.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="cmonitor.viewer.client.win" InternalName="cmonitor.viewer.client.win" FileVersion="0.0.0.19" ProductVersion="0.0.0.19" publishDir="/dist/" dstrip="false">
|
||||
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
|
||||
<folder name="资源文件" path="res" embed="true"/>
|
||||
<folder name="窗体文件" path="dlg" comment="目录" embed="true"/>
|
||||
</project>
|
||||
BIN
cmonitor.viewer.client.win/dist/cmonitor.viewer.client.win.exe
vendored
Normal file
17
cmonitor.viewer.client.win/lib/config.aardio
Normal file
@@ -0,0 +1,17 @@
|
||||
//config 配置文件
|
||||
import fsys.config;
|
||||
config = fsys.config("/config/");
|
||||
//config = fsys.config( io.appData("/软件作者/应用程序名/") );
|
||||
|
||||
//不需要序列化的配置名字前请添加下划线
|
||||
namespace config {
|
||||
__appName = "应用程序名";
|
||||
__website = "http://www.aardio.com/";
|
||||
}
|
||||
|
||||
/**intellisense(config)
|
||||
__appName = 应用程序名
|
||||
__website = 官方网站
|
||||
saveAll() = 写入所有配置到文件
|
||||
? = 获取值时指定不以下划线开始的配置表名称,\n返回一个可自动序列化到同名配置文件的表对象。\n如果此对象名以下划线开始,则可以正常读写值不会序列化为配置文件。\n否则不能对此对象直接赋值,只能对配置表对象的成员赋值。\n\n配置表可自动自文件加载,退出线程前自动序列化并存入文件。\n仅序列化以字符串、数值为键的元素,\n仅序列化值为字符串、数值、buffer 以及定义了 _serialize 元方法的成员。\n循环引用的值转换为 null,序列化时忽略成员函数\n!fsys_table.
|
||||
end intellisense**/
|
||||
63
cmonitor.viewer.client.win/main.aardio
Normal file
@@ -0,0 +1,63 @@
|
||||
import win.ui;
|
||||
/*DSG{{*/
|
||||
mainForm = win.form(text="cmonitor.viewer.client.win";right=757;bottom=467;border="thin";max=false;min=false;mode="popup";sysmenu=false;title=false)
|
||||
mainForm.add()
|
||||
/*}}*/
|
||||
|
||||
import win.ui.atom;
|
||||
var atom,hwndConflict = mainForm.atom("C71CEE67-B4CA-4759-8608-8B2B917B0D54");
|
||||
if(!atom){
|
||||
win.quitMessage(); return;
|
||||
};
|
||||
|
||||
mainForm.connecting = false;
|
||||
|
||||
import com.lite;
|
||||
import thread;
|
||||
var dll = com.lite("rdpviewerax.dll");
|
||||
mainForm.tsc = dll.createEmbedEx(mainForm,"{32be5ed2-5c86-480f-a914-0ff8885a1b3f}");
|
||||
mainForm.tsc.SmartSizing = true;
|
||||
mainForm.tsc.DisconnectedText = "正在连接至共享桌面....";
|
||||
|
||||
mainForm.tsc.OnConnectionFailed = function(){
|
||||
mainForm.connecting = false;
|
||||
}
|
||||
mainForm.tsc.OnConnectionTerminated = function(){
|
||||
mainForm.connecting = false;
|
||||
}
|
||||
mainForm.connect = function(){
|
||||
import win.reg;
|
||||
import console;
|
||||
if(mainForm.connecting === false){
|
||||
try{
|
||||
var reg = win.reg("HKEY_CURRENT_USER\Software\Cmonitor");
|
||||
mainForm.connecting = true;
|
||||
var invitationString = reg.queryValue("viewerConnectStr");
|
||||
if(string.len(invitationString)>0)
|
||||
{
|
||||
mainForm.tsc.Connect(invitationString,"snltty","snltty");
|
||||
}else{
|
||||
mainForm.connecting = false;
|
||||
}
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mainForm.show();
|
||||
if(!_STUDIO_INVOKED)
|
||||
{
|
||||
mainForm.fullscreen();
|
||||
mainForm.modifyStyleEx(0x40000/*_WS_EX_APPWINDOW*/,0x80/*_WS_EX_TOOLWINDOW*/);
|
||||
::SetWindowPos(mainForm.hwnd,-1/*_HWND_TOPMOST*/,0,0,0,0,0x2/*_SWP_NOMOVE*/ + 0x1/*_SWP_NOSIZE*/);
|
||||
}
|
||||
|
||||
mainForm.setInterval(
|
||||
function(){
|
||||
mainForm.connect();
|
||||
},1000
|
||||
);
|
||||
|
||||
return win.loopMessage();
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace cmonitor.share.win
|
||||
namespace cmonitor.viewer.server.win
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
@@ -44,5 +44,7 @@
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
192
cmonitor.viewer.server.win/MainForm.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using cmonitor.libs;
|
||||
using cmonitor.viewer.server.win.Properties;
|
||||
using common.libs;
|
||||
using Microsoft.Win32;
|
||||
using RDPCOMAPILib;
|
||||
using System.Diagnostics;
|
||||
using System.Resources;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace cmonitor.viewer.server.win
|
||||
{
|
||||
public partial class MainForm : Form
|
||||
{
|
||||
protected override CreateParams CreateParams
|
||||
{
|
||||
get
|
||||
{
|
||||
const int WS_EX_APPWINDOW = 0x40000;
|
||||
const int WS_EX_TOOLWINDOW = 0x80;
|
||||
CreateParams cp = base.CreateParams;
|
||||
cp.ExStyle &= (~WS_EX_APPWINDOW);
|
||||
cp.ExStyle |= WS_EX_TOOLWINDOW;
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Hook hook = new Hook();
|
||||
private readonly ShareMemory shareMemory;
|
||||
private int shareIndex = 0;
|
||||
private Mode shareMode = Mode.Client;
|
||||
private const string shareClientExe = "cmonitor.viewer.client.win";
|
||||
private byte[] shareKeyBytes = Encoding.UTF8.GetBytes(shareClientExe);
|
||||
|
||||
public MainForm(string key, int length, int size, int index, Mode mode)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
shareMode = mode;
|
||||
shareIndex = index;
|
||||
shareMemory = new ShareMemory(key, length, size);
|
||||
shareMemory.InitLocal();
|
||||
}
|
||||
|
||||
private void OnLoad(object sender, EventArgs e)
|
||||
{
|
||||
#if RELEASE
|
||||
this.FormBorderStyle = FormBorderStyle.None;
|
||||
this.ShowInTaskbar = false;
|
||||
this.WindowState = FormWindowState.Minimized;
|
||||
this.Visible = false;
|
||||
#endif
|
||||
|
||||
CheckRunning();
|
||||
|
||||
if (shareMode == Mode.Client)
|
||||
{
|
||||
OpenShareClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
OpenShareDesktop();
|
||||
}
|
||||
}
|
||||
private void CheckRunning()
|
||||
{
|
||||
hook.Close();
|
||||
shareMemory.AddAttribute(shareIndex, ShareMemoryAttribute.Running);
|
||||
shareMemory.RemoveAttribute(shareIndex, ShareMemoryAttribute.Closed);
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (shareMemory.ReadAttributeEqual(shareIndex, ShareMemoryAttribute.Closed))
|
||||
{
|
||||
CloseServer();
|
||||
}
|
||||
else
|
||||
{
|
||||
shareMemory.IncrementVersion(shareIndex);
|
||||
}
|
||||
if (Process.GetProcessesByName(shareClientExe).Length == 0)
|
||||
{
|
||||
shareMemory.AddAttribute(shareIndex, ShareMemoryAttribute.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
await Task.Delay(30);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
private void CloseServer()
|
||||
{
|
||||
shareMemory.RemoveAttribute(shareIndex, ShareMemoryAttribute.Running);
|
||||
CloseShareClient();
|
||||
CloseShareDesktop();
|
||||
Application.ExitThread();
|
||||
Application.Exit();
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
|
||||
private void OpenShareClient()
|
||||
{
|
||||
hook.Start((code) => { return true; });
|
||||
|
||||
CommandHelper.Windows(string.Empty, new string[] { $"start {shareClientExe}.exe" },false);
|
||||
}
|
||||
private void CloseShareClient()
|
||||
{
|
||||
hook.Close();
|
||||
CommandHelper.Windows(string.Empty, new string[] { $"taskkill /f /im {shareClientExe}.exe" });
|
||||
}
|
||||
|
||||
|
||||
RDPSession session;
|
||||
private NotifyIcon notifyIcon;
|
||||
private void OpenShareDesktop()
|
||||
{
|
||||
notifyIcon = new NotifyIcon();
|
||||
notifyIcon.Visible = true;
|
||||
notifyIcon.ContextMenuStrip = new ContextMenuStrip();
|
||||
notifyIcon.ContextMenuStrip.Items.Add("ˢ<>¹<EFBFBD><C2B9><EFBFBD>");
|
||||
notifyIcon.ContextMenuStrip.Items.Add("<22>˳<EFBFBD>");
|
||||
notifyIcon.ContextMenuStrip.ItemClicked += (object sender, ToolStripItemClickedEventArgs e) =>
|
||||
{
|
||||
if (e.ClickedItem.Text == "<22>˳<EFBFBD>")
|
||||
{
|
||||
CloseServer();
|
||||
}
|
||||
else if (e.ClickedItem.Text == "ˢ<>¹<EFBFBD><C2B9><EFBFBD>")
|
||||
{
|
||||
NewShare();
|
||||
}
|
||||
};
|
||||
NewShare();
|
||||
}
|
||||
private void NewShare()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
CloseShareDesktop();
|
||||
session = new RDPSession();
|
||||
session.OnAttendeeConnected += Session_OnAttendeeConnected;
|
||||
session.Open();
|
||||
IRDPSRAPIInvitation invitation = session.Invitations.CreateInvitation(Guid.NewGuid().ToString(), "snltty", "snltty", 1024);
|
||||
string invitationString = invitation.ConnectionString;
|
||||
|
||||
Registry.SetValue("HKEY_CURRENT_USER\\SOFTWARE\\Cmonitor", "viewerConnectStr", invitationString);
|
||||
|
||||
notifyIcon.Icon = Icon.FromHandle(Resources.logo_share_green.GetHicon());
|
||||
notifyIcon.Text = "<22><><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
notifyIcon.Icon = Icon.FromHandle(Resources.logo_share_gray.GetHicon());
|
||||
notifyIcon.Text = "<22><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void Session_OnAttendeeConnected(object pAttendee)
|
||||
{
|
||||
IRDPSRAPIAttendee attendee = (IRDPSRAPIAttendee)pAttendee;
|
||||
attendee.ControlLevel = CTRL_LEVEL.CTRL_LEVEL_VIEW;
|
||||
}
|
||||
private void CloseShareDesktop()
|
||||
{
|
||||
try
|
||||
{
|
||||
session?.Close();
|
||||
Registry.SetValue("HKEY_CURRENT_USER\\SOFTWARE\\Cmonitor", "viewerConnectStr", string.Empty);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum Mode : byte
|
||||
{
|
||||
Client = 0,
|
||||
Server = 1,
|
||||
}
|
||||
}
|
||||
400
cmonitor.viewer.server.win/MainForm.resx
Normal file
@@ -0,0 +1,400 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace cmonitor.share.win
|
||||
namespace cmonitor.viewer.server.win
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
@@ -16,18 +16,25 @@ namespace cmonitor.share.win
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += (a, b) =>
|
||||
{
|
||||
MessageBox.Show(b.ExceptionObject.ToString());
|
||||
};
|
||||
|
||||
string shareMkey = "cmonitor/share/screen";
|
||||
int shareItemMLength = 2 * 1024 * 1024;
|
||||
string shareMkey = "cmonitor/share";
|
||||
int shareMLength = 10;
|
||||
int shareItemMLength = 1024;
|
||||
int shareIndex = 5;
|
||||
Mode mode = Mode.Server;
|
||||
if (arg.Length > 0)
|
||||
{
|
||||
shareMkey = arg[0];
|
||||
shareItemMLength = int.Parse(arg[1]);
|
||||
shareMLength = int.Parse(arg[1]);
|
||||
shareItemMLength = int.Parse(arg[2]);
|
||||
shareIndex = int.Parse(arg[3]);
|
||||
mode = (Mode)byte.Parse(arg[4]);
|
||||
}
|
||||
|
||||
ApplicationConfiguration.Initialize();
|
||||
Application.Run(new MainForm(shareMkey, shareItemMLength));
|
||||
Application.Run(new MainForm(shareMkey, shareMLength, shareItemMLength, shareIndex, mode));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>bin\Release\net7.0-windows\publish\win-x86\</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
|
||||
<SelfContained>false</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishReadyToRun>false</PublishReadyToRun>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<History>True|2024-03-21T01:26:40.1376911Z;True|2024-03-21T09:24:13.2312644+08:00;True|2024-03-21T09:22:59.0517639+08:00;</History>
|
||||
<LastFailureDetails />
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
83
cmonitor.viewer.server.win/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace cmonitor.viewer.server.win.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("cmonitor.viewer.server.win.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap logo_share_gray {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("logo-share-gray", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap logo_share_green {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("logo-share-green", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
127
cmonitor.viewer.server.win/Properties/Resources.resx
Normal file
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="logo-share-gray" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\logo-share-gray.ico;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="logo-share-green" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\logo-share-green.ico;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
79
cmonitor.viewer.server.win/app.manifest
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<!-- UAC 清单选项
|
||||
如果想要更改 Windows 用户帐户控制级别,请使用
|
||||
以下节点之一替换 requestedExecutionLevel 节点。
|
||||
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
|
||||
如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此
|
||||
元素。
|
||||
-->
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
|
||||
Windows 版本的列表。取消评论适当的元素,
|
||||
Windows 将自动选择最兼容的环境。 -->
|
||||
|
||||
<!-- Windows Vista -->
|
||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
||||
|
||||
<!-- Windows 7 -->
|
||||
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
|
||||
|
||||
<!-- Windows 8 -->
|
||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
|
||||
|
||||
<!-- Windows 8.1 -->
|
||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
|
||||
|
||||
<!-- Windows 10 -->
|
||||
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
|
||||
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
|
||||
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
|
||||
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
|
||||
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
|
||||
|
||||
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
|
||||
<!--
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
-->
|
||||
|
||||
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
|
||||
<!--
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
</assembly>
|
||||
@@ -26,13 +26,25 @@
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<COMReference Include="RDPCOMAPILib">
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<Guid>cc802d05-ae07-4c15-b496-db9d22aa0a84</Guid>
|
||||
<Lcid>0</Lcid>
|
||||
<Isolated>false</Isolated>
|
||||
<EmbedInteropTypes>true</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="favicon.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SharpDX.Direct2D1" Version="4.2.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
||||
<EmbeddedResource Include="logo-share-gray.ico" />
|
||||
<EmbeddedResource Include="logo-share-green.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -41,9 +53,18 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Interop.RDPCOMAPILib">
|
||||
<HintPath>Interop.RDPCOMAPILib.dll</HintPath>
|
||||
</Reference>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<_LastSelectedProfileId>D:\desktop\cmonitor\cmonitor.share.win\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="MainForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
BIN
cmonitor.viewer.server.win/favicon.ico
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
cmonitor.viewer.server.win/logo-share-gray.ico
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
cmonitor.viewer.server.win/logo-share-gray.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
cmonitor.viewer.server.win/logo-share-green.ico
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
cmonitor.viewer.server.win/logo-share-green.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
@@ -1,4 +1,5 @@
|
||||
using cmonitor.libs;
|
||||
using common.libs;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
@@ -129,7 +130,8 @@ namespace cmonitor.wallpaper.win
|
||||
{
|
||||
try
|
||||
{
|
||||
if (hook.CurrentKeys == Keys.None)
|
||||
Keys currentKeys = (Keys)hook.CurrentKeys;
|
||||
if (currentKeys == Keys.None)
|
||||
{
|
||||
if (lastKey != Keys.None)
|
||||
{
|
||||
@@ -151,11 +153,11 @@ namespace cmonitor.wallpaper.win
|
||||
{
|
||||
sb.Append("Alt+");
|
||||
}
|
||||
sb.Append(hook.CurrentKeys.ToString());
|
||||
sb.Append(currentKeys.ToString());
|
||||
|
||||
shareMemory.Update(shareKeyBoardIndex, keyBytes, Encoding.UTF8.GetBytes(sb.ToString()));
|
||||
}
|
||||
lastKey = hook.CurrentKeys;
|
||||
lastKey = currentKeys;
|
||||
WriteWallpaper();
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -165,13 +167,26 @@ namespace cmonitor.wallpaper.win
|
||||
await Task.Delay(30);
|
||||
}
|
||||
});
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (cancellationTokenSource.Token.IsCancellationRequested == false)
|
||||
{
|
||||
if ((DateTime.Now - hook.LastDateTime).TotalMilliseconds > 1000)
|
||||
{
|
||||
hook.CurrentKeys = 0;
|
||||
}
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
private void WriteWallpaper()
|
||||
{
|
||||
long time = (long)(DateTime.UtcNow.Subtract(startTime)).TotalMilliseconds;
|
||||
if (time - lastTime >= 800)
|
||||
{
|
||||
shareMemory.Update(shareWallpaperIndex, wallpaperBytes, BitConverter.GetBytes(time));
|
||||
shareMemory.IncrementVersion(shareWallpaperIndex);
|
||||
lastTime = time;
|
||||
}
|
||||
if (shareMemory.ReadAttributeEqual(shareWallpaperIndex, ShareMemoryAttribute.Closed))
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\cmonitor.libs\cmonitor.libs.csproj" />
|
||||
<ProjectReference Include="..\common.libs\common.libs.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
7
cmonitor.web/src/apis/display.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { sendWebsocketMsg } from './request'
|
||||
|
||||
export const screenDisplay = (names, state) => {
|
||||
return sendWebsocketMsg('display/update', {
|
||||
names, state
|
||||
}, false, 1000);
|
||||
}
|
||||
@@ -14,9 +14,3 @@ export const screenClip = (name, data) => {
|
||||
clip: data
|
||||
}, false, 1000);
|
||||
}
|
||||
|
||||
export const screenDisplay = (names, state) => {
|
||||
return sendWebsocketMsg('screen/display', {
|
||||
names, state
|
||||
}, false, 1000);
|
||||
}
|
||||
5
cmonitor.web/src/apis/viewer.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import { sendWebsocketMsg } from './request'
|
||||
|
||||
export const viewerUpdate = (data) => {
|
||||
return sendWebsocketMsg('viewer/update', data);
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="checkbox-wrap absolute flex flex-column">
|
||||
<div class="head flex">
|
||||
<span>
|
||||
<span v-if="!state.single">
|
||||
<el-checkbox :indeterminate="state.isIndeterminate" v-model="state.checkAll" @change="handleCheckAllChange" :label="state.title" />
|
||||
</span>
|
||||
<span class="flex-1"></span>
|
||||
<slot name="title"></slot>
|
||||
</div>
|
||||
<div class="body flex-1 scrollbar">
|
||||
<el-checkbox-group v-model="state.checkList" @change="handleChange">
|
||||
<el-checkbox-group :max="state.single?1:65535" v-model="state.checkList" @change="handleChange">
|
||||
<ul>
|
||||
<template v-for="(item,index) in state.data" :key="index">
|
||||
<li class="flex">
|
||||
@@ -31,7 +31,7 @@
|
||||
<script>
|
||||
import { computed, onMounted, reactive, watch } from 'vue'
|
||||
export default {
|
||||
props: ['title', 'items', 'data', 'label', 'text'],
|
||||
props: ['title', 'items', 'data', 'label', 'text', 'single'],
|
||||
emits: ['change'],
|
||||
setup(props, { emit }) {
|
||||
|
||||
@@ -39,6 +39,7 @@ export default {
|
||||
title: props.title,
|
||||
label: props.label,
|
||||
text: props.text || props.label,
|
||||
single: props.single,
|
||||
data: computed(() => props.data),
|
||||
checkList: props.items.map(c => c[props.label]),
|
||||
checkAll: false,
|
||||
|
||||
@@ -5,29 +5,13 @@
|
||||
<el-button @click="handleDisplay(true)">亮屏</el-button>
|
||||
<el-button @click="handleDisplay(false)">息屏</el-button>
|
||||
</div>
|
||||
<div class="subitem">
|
||||
<span class="label">屏幕共享</span>
|
||||
<el-button @click="handleShare">开始</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog title="选择分享设备" destroy-on-close v-model="pluginState.screen.showShare" center align-center width="94%">
|
||||
<div class="t-c">
|
||||
<el-select v-model="pluginState.screen.device" placeholder="选择分享设备" size="large">
|
||||
<el-option v-for="item in globalState.devices" :key="item.MachineName" :label="item.MachineName" :value="item.MachineName" />
|
||||
</el-select>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancel">取 消</el-button>
|
||||
<el-button type="success" plain @click="handleConfirm">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { injectPluginState } from '../../provide'
|
||||
import { screenDisplay } from '../../../../apis/screen'
|
||||
import { screenDisplay } from '../../../../apis/display'
|
||||
import { injectGlobalData } from '@/views/provide';
|
||||
export default {
|
||||
setup() {
|
||||
@@ -47,17 +31,7 @@ export default {
|
||||
});
|
||||
}
|
||||
|
||||
const handleShare = () => {
|
||||
pluginState.value.screen.showShare = true;
|
||||
}
|
||||
const handleCancel = () => {
|
||||
pluginState.value.screen.showShare = false;
|
||||
}
|
||||
const handleConfirm = () => {
|
||||
ElMessage.success('操作成功');
|
||||
}
|
||||
|
||||
return { pluginState, globalState, handleDisplay, handleShare, handleCancel, handleConfirm }
|
||||
return { pluginState, globalState, handleDisplay }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -4,20 +4,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, watch } from 'vue';
|
||||
import { injectPluginState } from '../../provide'
|
||||
import { injectGlobalData } from '@/views/provide';
|
||||
export default {
|
||||
components: {},
|
||||
setup() {
|
||||
|
||||
const pluginState = injectPluginState();
|
||||
const globalState = injectGlobalData();
|
||||
watch(() => pluginState.value.screen.shareUpdateFlag, () => { });
|
||||
|
||||
onMounted(() => { })
|
||||
|
||||
return { pluginState }
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -5,7 +5,6 @@ export default {
|
||||
field() {
|
||||
return {
|
||||
Screen: {
|
||||
share: false,
|
||||
|
||||
regionImgs: [], //局部图
|
||||
fullImg: null, //全图
|
||||
@@ -208,10 +207,8 @@ export default {
|
||||
},
|
||||
state: {
|
||||
screen: {
|
||||
showShare: false,
|
||||
device: '',
|
||||
devices: [],
|
||||
shareUpdateFlag: 0
|
||||
devices: []
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
66
cmonitor.web/src/views/device/plugins/viewer/Command.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="item">
|
||||
<div class="subitem">
|
||||
<span class="label">屏幕共享</span>
|
||||
<el-button @click="handleShare">开始</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog title="选择分享设备" destroy-on-close v-model="pluginState.viewer.showShare" center align-center width="94%">
|
||||
<div class="t-c">
|
||||
<el-select v-model="pluginState.viewer.device" placeholder="选择分享设备" size="large">
|
||||
<el-option v-for="item in globalState.devices" :key="item.MachineName" :label="item.MachineName" :value="item.MachineName" />
|
||||
</el-select>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancel">取 消</el-button>
|
||||
<el-button type="success" plain @click="handleConfirm">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { injectPluginState } from '../../provide'
|
||||
import { injectGlobalData } from '@/views/provide';
|
||||
import { viewerUpdate } from '@/apis/viewer';
|
||||
export default {
|
||||
setup() {
|
||||
|
||||
const pluginState = injectPluginState();
|
||||
const globalState = injectGlobalData();
|
||||
|
||||
const handleShare = () => {
|
||||
pluginState.value.viewer.showShare = true;
|
||||
}
|
||||
const handleCancel = () => {
|
||||
pluginState.value.viewer.showShare = false;
|
||||
}
|
||||
const handleConfirm = () => {
|
||||
const clients = pluginState.value.command.devices.map(c => c.MachineName);
|
||||
if (clients.length == 0) {
|
||||
ElMessage.error('请至少选择一个目标设备');
|
||||
return;
|
||||
}
|
||||
if (!pluginState.value.viewer.device) {
|
||||
ElMessage.error('请选择一个共享设备');
|
||||
return;
|
||||
}
|
||||
viewerUpdate({
|
||||
Open: true,
|
||||
Server: pluginState.value.viewer.device,
|
||||
Clients: clients,
|
||||
}).then(() => {
|
||||
pluginState.viewer.showShare = false;
|
||||
ElMessage.success('操作成功');
|
||||
}).catch(() => {
|
||||
ElMessage.error('操作失败');
|
||||
});
|
||||
}
|
||||
|
||||
return { pluginState, globalState, handleShare, handleCancel, handleConfirm }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped></style>
|
||||
25
cmonitor.web/src/views/device/plugins/viewer/Index.vue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, watch } from 'vue';
|
||||
import { injectPluginState } from '../../provide'
|
||||
import { injectGlobalData } from '@/views/provide';
|
||||
export default {
|
||||
components: {},
|
||||
setup() {
|
||||
|
||||
const pluginState = injectPluginState();
|
||||
const globalState = injectGlobalData();
|
||||
watch(() => pluginState.value.viewer.shareUpdateFlag, () => { });
|
||||
|
||||
onMounted(() => { })
|
||||
|
||||
return { pluginState }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped></style>
|
||||
@@ -1,10 +1,9 @@
|
||||
<template>
|
||||
<div class="screen-share-wrap" v-if="data.Screen.share">
|
||||
<div class="viewer-share-wrap" v-if="data.Viewer.share && data.Viewer.mode == 'server'">
|
||||
<div class="inner">
|
||||
<h5>
|
||||
<span>正在共享屏幕</span>
|
||||
</h5>
|
||||
|
||||
<div>
|
||||
<el-popconfirm confirm-button-text="确认" cancel-button-text="取消" title="确认结束共享吗?" @confirm="handleConfirm">
|
||||
<template #reference>
|
||||
@@ -20,6 +19,7 @@
|
||||
import { reactive } from 'vue'
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { injectPluginState } from '../../provide';
|
||||
import { viewerUpdate } from '../../../../apis/viewer';
|
||||
export default {
|
||||
props: ['data'],
|
||||
setup(props) {
|
||||
@@ -28,7 +28,16 @@ export default {
|
||||
const state = reactive({
|
||||
loading: false
|
||||
});
|
||||
const handleConfirm = () => { }
|
||||
const handleConfirm = () => {
|
||||
viewerUpdate({
|
||||
open: false,
|
||||
server: props.data.MachineName
|
||||
}).then(() => {
|
||||
ElMessage.success('已操作!')
|
||||
}).catch(() => {
|
||||
ElMessage.error('操作失败!')
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
data: props.data, state, handleConfirm
|
||||
@@ -38,7 +47,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.screen-share-wrap {
|
||||
.viewer-share-wrap {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
29
cmonitor.web/src/views/device/plugins/viewer/index.js
Normal file
@@ -0,0 +1,29 @@
|
||||
export default {
|
||||
field() {
|
||||
return {
|
||||
Viewer: {
|
||||
share: false,
|
||||
mode: 'server'
|
||||
}
|
||||
};
|
||||
},
|
||||
state: {
|
||||
viewer: {
|
||||
showShare: false,
|
||||
device: '',
|
||||
devices: [],
|
||||
shareUpdateFlag: 0
|
||||
}
|
||||
},
|
||||
|
||||
init() {
|
||||
},
|
||||
uninit() {
|
||||
},
|
||||
|
||||
update(item, report) {
|
||||
if (!report.Viewer) return;
|
||||
item.Viewer.share = report.Viewer.Value;
|
||||
item.Viewer.mode = ['client', 'server'][report.Viewer.Mode];
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,21 @@ const globalDataSymbol = Symbol();
|
||||
|
||||
export const provideGlobalData = () => {
|
||||
const globalData = ref({
|
||||
//当前登录用户
|
||||
username: '',
|
||||
//默认用户
|
||||
publicUserName: 'snltty',
|
||||
//用户配置
|
||||
usernames: {},
|
||||
//已连接
|
||||
connected: false,
|
||||
//需要更新规则 用 watch
|
||||
updateRuleFlag: 0,
|
||||
//需要更新设备 用 watch
|
||||
updateDeviceFlag: 0,
|
||||
//所有设备
|
||||
allDevices: [],
|
||||
//当前用户设备
|
||||
devices: computed(() => {
|
||||
const user = globalData.value.usernames[globalData.value.username];
|
||||
if (user) {
|
||||
@@ -19,7 +27,9 @@ export const provideGlobalData = () => {
|
||||
}
|
||||
return [];
|
||||
}),
|
||||
//当前设备
|
||||
currentDevice: { MachineName: '' },
|
||||
//需要报告数据的设备
|
||||
reportNames: []
|
||||
});
|
||||
subWebsocketState((state) => {
|
||||
|
||||
@@ -1,55 +1,47 @@
|
||||
using cmonitor.api;
|
||||
using cmonitor.api.services;
|
||||
using cmonitor.client;
|
||||
using cmonitor.client.reports.active;
|
||||
using cmonitor.client.reports.light;
|
||||
using cmonitor.client.reports.hijack;
|
||||
using cmonitor.client.reports.llock;
|
||||
using cmonitor.client.reports.screen;
|
||||
using cmonitor.client.reports.volume;
|
||||
using cmonitor.client.reports.notify;
|
||||
using cmonitor.client.reports.command;
|
||||
using cmonitor.client.reports;
|
||||
using cmonitor.client.reports.share;
|
||||
using cmonitor.client.reports.system;
|
||||
using cmonitor.service;
|
||||
using cmonitor.service.messengers.active;
|
||||
using cmonitor.service.messengers.hijack;
|
||||
using cmonitor.service.messengers.llock;
|
||||
using cmonitor.service.messengers.report;
|
||||
using cmonitor.service.messengers.screen;
|
||||
using cmonitor.service.messengers.sign;
|
||||
using cmonitor.service.messengers.volume;
|
||||
using cmonitor.service.messengers.wallpaper;
|
||||
using cmonitor.service.messengers.keyboard;
|
||||
using cmonitor.service.messengers.system;
|
||||
using cmonitor.service.messengers.light;
|
||||
using cmonitor.service.messengers.share;
|
||||
using cmonitor.service.messengers.notify;
|
||||
using cmonitor.service.messengers.setting;
|
||||
using cmonitor.web;
|
||||
using common.libs;
|
||||
using common.libs;
|
||||
using common.libs.database;
|
||||
using common.libs.extends;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using cmonitor.client.reports.keyboard;
|
||||
using cmonitor.client.reports.wallpaper;
|
||||
using cmonitor.client.reports.snatch;
|
||||
using cmonitor.service.messengers.snatch;
|
||||
using cmonitor.libs;
|
||||
using cmonitor.client.reports.wlan;
|
||||
using cmonitor.service.messengers.wlan;
|
||||
using common.libs.winapis;
|
||||
|
||||
using cmonitor.startup;
|
||||
using cmonitor.config;
|
||||
|
||||
namespace cmonitor
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
Init(args);
|
||||
|
||||
//初始化配置文件
|
||||
Config config = new Config();
|
||||
config.Elevated = args.Any(c => c.Contains("elevated"));
|
||||
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
StartupTransfer.Init();
|
||||
|
||||
//依赖注入
|
||||
ServiceProvider serviceProvider = null;
|
||||
ServiceCollection serviceCollection = new ServiceCollection();
|
||||
//注入
|
||||
serviceCollection.AddSingleton((e) => serviceProvider);
|
||||
serviceCollection.AddSingleton((a) => config);
|
||||
serviceCollection.AddTransient(typeof(IConfigDataProvider<>), typeof(ConfigDataFileProvider<>));
|
||||
StartupTransfer.Add(serviceCollection, config, assemblies);
|
||||
|
||||
//运行
|
||||
serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
StartupTransfer.Use(serviceProvider, config, assemblies);
|
||||
|
||||
|
||||
GCHelper.FlushMemory();
|
||||
await Helper.Await();
|
||||
}
|
||||
|
||||
private static void Init(string[] args)
|
||||
{
|
||||
//单服务
|
||||
Mutex mutex = new Mutex(true, System.Diagnostics.Process.GetCurrentProcess().ProcessName, out bool isAppRunning);
|
||||
@@ -57,25 +49,6 @@ namespace cmonitor
|
||||
{
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
//日志输出
|
||||
LoggerConsole();
|
||||
|
||||
//读取参数
|
||||
Dictionary<string, string> dic = ArgumentParser.Parse(args, out string error);
|
||||
#if RELEASE
|
||||
//提权
|
||||
if (dic.ContainsKey("elevated") == false)
|
||||
{
|
||||
Win32Interop.RelaunchElevated();
|
||||
}
|
||||
#endif
|
||||
|
||||
//初始化配置文件
|
||||
Config config = new Config();
|
||||
InitConfig(config, dic);
|
||||
|
||||
|
||||
//全局异常
|
||||
AppDomain.CurrentDomain.UnhandledException += (a, b) =>
|
||||
{
|
||||
@@ -85,242 +58,24 @@ namespace cmonitor
|
||||
ThreadPool.SetMinThreads(1024, 1024);
|
||||
ThreadPool.SetMaxThreads(65535, 65535);
|
||||
|
||||
//日志输出
|
||||
LoggerConsole();
|
||||
|
||||
//注入对象
|
||||
ServiceProvider serviceProvider = null;
|
||||
ServiceCollection serviceCollection = new ServiceCollection();
|
||||
//注入 依赖注入服务供应 使得可以在别的地方通过注入的方式获得 ServiceProvider 以用来获取其它服务
|
||||
serviceCollection.AddSingleton((e) => serviceProvider);
|
||||
//注入
|
||||
serviceCollection.AddSingleton<Config>((a) => config);
|
||||
AddSingleton(serviceCollection, config);
|
||||
|
||||
serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
//运行服务
|
||||
RunService(serviceProvider, config);
|
||||
|
||||
|
||||
GCHelper.FlushMemory();
|
||||
await Helper.Await();
|
||||
}
|
||||
|
||||
private static void RunService(ServiceProvider serviceProvider, Config config)
|
||||
{
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
MessengerResolver messengerResolver = serviceProvider.GetService<MessengerResolver>();
|
||||
messengerResolver.LoadMessenger(assemblies);
|
||||
|
||||
if (config.IsServer)
|
||||
#if RELEASE
|
||||
//提权
|
||||
if (args.Any(c=>c.Contains("elevated")) == false)
|
||||
{
|
||||
Logger.Instance.Info($"start server");
|
||||
//api
|
||||
IClientServer clientServer = serviceProvider.GetService<IClientServer>();
|
||||
clientServer.LoadPlugins(assemblies);
|
||||
clientServer.Websocket();
|
||||
Logger.Instance.Info($"api listen:{config.ApiPort}");
|
||||
|
||||
//web
|
||||
IWebServer webServer = serviceProvider.GetService<IWebServer>();
|
||||
webServer.Start();
|
||||
Logger.Instance.Info($"web listen:{config.WebPort}");
|
||||
|
||||
//服务
|
||||
TcpServer tcpServer = serviceProvider.GetService<TcpServer>();
|
||||
tcpServer.Start();
|
||||
Logger.Instance.Info($"service listen:{config.ServicePort}");
|
||||
|
||||
}
|
||||
if (config.IsCLient)
|
||||
{
|
||||
Logger.Instance.Info($"start client");
|
||||
Logger.Instance.Info($"server ip {config.Server}");
|
||||
|
||||
ReportTransfer report = serviceProvider.GetService<ReportTransfer>();
|
||||
report.LoadPlugins(assemblies);
|
||||
|
||||
ShareMemory shareMemory = serviceProvider.GetService<ShareMemory>();
|
||||
shareMemory.InitLocal();
|
||||
shareMemory.InitGlobal();
|
||||
shareMemory.StartLoop();
|
||||
|
||||
ClientTransfer clientTransfer = serviceProvider.GetService<ClientTransfer>();
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddSingleton(ServiceCollection serviceCollection, Config config)
|
||||
{
|
||||
serviceCollection.AddTransient(typeof(IConfigDataProvider<>), typeof(ConfigDataFileProvider<>));
|
||||
|
||||
//客户端
|
||||
serviceCollection.AddSingleton<ClientSignInState>();
|
||||
serviceCollection.AddSingleton<ClientTransfer>();
|
||||
serviceCollection.AddSingleton<ClientConfig>();
|
||||
|
||||
//内存共享
|
||||
ShareMemory shareMemory = new ShareMemory(config.ShareMemoryKey, config.ShareMemoryLength, config.ShareMemoryItemSize);
|
||||
serviceCollection.AddSingleton<ShareMemory>((a) => shareMemory);
|
||||
|
||||
#region 功能
|
||||
|
||||
serviceCollection.AddSingleton<ReportTransfer>();
|
||||
|
||||
serviceCollection.AddSingleton<ActiveWindowReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IActiveWindow, ActiveWindowWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IActiveWindow, ActiveWindowLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IActiveWindow, ActiveWindowMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<CommandReport>();
|
||||
serviceCollection.AddSingleton<ICommandLine, CommandLineWindows>();
|
||||
|
||||
serviceCollection.AddSingleton<HijackConfig>();
|
||||
serviceCollection.AddSingleton<HijackReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IHijack, HijackWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IHijack, HijackLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IHijack, HijackMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<KeyboardReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IKeyboard, KeyboardWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IKeyboard, KeyboardLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IKeyboard, KeyboardMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<LightReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<ILight, LightWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<ILight, LightLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<ILight, LightMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<LLockReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<ILLock, LLockWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<ILLock, LLockLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<ILLock, LLockMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<NotifyReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<INotify, NotifyWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<INotify, NotifyLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<INotify, NotifyMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<ScreenReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IScreen, ScreenWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IScreen, ScreenLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IScreen, ScreenMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<VolumeReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IVolume, VolumeWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IVolume, VolumeLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IVolume, VolumeMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<WallpaperReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IWallpaper, WallpaperWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IWallpaper, WallpaperLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IWallpaper, WallpaperMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<SystemReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<ISystem, SystemWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<ISystem, SystemLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<ISystem, SystemMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<SnatchReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<ISnatch, SnatchWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<ISnatch, SnatchLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<ISnatch, SnatchMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<WlanReport>();
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IWlan, WlanWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IWlan, WlanLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IWlan, WlanMacOS>();
|
||||
|
||||
serviceCollection.AddSingleton<ShareReport>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region 服务
|
||||
serviceCollection.AddSingleton<TcpServer>();
|
||||
serviceCollection.AddSingleton<MessengerSender>();
|
||||
serviceCollection.AddSingleton<MessengerResolver>();
|
||||
|
||||
serviceCollection.AddSingleton<SignCaching>();
|
||||
serviceCollection.AddSingleton<SignInMessenger>();
|
||||
serviceCollection.AddSingleton<ReportMessenger>();
|
||||
serviceCollection.AddSingleton<CommandMessenger>();
|
||||
serviceCollection.AddSingleton<HijackMessenger>();
|
||||
serviceCollection.AddSingleton<ActiveMessenger>();
|
||||
serviceCollection.AddSingleton<LLockMessenger>();
|
||||
serviceCollection.AddSingleton<ScreenMessenger>();
|
||||
serviceCollection.AddSingleton<VolumeMessenger>();
|
||||
serviceCollection.AddSingleton<WallpaperMessenger>();
|
||||
serviceCollection.AddSingleton<LightMessenger>();
|
||||
serviceCollection.AddSingleton<ShareMessenger>();
|
||||
serviceCollection.AddSingleton<NotifyMessenger>();
|
||||
serviceCollection.AddSingleton<SettingMessenger>();
|
||||
serviceCollection.AddSingleton<KeyboardMessenger>();
|
||||
serviceCollection.AddSingleton<SystemMessenger>();
|
||||
serviceCollection.AddSingleton<SnatchMessenger>();
|
||||
serviceCollection.AddSingleton<WlanMessenger>();
|
||||
#endregion
|
||||
|
||||
#region api
|
||||
serviceCollection.AddSingleton<RuleConfig>();
|
||||
serviceCollection.AddSingleton<IClientServer, ClientServer>();
|
||||
serviceCollection.AddSingleton<SignInClientService>();
|
||||
serviceCollection.AddSingleton<CommandClientService>();
|
||||
serviceCollection.AddSingleton<ReportClientService>();
|
||||
serviceCollection.AddSingleton<HijackClientService>();
|
||||
serviceCollection.AddSingleton<ActiveClientService>();
|
||||
serviceCollection.AddSingleton<LLockClientService>();
|
||||
serviceCollection.AddSingleton<ScreenClientService>();
|
||||
serviceCollection.AddSingleton<VolumeClientService>();
|
||||
serviceCollection.AddSingleton<WallpaperClientService>();
|
||||
serviceCollection.AddSingleton<LightClientService>();
|
||||
serviceCollection.AddSingleton<ShareClientService>();
|
||||
serviceCollection.AddSingleton<NotifyClientService>();
|
||||
serviceCollection.AddSingleton<SettingClientService>();
|
||||
serviceCollection.AddSingleton<SystemClientService>();
|
||||
serviceCollection.AddSingleton<KeyboardClientService>();
|
||||
|
||||
serviceCollection.AddSingleton<SnatchClientService>();
|
||||
serviceCollection.AddSingleton<ISnatachCaching, SnatachCachingMemory>();
|
||||
|
||||
serviceCollection.AddSingleton<WlanClientService>();
|
||||
#endregion
|
||||
|
||||
//web
|
||||
serviceCollection.AddSingleton<IWebServer, WebServer>();
|
||||
}
|
||||
|
||||
private static void InitConfig(Config config, Dictionary<string, string> dic)
|
||||
{
|
||||
try
|
||||
{
|
||||
config.Server = IPAddress.Parse(dic["server"]);
|
||||
config.Name = dic["name"];
|
||||
config.WebPort = int.Parse(dic["web"]);
|
||||
config.ApiPort = int.Parse(dic["api"]);
|
||||
config.ServicePort = int.Parse(dic["service"]);
|
||||
config.ShareMemoryKey = dic["share-key"];
|
||||
config.ShareMemoryLength = int.Parse(dic["share-len"]);
|
||||
config.ShareMemoryItemSize = int.Parse(dic["share-item-len"]);
|
||||
config.ReportDelay = int.Parse(dic["report-delay"]);
|
||||
config.ScreenScale = float.Parse(dic["screen-scale"]);
|
||||
config.ScreenDelay = int.Parse(dic["screen-delay"]);
|
||||
config.Elevated = dic.ContainsKey("elevated");
|
||||
|
||||
Logger.Instance.Debug($"config:{config.ToJsonFormat()}");
|
||||
//Logger.Instance.Debug($"args:{string.Join(" ", args)}");
|
||||
|
||||
config.IsCLient = dic.ContainsKey("mode") && dic["mode"].Contains("client");
|
||||
config.IsServer = dic.ContainsKey("mode") && dic["mode"].Contains("server");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Instance.Error(ex);
|
||||
common.libs.winapis.Win32Interop.RelaunchElevated();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void LoggerConsole()
|
||||
{
|
||||
Logger.Instance.LoggerLevel = LoggerTypes.DEBUG;
|
||||
if (Directory.Exists("log") == false)
|
||||
if (Directory.Exists("logs") == false)
|
||||
{
|
||||
Directory.CreateDirectory("log");
|
||||
Directory.CreateDirectory("logs");
|
||||
}
|
||||
Logger.Instance.OnLogger += (model) =>
|
||||
{
|
||||
@@ -347,7 +102,7 @@ namespace cmonitor
|
||||
Console.ForegroundColor = currentForeColor;
|
||||
try
|
||||
{
|
||||
using StreamWriter sw = File.AppendText(Path.Combine("log", $"{DateTime.Now:yyyy-MM-dd}.log"));
|
||||
using StreamWriter sw = File.AppendText(Path.Combine("logs", $"{DateTime.Now:yyyy-MM-dd}.log"));
|
||||
sw.WriteLine(line);
|
||||
sw.Flush();
|
||||
sw.Close();
|
||||
@@ -358,209 +113,10 @@ namespace cmonitor
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public sealed class Config
|
||||
{
|
||||
public int WebPort { get; set; } = 1800;
|
||||
public int ApiPort { get; set; } = 1801;
|
||||
public int ServicePort { get; set; } = 1802;
|
||||
public IPAddress Server { get; set; } = IPAddress.Loopback;
|
||||
public string WebRoot { get; set; } = "./web/";
|
||||
public string Name { get; set; } = Dns.GetHostName();
|
||||
|
||||
|
||||
public int ReportDelay { get; set; } = 30;
|
||||
|
||||
public float ScreenScale { get; set; } = 0.2f;
|
||||
public int ScreenDelay { get; set; } = 30;
|
||||
|
||||
/// <summary>
|
||||
/// 0项保留
|
||||
/// </summary>
|
||||
public string ShareMemoryKey { get; set; } = "cmonitor/share";
|
||||
public int ShareMemoryLength { get; set; } = 10;
|
||||
public int ShareMemoryItemSize { get; set; } = 1024;
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
public bool SaveSetting { get; set; } = true;
|
||||
[JsonIgnore]
|
||||
public bool WakeUp { get; set; } = true;
|
||||
[JsonIgnore]
|
||||
public bool VolumeMasterPeak { get; set; } = false;
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
public string Version { get; set; } = "1.0.0.1";
|
||||
[JsonIgnore]
|
||||
public bool IsCLient { get; set; }
|
||||
[JsonIgnore]
|
||||
public bool IsServer { get; set; }
|
||||
[JsonIgnore]
|
||||
public bool Elevated { get; set; }
|
||||
|
||||
|
||||
//键盘
|
||||
public const int ShareMemoryKeyBoardIndex = 1;
|
||||
//壁纸
|
||||
public const int ShareMemoryWallpaperIndex = 2;
|
||||
//锁屏
|
||||
public const int ShareMemoryLLockIndex = 3;
|
||||
//SAS
|
||||
public const int ShareMemorySASIndex = 4;
|
||||
//抢答,问题,和回答分开存,为了保证数据安全性
|
||||
public const int ShareSnatchQuestionIndex = 5;
|
||||
public const int ShareSnatchAnswerIndex = 6;
|
||||
|
||||
public const int ShareScreenShareIndex = 7;
|
||||
}
|
||||
|
||||
public class ArgumentParser
|
||||
{
|
||||
public static Dictionary<string, string> Parse(string[] args, out string error)
|
||||
{
|
||||
Dictionary<string, string> dic = new Dictionary<string, string>();
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
if (args[i].IndexOf("--") == 0)
|
||||
{
|
||||
if (i + 1 < args.Length && args[i + 1].IndexOf("--") == -1)
|
||||
{
|
||||
dic.Add(args[i].Substring(2), args[i + 1]);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dic.Add(args[i].Substring(2), string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Validate(dic, out error);
|
||||
|
||||
return dic;
|
||||
}
|
||||
static bool Validate(Dictionary<string, string> dic, out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
|
||||
return ValidateMode(dic) &&
|
||||
ValidateServer(dic, out error)
|
||||
&& ValidateName(dic, out error)
|
||||
&& ValidatePort(dic, out error)
|
||||
&& ValidateMemoryKey(dic, out error)
|
||||
&& ValidateScreenScale(dic, out error)
|
||||
&& ValidateReport(dic, out error)
|
||||
&& ValidateElevated(dic, out error);
|
||||
}
|
||||
|
||||
static bool ValidateMode(Dictionary<string, string> dic)
|
||||
{
|
||||
//模式
|
||||
if (dic.ContainsKey("mode") == false || (dic["mode"].Contains("client") == false && dic["mode"].Contains("server") == false))
|
||||
{
|
||||
dic["mode"] = "server,client";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidateServer(Dictionary<string, string> dic, out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
//服务器地址
|
||||
if (dic.ContainsKey("server") == false || string.IsNullOrWhiteSpace(dic["server"]))
|
||||
{
|
||||
dic["server"] = IPAddress.Loopback.ToString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidateName(Dictionary<string, string> dic, out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
//服务器地址
|
||||
if (dic.ContainsKey("name") == false || string.IsNullOrWhiteSpace(dic["name"]))
|
||||
{
|
||||
dic["name"] = Dns.GetHostName();
|
||||
if (dic["name"].Length > 12)
|
||||
{
|
||||
dic["name"] = dic["name"].Substring(0, 12);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidatePort(Dictionary<string, string> dic, out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
//界面接口
|
||||
if (dic.ContainsKey("web") == false || string.IsNullOrWhiteSpace(dic["web"]))
|
||||
{
|
||||
dic["web"] = "1800";
|
||||
}
|
||||
//管理接口
|
||||
if (dic.ContainsKey("api") == false || string.IsNullOrWhiteSpace(dic["api"]))
|
||||
{
|
||||
dic["api"] = "1801";
|
||||
}
|
||||
//服务接口
|
||||
if (dic.ContainsKey("service") == false || string.IsNullOrWhiteSpace(dic["service"]))
|
||||
{
|
||||
dic["service"] = "1802";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidateMemoryKey(Dictionary<string, string> dic, out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
if (dic.ContainsKey("share-key") == false || string.IsNullOrWhiteSpace(dic["share-key"]))
|
||||
{
|
||||
dic["share-key"] = "cmonitor/share";
|
||||
}
|
||||
if (dic.ContainsKey("share-len") == false || string.IsNullOrWhiteSpace(dic["share-len"]))
|
||||
{
|
||||
dic["share-len"] = "10";
|
||||
}
|
||||
if (dic.ContainsKey("share-item-len") == false || string.IsNullOrWhiteSpace(dic["share-item-len"]))
|
||||
{
|
||||
dic["share-item-len"] = "1024";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidateScreenScale(Dictionary<string, string> dic, out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
if (dic.ContainsKey("screen-scale") == false || string.IsNullOrWhiteSpace(dic["screen-scale"]))
|
||||
{
|
||||
dic["screen-scale"] = "0.2";
|
||||
}
|
||||
if (dic.ContainsKey("screen-delay") == false || string.IsNullOrWhiteSpace(dic["screen-delay"]))
|
||||
{
|
||||
dic["screen-delay"] = "200";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidateReport(Dictionary<string, string> dic, out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
if (dic.ContainsKey("report-delay") == false || string.IsNullOrWhiteSpace(dic["report-delay"]))
|
||||
{
|
||||
dic["report-delay"] = "30";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidateElevated(Dictionary<string, string> dic, out string error)
|
||||
{
|
||||
error = string.Empty;
|
||||
if (dic.ContainsKey("elevated"))
|
||||
{
|
||||
dic["elevated"] = "1";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using cmonitor.api.websocket;
|
||||
using cmonitor.config;
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -12,7 +13,7 @@ namespace cmonitor.api
|
||||
/// <summary>
|
||||
/// 前段接口服务
|
||||
/// </summary>
|
||||
public sealed class ClientServer : IClientServer
|
||||
public sealed class ApiServer : IApiServer
|
||||
{
|
||||
private readonly Dictionary<string, PluginPathCacheInfo> plugins = new();
|
||||
private readonly ConcurrentDictionary<uint, ConnectionTimeInfo> connectionTimes = new();
|
||||
@@ -22,7 +23,7 @@ namespace cmonitor.api
|
||||
private WebSocketServer server;
|
||||
private readonly Config config;
|
||||
|
||||
public ClientServer(ServiceProvider serviceProvider, Config config)
|
||||
public ApiServer(ServiceProvider serviceProvider, Config config)
|
||||
{
|
||||
this.serviceProvider = serviceProvider;
|
||||
this.config = config;
|
||||
@@ -37,10 +38,12 @@ namespace cmonitor.api
|
||||
|
||||
Type voidType = typeof(void);
|
||||
|
||||
IEnumerable<Type> types = assemblys.SelectMany(c => c.GetTypes());
|
||||
foreach (Type item in types.Where(c => c.GetInterfaces().Contains(typeof(IClientService))))
|
||||
IEnumerable<Type> types = assemblys.SelectMany(c => c.GetTypes()).Where(c => c.GetInterfaces().Contains(typeof(IApiController)));
|
||||
Logger.Instance.Warning($"load server apis:{string.Join(",", types.Select(c => c.Name))}");
|
||||
|
||||
foreach (Type item in types)
|
||||
{
|
||||
string path = item.Name.Replace("ClientService", "");
|
||||
string path = item.Name.Replace("ApiController", "");
|
||||
object obj = serviceProvider.GetService(item);
|
||||
foreach (MethodInfo method in item.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
|
||||
{
|
||||
@@ -69,7 +72,7 @@ namespace cmonitor.api
|
||||
server = new WebSocketServer();
|
||||
try
|
||||
{
|
||||
server.Start(System.Net.IPAddress.Any, config.ApiPort);
|
||||
server.Start(System.Net.IPAddress.Any, config.Server.ApiPort);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -92,7 +95,7 @@ namespace cmonitor.api
|
||||
{
|
||||
timeInfo.DateTime = DateTime.Now;
|
||||
}
|
||||
var req = message.DeJson<ClientServiceRequestInfo>();
|
||||
var req = message.DeJson<ApiControllerRequestInfo>();
|
||||
req.Connection = connection;
|
||||
OnMessage(req).ContinueWith((result) =>
|
||||
{
|
||||
@@ -107,23 +110,23 @@ namespace cmonitor.api
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ClientServiceResponseInfo> OnMessage(ClientServiceRequestInfo model)
|
||||
public async Task<ApiControllerResponseInfo> OnMessage(ApiControllerRequestInfo model)
|
||||
{
|
||||
model.Path = model.Path.ToLower();
|
||||
if (plugins.TryGetValue(model.Path, out PluginPathCacheInfo plugin) == false)
|
||||
{
|
||||
return new ClientServiceResponseInfo
|
||||
return new ApiControllerResponseInfo
|
||||
{
|
||||
Content = "not exists this path",
|
||||
RequestId = model.RequestId,
|
||||
Path = model.Path,
|
||||
Code = ClientServiceResponseCodes.NotFound
|
||||
Code = ApiControllerResponseCodes.NotFound
|
||||
};
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ClientServiceParamsInfo param = new ClientServiceParamsInfo
|
||||
ApiControllerParamsInfo param = new ApiControllerParamsInfo
|
||||
{
|
||||
RequestId = model.RequestId,
|
||||
Content = model.Content,
|
||||
@@ -146,10 +149,10 @@ namespace cmonitor.api
|
||||
resultObject = resultAsync;
|
||||
}
|
||||
}
|
||||
return new ClientServiceResponseInfo
|
||||
return new ApiControllerResponseInfo
|
||||
{
|
||||
Code = param.Code,
|
||||
Content = param.Code != ClientServiceResponseCodes.Error ? resultObject : param.ErrorMessage,
|
||||
Content = param.Code != ApiControllerResponseCodes.Error ? resultObject : param.ErrorMessage,
|
||||
RequestId = model.RequestId,
|
||||
Path = model.Path,
|
||||
};
|
||||
@@ -157,12 +160,12 @@ namespace cmonitor.api
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Instance.Error(ex);
|
||||
return new ClientServiceResponseInfo
|
||||
return new ApiControllerResponseInfo
|
||||
{
|
||||
Content = ex.Message,
|
||||
RequestId = model.RequestId,
|
||||
Path = model.Path,
|
||||
Code = ClientServiceResponseCodes.Error
|
||||
Code = ApiControllerResponseCodes.Error
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -173,9 +176,9 @@ namespace cmonitor.api
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] bytes = JsonSerializer.Serialize(new ClientServiceResponseInfo
|
||||
byte[] bytes = JsonSerializer.Serialize(new ApiControllerResponseInfo
|
||||
{
|
||||
Code = ClientServiceResponseCodes.Success,
|
||||
Code = ApiControllerResponseCodes.Success,
|
||||
Content = content,
|
||||
Path = path,
|
||||
RequestId = 0
|
||||
@@ -208,9 +211,9 @@ namespace cmonitor.api
|
||||
{
|
||||
try
|
||||
{
|
||||
Memory<byte> headMemory = JsonSerializer.Serialize(new ClientServiceResponseInfo
|
||||
Memory<byte> headMemory = JsonSerializer.Serialize(new ApiControllerResponseInfo
|
||||
{
|
||||
Code = ClientServiceResponseCodes.Success,
|
||||
Code = ApiControllerResponseCodes.Success,
|
||||
Content = name,
|
||||
Path = path,
|
||||
RequestId = 0
|
||||
@@ -255,9 +258,9 @@ namespace cmonitor.api
|
||||
{
|
||||
if (connection.Connected == false) return;
|
||||
|
||||
byte[] bytes = JsonSerializer.Serialize(new ClientServiceResponseInfo
|
||||
byte[] bytes = JsonSerializer.Serialize(new ApiControllerResponseInfo
|
||||
{
|
||||
Code = ClientServiceResponseCodes.Success,
|
||||
Code = ApiControllerResponseCodes.Success,
|
||||
Content = content,
|
||||
Path = path,
|
||||
RequestId = 0
|
||||
33
cmonitor/api/ApiStartup.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using cmonitor.config;
|
||||
using cmonitor.startup;
|
||||
using common.libs;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace cmonitor.api
|
||||
{
|
||||
public sealed class ApiStartup : IStartup
|
||||
{
|
||||
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
}
|
||||
|
||||
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
serviceCollection.AddSingleton<IApiServer, ApiServer>();
|
||||
}
|
||||
|
||||
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
}
|
||||
|
||||
public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
Logger.Instance.Info($"start api server");
|
||||
IApiServer clientServer = serviceProvider.GetService<IApiServer>();
|
||||
clientServer.LoadPlugins(assemblies);
|
||||
clientServer.Websocket();
|
||||
Logger.Instance.Info($"api listen:{config.Server.ApiPort}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,12 @@ namespace cmonitor.api
|
||||
/// <summary>
|
||||
/// 前段接口
|
||||
/// </summary>
|
||||
public interface IClientService { }
|
||||
public interface IApiController { }
|
||||
|
||||
/// <summary>
|
||||
/// 前段接口response
|
||||
/// </summary>
|
||||
public sealed class ClientServiceResponseInfo
|
||||
public sealed class ApiControllerResponseInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 路径
|
||||
@@ -24,7 +24,7 @@ namespace cmonitor.api
|
||||
/// <summary>
|
||||
/// 状态码
|
||||
/// </summary>
|
||||
public ClientServiceResponseCodes Code { get; set; } = ClientServiceResponseCodes.Success;
|
||||
public ApiControllerResponseCodes Code { get; set; } = ApiControllerResponseCodes.Success;
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
@@ -34,7 +34,7 @@ namespace cmonitor.api
|
||||
/// <summary>
|
||||
/// 前端接口request
|
||||
/// </summary>
|
||||
public sealed class ClientServiceRequestInfo
|
||||
public sealed class ApiControllerRequestInfo
|
||||
{
|
||||
[JsonIgnore]
|
||||
public WebsocketConnection Connection { get; set; }
|
||||
@@ -55,7 +55,7 @@ namespace cmonitor.api
|
||||
/// <summary>
|
||||
/// 前端接口执行参数
|
||||
/// </summary>
|
||||
public sealed class ClientServiceParamsInfo
|
||||
public sealed class ApiControllerParamsInfo
|
||||
{
|
||||
public WebsocketConnection Connection { get; set; }
|
||||
/// <summary>
|
||||
@@ -69,7 +69,7 @@ namespace cmonitor.api
|
||||
/// <summary>
|
||||
/// 状态码
|
||||
/// </summary>
|
||||
public ClientServiceResponseCodes Code { get; private set; } = ClientServiceResponseCodes.Success;
|
||||
public ApiControllerResponseCodes Code { get; private set; } = ApiControllerResponseCodes.Success;
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
@@ -80,7 +80,7 @@ namespace cmonitor.api
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="errormsg"></param>
|
||||
public void SetCode(ClientServiceResponseCodes code, string errormsg = "")
|
||||
public void SetCode(ApiControllerResponseCodes code, string errormsg = "")
|
||||
{
|
||||
Code = code;
|
||||
ErrorMessage = errormsg;
|
||||
@@ -91,14 +91,14 @@ namespace cmonitor.api
|
||||
/// <param name="msg"></param>
|
||||
public void SetErrorMessage(string msg)
|
||||
{
|
||||
Code = ClientServiceResponseCodes.Error;
|
||||
Code = ApiControllerResponseCodes.Error;
|
||||
ErrorMessage = msg;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 前端接口状态码
|
||||
/// </summary>
|
||||
public enum ClientServiceResponseCodes : byte
|
||||
public enum ApiControllerResponseCodes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 成功
|
||||
@@ -119,13 +119,13 @@ namespace cmonitor.api
|
||||
/// 前端接口标识特性
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class ClientServiceAttribute : Attribute
|
||||
public class ApiControllerAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 参数类型
|
||||
/// </summary>
|
||||
public Type Param { get; set; }
|
||||
public ClientServiceAttribute(Type param)
|
||||
public ApiControllerAttribute(Type param)
|
||||
{
|
||||
Param = param;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace cmonitor.api
|
||||
/// <summary>
|
||||
/// 前端接口服务
|
||||
/// </summary>
|
||||
public interface IClientServer
|
||||
public interface IApiServer
|
||||
{
|
||||
/// <summary>
|
||||
/// websocket
|
||||
@@ -1,166 +0,0 @@
|
||||
using cmonitor.client.reports.hijack;
|
||||
using cmonitor.client.reports.screen;
|
||||
using common.libs.database;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace cmonitor.client
|
||||
{
|
||||
|
||||
[Table("client")]
|
||||
public sealed class ClientConfig
|
||||
{
|
||||
private readonly IConfigDataProvider<ClientConfig> configDataProvider;
|
||||
private readonly Config config;
|
||||
|
||||
public ClientConfig() { }
|
||||
public ClientConfig(IConfigDataProvider<ClientConfig> configDataProvider, Config config)
|
||||
{
|
||||
this.configDataProvider = configDataProvider;
|
||||
this.config = config;
|
||||
|
||||
ClientConfig clientConfig = configDataProvider.Load().Result ?? new ClientConfig();
|
||||
LLock = clientConfig.LLock;
|
||||
Wallpaper = clientConfig.Wallpaper;
|
||||
WallpaperUrl = clientConfig.WallpaperUrl;
|
||||
HijackConfig = clientConfig.HijackConfig;
|
||||
HijackIds = clientConfig.HijackIds;
|
||||
WindowNames = clientConfig.WindowNames;
|
||||
WindowIds = clientConfig.WindowIds;
|
||||
UserSid = clientConfig.UserSid;
|
||||
Wlan = clientConfig.Wlan;
|
||||
WlanAuto = clientConfig.WlanAuto;
|
||||
SaveTask();
|
||||
}
|
||||
|
||||
private void SaveTask()
|
||||
{
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (updated && config.SaveSetting)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
}
|
||||
|
||||
private bool updated = false;
|
||||
|
||||
private bool _llock;
|
||||
public bool LLock
|
||||
{
|
||||
get => _llock; set
|
||||
{
|
||||
_llock = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _wallpaper;
|
||||
public bool Wallpaper
|
||||
{
|
||||
get => _wallpaper; set
|
||||
{
|
||||
_wallpaper = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private string _wallpaperUrl;
|
||||
public string WallpaperUrl
|
||||
{
|
||||
get => _wallpaperUrl; set
|
||||
{
|
||||
_wallpaperUrl = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private HijackConfig _hijackConfig = new HijackConfig();
|
||||
public HijackConfig HijackConfig
|
||||
{
|
||||
get => _hijackConfig; set
|
||||
{
|
||||
_hijackConfig = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private uint[] _hijackIds = Array.Empty<uint>();
|
||||
public uint[] HijackIds
|
||||
{
|
||||
get => _hijackIds; set
|
||||
{
|
||||
_hijackIds = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string[] _windowNames = Array.Empty<string>();
|
||||
public string[] WindowNames
|
||||
{
|
||||
get => _windowNames; set
|
||||
{
|
||||
_windowNames = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private uint[] _windowIds = Array.Empty<uint>();
|
||||
public uint[] WindowIds
|
||||
{
|
||||
get => _windowIds; set
|
||||
{
|
||||
_windowIds = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private string _userSid = string.Empty;
|
||||
public string UserSid
|
||||
{
|
||||
get => _userSid; set
|
||||
{
|
||||
_userSid = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string _wlan = string.Empty;
|
||||
public string Wlan
|
||||
{
|
||||
get => _wlan; set
|
||||
{
|
||||
_wlan = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
private bool _wlanAuto;
|
||||
public bool WlanAuto
|
||||
{
|
||||
get => _wlanAuto; set
|
||||
{
|
||||
_wlanAuto = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
configDataProvider.Save(this).Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using cmonitor.service;
|
||||
using cmonitor.server;
|
||||
|
||||
namespace cmonitor.client
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using cmonitor.service;
|
||||
using cmonitor.service.messengers.sign;
|
||||
using cmonitor.config;
|
||||
using cmonitor.plugins.signIn.messenger;
|
||||
using cmonitor.server;
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using MemoryPack;
|
||||
@@ -8,28 +9,25 @@ using System.Net.Sockets;
|
||||
|
||||
namespace cmonitor.client
|
||||
{
|
||||
public sealed class ClientTransfer
|
||||
public sealed class ClientSignInTransfer
|
||||
{
|
||||
private readonly ClientSignInState clientSignInState;
|
||||
private readonly Config config;
|
||||
private readonly TcpServer tcpServer;
|
||||
private readonly MessengerSender messengerSender;
|
||||
|
||||
public ClientTransfer(ClientSignInState clientSignInState, Config config, TcpServer tcpServer, MessengerSender messengerSender)
|
||||
public ClientSignInTransfer(ClientSignInState clientSignInState, Config config, TcpServer tcpServer, MessengerSender messengerSender)
|
||||
{
|
||||
this.clientSignInState = clientSignInState;
|
||||
this.config = config;
|
||||
this.tcpServer = tcpServer;
|
||||
this.messengerSender = messengerSender;
|
||||
|
||||
if (config.IsCLient)
|
||||
SignInTask();
|
||||
tcpServer.OnDisconnected += (hashcode) =>
|
||||
{
|
||||
SignInTask();
|
||||
tcpServer.OnDisconnected += (hashcode) =>
|
||||
{
|
||||
clientSignInState.PushNetworkDisabled();
|
||||
};
|
||||
}
|
||||
clientSignInState.PushNetworkDisabled();
|
||||
};
|
||||
}
|
||||
|
||||
private void SignInTask()
|
||||
@@ -58,7 +56,7 @@ namespace cmonitor.client
|
||||
}
|
||||
private async Task SignIn()
|
||||
{
|
||||
IPAddress[] ips = new IPAddress[] { config.Server };
|
||||
IPAddress[] ips = new IPAddress[] { config.Client.ServerEP.Address };
|
||||
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Info($"get ip:{ips.ToJsonFormat()}");
|
||||
@@ -68,7 +66,7 @@ namespace cmonitor.client
|
||||
{
|
||||
try
|
||||
{
|
||||
IPEndPoint remote = new IPEndPoint(ip, config.ServicePort);
|
||||
IPEndPoint remote = new IPEndPoint(ip, config.Client.ServerEP.Port);
|
||||
//Logger.Instance.Info($"connect server {remote}");
|
||||
Socket socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
socket.KeepAlive();
|
||||
@@ -86,7 +84,7 @@ namespace cmonitor.client
|
||||
MessengerId = (ushort)SignInMessengerIds.SignIn,
|
||||
Payload = MemoryPackSerializer.Serialize(new SignInfo
|
||||
{
|
||||
MachineName = config.Name,
|
||||
MachineName = config.Client.Name,
|
||||
Version = config.Version
|
||||
})
|
||||
});
|
||||
61
cmonitor/client/ClientStartup.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using cmonitor.client.runningConfig;
|
||||
using cmonitor.client.report;
|
||||
using cmonitor.client.ruleConfig;
|
||||
using cmonitor.config;
|
||||
using cmonitor.libs;
|
||||
using cmonitor.startup;
|
||||
using common.libs;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace cmonitor.client
|
||||
{
|
||||
public sealed class ClientStartup : IStartup
|
||||
{
|
||||
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
serviceCollection.AddSingleton<RuleConfig>();
|
||||
|
||||
serviceCollection.AddSingleton<ClientReportTransfer>();
|
||||
|
||||
serviceCollection.AddSingleton<ClientSignInState>();
|
||||
serviceCollection.AddSingleton<ClientSignInTransfer>();
|
||||
|
||||
|
||||
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<IRunningConfig, RunningConfigWindows>();
|
||||
else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<IRunningConfig, RunningConfigLinux>();
|
||||
else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<IRunningConfig, RunningConfigMacOS>();
|
||||
|
||||
//内存共享
|
||||
ShareMemory shareMemory = new ShareMemory(config.Client.ShareMemoryKey, config.Client.ShareMemoryCount, config.Client.ShareMemorySize);
|
||||
serviceCollection.AddSingleton<ShareMemory>((a) => shareMemory);
|
||||
}
|
||||
|
||||
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
}
|
||||
|
||||
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
Logger.Instance.Info($"start client");
|
||||
Logger.Instance.Info($"server ip {config.Server}");
|
||||
|
||||
Logger.Instance.Info($"start client report transfer");
|
||||
ClientReportTransfer report = serviceProvider.GetService<ClientReportTransfer>();
|
||||
report.LoadPlugins(assemblies);
|
||||
|
||||
Logger.Instance.Info($"start client share memory");
|
||||
ShareMemory shareMemory = serviceProvider.GetService<ShareMemory>();
|
||||
shareMemory.InitLocal();
|
||||
shareMemory.InitGlobal();
|
||||
shareMemory.StartLoop();
|
||||
|
||||
Logger.Instance.Info($"start client signin transfer");
|
||||
ClientSignInTransfer clientTransfer = serviceProvider.GetService<ClientSignInTransfer>();
|
||||
}
|
||||
|
||||
public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,15 @@
|
||||
using cmonitor.service.messengers.sign;
|
||||
using cmonitor.service;
|
||||
using cmonitor.config;
|
||||
using cmonitor.plugins.report.messenger;
|
||||
using cmonitor.server;
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using MemoryPack;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using common.libs.extends;
|
||||
using System.Reflection;
|
||||
|
||||
namespace cmonitor.client.reports
|
||||
namespace cmonitor.client.report
|
||||
{
|
||||
public interface IReport
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
public object GetReports(ReportType reportType);
|
||||
}
|
||||
|
||||
public sealed class ReportTransfer : IReport
|
||||
public sealed class ClientReportTransfer
|
||||
{
|
||||
public string Name => string.Empty;
|
||||
|
||||
@@ -24,32 +18,26 @@ namespace cmonitor.client.reports
|
||||
private readonly ServiceProvider serviceProvider;
|
||||
private readonly Config config;
|
||||
|
||||
private List<IReport> reports;
|
||||
private List<IClientReport> reports;
|
||||
private Dictionary<string, object> reportObj;
|
||||
private ReportType reportType = ReportType.Full | ReportType.Trim;
|
||||
|
||||
public ReportTransfer(ClientSignInState clientSignInState, MessengerSender messengerSender, ServiceProvider serviceProvider, Config config)
|
||||
public ClientReportTransfer(ClientSignInState clientSignInState, MessengerSender messengerSender, ServiceProvider serviceProvider, Config config)
|
||||
{
|
||||
this.clientSignInState = clientSignInState;
|
||||
this.messengerSender = messengerSender;
|
||||
this.serviceProvider = serviceProvider;
|
||||
this.config = config;
|
||||
if (config.IsCLient)
|
||||
{
|
||||
ReportTask();
|
||||
}
|
||||
}
|
||||
|
||||
public object GetReports(ReportType reportType)
|
||||
{
|
||||
return null;
|
||||
ReportTask();
|
||||
}
|
||||
|
||||
public void LoadPlugins(Assembly[] assembs)
|
||||
{
|
||||
IEnumerable<Type> types = ReflectionHelper.GetInterfaceSchieves(assembs, typeof(IReport));
|
||||
reports = types.Select(c => (IReport)serviceProvider.GetService(c)).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList();
|
||||
IEnumerable<Type> types = ReflectionHelper.GetInterfaceSchieves(assembs, typeof(IClientReport));
|
||||
reports = types.Select(c => (IClientReport)serviceProvider.GetService(c)).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList();
|
||||
reportObj = new Dictionary<string, object>(reports.Count);
|
||||
|
||||
Logger.Instance.Info($"load reports:{string.Join(",", reports.Select(c => c.Name))}");
|
||||
}
|
||||
|
||||
private uint reportFlag = 0;
|
||||
@@ -81,15 +69,15 @@ namespace cmonitor.client.reports
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
Logger.Instance.Error(ex);
|
||||
}
|
||||
await Task.Delay(config.ReportDelay);
|
||||
await Task.Delay(30);
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
}
|
||||
private async Task SendReport()
|
||||
{
|
||||
reportObj.Clear();
|
||||
|
||||
foreach (IReport item in reports)
|
||||
|
||||
foreach (IClientReport item in reports)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(item.Name) == false)
|
||||
{
|
||||
@@ -116,9 +104,4 @@ namespace cmonitor.client.reports
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ReportType : byte
|
||||
{
|
||||
Full = 1, Trim = 2
|
||||
}
|
||||
}
|
||||
13
cmonitor/client/report/IClientReport.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace cmonitor.client.report
|
||||
{
|
||||
public interface IClientReport
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
public object GetReports(ReportType reportType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
16
cmonitor/client/report/ReportInfo.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace cmonitor.client.report
|
||||
{
|
||||
public abstract class ReportInfo
|
||||
{
|
||||
public abstract int HashCode();
|
||||
|
||||
private int hashcode = 0;
|
||||
public bool Updated()
|
||||
{
|
||||
int code = HashCode();
|
||||
bool updated = code != hashcode;
|
||||
hashcode = code;
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
cmonitor/client/report/ReportType.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace cmonitor.client.report
|
||||
{
|
||||
public enum ReportType : byte
|
||||
{
|
||||
Full = 1, Trim = 2
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
using cmonitor.libs;
|
||||
|
||||
namespace cmonitor.client.reports.llock
|
||||
{
|
||||
public sealed class LLockReport : IReport
|
||||
{
|
||||
public string Name => "LLock";
|
||||
|
||||
private LLockReportInfo report = new LLockReportInfo();
|
||||
|
||||
private readonly ClientConfig clientConfig;
|
||||
private readonly ILLock lLock;
|
||||
private readonly ShareMemory shareMemory;
|
||||
private long version = 0;
|
||||
|
||||
public LLockReport(Config config, ClientConfig clientConfig, ILLock lLock, ShareMemory shareMemory,ClientSignInState clientSignInState)
|
||||
{
|
||||
this.clientConfig = clientConfig;
|
||||
this.lLock = lLock;
|
||||
this.shareMemory = shareMemory;
|
||||
|
||||
if (config.IsCLient)
|
||||
{
|
||||
clientSignInState.NetworkFirstEnabledHandle +=()=> { LockScreen(clientConfig.LLock); };
|
||||
}
|
||||
}
|
||||
|
||||
DateTime startTime = new DateTime(1970, 1, 1);
|
||||
public object GetReports(ReportType reportType)
|
||||
{
|
||||
bool updated = shareMemory.ReadVersionUpdated(Config.ShareMemoryLLockIndex,ref version);
|
||||
if (reportType == ReportType.Full || updated)
|
||||
{
|
||||
long value = shareMemory.ReadValueInt64(Config.ShareMemoryLLockIndex);
|
||||
clientConfig.LLock = report.LockScreen = value > 0 && (long)(DateTime.UtcNow.Subtract(startTime)).TotalMilliseconds - value < 1000;
|
||||
return report;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void LockScreen(bool open)
|
||||
{
|
||||
clientConfig.LLock = open;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
shareMemory.AddAttribute(Config.ShareMemoryLLockIndex, ShareMemoryAttribute.Closed);
|
||||
await Task.Delay(100);
|
||||
lLock.Set(open);
|
||||
});
|
||||
}
|
||||
|
||||
public void LockSystem()
|
||||
{
|
||||
lLock.LockSystem();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public sealed class LLockReportInfo
|
||||
{
|
||||
public bool LockScreen { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using FFmpeg.AutoGen.Abstractions;
|
||||
|
||||
namespace cmonitor.client.reports.screen.h264;
|
||||
|
||||
internal static class FFmpegHelper
|
||||
{
|
||||
public static unsafe string av_strerror(int error)
|
||||
{
|
||||
var bufferSize = 1024;
|
||||
var buffer = stackalloc byte[bufferSize];
|
||||
ffmpeg.av_strerror(error, buffer, (ulong)bufferSize);
|
||||
var message = Marshal.PtrToStringAnsi((IntPtr)buffer);
|
||||
return message;
|
||||
}
|
||||
|
||||
public static int ThrowExceptionIfError(this int error)
|
||||
{
|
||||
|
||||
if (error < 0) throw new ApplicationException(av_strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
RegisterFFmpegBinaries();
|
||||
FFmpeg.AutoGen.Bindings.DynamicallyLoaded.DynamicallyLoadedBindings.Initialize();
|
||||
}
|
||||
internal static void RegisterFFmpegBinaries()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
var current = Environment.CurrentDirectory;
|
||||
while (current != null)
|
||||
{
|
||||
var ffmpegBinaryPath = Path.Combine(current, "ffmpeg");
|
||||
|
||||
if (Directory.Exists(ffmpegBinaryPath))
|
||||
{
|
||||
//Console.WriteLine($"FFmpeg binaries found in: {ffmpegBinaryPath}");
|
||||
FFmpeg.AutoGen.Bindings.DynamicallyLoaded.DynamicallyLoadedBindings.LibrariesPath = ffmpegBinaryPath;
|
||||
return;
|
||||
}
|
||||
|
||||
current = Directory.GetParent(current)?.FullName;
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new NotSupportedException(); // fell free add support for platform of your choose
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
using FFmpeg.AutoGen;
|
||||
using System.Drawing;
|
||||
|
||||
namespace cmonitor.client.reports.screen.h264
|
||||
{
|
||||
public unsafe class H264VideoStreamDecoder
|
||||
{
|
||||
private readonly AVCodecContext* _pCodecContext;
|
||||
private readonly AVFrame* _pFrame;
|
||||
private readonly AVPacket* _pPacket;
|
||||
|
||||
public H264VideoStreamDecoder(int fps, Size frameSize, string[] args)
|
||||
{
|
||||
var codecId = AVCodecID.AV_CODEC_ID_H264;
|
||||
var pCodec = ffmpeg.avcodec_find_decoder(codecId);
|
||||
if (pCodec == null) throw new InvalidOperationException("Codec not found.");
|
||||
|
||||
_pCodecContext = ffmpeg.avcodec_alloc_context3(pCodec);
|
||||
_pCodecContext->width = frameSize.Width;
|
||||
_pCodecContext->height = frameSize.Height;
|
||||
_pCodecContext->time_base = new AVRational { num = 1, den = fps };
|
||||
_pCodecContext->pix_fmt = AVPixelFormat.AV_PIX_FMT_YUV420P;
|
||||
foreach (var arg in args)
|
||||
{
|
||||
var optionName = arg.Split('=')[0];
|
||||
var value = arg.Split('=')[1];
|
||||
ffmpeg.av_opt_set(_pCodecContext->priv_data, optionName, value, 0);
|
||||
}
|
||||
//ffmpeg.av_opt_set(_pCodecContext->priv_data, "preset", "veryfast", 0);
|
||||
//ffmpeg.av_opt_set(_pCodecContext->priv_data, "tune", "zerolatency", 0);
|
||||
ffmpeg.avcodec_open2(_pCodecContext, pCodec, null).ThrowExceptionIfError();
|
||||
}
|
||||
|
||||
public AVFrame Decoder(AVPacket packet)
|
||||
{
|
||||
var frame = ffmpeg.av_frame_alloc();
|
||||
int error;
|
||||
do
|
||||
{
|
||||
ffmpeg.avcodec_send_packet(_pCodecContext, &packet).ThrowExceptionIfError();
|
||||
error = ffmpeg.avcodec_receive_frame(_pCodecContext, frame);
|
||||
} while (error == ffmpeg.AVERROR(ffmpeg.EAGAIN));
|
||||
|
||||
ffmpeg.av_packet_unref(&packet);
|
||||
|
||||
return *frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using FFmpeg.AutoGen.Abstractions;
|
||||
|
||||
namespace cmonitor.client.reports.screen.h264;
|
||||
|
||||
public sealed unsafe class H264VideoStreamEncoder : IDisposable
|
||||
{
|
||||
private readonly Size _frameSize;
|
||||
private readonly int _linesizeU;
|
||||
private readonly int _linesizeV;
|
||||
private readonly int _linesizeY;
|
||||
private readonly AVCodec* _pCodec;
|
||||
private readonly AVCodecContext* _pCodecContext;
|
||||
private readonly int _uSize;
|
||||
private readonly int _ySize;
|
||||
|
||||
public H264VideoStreamEncoder(int fps, Size frameSize)
|
||||
{
|
||||
_frameSize = frameSize;
|
||||
|
||||
var codecId = AVCodecID.AV_CODEC_ID_H264;
|
||||
_pCodec = ffmpeg.avcodec_find_encoder(codecId);
|
||||
if (_pCodec == null) throw new InvalidOperationException("Codec not found.");
|
||||
|
||||
_pCodecContext = ffmpeg.avcodec_alloc_context3(_pCodec);
|
||||
_pCodecContext->width = frameSize.Width;
|
||||
_pCodecContext->height = frameSize.Height;
|
||||
_pCodecContext->time_base = new AVRational { num = 1, den = fps };
|
||||
_pCodecContext->pix_fmt = AVPixelFormat.AV_PIX_FMT_YUV420P;
|
||||
ffmpeg.av_opt_set(_pCodecContext->priv_data, "preset", "superfast", 0);
|
||||
//ffmpeg.av_opt_set(_pCodecContext->priv_data, "-b:v", "50K", 0);
|
||||
//ffmpeg.av_opt_set(_pCodecContext->priv_data, "-minrate", "50K", 0);
|
||||
//ffmpeg.av_opt_set(_pCodecContext->priv_data, "-maxrate", "5000K", 0);
|
||||
//ffmpeg.av_opt_set(_pCodecContext->priv_data, "-bufsize", "5000K", 0);
|
||||
|
||||
ffmpeg.avcodec_open2(_pCodecContext, _pCodec, null).ThrowExceptionIfError();
|
||||
|
||||
_linesizeY = frameSize.Width;
|
||||
_linesizeU = frameSize.Width / 2;
|
||||
_linesizeV = frameSize.Width / 2;
|
||||
|
||||
_ySize = _linesizeY * frameSize.Height;
|
||||
_uSize = _linesizeU * frameSize.Height / 2;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ffmpeg.avcodec_close(_pCodecContext);
|
||||
ffmpeg.av_free(_pCodecContext);
|
||||
ffmpeg.av_free(_pCodec);
|
||||
}
|
||||
|
||||
public void SendFrame(AVFrame frame)
|
||||
{
|
||||
if (frame.format != (int)_pCodecContext->pix_fmt)
|
||||
throw new ArgumentException("Invalid pixel format.", nameof(frame));
|
||||
if (frame.width != _frameSize.Width) throw new ArgumentException("Invalid width.", nameof(frame));
|
||||
if (frame.height != _frameSize.Height) throw new ArgumentException("Invalid height.", nameof(frame));
|
||||
if (frame.linesize[0] < _linesizeY) throw new ArgumentException("Invalid Y linesize.", nameof(frame));
|
||||
if (frame.linesize[1] < _linesizeU) throw new ArgumentException("Invalid U linesize.", nameof(frame));
|
||||
if (frame.linesize[2] < _linesizeV) throw new ArgumentException("Invalid V linesize.", nameof(frame));
|
||||
if (frame.data[1] - frame.data[0] < _ySize)
|
||||
throw new ArgumentException("Invalid Y data size.", nameof(frame));
|
||||
if (frame.data[2] - frame.data[1] < _uSize)
|
||||
throw new ArgumentException("Invalid U data size.", nameof(frame));
|
||||
|
||||
try
|
||||
{
|
||||
ffmpeg.avcodec_send_frame(_pCodecContext, &frame).ThrowExceptionIfError();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
ffmpeg.av_frame_unref(&frame);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public byte[] ReceivePacket()
|
||||
{
|
||||
AVPacket* pPacket = ffmpeg.av_packet_alloc();
|
||||
|
||||
try
|
||||
{
|
||||
ffmpeg.av_packet_unref(pPacket);
|
||||
int response = ffmpeg.avcodec_receive_packet(_pCodecContext, pPacket);
|
||||
if(response == 0)
|
||||
{
|
||||
byte[] bytes = new byte[pPacket->size];
|
||||
Marshal.Copy((IntPtr)pPacket->data, bytes, 0, pPacket->size);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
ffmpeg.av_packet_free(&pPacket);
|
||||
}
|
||||
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using FFmpeg.AutoGen;
|
||||
|
||||
namespace cmonitor.client.reports.screen.h264;
|
||||
|
||||
public sealed unsafe class VideoConverter : IDisposable
|
||||
{
|
||||
private readonly SwsContext* _pConvertContext;
|
||||
|
||||
public VideoConverter(Size sourceSize, AVPixelFormat sourcePixelFormat,
|
||||
Size destinationSize, AVPixelFormat destinationPixelFormat)
|
||||
{
|
||||
_pConvertContext = ffmpeg.sws_getContext(sourceSize.Width,
|
||||
sourceSize.Height,
|
||||
sourcePixelFormat,
|
||||
destinationSize.Width,
|
||||
destinationSize.Height,
|
||||
destinationPixelFormat,
|
||||
ffmpeg.SWS_FAST_BILINEAR,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
if (_pConvertContext == null)
|
||||
throw new ApplicationException("Could not initialize the conversion context.");
|
||||
|
||||
var convertedFrameBufferSize = ffmpeg.av_image_get_buffer_size(destinationPixelFormat,
|
||||
destinationSize.Width,
|
||||
destinationSize.Height,
|
||||
1);
|
||||
var convertedFrameBufferPtr = Marshal.AllocHGlobal(convertedFrameBufferSize);
|
||||
var dstData = new byte_ptrArray4();
|
||||
var dstLinesize = new int_array4();
|
||||
|
||||
ffmpeg.av_image_fill_arrays(ref dstData,
|
||||
ref dstLinesize,
|
||||
(byte*)convertedFrameBufferPtr,
|
||||
destinationPixelFormat,
|
||||
destinationSize.Width,
|
||||
destinationSize.Height,
|
||||
1);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public AVFrame Convert(AVFrame sourceFrame)
|
||||
{
|
||||
var dstData = new byte_ptrArray4();
|
||||
var dstLinesize = new int_array4();
|
||||
|
||||
ffmpeg.sws_scale(_pConvertContext,
|
||||
sourceFrame.data,
|
||||
sourceFrame.linesize,
|
||||
0,
|
||||
sourceFrame.height,
|
||||
dstData,
|
||||
dstLinesize);
|
||||
|
||||
return new AVFrame();
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using FFmpeg.AutoGen.Abstractions;
|
||||
|
||||
|
||||
namespace cmonitor.client.reports.screen.h264;
|
||||
|
||||
public sealed unsafe class VideoFrameConverter : IDisposable
|
||||
{
|
||||
private readonly IntPtr _convertedFrameBufferPtr;
|
||||
private readonly Size _destinationSize;
|
||||
private readonly byte_ptr4 _dstData;
|
||||
private readonly int4 _dstLinesize;
|
||||
private readonly SwsContext* _pConvertContext;
|
||||
|
||||
public VideoFrameConverter(Size sourceSize, AVPixelFormat sourcePixelFormat,
|
||||
Size destinationSize, AVPixelFormat destinationPixelFormat)
|
||||
{
|
||||
_destinationSize = destinationSize;
|
||||
|
||||
_pConvertContext = ffmpeg.sws_getContext(sourceSize.Width,
|
||||
sourceSize.Height,
|
||||
sourcePixelFormat,
|
||||
destinationSize.Width,
|
||||
destinationSize.Height,
|
||||
destinationPixelFormat,
|
||||
ffmpeg.SWS_FAST_BILINEAR,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
if (_pConvertContext == null)
|
||||
throw new ApplicationException("Could not initialize the conversion context.");
|
||||
|
||||
var convertedFrameBufferSize = ffmpeg.av_image_get_buffer_size(destinationPixelFormat,
|
||||
destinationSize.Width,
|
||||
destinationSize.Height,
|
||||
1);
|
||||
_convertedFrameBufferPtr = Marshal.AllocHGlobal(convertedFrameBufferSize);
|
||||
_dstData = new byte_ptr4();
|
||||
_dstLinesize = new int4();
|
||||
|
||||
ffmpeg.av_image_fill_arrays(ref _dstData,
|
||||
ref _dstLinesize,
|
||||
(byte*)_convertedFrameBufferPtr,
|
||||
destinationPixelFormat,
|
||||
destinationSize.Width,
|
||||
destinationSize.Height,
|
||||
1);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Marshal.FreeHGlobal(_convertedFrameBufferPtr);
|
||||
ffmpeg.sws_freeContext(_pConvertContext);
|
||||
}
|
||||
|
||||
public FFmpeg.AutoGen.Abstractions.AVFrame Convert(FFmpeg.AutoGen.Abstractions.AVFrame sourceFrame)
|
||||
{
|
||||
ffmpeg.sws_scale(_pConvertContext,
|
||||
sourceFrame.data,
|
||||
sourceFrame.linesize,
|
||||
0,
|
||||
sourceFrame.height,
|
||||
_dstData,
|
||||
_dstLinesize);
|
||||
|
||||
var data = new byte_ptr8();
|
||||
data.UpdateFrom(_dstData);
|
||||
var linesize = new int8();
|
||||
linesize.UpdateFrom(_dstLinesize);
|
||||
|
||||
ffmpeg.av_frame_unref(&sourceFrame);
|
||||
|
||||
return new FFmpeg.AutoGen.Abstractions.AVFrame
|
||||
{
|
||||
data = data,
|
||||
linesize = linesize,
|
||||
width = _destinationSize.Width,
|
||||
height = _destinationSize.Height
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using FFmpeg.AutoGen.Abstractions;
|
||||
|
||||
namespace cmonitor.client.reports.screen.h264;
|
||||
|
||||
public sealed unsafe class VideoStreamDecoder : IDisposable
|
||||
{
|
||||
private readonly AVCodecContext* _pCodecContext;
|
||||
private readonly AVFormatContext* _pFormatContext;
|
||||
private readonly AVFrame* _pFrame;
|
||||
private readonly AVPacket* _pPacket;
|
||||
private readonly AVFrame* _receivedFrame;
|
||||
private readonly int _streamIndex;
|
||||
|
||||
public VideoStreamDecoder(string url, AVHWDeviceType HWDeviceType = AVHWDeviceType.AV_HWDEVICE_TYPE_NONE)
|
||||
{
|
||||
_pFormatContext = ffmpeg.avformat_alloc_context();
|
||||
_receivedFrame = ffmpeg.av_frame_alloc();
|
||||
var pFormatContext = _pFormatContext;
|
||||
ffmpeg.avformat_open_input(&pFormatContext, url, null, null).ThrowExceptionIfError();
|
||||
ffmpeg.avformat_find_stream_info(_pFormatContext, null).ThrowExceptionIfError();
|
||||
AVCodec* codec = null;
|
||||
_streamIndex = ffmpeg
|
||||
.av_find_best_stream(_pFormatContext, AVMediaType.AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0)
|
||||
.ThrowExceptionIfError();
|
||||
_pCodecContext = ffmpeg.avcodec_alloc_context3(codec);
|
||||
|
||||
if (HWDeviceType != AVHWDeviceType.AV_HWDEVICE_TYPE_NONE)
|
||||
{
|
||||
ffmpeg.av_hwdevice_ctx_create(&_pCodecContext->hw_device_ctx, HWDeviceType, null, null, 0)
|
||||
.ThrowExceptionIfError();
|
||||
}
|
||||
|
||||
ffmpeg.avcodec_parameters_to_context(_pCodecContext, _pFormatContext->streams[_streamIndex]->codecpar)
|
||||
.ThrowExceptionIfError();
|
||||
ffmpeg.avcodec_open2(_pCodecContext, codec, null).ThrowExceptionIfError();
|
||||
|
||||
CodecName = ffmpeg.avcodec_get_name(codec->id);
|
||||
FrameSize = new Size(_pCodecContext->width, _pCodecContext->height);
|
||||
PixelFormat = _pCodecContext->pix_fmt;
|
||||
|
||||
_pPacket = ffmpeg.av_packet_alloc();
|
||||
_pFrame = ffmpeg.av_frame_alloc();
|
||||
}
|
||||
|
||||
public string CodecName { get; }
|
||||
public Size FrameSize { get; }
|
||||
public AVPixelFormat PixelFormat { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var pFrame = _pFrame;
|
||||
ffmpeg.av_frame_free(&pFrame);
|
||||
|
||||
var pPacket = _pPacket;
|
||||
ffmpeg.av_packet_free(&pPacket);
|
||||
|
||||
ffmpeg.avcodec_close(_pCodecContext);
|
||||
var pFormatContext = _pFormatContext;
|
||||
ffmpeg.avformat_close_input(&pFormatContext);
|
||||
}
|
||||
|
||||
public bool TryDecodeNextFrame(out AVFrame frame)
|
||||
{
|
||||
ffmpeg.av_frame_unref(_pFrame);
|
||||
ffmpeg.av_frame_unref(_receivedFrame);
|
||||
int error;
|
||||
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
ffmpeg.av_packet_unref(_pPacket);
|
||||
error = ffmpeg.av_read_frame(_pFormatContext, _pPacket);
|
||||
|
||||
if (error == ffmpeg.AVERROR_EOF)
|
||||
{
|
||||
frame = *_pFrame;
|
||||
return false;
|
||||
}
|
||||
|
||||
error.ThrowExceptionIfError();
|
||||
} while (_pPacket->stream_index != _streamIndex);
|
||||
|
||||
ffmpeg.avcodec_send_packet(_pCodecContext, _pPacket).ThrowExceptionIfError();
|
||||
}
|
||||
finally
|
||||
{
|
||||
ffmpeg.av_packet_unref(_pPacket);
|
||||
}
|
||||
|
||||
error = ffmpeg.avcodec_receive_frame(_pCodecContext, _pFrame);
|
||||
} while (error == ffmpeg.AVERROR(ffmpeg.EAGAIN));
|
||||
|
||||
error.ThrowExceptionIfError();
|
||||
|
||||
if (_pCodecContext->hw_device_ctx != null)
|
||||
{
|
||||
ffmpeg.av_hwframe_transfer_data(_receivedFrame, _pFrame, 0).ThrowExceptionIfError();
|
||||
frame = *_receivedFrame;
|
||||
}
|
||||
else
|
||||
frame = *_pFrame;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, string> GetContextInfo()
|
||||
{
|
||||
AVDictionaryEntry* tag = null;
|
||||
var result = new Dictionary<string, string>();
|
||||
|
||||
while ((tag = ffmpeg.av_dict_get(_pFormatContext->metadata, "", tag, ffmpeg.AV_DICT_IGNORE_SUFFIX)) != null)
|
||||
{
|
||||
var key = Marshal.PtrToStringAnsi((IntPtr)tag->key);
|
||||
var value = Marshal.PtrToStringAnsi((IntPtr)tag->value);
|
||||
result.Add(key, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace cmonitor.client.reports.wallpaper
|
||||
{
|
||||
public interface IWallpaper
|
||||
{
|
||||
public void Set(bool value, string url);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace cmonitor.client.reports.wallpaper
|
||||
{
|
||||
public sealed class WallpaperLinux : IWallpaper
|
||||
{
|
||||
public void Set(bool value, string url)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace cmonitor.client.reports.wallpaper
|
||||
{
|
||||
public sealed class WallpaperMacOS : IWallpaper
|
||||
{
|
||||
public void Set(bool value, string url)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
using cmonitor.libs;
|
||||
|
||||
namespace cmonitor.client.reports.wallpaper
|
||||
{
|
||||
public sealed class WallpaperReport : IReport
|
||||
{
|
||||
public string Name => "Wallpaper";
|
||||
|
||||
private WallpaperReportInfo report = new WallpaperReportInfo();
|
||||
private readonly ClientConfig clientConfig;
|
||||
private readonly IWallpaper wallpaper;
|
||||
private readonly ShareMemory shareMemory;
|
||||
private long version = 0;
|
||||
private bool opened = false;
|
||||
|
||||
public WallpaperReport(Config config, ClientConfig clientConfig, IWallpaper wallpaper, ShareMemory shareMemory, ClientSignInState clientSignInState)
|
||||
{
|
||||
this.clientConfig = clientConfig;
|
||||
this.wallpaper = wallpaper;
|
||||
this.shareMemory = shareMemory;
|
||||
|
||||
if (config.IsCLient)
|
||||
{
|
||||
clientSignInState.NetworkFirstEnabledHandle += () => { Update(clientConfig.Wallpaper, clientConfig.WallpaperUrl); };
|
||||
WallpaperTask();
|
||||
}
|
||||
}
|
||||
|
||||
DateTime startTime = new DateTime(1970, 1, 1);
|
||||
public object GetReports(ReportType reportType)
|
||||
{
|
||||
if (reportType == ReportType.Full || shareMemory.ReadVersionUpdated(Config.ShareMemoryWallpaperIndex, ref version))
|
||||
{
|
||||
report.Value = Running();
|
||||
return report;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Update(bool open, string url)
|
||||
{
|
||||
opened = open;
|
||||
clientConfig.Wallpaper = open;
|
||||
clientConfig.WallpaperUrl = url;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
shareMemory.AddAttribute(Config.ShareMemoryWallpaperIndex, ShareMemoryAttribute.Closed);
|
||||
await Task.Delay(100);
|
||||
wallpaper.Set(open, url);
|
||||
});
|
||||
}
|
||||
|
||||
private void WallpaperTask()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (opened)
|
||||
{
|
||||
if (Running() == false)
|
||||
{
|
||||
Update(clientConfig.Wallpaper, clientConfig.WallpaperUrl);
|
||||
}
|
||||
}
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
private bool Running()
|
||||
{
|
||||
long value = shareMemory.ReadValueInt64(Config.ShareMemoryWallpaperIndex);
|
||||
return value > 0 && (long)(DateTime.UtcNow.Subtract(startTime)).TotalMilliseconds - value < 1000;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class WallpaperReportInfo
|
||||
{
|
||||
public bool Value { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using common.libs;
|
||||
|
||||
namespace cmonitor.client.reports.wallpaper
|
||||
{
|
||||
public sealed class WallpaperWindows : IWallpaper
|
||||
{
|
||||
private readonly Config config;
|
||||
public WallpaperWindows(Config config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
public void Set(bool value, string url)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
CommandHelper.Windows(string.Empty, new string[] {
|
||||
$"start cmonitor.wallpaper.win.exe \"{url}\" {config.ShareMemoryKey} {config.ShareMemoryLength} {config.ShareMemoryItemSize} {Config.ShareMemoryKeyBoardIndex} {Config.ShareMemoryWallpaperIndex}"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using common.libs.winapis;
|
||||
|
||||
namespace cmonitor.client.reports.wlan
|
||||
{
|
||||
public sealed class WlanReport : IReport
|
||||
{
|
||||
public string Name => "Wlan";
|
||||
private readonly Config config;
|
||||
private readonly ClientConfig clientConfig;
|
||||
private readonly IWlan wlan;
|
||||
|
||||
public WlanReport(Config config, ClientConfig clientConfig, IWlan wlan)
|
||||
{
|
||||
this.config = config;
|
||||
this.clientConfig = clientConfig;
|
||||
this.wlan = wlan;
|
||||
|
||||
if (config.IsCLient)
|
||||
{
|
||||
WlanTask();
|
||||
}
|
||||
}
|
||||
|
||||
public object GetReports(ReportType reportType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<string> WlanEnums()
|
||||
{
|
||||
return wlan.WlanEnums();
|
||||
}
|
||||
public void WlanConnect(WlanSetInfo wlanSetInfo)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
foreach (var item in wlanSetInfo.Names)
|
||||
{
|
||||
bool res = await wlan.WlanConnect(item);
|
||||
if (res)
|
||||
{
|
||||
clientConfig.Wlan = item;
|
||||
clientConfig.WlanAuto = wlanSetInfo.Auto;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void WlanTask()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (wlan.Connected() == false /*&& string.IsNullOrWhiteSpace(clientConfig.Wlan) == false && clientConfig.WlanAuto*/)
|
||||
{
|
||||
var wafis = wlan.WlanEnums();
|
||||
foreach (var wifi in wafis)
|
||||
{
|
||||
bool res = await wlan.WlanConnect(wifi/*clientConfig.Wlan*/);
|
||||
if (res)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
await Task.Delay(3000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class WlanSetInfo
|
||||
{
|
||||
public string[] Names { get; set; }
|
||||
public bool Auto { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
15
cmonitor/client/ruleConfig/IRuleConfig.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace cmonitor.client.ruleConfig
|
||||
{
|
||||
public interface IRuleConfig
|
||||
{
|
||||
public T Get<T>(T defaultValue);
|
||||
public T Get<T>(string name, T defaultValue);
|
||||
public void Set<T>(T data);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using cmonitor.client.reports.snatch;
|
||||
using cmonitor.plugins.snatch.report;
|
||||
using common.libs.database;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace cmonitor.api
|
||||
namespace cmonitor.client.ruleConfig
|
||||
{
|
||||
|
||||
[Table("rule")]
|
||||
@@ -15,12 +15,7 @@ namespace cmonitor.api
|
||||
this.configDataProvider = configDataProvider;
|
||||
RuleConfig config = configDataProvider.Load().Result ?? new RuleConfig
|
||||
{
|
||||
UserNames = new Dictionary<string, UserNameInfo> { { "snltty", new UserNameInfo {
|
||||
Rules = new List<RulesInfo>{ new RulesInfo { ID = 1, Name = "默认" } },
|
||||
Processs = new List<GroupInfo>{ new GroupInfo { ID = 2, Name = "默认" } },
|
||||
Windows = new List<WindowGroupInfo> { new WindowGroupInfo { ID = 3, Name = "默认" } },
|
||||
Snatchs = new List<SnatchGroupInfo>{ new SnatchGroupInfo { ID=4, Name="默认" } }
|
||||
} } }
|
||||
UserNames = new Dictionary<string, UserNameInfo> { { "snltty", DefaultUser() } }
|
||||
};
|
||||
UserNames = config.UserNames;
|
||||
MaxID = config.MaxID;
|
||||
@@ -38,6 +33,18 @@ namespace cmonitor.api
|
||||
}
|
||||
|
||||
private readonly object lockObj = new object();
|
||||
private UserNameInfo DefaultUser()
|
||||
{
|
||||
return new UserNameInfo
|
||||
{
|
||||
Rules = new List<RulesInfo> { new RulesInfo { ID = 1, Name = "默认" } },
|
||||
Processs = new List<GroupInfo> { new GroupInfo { ID = 2, Name = "默认" } },
|
||||
Windows = new List<WindowGroupInfo> { new WindowGroupInfo { ID = 3, Name = "默认" } },
|
||||
Snatchs = new List<SnatchGroupInfo> { new SnatchGroupInfo { ID = 4, Name = "默认" } },
|
||||
Modes = "{}",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public string AddName(string name)
|
||||
{
|
||||
@@ -45,12 +52,7 @@ namespace cmonitor.api
|
||||
{
|
||||
if (UserNames.ContainsKey(name) == false)
|
||||
{
|
||||
UserNames.Add(name, new UserNameInfo
|
||||
{
|
||||
Rules = new List<RulesInfo> { new RulesInfo { ID = 1, Name = "默认" } },
|
||||
Processs = new List<GroupInfo> { new GroupInfo { ID = 1, Name = "默认" } },
|
||||
Windows = new List<WindowGroupInfo> { new WindowGroupInfo { ID = 1, Name = "默认" } },
|
||||
});
|
||||
UserNames.Add(name, DefaultUser());
|
||||
}
|
||||
Save();
|
||||
}
|
||||
@@ -457,17 +459,26 @@ namespace cmonitor.api
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public SnatchItemInfo[] SnatchRandom(int length)
|
||||
{
|
||||
return UserNames.Values
|
||||
.SelectMany(c => c.Snatchs)
|
||||
.SelectMany(c => c.List).OrderBy(c => Guid.NewGuid())
|
||||
.Where(c => c.Cate == SnatchCate.Question)
|
||||
.Where(c => (c.Type == SnatchType.Select && c.Options.Any(c => c.Value)) || (c.Type == SnatchType.Input && string.IsNullOrWhiteSpace(c.Correct) == false))
|
||||
.Where(c => c.Type == SnatchType.Select && c.Options.Any(c => c.Value) || c.Type == SnatchType.Input && string.IsNullOrWhiteSpace(c.Correct) == false)
|
||||
.Take(length).ToArray();
|
||||
}
|
||||
|
||||
|
||||
public string UpdateModes(UpdateModesInfo info)
|
||||
{
|
||||
if (UserNames.TryGetValue(info.UserName, out UserNameInfo userNameInfo))
|
||||
{
|
||||
userNameInfo.Modes = info.Modes;
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
configDataProvider.Save(this).Wait();
|
||||
@@ -481,6 +492,8 @@ namespace cmonitor.api
|
||||
public List<string> Devices { get; set; } = new List<string>();
|
||||
public List<WindowGroupInfo> Windows { get; set; } = new List<WindowGroupInfo>();
|
||||
public List<SnatchGroupInfo> Snatchs { get; set; } = new List<SnatchGroupInfo>();
|
||||
|
||||
public string Modes { get; set; } = "{}";
|
||||
}
|
||||
public sealed class UpdateDevicesInfo
|
||||
{
|
||||
@@ -623,8 +636,6 @@ namespace cmonitor.api
|
||||
public uint GroupID { get; set; }
|
||||
public uint ID { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public sealed class SnatchItemInfo
|
||||
{
|
||||
public uint ID { get; set; }
|
||||
@@ -654,4 +665,11 @@ namespace cmonitor.api
|
||||
public string Text { get; set; }
|
||||
public bool Value { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public sealed class UpdateModesInfo
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
public string Modes { get; set; }
|
||||
}
|
||||
}
|
||||
75
cmonitor/client/ruleConfig/RuleConfigJsonFile.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
namespace cmonitor.client.ruleConfig
|
||||
{
|
||||
/*
|
||||
public sealed class RuleConfigJsonFile : IRuleConfig
|
||||
{
|
||||
private Dictionary<string, object> cache = new Dictionary<string, object>();
|
||||
|
||||
public RuleConfigJsonFile()
|
||||
{
|
||||
}
|
||||
|
||||
public T Get<T>(T defaultValue)
|
||||
{
|
||||
string name = nameof(T);
|
||||
return Get(name, defaultValue);
|
||||
|
||||
}
|
||||
|
||||
public T Get<T>(string name, T defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (cache.TryGetValue(name, out object cacheValue))
|
||||
{
|
||||
return (T)cacheValue;
|
||||
}
|
||||
|
||||
string value = (Registry.GetValue(savePath, name, string.Empty)).ToString();
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
T data = value.DeJson<T>();
|
||||
cache[name] = data;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void Set<T>(T data)
|
||||
{
|
||||
try
|
||||
{
|
||||
string name = nameof(T);
|
||||
string value = data.ToJson();
|
||||
Registry.SetValue(savePath, name, value);
|
||||
cache[name] = data;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Table("rule-config")]
|
||||
public sealed class RuleConfig
|
||||
{
|
||||
private readonly IConfigDataProvider<RuleConfig> configDataProvider;
|
||||
public RuleConfig() { }
|
||||
public RuleConfig(IConfigDataProvider<RuleConfig> configDataProvider)
|
||||
{
|
||||
this.configDataProvider = configDataProvider;
|
||||
RuleConfig config = configDataProvider.Load().Result ?? new RuleConfig
|
||||
{
|
||||
UserNames = new Dictionary<string, string> { { "snltty", "{}" } }
|
||||
};
|
||||
UserNames = config.UserNames;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> UserNames { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
}*/
|
||||
}
|
||||