DatistEQ之Windows标准API
2021-03-27 本文已影响0人
了无_数据科学
2021 Q1版DatistEQ提供标准Windows API,应用程序可给DatistEQ发送一个或多个文件的路径,DatistEQ自动创建数据源节点。支持文件:.db,.db3,.sqlite,.csv,.txt,.json,.htm,.html,.xml,.eqt,.xls,.xlsx,.pdf,.doc,.docx,.e2d,grd,.dxf,.kml,.shp,.png,.jpg,.wis
发送消息C#示例代码如下:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApp7
{
public struct COPYDATASTRUCT
{
public IntPtr dwData; // 任意值
public int cbData; // 指定lpData内存区域的字节数
[MarshalAs(UnmanagedType.LPStr)]
//[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string lpData; // 发送给目标窗口文件名称
}
public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
class Program
{
const int WM_COPYDATA = 0x004A; // 固定数值,不可更改
const int WM_USER = 0x0400;// 0x00C2;
// 导出SendMessage函数
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
static void Main(string[] args)
{
//待发送文件路径,多个文件以“|”间隔
//支持的文件类型有.db,.db3,.sqlite,.csv,.txt,.json,.htm,.html,.xml,.eqt,.xls,.xlsx,
//.pdf,path,.doc,.docx,.e2d,grd,.dxf,.kml,.shp,.png,.jpg,.wis
string s = @"C:\Users\Yao\Desktop\DSendmessage\xxx.txt";
// 枚举进程
var procs = Process.GetProcesses();
foreach (Process p in procs)
{
//Datist为DatistEQ的进程名称
if (!p.ProcessName.Equals("Datist")) continue;//Datist WpfApp3
// 获取目标进程句柄
var lst = GetRootWindowsOfProcess(p.Id);
//IntPtr hWnd = p.MainWindowHandle;
foreach (var hWnd in lst)
{
Console.WriteLine($"{p.Id} : { hWnd}");
// 封装消息
byte[] sarr = Encoding.Default.GetBytes(s);
COPYDATASTRUCT cds2;
cds2.dwData = (IntPtr)0;
cds2.cbData = sarr.Length + 1;
cds2.lpData = s;
// 发送消息
SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ref cds2);
Console.WriteLine("SendMessage");
}
}
Console.ReadKey();
}
static List<IntPtr> GetRootWindowsOfProcess(int pid)
{
List<IntPtr> rootWindows = GetChildWindows(IntPtr.Zero);
List<IntPtr> dsProcRootWindows = new List<IntPtr>();
foreach (IntPtr hWnd in rootWindows)
{
GetWindowThreadProcessId(hWnd, out var lpdwProcessId);
if (lpdwProcessId != pid) continue;
var title = GetText(hWnd);
if (title.StartsWith("地震数据专家"))
{
dsProcRootWindows.Add(hWnd);
}
}
return dsProcRootWindows;
}
public static string GetText(IntPtr hWnd)
{
// Allocate correct string length first
int length = GetWindowTextLength(hWnd);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(hWnd, sb, sb.Capacity);
return sb.ToString();
}
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
var childProc = new Win32Callback(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
}
}
delphi示例代码如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,StrUtils,
Dialogs, StdCtrls,Tlhelp32;
type
TForm1 = class(TForm)
Button3: TButton;
Edit1: TEdit;
Button4: TButton;
procedure Button3Click(Sender: TObject);
procedure FindProcess();
procedure Button4Click(Sender: TObject);
function GetHWndByPID(const hPID: THandle): THandle;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button3Click(Sender: TObject);
var
h: HWND;
x : TStringList;
copydata : TCopyDataStruct;
ms : TMemoryStream;
lvStream:TMemoryStream;
begin
h := FindWindow(nil, PChar('地震数据专家(DatistEQ) - 新建流程1xxxxxx.DMS')); // MainWindow
x:=TStringList.Create;
x.add(Edit1.Text);
ms := TMemoryStream.Create;
x.SaveToStream(ms);
lvStream := TMemoryStream.Create;
lvStream.Write(Edit1.Text[1], Length(Edit1.Text));
lvStream.Position := 0;
copyData.dwData := 1;
CopyData.lpData := ms.Memory;
CopyData.cbData := ms.Size;
SendMessage(h,WM_CopyData,0,integer(@CopyData));
x.free;
ms.free;
end;
procedure TForm1.FindProcess();
var
hSnapshot: THandle;//用于获得进程列表
lppe: TProcessEntry32;//用于查找进程
Found: Boolean;//用于判断进程遍历是否完成
AFileName:string;
h: HWND;
x : TStringList;
copydata : TCopyDataStruct;
ms : TMemoryStream;
begin
AFileName:='Datist.exe';
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获得系统进程列表
lppe.dwSize := SizeOf(TProcessEntry32);//在调用Process32First API之前,需要初始化lppe记录的大小
Found := Process32First(hSnapshot, lppe);//将进程列表的第一个进程信息读入ppe记录中
while Found do
begin
if ((UpperCase(ExtractFileName(lppe.szExeFile))=UpperCase(AFileName)) or (UpperCase(lppe.szExeFile )=UpperCase(AFileName))) then
begin
h := GetHWndByPID(lppe.th32ProcessID);
x:=TStringList.Create;
//x.add(Edit1.Text);
//注意字符串的长度,Delphi向C#发信息时,长度为奇数时会引起异常。
if Length(Edit1.Text) mod 2=0 then x.add(Edit1.Text+' ') else x.add(Edit1.Text);
ms := TMemoryStream.Create;
x.SaveToStream(ms);
copyData.dwData := 1;
CopyData.lpData := ms.Memory;
CopyData.cbData := ms.Size;
SendMessage(h,WM_CopyData,0,integer(@CopyData)); //最好用PostMessage
x.free;
ms.free;
end;
Found := Process32Next(hSnapshot, lppe);//将进程列表的下一个进程信息读入lppe记录中
end;
end;
//跟据ProcessId获取进程的窗口句柄
function TForm1.GetHWndByPID(const hPID: THandle): THandle;
type
PEnumInfo = ^TEnumInfo;
TEnumInfo = record
ProcessID: DWORD;
HWND: THandle;
end;
function IsMainWindow(AHandle: THandle): Boolean;
var
ATitle: string;
ALen: Integer;
begin
Result :=(GetWindow(AHandle, GW_OWNER) = 0) and (IsWindowVisible(AHandle));
if Result then begin
ALen := GetWindowTextLength(AHandle) + 1;
SetLength(ATitle, ALen);
GetWindowText(AHandle, PChar(ATitle), ALen);
Result:= AnsiStartsStr('地震数据专家',ATitle); //获取主窗体
end;
end;{ IsMainWindow }
function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall;
var
PID: DWORD;
begin
GetWindowThreadProcessID(Wnd, @PID);
Result := (PID <> EI.ProcessID) or (not IsMainWindow(WND)) ;
if not Result then EI.HWND := WND;
end; { EnumWindowsProc }
function FindMainWindow(PID: DWORD): DWORD;
var
EI: TEnumInfo;
begin
EI.ProcessID := PID;
EI.HWND := 0;
EnumWindows(@EnumWindowsProc, Integer(@EI));
Result := EI.HWND;
end; {FindMainWindow}
begin
if hPID<>0 then
Result:=FindMainWindow(hPID)
else
Result:=0;
end;{GetHWndByPID}
procedure TForm1.Button4Click(Sender: TObject);
begin
FindProcess();
end;
end.
文件路径消息:
发送一个或多个文件路径,数据专家自动创建一个或多个节点。多个文件路径之间以“|”或换行回车为间隔。
文件路径消息
运行节点消息:
格式为“Run:节点ID”。
运行节点